監聽器:listener是servlet規範中定義的一種特殊類。用於監聽servletContext、HttpSession和servletRequest等域對象的建立和銷燬事件。監聽域對象的屬性發生修改的事件。用於在事件發生前、發生後作一些必要的處理。其主要可用於如下方面:一、統計在線人數和在線用戶二、系統啓動時加載初始化信息三、統計網站訪問量四、記錄用戶訪問路徑。html
過濾器:Filter是Servlet技術中最實用的技術,Web開發人員經過Filter技術,對web服務器管理的全部web資源:例如Jsp, Servlet, 靜態圖片文件或靜態 html 文件等進行攔截,從而實現一些特殊的功能。例如實現URL級別的權限訪問控制、過濾敏感詞彙、壓縮響應信息等一些高級功能。它主要用於對用戶請求進行預處理,也能夠對HttpServletResponse進行後處理。使用Filter的完整流程:Filter對用戶請求進行預處理,接着將請求交給Servlet進行處理並生成響應,最後Filter再對服務器響應進行後處理。java
攔截器:Interceptor 在AOP(Aspect-Oriented Programming)中用於在某個方法或字段被訪問以前,進行攔截而後在以前或以後加入某些操做。好比日誌,安全等。通常攔截器方法都是經過動態代理的方式實現。能夠經過它來進行權限驗證,或者判斷用戶是否登錄,或者是像12306 判斷當前時間是不是購票時間。web
過濾器Filter只在Servlet先後起做用,而攔截器Interceptor能夠深刻到方法先後,異常拋出先後等,具備更大的彈性。因此在Spring的程序裏應該儘可能用攔截器,在簡單的java—web項目裏能夠使用較爲簡單的過濾器。spring
過濾器的使用有兩種方式。安全
這種使用方式簡單:編寫過濾器、注入到spring中。springboot
過濾器1:服務器
package cn.qlq.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; public class MyFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("=========enter filter==========="); chain.doFilter(request, response); } @Override public void destroy() { } @Override public void init(FilterConfig arg0) throws ServletException { } }
過濾器2:session
package cn.qlq.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; public class MyFilter2 implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("=========enter filter (MyFilter2)==========="); chain.doFilter(request, response); } @Override public void destroy() { } @Override public void init(FilterConfig arg0) throws ServletException { } }
註冊到spring中:(這種註冊方式的順序能夠過濾器的指定)ide
package cn.qlq.config; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import cn.qlq.filter.MyFilter; import cn.qlq.filter.MyFilter2; /** * 註冊filter,setOrder能夠控制順序 * * @author Administrator * */ @Configuration public class FilterConfig { @Bean public FilterRegistrationBean registMyFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new MyFilter()); registration.addUrlPatterns("/*"); registration.setName("myFilter"); registration.setOrder(2); return registration; } @Bean public FilterRegistrationBean registMyFilter2() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new MyFilter2()); registration.addUrlPatterns("/*"); registration.setName("myFilter2"); registration.setOrder(1); return registration; } }
測試:post
這種方式只須要在過濾器加上註解@WebFilter便可。過濾器的執行順序是按照類名的字母順序進行過濾。這種方式須要在springboot的運行類增長@ServletComponentScan註解。ServletComponentScan註解的爲了Servlet、Filter、Listener能夠直接經過@WebServlet、@WebFilter、@WebListener註解自動註冊,無需其餘代碼。
package cn.qs; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; @SpringBootApplication // Servlet、Filter、Listener能夠直接經過@WebServlet、@WebFilter、@WebListener註解自動註冊,無需其餘代碼。 @ServletComponentScan("cn") public class MySpringBootApplication { public static void main(String[] args) { // 入口運行類 SpringApplication.run(MySpringBootApplication.class, args); } }
package cn.qlq.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; /** * 註解配置的filter執行順序按類名的順序執行 */ @WebFilter(filterName = "myFilter", urlPatterns = "/*") public class MyFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("=========enter filter==========="); chain.doFilter(request, response); } @Override public void destroy() { } @Override public void init(FilterConfig arg0) throws ServletException { } }
package cn.qlq.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; @WebFilter(filterName = "myFilter2", urlPatterns = "/*") public class MyFilter2 implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("=========enter filter (MyFilter2)==========="); chain.doFilter(request, response); } @Override public void destroy() { } @Override public void init(FilterConfig arg0) throws ServletException { } }
測試:
攔截器的使用方法是先編寫攔截器,而後註冊到spring。攔截器的執行順序是按照其註冊順序攔截。
package cn.qlq.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class MyInterceptor1 implements HandlerInterceptor { /** * 在請求處理以前進行調用(Controller方法調用以前) */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception { System.out.println("被 MyInterceptor1 postHandle攔截,放行..."); return true; } /** * 請求處理以後進行調用,可是在視圖被渲染以前(Controller方法調用以後) */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView mv) throws Exception { System.out.println("被 MyInterceptor1 postHandle 攔截,放行..."); } /** * 在整個請求結束以後被調用,也就是在DispatcherServlet 渲染了對應的視圖以後執行 (主要是用於進行資源清理工做) */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception ex) throws Exception { System.out.println("被 MyInterceptor1 afterCompletion 攔截,放行..."); } }
package cn.qlq.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class MyInterceptor2 implements HandlerInterceptor { /** * 在請求處理以前進行調用(Controller方法調用以前) */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception { System.out.println("被 MyInterceptor2 postHandle攔截,放行..."); return true; } /** * 請求處理以後進行調用,可是在視圖被渲染以前(Controller方法調用以後) */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView mv) throws Exception { System.out.println("被 MyInterceptor2 postHandle 攔截,放行..."); } /** * 在整個請求結束以後被調用,也就是在DispatcherServlet 渲染了對應的視圖以後執行 (主要是用於進行資源清理工做) */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception ex) throws Exception { System.out.println("被 MyInterceptor2 afterCompletion 攔截,放行..."); } }
註冊到spring中:
package cn.qlq.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import cn.qlq.interceptor.MyInterceptor1; import cn.qlq.interceptor.MyInterceptor2; /** * 註冊攔截器 * * @author Administrator * */ @Configuration public class InterceptorConfig extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { /** * 攔截器按照順序執行 */ registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/th/**").addPathPatterns("/freemarker/**"); registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/freemarker/**"); super.addInterceptors(registry); } }
監聽器的使用與過濾器使用差很少,也是先編寫監聽器,而後注入到spring中。
package cn.qlq.listener; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; public class MyHttpSessionListener implements HttpSessionListener { public static int online = 0; @Override public void sessionCreated(HttpSessionEvent se) { System.out.println("建立session,在線用戶數:" + (++online)); } @Override public void sessionDestroyed(HttpSessionEvent se) { System.out.println("銷燬session,在線用戶數:" + (--online)); online--; } }
package cn.qlq.listener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class MyServletContextListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("容器建立"); } @Override public void contextDestroyed(ServletContextEvent sce) { System.out.println("容器銷燬"); } }
注入到spring中:
package cn.qlq.config; import org.springframework.boot.web.servlet.ServletListenerRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import cn.qlq.listener.MyHttpSessionListener; import cn.qlq.listener.MyServletContextListener; /** * * @author Administrator * */ @Configuration public class ListenerConfig { @Bean public ServletListenerRegistrationBean<MyHttpSessionListener> listenerRegist() { ServletListenerRegistrationBean<MyHttpSessionListener> srb = new ServletListenerRegistrationBean<MyHttpSessionListener>(); srb.setListener(new MyHttpSessionListener()); return srb; } @Bean public ServletListenerRegistrationBean<MyServletContextListener> listenerRegist2() { ServletListenerRegistrationBean<MyServletContextListener> srb = new ServletListenerRegistrationBean<MyServletContextListener>(); srb.setListener(new MyServletContextListener()); return srb; } }
測試:
補充:固然監聽器能夠使用註解方式,以下:
package cn.qs.listener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; @WebListener public class StartListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("容器啓動"); } @Override public void contextDestroyed(ServletContextEvent sce) { System.out.println("容器銷燬"); } }