基于 ThreadContext 封装多个“业务上下文类”以实现可复用、易拓展
前言
本文针对已经了解了ThreadLocal的读者 本文将会运用threadLocal给出完整的需要在一个上下文中传递全局参数 如userInfo 信息的解决方案
基本思路:
1、定义ThreadContext 作为底层“线程隔离存储容器”
2、基于ThreadContext 衍生出多个特定场景的业务封装类(Context 工具类)
3、新增一个业务上下文,只需加一个封装类,不改底层逻辑
ThreadContext
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;public final class ThreadContext {private static final ThreadLocal<Map<String, Object>> THREAD_LOCAL = new ThreadLocal();public ThreadContext() {}public static <T> T getAttribute(String key) {return getNotInheritableAttributes().get(key);}private static Map<String, Object> getNotInheritableAttributes() {Map<String, Object> attributes = (Map)THREAD_LOCAL.get();if (attributes == null) {attributes = new ConcurrentHashMap(32);THREAD_LOCAL.set(attributes);}return (Map)attributes;}public static void setNotInheritableAttribute(String key, Object value) {Assert.notBlank(key, "ThreadLocal的key不能为空!", new Object[0]);Assert.notNull(value, "ThreadLocal的value不能为空!", new Object[0]);getNotInheritableAttributes().put(key, value);}public static void setNotInheritableAttributes(Map<String, ?> attributes) {Assert.notEmpty(attributes, "ThreadLocal的参数不能为空!", new Object[0]);getNotInheritableAttributes().putAll(attributes);}public static void removeAttribute(String key) {Assert.notBlank(key, "key不能为空!", new Object[0]);getNotInheritableAttributes().remove(key);}public static void clearAttributes() {THREAD_LOCAL.remove();}
}
然后就可以基于ThreadContext 根据不同的业务衍生不同的Context 工具类
UserContext
public class UserContext {public static void setUserInfo(User user) {ThreadContext.setNotInheritableAttribute("USER_INFO", user);}public static User getUserInfo() {User user = (User)ThreadContext.getAttribute("USER_INFO");if (user == null) {throw new IllegalArgumentException("无法获取登录用户信息!");} else {return user;}}public static boolean hasUserInfo() {return ThreadContext.containsAttribute("USER_INFO");}public static void clear() {ThreadContext.removeAttribute("USER_INFO");}
}
任意类型的XXContext
public class BusinessContext {private static final String KEY = "business";public static void setBusiness(String info) {ThreadContext.setNotInheritableAttribute(KEY, info);}public static String getBusiness() {return (String)ThreadContext.getAttribute(KEY);}public static void clear() {ThreadContext.removeAttribute(KEY);}
}
总结
ThreadContext 管理存取逻辑
UserContext / BusinessContext 等专注业务字段
可复用、易拓展
新增一个业务上下文,只需加一个封装类,不改底层逻辑。