詳解IDEA中SpringBoot整合Servlet三大元件的過程
Spring MVC整合
SpringBoot提供為整合MVC框架提供的功能特性
- 內建兩個檢視解析器:ContentNegotiatingViewResolver和BeanNameViewResolver
- 支援靜態資源以及WebJars
- 自動註冊了轉換器和格式化器
- 支援Http訊息轉換器
- 自動註冊了訊息程式碼解析器
- 支援靜態專案首頁index.html
- 支援定製應用圖示favicon.ico
- 自動初始化Web資料繫結器:ConfigurableWebBindingInitializer
Spring MVC功能擴充套件實現
- 專案環境搭建(結構如這篇部落格)
- 功能擴充套件實現
- 註冊檢視管理器
/* 在config資料夾下編寫配置類 實現WebMvcConfigurer介面,擴充套件MVC功能 測試前將LoginController控制類註釋,更好的觀察效果 */ @Configuration public class MyMVCConfig implements WebMvcConfigurer { //新增檢視管理 @Override public void addViewControllers(ViewControllerRegistry registry) { // 請求toLoginPage對映路徑或者login.html頁面都會自動對映到login.html頁面 registry.addViewController("/toLoginPage").setViewName("login"); registry.addViewController("/login.html").setViewName("login"); } }
- 測試後發現,使用這種方式無法獲取後臺處理的資料,比如登入頁面中的年份。
- 使用WebMvcConfigurer介面中的addViewControllers(ViewControllerRegistry registry)方法定製
檢視控制,只適合較為簡單的無引數檢視Get方式的請求跳轉,對於有引數或需要業務處理的跳轉請求,最好還是採用傳統方式處理請求。
註冊自定義攔截器
/* 自定義一個攔截器類,實現簡單的攔截業務 */ @Configuration public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception { // 使用者請求/admin開頭路徑時,判斷使用者是否登入 String uri = request.getRequestURI(); Object loginUser = request.getSession().getAttribute("loginUser"); if(uri.startsWith("/admin")&&null==loginUser){ response.sendRedirect("/toLoginPage"); return false; } return true; } @Override public void postHandle(HttpServletRequest request,Object handler,@Nullable ModelAndView modelAndView) throws Exception { //向request域中存放當前年份用於頁面動態展示 request.setAttribute("currentYear",Calendar.getInstance().get(Calendar.YEAR)); } @Override public void afterCompletion(HttpServletRequest request,Exception ex) throws Exception { } }
- 自定義攔截器類MyInterceptor實現了HandlerInterceptor介面。在preHandle()方法中,如果使用者請求以“/admin”開頭,
則判斷使用者是否登入,如果沒有登入,則重定向到“/toLoginPage”請求對應的登入頁面。
- 在postHandle()方法中,使用request物件向前端頁面傳遞表示年份的currentYear資料。
- 在自定義配置類MyMVCConfig中,重寫addInterceptors()方法註冊自定義的攔截器,如下
@Autowired private MyInterceptor myInterceptor; //新增攔截器管理 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(myInterceptor) .addPathPatterns("/**") .excludePathPatterns("/login.html"); }
- 使用@Autowired註解引入自定義的MyInterceptor攔截器元件,重寫其中addInterceptors()方法註冊自定義的攔截器
- 使用addPathPatterns("/**")方法攔截所有路徑請求,excludePathPatterns("/login.html")方法對“login.html”路徑請求放行處理。
- 專案重啟後,訪問localhost:8080/admin,跳轉到登入介面,自定義攔截器生效。
Spring Boot 整合Servlet三大元件
元件註冊方式整合Servlet三大元件
在Spring Boot中,使用元件註冊方式整合內嵌Servlet容器的Servlet、Filter、Listener三大元件時,
只需要將這些自定義元件通過ServletRegistrationBean、FilterRegistrationBean、ServletListenerRegistrationBean類註冊到容器中即可
元件註冊方式整合 Servlet
/* 自定義Servlet類 使用@Component註解將MyServlet類作為元件注入Spring容器。該類繼承自HTTPServlet, 通過HttpServletResponse物件向頁面輸出"hello MyServlet" */ @Component public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException { this.doPost(req,resp); } @Override protected void doPost(HttpServletRequest req,IOException { resp.getWriter().write("hello MyServlet"); } }
/* 嵌入式Servlet容器三大元件配置 @Configuration註解將該類標註為配置類,getServlet()方法用於註冊自定義MyServlet, 返回ServletRegistrationBean型別的Bean物件 */ @Configuration public class ServletConfig { // 註冊Servlet元件 @Bean public ServletRegistrationBean<javax.servlet.Servlet> getServlet(MyServlet myServlet){ return new ServletRegistrationBean<javax.servlet.Servlet>(myServlet,"/myServlet"); } }
啟動測試,訪問myServlet,顯示資料說明成功整合Servlet元件
元件註冊方式整合Filter
/* 自定義Filter類 使用@Component註解將當前MyFilter類作為元件注入到Spring容器中 MyFilter類實現Filter介面,重寫如下三個方法,在doFilter()方法中想控制檯列印"hello MyFilter" */ @Component public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } @Override public void doFilter(ServletRequest servletRequest,ServletResponse servletResponse,FilterChain filterChain) throws IOException,ServletException { System.out.println("hello MyFilter"); filterChain.doFilter(servletRequest,servletResponse); } }
//註冊Filter元件 @Bean public FilterRegistrationBean<javax.servlet.Filter> getFilter(MyFilter myFilter){ FilterRegistrationBean<javax.servlet.Filter> registrationBean = new FilterRegistrationBean<>(myFilter); registrationBean.setUrlPatterns(Arrays.asList("/toLoginPage","/myFilter")); return registrationBean; }
啟動測試,訪問/myFilter,控制檯看到hello MyFilter
元件註冊方式整合Listener
/* 自定義Listener類 */ @Component public class MyListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("contextInitialized ..."); } @Override public void contextDestroyed(ServletContextEvent sce) { System.out.println("contextDestroyed ..."); } }
//註冊Listener元件 @Bean public ServletListenerRegistrationBean<java.util.EventListener> getServletListener(MyListener myListener){ return new ServletListenerRegistrationBean<>(myListener); }
程式啟動成功後,會自動列印輸出"contextInitialized ...",單擊坐下的Exit關閉會輸出銷燬的監聽資訊,如果直接強制關閉程式,無法列印監聽資訊。
- 注意:當自定義的Servlet元件配置類ServletConfig全部註釋並重啟專案後,自定義的Servlet、Filter、Listener元件仍然生效。
- 原因:嵌入式Servlet容器對Servlet、Filter、Listener元件進行了自動化識別和配置,而自定義的Servlet、Filter、Listener都繼承/實現了對應的類/介面,同時自定義的這三個元件都使用了@Component註解,會自動被掃描為Spring元件。
路徑掃描整合Servlet三大元件
- 使用路徑掃描的方式整合三大元件,需要再自定義元件上分別新增@WebServlet、@WebFilter、@WebListener註解進行宣告,並配置相關注解屬性,在主程式啟動類上使用@ServletComponentScan註解開啟元件掃描。
- 分別用以下三個註解代替@Component註解進行配置三個元件
@WebFilter(value={"/antionLogin","/antionMyFilter"})
@WebListener
@WebServlet("/annotationServlet")
- 啟動類上加入
@ServletComponentScan
註解,開啟基於註解的元件掃描支援 - 對於Filter測試訪問"/antionLogin","/antionMyFilter",對於Servlet測試訪問"/annotationServlet",測試結果如上。
到此這篇關於詳解IDEA中SpringBoot整合Servlet三大元件的過程的文章就介紹到這了,更多相關SpringBoot整合Servlet三大元件內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!