首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

SSH 架構跨層數據共享:單例模式與 ThreadLocal 實戰對比

     編輯:程式設計綜合問答

問題:Controller、Service、DAO 三層需共享同一 `Map` 實例(如請求級緩存、上下文傳遞)。

反模式:public 靜態字段

// ❌ 線程不安全,併發請求數據互相覆蓋
public class GlobalContext {
    public static Map sharedMap = new HashMap<>();
}

方案一:請求作用域單例 (Spring 管理)

@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestContext {
    private final Map data = new ConcurrentHashMap<>();
    
    public void put(String key, Object val) { data.put(key, val); }
    public Object get(String key) { return data.get(key); }
}

// 注入到三層
@Service public class UserService {
    @Autowired RequestContext ctx; // 每個 HTTP 請求獲得同一實例
}
@Repository public class UserDao {
    @Autowired RequestContext ctx;
}
  • 優點:Spring 容器管理生命周期,請求結束自動銷毀,線程安全。
  • 缺點:耦合 Spring,非 Web 環境(定時任務、測試)需手動模擬作用域。

方案二:ThreadLocal 隔離 (無框架依賴)

public final class RequestHolder {
    private static final ThreadLocal> HOLDER = 
        ThreadLocal.withInitial(HashMap::new);
    
    public static void set(String key, Object val) { HOLDER.get().put(key, val); }
    public static Object get(String key) { return HOLDER.get().get(key); }
    public static void clear() { HOLDER.remove(); } // 必須調用,防內存洩漏
}

// Filter/Interceptor 中調用
public class ContextFilter implements Filter {
    public void doFilter(...) {
        try { chain.doFilter(req, res); }
        finally { RequestHolder.clear(); }
    }
}
  • 優點:純 Java,無框架依賴,性能極高(無鎖)。
  • 缺點:異步線程(`CompletableFuture`、線程池)需手動傳遞上下文,否則丟失。

方案三:繼承式上下文傳遞 (Alibaba TransmittableThreadLocal)

// 依賴 com.alibaba:transmittable-thread-local
private static final TransmittableThreadLocal> CTX = 
    new TransmittableThreadLocal<>();

// 父線程設置後,線程池子線程自動繼承副本
CTX.set(new HashMap<>());
executor.submit(() -> { 
    CTX.get().put("asyncKey", "value"); // 可見父線程數據
});

選型建議

場景推薦方案
純 Spring MVC/WebFlux 請求級共享@Scope(REQUEST) + ScopedProxy
非 Web / 多框架混合 / 高性能要求ThreadLocal + Filter 清理
大量異步/線程池任務需繼承上下文TransmittableThreadLocal
分布式追蹤SkyWalking / Zipkin 自動埋點,勿手工實現
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved