Several postures of bean injected by interceptors of springboot series

Time:2022-1-6

Several postures of bean injected by interceptors of springboot series

Previously, I introduced the basic use posture of Interceptor: [web series] Introduction to the use posture of interceptor of springboot interceptor

In springboot, by implementingWebMvcConfigurerofaddInterceptorsMethod to register the interceptor, so how can we adjust it when we want to use beans in our interceptor?

<!– more –>

1. Project construction

The project relies onSpringBoot 2.2.1.RELEASE + maven 3.5.3 + IDEADevelop

Open a web service for testing

<dependencies>
    <!--  Core dependency of mail sending -- >
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

II. Interceptor

The implementation of interceptor is relatively simpleHandlerInterceptorThe interface is OK. For example, we implement a basic permission verification interceptor, which obtains parameters from the request header. When the conditions are met, it means that it passes

0. Security check 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 requires that 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;
    }

    /**
     *The controller is called after execution, and is called before the dispatcher servlet performs view return rendering,
     *Therefore, we can operate the modelandview object processed by the controller in this method.
     * <p>
     *The prehandler returns false, which will not be executed
     *
     * @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 ("execution completed!");
        response.setHeader("res", "postHandler");
    }


    /**
     *Method can only be executed when the return value of the prehandle method of the current corresponding interceptor class is true.
     *As the name suggests, this method will be executed after the end of the entire request, that is, after the dispatcher servlet renders the corresponding view. This method is mainly used for resource cleanup.
     *
     * @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 ("recycle");
    }
}

Next is 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() {
        return UUID.randomUUID().toString();
    }
}

Next, the question comes. We want the value used for verification to be placed in the configuration file instead of being written in the code. How can we adjust it?

1. Specify configuration

In the project resource file, add a request header configured to represent verification

application.yml

security:
  check: yihuihui

Configured reading, you can useEnvrioment.getProperty(), you can also use@Valueannotation

However, notice the interceptor registration above. A method constructed directly is added toInterceptorRegistry, in the interceptor, even if you add@Value@AutowiredAnnotations will not take effect (in the final analysis, the interceptor is not managed by the spring context)

2. Interceptor injection bean

So how can I use the bean object in the spring container in the interceptor?

2.1 add static ApplicationContext container class

A feasible approach is to maintain a tool class in the project, which is held internallyApplicationContextThrough this tool class to access the bean object

@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) {
        return environment.getProperty(key);
    }
}

Based on this, if you want to obtain the configuration in the interceptor, you can directly change it to the following

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //A simple security check requires that 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;
    }

The advantage of accessing beans in this way isMore versatility and wide application range

2.2 register interceptors as beans

Although the above method is feasible, it seems not so elegant. There is a way to declare the interceptor as a bean object and use it directly@AutowiredAnnotations to inject dependent beans

Of course, it is feasible. Pay attention to several gestures of bean registration. Here we use the following method to register the interceptor

@Bean
public SecurityInterceptor securityInterceptor() {
    return new SecurityInterceptor();
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(securityInterceptor()).addPathPatterns("/**");
}

The bean is declared by configuring the class, and then the constructor is not directly used to create the instance where the interceptor is registered; The above usage indicates that the bean container of spring is used to register, and the bean declaration of the interceptor is implemented based on this method

Therefore, other dependencies can be injected into the interceptor

The test is relatively simple, as follows

[email protected]: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%

3. Summary

Although this article introduces how to inject beans into the interceptor, the actual knowledge point is still several postures for creating bean objects; The above provides two common ways. One is that a springutil holds the springcontext, and then uses this tool class to access bean objects. Using it skillfully can save a lot of things;

The other is to declare the interceptor as a bean. The main point to note in this way is that the interceptor cannot be registered directlynewInterceptor; Of course, in addition to the above methods, there are other cases for bean creation. Interested partners can try it

3. Can not miss the source code and related knowledge points

0. Project

Related blog posts:

  • Introduction to the use posture of interceptor of springboot interceptor

Project source code:

  • Project: https://github.com/liuyueyi/spring-boot-demo
  • Source code: https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-boot/213-web-interceptor

1. WeChat official account: a gray Blog

The above contents are only the words of one family. Due to limited personal ability, it is inevitable that there are omissions and mistakes. If you find a bug or have better suggestions, you are welcome to criticize and correct and be grateful

The following is a gray personal blog, which records all blog posts in study and work. Welcome to visit

  • A personal blog https://blog.hhui.top
  • A gray blog spring special blog http://spring.hhui.top

Several postures of bean injected by interceptors of springboot series