“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