1, How to implement interceptor
In Spring Boot projects, interceptors are often used for login verification, logging and other operations. Interceptors are provided by Spring, so they can be injected into bean s and managed by IOC container. The way to implement the interceptor is very simple. It mainly consists of the following two steps:
-
The custom interceptor class implements the HandlerInterceptor interface
-
The custom WebMvc configuration class implements the WebMvcConfigurer interface and adds a custom interceptor class
The brief implementation code is as follows:
custom interceptor LoginInterceptor:
public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("token"); if(StringUtils.isEmpty(token)){ ... return false; } return true; } }
To configure a custom Interceptor:
@Configuration public class WebConfiguration implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) // Blocked requests .addPathPatterns("/**") // Requests not intercepted .excludePathPatterns("/login"); } }
The main function of this interceptor is to intercept all access requests and verify whether the token is valid. Only after the token is verified successfully can we access our business interface. At this time, you need to provide an interface to verify the validity of the token and verify the token in the interceptor. Since the interceptor is provided by Spring, it is easy to think of using @ Component annotation to annotate the interceptor into a bean. Then use the @ Autowired annotation to inject the verification token class into the interceptor for verification.
The modified code is as follows:
Verify token interface class:
@Component public class TokenUtil { /** * Verify whether the token is valid */ public boolean checkToken(String token){ ... } }
The modified interceptor code is as follows:
@Component public class LoginInterceptor implements HandlerInterceptor { @Autowired private TokenUtil tokenUtil; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if(!tokenUtil.checkToken(token)){ ... return false; } return true; } }
When calling the interface, it is found that TokenUtil is not injected! Obviously, the code is OK. Why can't TokenUtil be injected normally?
Carefully observe our customized configuration class WebConfiguration. When adding an interceptor, we use new LoginInterceptor(). If you want the interceptor to take effect, you must configure the interceptor into the configuration class of WebMvc, that is, our customized WebConfiguration class. Now when adding interceptors, new has an interceptor, that is, the interceptor is not managed to the IOC container, so Spring bean objects cannot be introduced.
2, How to host interceptors to IOC containers
The idea to solve the problem is also very simple, that is, hosting the interceptor to the IOC container, so that the objects in the container can be injected into each other. There are three ways to deal with the above problems.
2.1 inject interceptor in WebConfiguration
The interceptor code remains unchanged. Use @ Component on the interceptor and inject the interceptor with @ Autowired annotation in WebConfiguration.
Interceptor Code:
@Component public class LoginInterceptor implements HandlerInterceptor { }
Configuration class code:
@Configuration public class WebConfiguration implements WebMvcConfigurer { @Autowired private LoginInterceptor loginInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor); } }
2.2 inject interceptors into bean s in WebConfiguration
The interceptor does not need to add the @ Component annotation. Use the @ bean annotation in the WebConfiguration class to annotate the interceptor as a bean.
Interceptor Code:
public class LoginInterceptor implements HandlerInterceptor { }
Configuration class code:
@Configuration public class WebConfiguration implements WebMvcConfigurer { @Bean public LoginInterceptor loginInterceptor(){ return new LoginInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor( loginInterceptor()); } }
2.3 processing by constructor
The idea is to inject the business class required to verify the token into the WebConfiguration class, and then bring the business class into the interceptor through the constructor when initializing the interceptor, so that the interceptor does not need to be injected into a Spring Bean object.
Interceptor Code:
public class LoginInterceptor implements HandlerInterceptor { private TokenUtil tokenUtil; public LoginInterceptor(TokenUtil tokenUtil) { this.tokenUtil = tokenUtil; } }
Configuration class code:
@Configuration public class WebConfiguration implements WebMvcConfigurer { @Autowired private TokenUtil tokenUtil; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor(tokenUtil)); } }
3, Summary
The interceptor code on the Internet is basically configured through a new interceptor. At this time, other beans cannot be injected. Many people take it for granted to add @ Component annotation directly to the interceptor to make it a bean object. This is a wrong approach. What we need to ensure is that the interceptor added in the WebMvc configuration class is a Spring bean object, that is, we need to inject the interceptor into a bean and add the bean to the WebMvc configuration class.