在工做中使用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