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 restful
the style, but the request method
was put
, delete
or 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 WebMvcConfigurer
configuration 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
, post
operation, found elementService
an 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 Bean
objects
/**
* @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 Bean
is 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 @Autowired
the 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!