需求背景
借用log4j2,向数据库中新增一条记录,对于特殊的字段需要借助线程的环境变量。其中某个字段需要在数据库中查询到具体信息后插入,在借助Spring MVC的Dao层时遇到了加载顺序问题。
解决方案
log4j2插入数据库的方案参考文章:
<Column name="user_info" pattern="%X{user_info}" isUnicode="false" />
需要执行日志插入操作(比如绑定到一个级别为insert、logger.insert())的线程中有环境变量user_info。
解决环境变量的方法:
拦截器:
@Component
public class LogInterceptor implements HandlerInterceptor {
/**
* 需要记录在log中的参数
*/
public static final String USER_INFO= "user_info";
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object arg)
throws Exception {
String userName = LoginContext.getCurrentUsername();
ThreadContext.put(USER_INFO, getUserInfo());
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Object arg, Exception exception) throws Exception {
ThreadContext.remove(USER_INFO);
}
需要拦截的URL配置:
@Configuration
public class LogConfigurer implements WebMvcConfigurer {
String[] logUrl = new String[] {
"/**",
};
String[] excludeUrl = new String[] {
"/**/*.js", "/**/*.css", "/**/*.jpg", "/**/*.png", "/**/*.svg", "/**/*.woff", "/**/*.eot", "/**/*.ttf",
"/**/*.less", "/favicon.ico", "/license/lackofresource", "/error"
};
/**
* 注册一个拦截器
*
* @return HpcLogInterceptor
*/
@Bean
public LogInterceptor setLogBean() {
return new LogInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry reg) {
// 拦截的对象会进入这个类中进行判断
InterceptorRegistration registration = reg.addInterceptor(setLogBean());
// 添加要拦截的路径与不用拦截的路径
registration.addPathPatterns(logUrl).excludePathPatterns(excludeUrl);
}
}
如下待优化:
问题就出在如何获取信息这个步骤,原本的方案是:
通过Dao userDao从数据库查询信息,然后填充进去。
出现的问题是:userDao无法通过@Autowired方式注入。
原因:
调用处SpringBoot未完成初始化,导致dao层在调用时每次都是null。
因此最后采用的方式如下:
@Component
public class LogInterceptor implements HandlerInterceptor {
/**
* 需要记录在log中的参数
*/
public static final String USER_INFO= "user_info";
@Resource(name = "jdbcTemplate")
private JdbcTemplate jdbcTemplate;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object arg)
throws Exception {
String userName = LoginContext.getCurrentUsername();
ThreadContext.put(USER_INFO, getUserInfo());
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Object arg, Exception exception) throws Exception {
ThreadContext.remove(USER_INFO);
}
public String getUserInfo(String userName) {
String sqlTemplate = "select user_info from Test.test_user where user_name = ?";
List<String> userInfo= new ArrayList<>();
userInfo= jdbcTemplate.query(sqlTemplate, preparedStatement -> {
preparedStatement.setString(1, userName);
}, new SecurityRoleDtoMapper());
if (userInfo.size() == 0) {
return Constants.HPC_NORMAL_USER;
}
return userInfo.get(0);
}