在工做中使用Web框架,老是避免不了與這些概念打交道,作一下總結,一口氣說完攔截器、過濾器、監聽器。java
GitHub源碼地址git
監聽器 > 過濾器 > 攔截器
【注】如下代碼基於springboot2.0github
(1)攔截器web
MyInterceptor1 繼承 HandlerInterceptorAdapterspring
MyInterceptor2 實現 HandlerInterceptor接口springboot
public class MyInterceptor1 extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { request.setAttribute("startTime", System.currentTimeMillis()); System.out.println(">>>>> MyInterceptor1 preHandle >>>>>>>>>>>>>>>>>>>>>>"); return super.preHandle(request, response, handler); } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { long startTime = (long) request.getAttribute("startTime"); System.out.println("MyInterceptor1 執行:" + (System.currentTimeMillis() - startTime)); System.out.println(">>>>> MyInterceptor1 postHandle >>>>>>>>>>>>>>>>>>>>>>"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { request.removeAttribute("startTime"); System.out.println(">>>>> MyInterceptor1 afterCompletion >>>>>>>>>>>>>>>>>>>>>>"); } @Override public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { super.afterConcurrentHandlingStarted(request, response, handler); System.out.println(">>>>> MyInterceptor1 afterConcurrentHandlingStarted >>>>>>>>>>>>>>>>>>>>>>"); } }
public class MyInterceptor2 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { request.setAttribute("startTime", System.currentTimeMillis()); System.out.println(">>>>> MyInterceptor2 preHandle >>>>>>>>>>>>>>>>>>>>>>"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { long startTime = (long) request.getAttribute("startTime"); System.out.println("MyInterceptor2 執行:" + (System.currentTimeMillis() - startTime)); System.out.println(">>>>> MyInterceptor2 postHandle >>>>>>>>>>>>>>>>>>>>>>"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { request.removeAttribute("startTime"); System.out.println(">>>>> MyInterceptor2 afterCompletion >>>>>>>>>>>>>>>>>>>>>>"); } }
(2)配置app
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**"); registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**"); } }
(3)請求框架
@RestController @SpringBootApplication public class SpringbootInterceptorApplication { public static void main(String[] args) { SpringApplication.run(SpringbootInterceptorApplication.class, args); } @GetMapping(value = "/hello1") public ResponseEntity<String> hello() throws InterruptedException { Thread.sleep(500); return ResponseEntity.ok("HelloWorld"); } @GetMapping(value = "/hello2") public StreamingResponseBody hello2() throws InterruptedException { Thread.sleep(500); return (OutputStream outputStream) -> { outputStream.write("success".getBytes()); outputStream.flush(); outputStream.close(); }; } @GetMapping(value = "/hello3") public Future<String> hello3() throws InterruptedException { Thread.sleep(500); return new AsyncResult<>("Hello"); } }
(4) 運行結果ide
請求/hello1函數
>>>>> MyInterceptor1 preHandle >>>>>>>>>>>>>>>>>>>>>> >>>>> MyInterceptor2 preHandle >>>>>>>>>>>>>>>>>>>>>> MyInterceptor2 執行:516 >>>>> MyInterceptor2 postHandle >>>>>>>>>>>>>>>>>>>>> MyInterceptor1 執行:516 >>>>> MyInterceptor1 postHandle >>>>>>>>>>>>>>>>>>>>> >>>>> MyInterceptor2 afterCompletion >>>>>>>>>>>>>>>> >>>>> MyInterceptor1 afterCompletion >>>>>>>>>>>>>>>>
執行按preHandle > postHandle > afterCompletion
請求/hello2 或 /hello3
>>>>> MyInterceptor1 preHandle >>>>>>>>>>>>>>>>>>>>>> >>>>> MyInterceptor2 preHandle >>>>>>>>>>>>>>>>>>>>>> >>>>> MyInterceptor1 afterConcurrentHandlingStarted >>>>>>>>>>>>>>>>>>>>>> >>>>> MyInterceptor1 preHandle >>>>>>>>>>>>>>>>>>>>>> >>>>> MyInterceptor2 preHandle >>>>>>>>>>>>>>>>>>>>>> MyInterceptor2 執行:1 >>>>> MyInterceptor2 postHandle >>>>>>>>>>>>>>>>>>>>>> MyInterceptor1 執行:1 >>>>> MyInterceptor1 postHandle >>>>>>>>>>>>>>>>>>>>>> >>>>> MyInterceptor2 afterCompletion >>>>>>>>>>>>>>>>>>>>>> >>>>> MyInterceptor1 afterCompletion >>>>>>>>>>>>>>>>>>>>>>
MyInterceptor1 執行順序 preHandle > afterConcurrentHandlingStarted > preHandle > postHandle >afterCompletion
MyInterceptor2 執行順序 preHandle > preHandle > postHandle > afterCompletion
綜上.對於concurrent類型的返回值,spring會啓用一個新的線程來處理concurrent類型消息,在新的線程中會從新調用preHandle方法。
(1) 過濾器
public class MyFilter1 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println(filterConfig.getInitParameter("initParam")); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("doFilter1 >>>>>>>>>>>"); filterChain.doFilter(servletRequest, servletResponse); } }
(2) 配置
@Bean public FilterRegistrationBean<MyFilter1> filterRegistrationBean() { FilterRegistrationBean<MyFilter1> filterRegistrationBean = new FilterRegistrationBean<>(); filterRegistrationBean.addUrlPatterns("/*");//過濾全部 filterRegistrationBean.setFilter(new MyFilter1()); filterRegistrationBean.setOrder(1); filterRegistrationBean.addInitParameter("initParam", "initOk"); return filterRegistrationBean; }
@Bean public MyFilter1 myFilter() { return new MyFilter1(); }
@WebFilter("/test/*") public class MyFilter2 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("MyFilter2"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(servletRequest, servletResponse); System.out.println("DoFilter 2"); } }
經過@WebFilter("/test/*")註解,首先須要@ServletComponentScan("com.jiuxian")
Filter 全局攔截的配置(/*)和 Interceptor(/**)有所區別須要注意
(1) 監聽器
public class MyListener1 implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("MyListener1 ... "); } }
(2) 配置方式和Filter相似
@Bean public ServletListenerRegistrationBean<MyListener1> registrationBean() { ServletListenerRegistrationBean<MyListener1> servletListenerRegistrationBean = new ServletListenerRegistrationBean<>(); servletListenerRegistrationBean.setListener(new MyListener1()); return servletListenerRegistrationBean; }
@Bean public MyListener1 myListener1() { return new MyListener1(); }
@WebListener public class MyListener2 implements ServletRequestListener { @Override public void requestInitialized(ServletRequestEvent sre) { System.out.println("MyListener2"); } }
使用@WebListener註解,首先須要@ServletComponentScan("com.jiuxian")
【注】以上代碼基於springboot2.0