First, interceptors and filters
Before we talk about spring boot, let's look at filters and interceptors first. The two are similar in function, but the gap is still relatively large in the specific technology implementation. Before we analyze the difference between the two, we first understand the concept of AOP, which is not a specific technology, but a programming idea. In the process of object-oriented programming, it is easy to solve vertical scaling through inheritance and polymorphism. But for horizontal functions, such as opening transactions in all service methods, or unifying logging functions, object-oriented is unresolved. So aop---oriented programming is actually a complement to the object-oriented programming idea. The filters and interceptors we talk about today are specific implementations of aspect-oriented programming. The main differences between the two include the following:
1. The filter is dependent on the servlet container, which is part of the servlet specification, and the interceptor is independent and can be used under any circumstances.
2, the execution of the filter is done by the servlet container callback, and the interceptor is usually executed by a dynamic proxy.
3. The life cycle of the filter is managed by the servlet container, and the interceptor can be managed by the IOC container, so it is easier to use it by injecting other instances of the bean.
Second, the filter configuration
We now implement the function of recording request execution time through filters, which are implemented as follows:
?
123456789101112131415161718 |
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 simple, that is, the time stamp is recorded before the method executes, and then the execution of the request is completed through the filter chain, and the execution time is calculated between the returned results. The main requirement here is that the class must inherit the filter class, which is the specification of the servlet, which is no different from the previous Web project. However, with the filter class, the previous Web project can be configured in XML, but the Spring boot project does not have the Web. xml file, how do I configure it? In spring boot, we need Filterregistrationbean to complete the configuration. The implementation process is as follows:
?
1234567891011121314 |
@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 configuration is done, the options that need to be configured mainly include instantiating the filter class, specifying the URL's matching pattern, setting the filter name and execution order, which is no different from the configuration in Web. XML, except in the form. Now we can start the server to access any URL:
You can see that the above configuration is already in effect. In addition to being configured via Filterregistrationbean, there is a more straightforward way to do this directly with annotations:
?
12345678910111213141516171819 |
@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() {
}
}
|
This can be configured directly with @webfilter, and similarly, you can set the URL matching mode, filter name and so on. One thing to note here is that @webfilter this annotation is a Servlet3.0 specification and is not provided by spring boot. In addition to this annotation, we need to add another annotation to the configuration class: @ServletComponetScan, specify the scanned package.
?
12345678 |
@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 back to any URL:
As you can see, the two filters we configured are in effect. The careful reader will find that the second filter does not specify the order of execution, but it executes before the first filter. Here we need to explain that @WebFilter this annotation does not specify the execution order of the properties, whose execution depends on the name of the filter, and is based on the filter class name (note that the name of the filter is not configured) in descending order of the alphabet, And the @webfilter specified filter priority is higher than the Filterregistrationbean configured filter. Interested friends can experiment with their own.
Third, the configuration of the Interceptor
We've covered the configuration of the filter above, and then we'll look at how to configure an interceptor. We use interceptors to achieve the same functionality as above, recording the execution time of the request. First we implement the Interceptor class:
?
1234567891011121314151617 |
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 handlerinterceptor this interface, which consists of three methods, Prehandle is executed before the request execution, Posthandler is the request to end execution, but only when the Prehandle method returns True, the execution, Aftercompletion is performed only after the view rendering is complete, and also requires Prehandle to return true, which is typically used to clean up resources. In addition to implementing the above interface, we also need to configure it:
?
123456789 |
@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, see the previous article friend should have seen this class, in the static resource directory configuration we used this class. Here we rewrite the Addinterceptors method, the Interceptor configuration, the main configuration of two, one is to specify the interceptor, the second is to specify the blocked URL. Now we can start the system to access any URL:
As you can see, we have implemented the same function through interceptors. However, it is also important to note that this implementation is problematic, because Prehandle and Posthandle are two methods, so we have to set up a shared variable start to store the start value, but there is a thread safety problem. Of course, we can solve by other means, such as through threadlocal can be a good solution to this problem, interested students can achieve their own. But with this we can actually see that while interceptors are better than filters in many scenarios, filters are easier to implement than interceptors in this scenario.
Iv. Summary
This article mainly explains the configuration of filters and interceptors based on spring boot. Both the filter and the interceptor are the specific implementations of AOP (aspect-oriented programming) ideas. In addition to the two implementations we have seen another more flexible AOP implementation technology, aspect, we can do more and more powerful functions through aspect. This follow-up to share with you.
Spring Boot Combat: Interceptors and filters