ThreadLocal在拦截器中的使用

前置过滤捕获,写入context中,后置删除

每个request请求都有自己线程独享的数据,所以用到了ThreadLocal

1.添加拦截器

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new IdentityInterceptor())
                .addPathPatterns("/**");
    }
}

2.拦截器定义

@Slf4j
@Component
public class IdentityInterceptor implements HandlerInterceptor {

    /*
    根据HttpHeader中的roleType判断用户身份
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        var identityStr = request.getHeader("roleType");
        var loginContext = LoginContext.getLoginContext();

        var pin = loginContext != null ? loginContext.getPin() : null;
        Identity identity;
        if (Strings.isNullOrEmpty(identityStr) ||
                !Enums.getIfPresent(IdentityType.class, identityStr).isPresent()) {
            log.warn("Identity:[{}] not found,use default identity instead.url:{}, User:{}", identityStr, request.getRequestURL(), pin);
            identity = Identity.DEFAULT_IDENTITY;
        } else {
            identity = new Identity(identityStr);
        }
        Identity.setIdentity(identity); // 核心是这个,写入用户角色身份上下文
        log.info("RoleType:[{}],user:[{}]-Identity:[{}] for url:{}. ", identityStr, pin, identity.getIdentityType(), request.getRequestURL());

        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

        log.info("remove Identity for [{}] from url {}"
                , Identity.getIdentity() == null ? "null" : Identity.getIdentity().getIdentityType()
                , request.getRequestURL());
        Identity.remove(); // 删除用户角色上下文数据
    }
}

3.Identity用户身份定义

package delta.service.session;

import com.alibaba.fastjson.JSON;
import com.jd.jsf.gd.util.RpcContext;
import org.apache.logging.log4j.util.Strings;

/**
 * 用户身份信息
 *
 * @author zhoulun
 * @date 2023-03-28 15:53
 */
public class Identity implements java.io.Serializable {

    /**
     * 序列化兼容
     */
    private static final long serialVersionUID = 1L;

    /**
     * 用户身份属性在Session中的Key
     */
    public static final String IDENTITY_CONTEXT_KEY = "delta-identity";
    /**
     * 用户身份 线程缓存
     */
    private static final ThreadLocal<Identity> HOLDER = new ThreadLocal<>();
    /**
     * 默认构造函数
     *
     * @param identityTypeStr 用户身份类型
     */
    public Identity(String identityTypeStr,String pin) {
        //判断枚举项中是否存在该值
        this.identityType = IdentityType.valueOf(identityTypeStr);
        this.pin = pin;
    }

    /**
     * 默认用户身份
     */
    public static final Identity DEFAULT_IDENTITY = new Identity(IdentityType.COMMON_USER.name(),"AnonymousUser");

    /**
     * 用户身份类型
     */
    private final IdentityType identityType;
    /**
     * 设置当前用户身份
     *
     * @param id 用户身份
     */
    public static void setIdentity(Identity id) {
        HOLDER.set(id);
        //序列化为String再放Session中
        RpcContext
                .getContext()
                .setSessionAttribute(
                        IDENTITY_CONTEXT_KEY,
                        JSON.toJSONString(id));
    }

    /**
     * @return 获取当前用户身份
     */
    public IdentityType getIdentityType() {
        return identityType;
    }
    /** 用户pin */
    private String pin;

    public String getPin() {
        return pin;
    }
    public void setPin(String pin) {
        this.pin = pin;
    }

    /**
     * 请求结束时清理用户身份信息
     */
    public static void remove() {
        HOLDER.remove();
        RpcContext.getContext().clearSession();
    }

    /**
     * @return 获取当前用户身份
     */
    public static Identity getIdentity() {
        Identity identity = HOLDER.get();
        if (identity == null) {
            String identityStr = (String) RpcContext.getContext().getSessionAttribute(IDENTITY_CONTEXT_KEY);
            if (Strings.isNotEmpty(identityStr)) {
                identity = JSON.parseObject(identityStr, Identity.class);
                HOLDER.set(identity);
            }
        }
        return identity;
    }

    @Override
    public String toString() {
        return "Identity{" +
                "identityType=" + identityType +
                ", pin='" + pin + '\'' +
                '}';
    }
}

posted @ 2023-05-29 14:42  SpecialSpeculator  阅读(239)  评论(0编辑  收藏  举报