Interceptors and filters in spring boot
Interceptor
Execution process of interceptor
Directly on the code, the code has comments
package com.hjx.config; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Implementation of interceptor */ @Component public class MyInterceptor implements HandlerInterceptor { /** * * The preprocessing callback method realizes the preprocessing of the processor * Return value: true indicates to continue the process; false indicates that the process is interrupted and will not continue to call other interceptors or processors * Execute before method processing */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("Controller Execute before method execution in"); return true; //Return value: true indicates to continue downward execution; false indicates that the process is interrupted and will not continue to call other interceptors or methods in the Controller to be executed } /** * The post-processing callback method implements the post-processing of the processor (controller), but before rendering the view * At this time, we can process model data or view through modelAndView */ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("Controller Execute after method execution in"); } /** * Callback method after the whole request is processed, that is, callback when the view rendering is completed, * For example, in performance monitoring, we can record the end time and output the consumption time here, * You can also clean up some resources, similar to finally in try catch finally, * But only call the processor in the execution chain */ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("Execute after view generation"); } }
The interceptors are implemented in the following ways:
1. Implement the interface HandlerInterceptor and override the preHandle, postHandle and afterCompletion methods. Finally, register the interceptor
2. Inherit HandlerInterceptorAdapter class (implementation class of HandlerInterceptor interface).
3. Implement the WebRequestInterceptor interface or inherit the implementation class of the interface.
Note:
1. When we register the interceptor by inheriting the WebMvcConfigurationSupport class, the static resources (including those under templates) will be intercepted by default, resulting in the problem of No mapping for GET xxxx
When using interceptors, when configuring interceptors, because before Spring Boot 2.0, we directly inherited the WebMvcConfigurerAdapter class, and then overridden the addInterceptors method to implement interceptor configuration. However, after Spring Boot 2.0, this method has been abandoned (of course, it can continue to be used) and replaced by the WebMvcConfigurationSupport method, as follows
Solution 1: the simplest way is to implement the WebMvcConfigurer interface and register the interceptor to release static resources. As follows:
@Configuration public class ViewConfig implements WebMvcConfigurer { @Autowired // The filter configuration implements the HandlerInterceptor interface private MyInterceptor myInterceptor; //Configuration of interceptors @Override public void addInterceptors(InterceptorRegistry registry) { // Implementing WebMvcConfigurer will not cause static resources to be intercepted registry.addInterceptor(myInterceptor).addPathPatterns("/**"); } }
Solution 2
The interceptor is still registered using the inherited WebMvcConfigurationSupport method, but one of the methods addResourceHandlers needs to be overridden to release static resources, as follows:
/** * It is used to specify that static resources are not intercepted. Otherwise, it inherits WebMvcConfigurationSupport, which will make static resources inaccessible directly * @param registry */ @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**").addResourceLocations("classpath:/static/"); super.addResourceHandlers(registry); }
However, it is best to use scheme 1: it is easy to manage and the code is lighter.
Execution flow during multiple interceptions
The preHandle executes in the order in the configuration file.
However, their postHandle and afterCompletion methods are executed in reverse order in the configuration file
filter
Implementation mode 1
1. Use component registration to integrate filters. The specific methods are as follows:
1. Define a class to implement the Filter interface and override init, doFilter and destroy methods. The class is decorated with @ Component annotation.
2. Create a new Configuration class and modify it with @ Configuration. Declare a method and modify it with @ Bean annotation (inject the return value of the annotation modified method into the Bean), as follows:
Component public class Myfilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { Filter.super.init(filterConfig); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { } @Override public void destroy() { Filter.super.destroy(); } }
@Bean public FilterRegistrationBean FilterRegister(Myfilter myfilter){ FilterRegistrationBean registrationBean=new FilterRegistrationBean(myfilter); registrationBean.setUrlPatterns(Arrays.asList("/login","/a")); return registrationBean; }
Implementation mode 2
The method of path scanning is as follows:
// The main startup class starts package scanning (filter to be scanned) @ServletComponentScan("com.hjx.Controller.Filter") // Intercept the specified path @WebFilter(value = {"/a","/b"}) public class Myfilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { Filter.super.init(filterConfig); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { } @Override public void destroy() { Filter.super.destroy(); } }
Difference between filter and interceptor
difference
1. The Filter is implemented based on Servlet. The main application scenario of the Filter is to Filter character coding, cross domain and other problems. The working principle of Servlet is to intercept the configured client Request, and then process the Request and Response. The Filter starts with the start of the web application and is initialized only once.
3. Interceptor is a method enhancement tool based on Java reflection (dynamic proxy) mechanism implemented in spring MVC
4. The filter belongs to Servlet level and the interceptor belongs to Spring level
Filter is defined in the javax.servlet package and depends on the network container, so it can only be used in web projects.
Interceptor is implemented in Spring MVC. In the final analysis, interceptor is a Spring component managed by Spring container.
5. The filter is implemented based on function callback, and the interceptor is implemented based on Java reflection mechanism
Same point
1. Both interceptors and filters embody the idea of AOP, enhance the implementation of methods, and can intercept request methods.
2. Both interceptors and filters can set the execution Order through the Order annotation
Interceptor and filter execution path diagram
Application scenario
Application scenarios of Interceptor: permission control, log printing and parameter verification
Application scenarios of filter: cross domain problem solving, code conversion