spring监听请求执行结束,移除当前ThreadLocal数据两种方法
在开发过程中,很多时候我们会使用ThreadLocal来临时缓存数据,当一次数据请求执行完成后需要主动执行释放当前ThreadLocal缓存数据资源,防止未能及时释放导致下一次访问时候ThreadLocal依然保持上一次缓存的数据。
spring提供两种方式去监听一次请求完成事件。
1、HandlerInterceptor -> afterCompletion 使用拦截方式,再执行完成后执行afterCompletion
2、ApplicationListener -> ServletRequestHandledEvent ,ApplicationListener 提供的是监听那种事件类型,ServletRequestHandledEvent 就是一次请求结束后的事件。
通过上述两种方式可以很方便的在一次请求完成移除当前线程ThreadLocal。
ThreadLocal 工具
public class ThreadLocal2UserSessionUtil {
private static final ThreadLocal<Object> LOCAL = new ThreadLocal<>();
/**
* 设置数据
*
* @param paramMap
*/
public static void set(Map<String, Object> paramMap) {
LOCAL.set(paramMap);
}
/**
* 获取值
*
* @return
*/
public static Map<String, Object> get() {
if (Objects.isNull(LOCAL.get())) {
return new HashMap<>();
} else {
return (Map<String, Object>) LOCAL.get();
}
}
/**
* 获取值
*
* @return
*/
public static Object get(String key) {
Map<String, Object> resMap = (Map<String, Object>) LOCAL.get();
if (null == resMap) {
return null;
}
return (null != resMap.get(key)) ? resMap.get(key) : null;
}
/**
* 每次取出数据后必须清空 否则就会出现值重复
*/
public static void remove() {
LOCAL.remove();
}
/**
* 获取app登录token
*
* @return
*/
public static String getToken4App() {
Map<String, Object> map = get();
return (null == map) ? "" : (String) map.get(EncryptReqParamNameConstant.PARAM_TOKEN);
}
/**
* 初始化数值
*
* @return
*/
public static void pushUserToken4App(String appToken) {
Map<String, Object> localMap = get();
if (StringUtil.isNotBlank(appToken)) {
localMap.put(EncryptReqParamNameConstant.PARAM_TOKEN, appToken);
set(localMap);
}
}
/**
* 初始化数值
*
* @return
*/
public static void pushUserId4App(Long userId) {
Map<String, Object> localMap = get();
if (null != userId) {
localMap.put(EncryptReqParamNameConstant.USER_ID, userId);
set(localMap);
}
}
/**
* 初始化数值 注意这里只有加解密才将用户id放入
*
* @return
*/
public static Long getUserId4App() {
Map<String, Object> map = get();
return (null == map) ? null : (Long) map.get(EncryptReqParamNameConstant.USER_ID);
}
}
HandlerInterceptor 方式
@Slf4j
@Component
public class ThreadLocalRemoveInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
ThreadLocal2UserSessionUtil.remove();
}
}
在web控制器中加入监听器
@Configuration
public class PathPrefixMvcConfigurer implements WebMvcConfigurer {
@Autowired
private ThreadLocalRemoveInterceptor threadLocalRemoveInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(threadLocalRemoveInterceptor).addPathPatterns("/*");
}
}
2、通过监听器方式
@Slf4j
@Component
public class ServletRequestHandledEventListener implements ApplicationListener<ServletRequestHandledEvent> {
@Override
public void onApplicationEvent(ServletRequestHandledEvent event) {
ThreadLocal2UserSessionUtil.remove();
}
}
完成