Interceptor achieve CRUD operations log management (Interceptor in NullPointException reasons)

In the system of project, you need to write a log management, each time the user is about to CRUD operations are stored in the database, this time, set by the interceptor, by determining the user's request, because the project conforms to restfulthe style, but the request methodwas put, deleteor post, the request for user information and information into the database

The first is the definition of an interceptor

/**
 * @author fuzihao
 * @date 2019/8/14 16:03
 */
public class OperationLogInterceptor extends HandlerInterceptorAdapter {
    @Autowired
    private ILogService logService;
    @Autowired
    private IElementService elementService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if(handler instanceof HandlerMethod){
            String methodType = request.getMethod();
            System.out.println(request.getRequestURI());
            //如果是post、delete或put
            if(StringUtils.equalsIgnoreCase(HttpMethodEnum.POST.name(),methodType)||
                    StringUtils.equalsIgnoreCase(HttpMethodEnum.DELETE.name(),methodType)||
                    StringUtils.equalsIgnoreCase(HttpMethodEnum.PUT.name(),methodType)){
                //插入记录到日志表中
                insertToLog(methodType,request.getRequestURI());
            }
        }
        return true;
    }

    private void insertToLog(String methodType, String requestURI) {
		......
    }
}

In the WebMvcConfigurerconfiguration of the interceptor global configuration file

/**
 * @author fuzihao
 * @date 2019/8/14 16:13
 * 全局拦截器,用于日志操作
 */
@Configuration
public class TrainWebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new OperationLogInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/api/**");
    }
}

At this time put, delete, postoperation, found elementServicean error NPE, through the universal search engine, find the following reasons:

new Interceptor() 即是我们定义的拦截器。此时若是在Interceptor类内使用@Autowired注解引入bean实例,必然导致无法注入,实例为null的情况。即如果类A中存在成员属性b, b是通过@Autowired自动注入,而类A的实例是通过new的方式产生的,那么自动注入会失效的。

网上传说:了解SpringBoot的都知道SpringBoot的目录格式有着明确的规定,它减轻编程人员负担的同时,更加要求了编程的规范化,SpringBoot初始化的时候,会加载com.boot.app下的bean,一层一层加载,当注册LoggerInterceptor的时候,发现LoggerInterceptor中有@Autowired注解,就会去另外一个spring管理器中索取另外一个LoggerJpa,而这时候LoggerJpa根本没有初始化.所以就无法注入LoggerJpa的bean类完成相应的操作.

自我理解:注册拦截器时直接通过new LoggerInterceptor(),并没有触发Spring去管理bean,所以@Autowired没有生效.

转自简书:https://www.jianshu.com/p/60ff6d0dae7f

At this point we can manually initialize Beanobjects

/**
 * @author fuzihao
 * @date 2019/8/14 16:13
 * 全局拦截器,用于日志操作
 */
@Configuration
public class TrainWebConfig implements WebMvcConfigurer {
    @Bean
    public OperationLogInterceptor operationLogInterceptor(){
        return new OperationLogInterceptor();
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new OperationLogInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/api/**");
    }
}

To run.
Of course, if we can set up a SpringContextUtils, in each interceptor injected manually service, but this method is better than direct statement Beanis more convenient.

/**
 * @author fuzihao
 * @date 2019/8/14 16:52
 */
@Component
public class SpringContextUtils implements ApplicationContextAware {
    /**
     * 上下文对象实例
     */
    private static ApplicationContext applicationContext;

    @Override
    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtils.applicationContext = applicationContext;
    }

    /**
     * 获取applicationContext
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 通过name获取 Bean.
     * @param name
     * @return
     */
    public static Object getBean(String name){
        return getApplicationContext().getBean(name);
    }
    
}

At this time, the interceptor can be injected by way of @Autowiredthe following:

private ILogService logService= (ILogService) SpringContextUtils.getBean("logServiceImpl");
private IElementService elementService= (IElementService) SpringContextUtils.getBean("elementServiceImpl");

At this point TrainWebConfig no longer need to manually inject interceptors up!
the above!

Published 63 original articles · won praise 29 · views 20000 +

Guess you like

Origin blog.csdn.net/Hpsyche/article/details/99901250