JAVA使用ThreadLocal实现全局存信息

目录

概述

实现效果

1.TenantKeyContext(ThreadLocal的工具类)

2.WebMvcConfig注册拦截器

3.TenantKeyInterceptor拦截器

总结


概述

 实现的步骤如下:

  1. 将登录需要的信息塞入当前线程(ThreadLocal)。
  2. 使用拦截器拦截controller的请求,让ThreadLocal的信息保留。
  3. 将接收的request参数转化为body接收参数。(拦截器不支持接收body的参数)
  4. 在Serviceimpl调用ThreadLocal拿到信息。

实现效果

首先登陆信息是空的,通过body把登陆信息传递进去。

 body中传入登陆所需要的信息,从而实现了登陆。

1.TenantKeyContext(ThreadLocal的工具类)

主要是创建一个本地线程。

public class TenantKeyContext{

    private static final ThreadLocal<String> TENANT_KEY = new ThreadLocal<String>();

    public static void setTenantKey(String tenantKey) {
        TENANT_KEY.set(tenantKey);
    }

    public static String getTenantKey() {
        return TENANT_KEY.get();
    }

    public static void remove(){
        TENANT_KEY.remove();
    }
}

2.WebMvcConfig注册拦截器

注册一个拦截器,然后拦截controller所有请求。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfigimplements WebMvcConfigurer {

    @Bean
    public WebMvcConfiggetMyWebMvcConfig(){
        return new WebMvcConfig() {

            //注册拦截器
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                registry.addInterceptor(new TenantKeyInterceptor()).addPathPatterns("/**");
            }
        };
    }
}

3.TenantKeyInterceptor拦截器

主要分为几个步骤:

  • 使用getTenantKeyFromRequest将传递进来的request请求改为接收传入body请求,实现body传参。
  • 调用TenantKeyContext工具类,传入request请求的参数。
  • 使用完成之后将本地线程销毁掉。
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.weaver.front.monitor.util.common.TenantKeyContext;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

@Component
public class TenantKeyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String tenantKey = getTenantKeyFromRequest(request);
        TenantKeyContext.setTenantKey(tenantKey);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        TenantKeyContext.remove();
    }


    /**
     * 从request中获取tenantKey
     * @param request
     * @return
     */
    public static String getTenantKeyFromRequest(HttpServletRequest request) {
        String tenantKey = null;
        StringBuilder sb = new StringBuilder();
        try (InputStream inputStream = request.getInputStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
            String line = "";
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            JSONObject jo = JSON.parseObject(sb.toString());
            tenantKey = jo.getString("tenantKey");
        } catch (Exception ignore) {
        }
        return tenantKey;
    }

}

总结

这样就实现了,将登录信息或者需要的某一个信息塞入本地线程,然后在需要的Service层去调用。

但是这样就存在一个问题,就是如果调用的地方,拿到的是一个空的信息怎么办,需要抛出一个异常,每层都往上抛很麻烦,这就涉及到了全局异常的捕获,然后手动直接抛出异常。

详情见手动抛出异常全局捕获异常,手动抛出异常

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ybbgrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值