Analysis of spring boot interceptor and filter instance

Time:2020-3-25

This article mainly introduces the spring boot interceptor and filter instance analysis. The example code is introduced in detail in this article, which has certain reference learning value for your study or work. You can refer to the following for your friends

1、 Interceptors and filters

Before we talk about spring boot, let’s take a look at filters and interceptors. The two are similar in function, but there is a big gap in specific technology implementation. Before analyzing the difference between the two, let’s understand the concept of AOP. AOP is not a specific technology, but a programming idea. In the process of object-oriented programming, we can easily solve the vertical expansion by inheritance and polymorphism. However, for horizontal functions, such as enabling transactions in all service methods, or recording logs in a unified way, object-oriented cannot be solved. So AOP — aspect oriented programming is actually a supplement to the idea of object-oriented programming. The filters and interceptors we talk about today belong to the concrete implementation of aspect oriented programming. The main differences between the two are as follows:

1. Filter is dependent on the servlet container and is part of the servlet specification, while interceptor is independent and can be used under any circumstances.

2. Filter is executed by servlet container callback, while interceptor is usually executed by dynamic agent.

3. Filter’s life cycle is managed by servlet container, while interceptor can be managed by IOC container, so it can obtain other bean instances by injection and other ways, so it will be more convenient to use.

2、 Filter configuration

Now we use the filter to record the execution time of the request, which is as follows:


public class LogCostFilter implements Filter {
  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
 
  }
 
  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    long start = System.currentTimeMillis();
    filterChain.doFilter(servletRequest,servletResponse);
    System.out.println("Execute cost="+(System.currentTimeMillis()-start));
  }
 
  @Override
  public void destroy() {
 
  }
}

The logic of this code is relatively simple, that is to record the time stamp before the method is executed, and then complete the execution of the request through the filter chain, and calculate the execution time between the returned results. This class must inherit the filter class. This is the servlet specification. This is no different from previous web projects. However, with the filter class, the previous web project can be configured in web.xml, but the spring boot project does not have the web.xml file, so how to configure? In spring boot, we need filter registration bean to complete the configuration. The implementation process is as follows:


@Configuration
public class FilterConfig {
 
  @Bean
  public FilterRegistrationBean registFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new LogCostFilter());
    registration.addUrlPatterns("/*");
    registration.setName("LogCostFilter");
    registration.setOrder(1);
    return registration;
  }
 
}

This completes the configuration. The options to be configured mainly include instantiating the filter class, specifying the URL matching pattern, setting the filter name and execution order. This process is no different from the configuration in web.xml, but in different forms. Now we can start the server to access any URL:

You can see that the above configuration has taken effect. In addition to the configuration through the filterregistrationbean, there is a more direct way, which can be done directly through annotation:


@WebFilter(urlPatterns = "/*", filterName = "logFilter2")
public class LogCostFilter2 implements Filter {
  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
 
  }
 
  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    long start = System.currentTimeMillis();
    filterChain.doFilter(servletRequest, servletResponse);
    System.out.println("LogFilter2 Execute cost=" + (System.currentTimeMillis() - start));
  }
 
  @Override
  public void destroy() {
 
  }
}

Here you can directly use @ webfilter to configure. Similarly, you can set URL matching mode, filter name, etc. It should be noted that @ webfilter annotation is the specification of servlet 3.0, which is not provided by spring boot. In addition to this annotation, we need to add another annotation to the configuration class: @ servletcomponetscan, which specifies the scanned package.


@SpringBootApplication
@MapperScan("com.pandy.blog.dao")
@ServletComponentScan("com.pandy.blog.filters")
public class Application {
  public static void main(String[] args) throws Exception {
    SpringApplication.run(Application.class, args);
  }
}

Now, let’s go to any URL:

As you can see, both of the filters we configured are working. Careful readers will find that we do not specify the order of execution for the second filter, but execute it before the first filter. It needs to be explained here that the @ webfilter annotation does not specify the attribute of execution order. Its execution order depends on the filter name. It is arranged in reverse alphabetical order according to the filter class name (note that it is not the name of the configured filter). Moreover, the filter priority specified by @ webfilter is higher than that configured by the filter registration bean. Interested friends can experiment on their own.

3、 Interceptor configuration

Now that we have introduced the filter configuration method, let’s take a look at how to configure an interceptor. We use interceptors to achieve the same function above, recording the execution time of the request. First, we implement the interceptor class:


public class LogCostInterceptor implements HandlerInterceptor {
  long start = System.currentTimeMillis();
  @Override
  public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
    start = System.currentTimeMillis();
    return true;
  }
 
  @Override
  public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    System.out.println("Interceptor cost="+(System.currentTimeMillis()-start));
  }
 
  @Override
  public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
  }
}

Here we need to implement the handlerinterceptor interface, which includes three methods: prehandle is executed before the request is executed, posthandler is executed after the request is executed, but only when the prehandle method returns true, aftercompletion is executed after the view rendering is completed, and prehandle also needs to return true, which is usually used to clean up resources and other works Do. In addition to implementing the above interfaces, we need to configure them:


@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {
 
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LogCostInterceptor()).addPathPatterns("/**");
    super.addInterceptors(registry);
  }
}

Here we inherit the webmvcconfigureradapter. The friends who have read the previous article should have seen this class. We used this class in the static resource directory configuration. Here we rewrite the addinterceptors method to configure the interceptor. There are two main configuration items: one is to specify the interceptor, and the other is to specify the interceptor URL. Now let’s start the system to access any URL:

As you can see, we implemented the same function through interceptors. However, it should be noted that there is a problem in this implementation. Because prehandle and posthandle are two methods, we have to set a shared variable start to store the start value, but there will be thread safety problems. Of course, we can solve this problem by other methods, such as ThreadLocal. Interested students can implement it by themselves. However, we can see from this point that, although interceptors are better than filters in many scenarios, in this scenario, filters are easier to implement than interceptors.

Four, summary

This paper mainly introduces the configuration of filter and Interceptor Based on spring boot. Both filters and interceptors belong to the specific implementation of AOP (aspect oriented programming). In addition to these two implementations, we have seen another more flexible AOP implementation technology, which is aspect. We can accomplish more and more powerful functions through aspect. I’ll share this later.

The above is the whole content of this article. I hope it will help you in your study, and I hope you can support developepaer more.

Recommended Today

Positioning style

Detailed explanation of positioning style usage method:Use the position property to set the location A base point used to establish the position of an object According to this reference, the position is shiftedOptional value Static static positioning the default value element is static and positioning is not turned on Relative turns on the relative positioning […]