“This is the 13th day of my participation in the November Gwen Challenge. See details: The Last Gwen Challenge 2021”.
SpringBoot Interceptor Interceptor: SpringBoot Interceptor Interceptor: SpringBoot Interceptor Interceptor: SpringBoot Interceptor Interceptor
In SpringBoot, we register interceptors by implementing WebMvcConfigurer’s addInterceptors method. What happens when we want to use beans in our interceptors?
I. Project construction
This project is developed by SpringBoot 2.2.1.RELEASE + Maven 3.5.3 + IDEA
Open a Web service for testing
<dependencies>
<! -- Core dependencies for sending messages -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
Copy the code
II. The interceptor
Implementation of the interceptor is relatively simple, implement the HandlerInterceptor interface can be, for example, we implement a basic permission check interceptor, by getting parameters from the request header, when the condition is passed
0. Security verification interceptor
@Slf4j
public class SecurityInterceptor implements HandlerInterceptor {
/** * call ** before executing the specific Controller method@param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// A simple security check. The request header must contain req-name: yihuihui
String header = request.getHeader("req-name");
if ("yihuihui".equals(header)) {
return true;
}
log.info("Request header error: {}", header);
return false;
}
/** * Controller is called after execution, before the DispatcherServlet renders the view return, * so we can operate on the ModelAndView object after controller processing in this method. * <p> * preHandler returns false, which also does not execute * *@param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("Executed!");
response.setHeader("res"."postHandler");
}
The /** * method is executed only when the corresponding Interceptor class's preHandle method returns true. * As the name implies, this method is executed after the entire request has been completed, after the corresponding view has been rendered by the DispatcherServlet. This method is mainly used to clean up resources. * *@param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("Recycling"); }}Copy the code
Next comes the registration of the interceptor
@RestController
@SpringBootApplication
public class Application implements WebMvcConfigurer {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/ * *");
}
@GetMapping(path = "show")
public String show(a) {
returnUUID.randomUUID().toString(); }}Copy the code
The next question is, we want the validation value to be in the configuration file, not in code. What can we do?
1. Specify the configuration
In the project resource file, add a request header configured to represent validation
application.yml
security:
check: yihuihui
Copy the code
Configured reads can be done using envrioment.getProperty () or @Value annotations
But note that the interceptor registration above, a directly constructed method, is added to the InterceptorRegistry. In the interceptor, the @AutoWired annotation does not take effect even if @Value is added (after all, the interceptor is not managed by the Spring context).
2. The interceptor injects beans
What if you want to use a bean object from the Spring container in an interceptor?
2.1 Added the static ApplicationContext container class
One possible approach is to maintain a utility class in your project that holds a reference to the ApplicationContext and accesses bean objects through this utility class
@Component
public class SpringUtil implements ApplicationContextAware.EnvironmentAware {
private static ApplicationContext applicationContext;
private static Environment environment;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringUtil.applicationContext = applicationContext;
}
@Override
public void setEnvironment(Environment environment) {
SpringUtil.environment = environment;
}
public static <T> T getBean(Class<T> clz) {
return applicationContext.getBean(clz);
}
public static String getProperty(String key) {
returnenvironment.getProperty(key); }}Copy the code
Based on this, in the interceptor, if you want to get the configuration, you can simply change to the following
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// A simple security check. The request header must contain req-name: yihuihui
String header = request.getHeader("req-name");
if (Objects.equals(SpringUtil.getProperty("security.check"), header)) {
return true;
}
log.info("Request header error: {}", header);
return false;
}
Copy the code
This way to access beans, the advantage is more universal, a wide range of application
2.2 Interceptors are registered as beans
The above approach is possible, but still not very elegant. Is there a way to directly declare the interceptor as a bean object, and then directly inject the dependent bean using the @AutoWired annotation
Of course it does. Note the several ways in which beans can be registered. Here we use the following approach to register interceptors
@Bean
public SecurityInterceptor securityInterceptor(a) {
return new SecurityInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(securityInterceptor()).addPathPatterns("/ * *");
}
Copy the code
We declare the bean by configuring the class above, and then do not use constructors directly to create instances where interceptors are registered. The above usage representation uses Spring’s bean container to register the interceptor’s bean declaration in this way
Other dependencies can therefore be injected into the interceptor
The test is easier, as follows
yihui@M-162D9NNES031U:SpringBlog git:(master) $ curl 'http://127.0.0.1:8080/show' -H 'req-name:yihuihui'-I HTTP/1.1 200 Content-type: text/plain; charset=UTF-8 Content-Length: 36 Date: Mon, 15 Nov 2021 10:56:30 GMT 6610e593-7c60-4dab-97b7-cc671c27762d%Copy the code
3. Summary
Although this article has shown you how to inject beans into interceptors, it is still about creating bean objects in several ways. There are two common ways to do this: a SpringUtil holds the SpringContext and uses this utility class to access bean objects.
The other is to declare interceptors as beans. The main point of this approach is that interceptors cannot be registered directly with new interceptors. Of course, bean creation, in addition to the above way, there are other cases, interested partners can try
III. Can’t miss the source code and related knowledge points
0. Project
- Project: github.com/liuyueyi/sp…
- Source: github.com/liuyueyi/sp…
1. Wechat official account: Yash Blog
As far as the letter is not as good, the above content is purely one’s opinion, due to the limited personal ability, it is inevitable that there are omissions and mistakes, if you find bugs or have better suggestions, welcome criticism and correction, don’t hesitate to appreciate
Below a gray personal blog, record all the study and work of the blog, welcome everyone to go to stroll
- A grey Blog Personal Blog blog.hhui.top
- A Grey Blog-Spring feature Blog Spring.hhui.top