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();
    }
}

完成

你可能感兴趣的:(java开发,spring,java,spring,boot)