1. Introduction

Today, when designing interceptors in my Spring Boot project, I entered an empty service class. Here is a record.

The prerequisites for solving this problem are as follows: I’m using Spring Boot 2.3.4Release, and you annotated the DAO, Service, and Controller layers correctly: @mapper, @Service(“xxxService”), @RestController, And you’ve injected the @autowired annotation into the Service class. Cross domain has been configured (using the @Crossorigin annotation on the Controller class, or configuring your own custom cross domain rules). Details about cross domain issues can be found on my other blog: juejin.cn/post/694088…

If you still have a problem with the title after all the above instructions, please read on.

Key words: Spring Boot, Interceptor, Service, JWT, Java

2. Problem recurrence

The background of this problem is to add an interceptor based on a login registration function. The interceptor configuration is as follows:

import com.ark.fitnesshub.core.interceptor.JWTInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JWTInterceptor())
                // Intercepted path
                .addPathPatterns("/ * *")
                // Exclude interfaces such as login
                .excludePathPatterns("/")
                .excludePathPatterns("/login")
                .excludePathPatterns("/register")
                .excludePathPatterns("/captcha.jpg"); }}Copy the code

Interceptors are used as follows:

The user entity class cannot be retrieved and an NPE exception is reported:

The console error print is as follows:

java.lang.NullPointerException: null at com.ark.fitnesshub.core.interceptor.JWTInterceptor.preHandle(JWTInterceptor.java:47) ~[classes/:na] at org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:151) ~ [spring - webmvc - 5.2.9. RELEASE. The jar: 5.2.9. RELEASE] the at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1035) ~ [spring - webmvc - 5.2.9. RELEASE. The jar: 5.2.9. RELEASE] the at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~ [spring - webmvc - 5.2.9. RELEASE. The jar: 5.2.9. RELEASE] the at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~ [spring - webmvc - 5.2.9. RELEASE. The jar: 5.2.9. RELEASE]...Copy the code

There are two ways to solve the problem of service injection in interceptor.

Problem solving

A [1]. The method

Modify the interceptor configuration class as follows:

import com.ark.fitnesshub.core.interceptor.JWTInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    // It is important to add beans for Spring's automatic injection
    @Bean
    public JWTInterceptor initJWTInterceptor(a) {
        return new JWTInterceptor();
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(initJWTInterceptor())
                // Intercepted path
                .addPathPatterns("/ * *")
                // Exclude the login interface
                .excludePathPatterns("/")
                .excludePathPatterns("/login")
                .excludePathPatterns("/register")
                .excludePathPatterns("/captcha.jpg"); }}Copy the code

The reason for this is that the interceptor must create a new object to inject, and creating it directly in the interceptor registry does not complete the initialization of the Bean.

[2]. Method 2

Modify the interceptor configuration class as follows:

import com.ark.fitnesshub.core.interceptor.JWTInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    // Autoassemble your custom interceptor here
    @Autowired
    private JWTInterceptor initJWTInterceptor;

    // Add your own interceptor
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(initJWTInterceptor)
                // Intercepted path
                .addPathPatterns("/ * *")
                // Exclude the login interface
                .excludePathPatterns("/")
                .excludePathPatterns("/login")
                .excludePathPatterns("/register")
                .excludePathPatterns("/captcha.jpg"); }}Copy the code

In addition, configure the annotations for the custom interceptor as follows:

// Your custom interceptor class with the @Component annotation (similar to the @bean)
@Component
public class JWTInterceptor implements HandlerInterceptor {
    @Autowired
    privateUserService userService; . }Copy the code

Following the above method to modify the interceptor must must must restart the project! Filters and interceptors need to be configured before the interface is requested to log in. Normal service injection can be achieved by using the above two methods.

4. Question summary and thinking

The purpose of method one is primarily to create and initialize an @Bean object so that the Spring container can load the interceptor object properly. The second method mainly uses the custom interceptor directly as the union object, which can be directly injected and added in the interceptor configuration class.

When I was working on the project, I found this problem for a long time and looked up a lot of materials before finally solving it, which made me understand that it is particularly important to understand the bottom layer and distribution mode of Spring.

Reference article:Stackoverflow.com/questions/2…

If you have any other solutions or questions about this problem, feel free to leave a comment! (This article is updated with the SegmentFault Community article.)