Просмотр исходного кода

refactor(token-namespace): 基座 4 vendor token cache key 迁移到 namespace API

阶段 2 收尾。基座原有 4 处硬编码 cache key(DDImpl 3 个 / INTP 1 个 / FXK 1 个 / TB 1 个)多 appKey/多 corp 场景会撞 key。各 Conf 加 NS 常量(vendor name),cache key 改为 UtilToken.get(NS, "{type}:" + appKey/clientId) 形式:

- DDImplClient: appToken/userToken/jsapiTicket 三处按 ddConf.getAppKey() 隔离
- INTPImplClient_User: 按 intpConf.getClientId() 隔离,删 INTPConf.CACHE_KEY_TOKEN 老常量
- FXKImplClient: 按 fxkConf.getAppId() 隔离,删 UNIQUE_STORAGE_ID 私有常量
- TBClientImpl: 按 tbConf.getAppID() 隔离
- DynamicDDService 改引 DDConf.NS 避免硬编码字符串重复

旧 key 缓存条目失效(首次调用重新拉 token),无业务异常。Interface 签名 0 变更。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
malk 1 неделя назад
Родитель
Сommit
136468ad91

+ 1 - 1
mjava-pro/src/main/java/com/malk/pro/service/dingtalk/DynamicDDService.java

@@ -25,7 +25,7 @@ import org.springframework.stereotype.Service;
 @Service
 public class DynamicDDService {
 
-    private static final String VENDOR = "dingtalk";
+    private static final String VENDOR = com.malk.server.dingtalk.DDConf.NS;
     // 钉钉 access_token 官方 TTL 7200s;UtilToken.put 内部会再扣 5s 容错
     private static final long DEFAULT_TOKEN_TTL_MS = 7200_000L;
 

+ 5 - 0
mjava/src/main/java/com/malk/server/dingtalk/DDConf.java

@@ -35,6 +35,11 @@ public class DDConf {
     // 机器人编号
     private String robotCode;
 
+    /**
+     * UtilToken namespace(多 appKey / 多租户场景按 vendor 隔离 cache key)
+     */
+    public static final String NS = "dingtalk";
+
     /**
      * 钉钉一级部门: 1
      */

+ 5 - 0
mjava/src/main/java/com/malk/server/fxiaoke/FXKConf.java

@@ -21,4 +21,9 @@ public class FXKConf {
 
     /// 永久授权码
     private String permanentCode;
+
+    /**
+     * UtilToken namespace(按 vendor 隔离 cache key)
+     */
+    public static final String NS = "fxiaoke";
 }

+ 2 - 2
mjava/src/main/java/com/malk/server/integration/INTPConf.java

@@ -36,9 +36,9 @@ public class INTPConf {
     private String clientSecret;
 
     /**
-     * access_token 缓存 key
+     * UtilToken namespace(按 vendor 隔离 cache key;与 dingtalk / aliwork 等并列)
      */
-    public static final String CACHE_KEY_TOKEN = "integration:accessToken";
+    public static final String NS = "integration";
 
     /**
      * token 过期前提前失效(秒)

+ 5 - 0
mjava/src/main/java/com/malk/server/teambition/TBConf.java

@@ -33,6 +33,11 @@ public class TBConf {
         return "https://open.teambition.com/api"; // 公有云环境
     }
 
+    /**
+     * UtilToken namespace(按 vendor 隔离 cache key)
+     */
+    public static final String NS = "teambition";
+
     /**
      * 一个分页数量上限 [上限 1000]
      */

+ 10 - 6
mjava/src/main/java/com/malk/service/dingtalk/impl/DDImplClient.java

@@ -31,7 +31,8 @@ public class DDImplClient implements DDClient {
     @Synchronized
     @Override
     public String getAccessToken() {
-        String accessToken = UtilToken.get("invalid-token-dingtalk");
+        String key = "appToken:" + ddConf.getAppKey();
+        String accessToken = UtilToken.get(DDConf.NS, key);
         if (StringUtils.isNotBlank(accessToken)) return accessToken;
         Map param = new HashMap();
         param.put("appkey", ddConf.getAppKey());
@@ -40,7 +41,7 @@ public class DDImplClient implements DDClient {
         log.info("响应token, {}", r.getAccessToken());
         accessToken = r.getAccessToken();
         // token失效自动重置: DD重新调用会重置过期时间
-        UtilToken.put("invalid-token-dingtalk", accessToken, r.getExpiresIn() * 1000L);
+        UtilToken.put(DDConf.NS, key, accessToken, r.getExpiresIn() * 1000L);
         return accessToken;
     }
 
@@ -61,7 +62,8 @@ public class DDImplClient implements DDClient {
     @Synchronized
     @Override
     public String getUserAccessToken(boolean isRefresh, String code_refreshToken) {
-        String accessToken = UtilToken.get("invalid-user-token-dingtalk");
+        String key = "userToken:" + ddConf.getAppKey();
+        String accessToken = UtilToken.get(DDConf.NS, key);
         if (StringUtils.isNotBlank(accessToken)) return accessToken;
         Map boyd = UtilMap.map("clientId, clientSecret", ddConf.getAppKey(), ddConf.getAppSecret());
         if (isRefresh) {
@@ -75,7 +77,7 @@ public class DDImplClient implements DDClient {
         log.info("用户token, {}", r.getAccessToken());
         accessToken = r.getAccessToken();
         // token失效自动重置: DD重新调用会重置过期时间
-        UtilToken.put("invalid-user-token-dingtalk", accessToken, r.getExpiresIn() * 1000L);
+        UtilToken.put(DDConf.NS, key, accessToken, r.getExpiresIn() * 1000L);
         return accessToken;
     }
 
@@ -103,13 +105,15 @@ public class DDImplClient implements DDClient {
     @Synchronized
     @Override
     public String getJsApiTicket(String accessToken) {
-        String ticket = UtilToken.get("invalid-ticket-dingtalk");
+        // ppExt: jsapi ticket 是 corp/app 级别(用 appKey 区分),不绑特定 accessToken
+        String key = "jsapiTicket:" + ddConf.getAppKey();
+        String ticket = UtilToken.get(DDConf.NS, key);
         if (StringUtils.isNotBlank(ticket)) return ticket;
         DDR r = DDR.doGet("https://oapi.dingtalk.com/get_jsapi_ticket", null, UtilMap.map("access_token", accessToken));
         log.info("响应ticket, {}", r.getAccessToken());
         ticket = r.getTicket();
         // token失效自动重置: DD重新调用会重置过期时间
-        UtilToken.put("invalid-ticket-dingtalk", ticket, r.getExpiresIn() * 1000L);
+        UtilToken.put(DDConf.NS, key, ticket, r.getExpiresIn() * 1000L);
         return ticket;
     }
 

+ 3 - 4
mjava/src/main/java/com/malk/service/fxiaoke/impl/FXKImplClient.java

@@ -25,8 +25,6 @@ public class FXKImplClient implements FXKClient {
     @Autowired
     private FXKConf fxkConf;
 
-    private final static String UNIQUE_STORAGE_ID = "invalid-token-fxiaoke";
-
     /**
      * 获取访问授权
      *
@@ -35,7 +33,8 @@ public class FXKImplClient implements FXKClient {
     @Synchronized
     @Override
     public String getAccessToken() {
-        String accessToken = UtilToken.get(UNIQUE_STORAGE_ID);
+        String key = "corpToken:" + fxkConf.getAppId();
+        String accessToken = UtilToken.get(FXKConf.NS, key);
         if (StringUtils.isNotBlank(accessToken)) return accessToken;
         Map body = new HashMap();
         body.put("appId", fxkConf.getAppId());
@@ -45,7 +44,7 @@ public class FXKImplClient implements FXKClient {
         log.info("响应token, {}", r.getCorpAccessToken());
         accessToken = r.getCorpAccessToken();
         // token失效自动重置: FXK重新调用不会重置过期时间
-        UtilToken.put(UNIQUE_STORAGE_ID, accessToken, r.getExpiresIn() * 1000L);
+        UtilToken.put(FXKConf.NS, key, accessToken, r.getExpiresIn() * 1000L);
         return accessToken;
     }
 

+ 1 - 1
mjava/src/main/java/com/malk/service/integration/INTPClient_User.java

@@ -11,7 +11,7 @@ import java.util.Map;
  * 调用方约定:
  * <ul>
  *   <li>每个方法第一个参数 access_token 必传,调用方先调 {@link #getAccessToken()} 拿到再传入</li>
- *   <li>{@link #getAccessToken()} 内部由 UtilToken 缓存({@link com.malk.server.integration.INTPConf#CACHE_KEY_TOKEN}),过期前自动刷新</li>
+ *   <li>{@link #getAccessToken()} 内部由 UtilToken 缓存(namespace = {@link com.malk.server.integration.INTPConf#NS} / key = {@code "token:" + clientId}),过期前自动刷新</li>
  *   <li>响应失败由 INTPR.assertSuccess 抛 McException,全局拦截转 HTTP 4xx;调用方无需手动判 result</li>
  * </ul>
  * <p>

+ 3 - 2
mjava/src/main/java/com/malk/service/integration/impl/INTPImplClient_User.java

@@ -24,7 +24,8 @@ public class INTPImplClient_User implements INTPClient_User {
 
     @Override
     public String getAccessToken() {
-        String cached = UtilToken.get(INTPConf.CACHE_KEY_TOKEN);
+        String key = "token:" + intpConf.getClientId();
+        String cached = UtilToken.get(INTPConf.NS, key);
         if (StringUtils.isNotBlank(cached)) {
             return cached;
         }
@@ -35,7 +36,7 @@ public class INTPImplClient_User implements INTPClient_User {
                 null, null, null, form, INTPR.class);
         // fixme: expires_in 通常 7200s;提前 60s 失效,UtilToken.put 内部还会再扣 5s
         long ttlMillis = (long) (r.getExpires_in() - INTPConf.TOKEN_AHEAD_SECONDS) * 1000L;
-        UtilToken.put(INTPConf.CACHE_KEY_TOKEN, r.getAccess_token(), ttlMillis);
+        UtilToken.put(INTPConf.NS, key, r.getAccess_token(), ttlMillis);
         return r.getAccess_token();
     }
 

+ 3 - 2
mjava/src/main/java/com/malk/service/teambition/impl/TBClientImpl.java

@@ -35,7 +35,8 @@ public class TBClientImpl implements TBClient {
     // 获取访问授权
     @Synchronized
     private String getAccessToken() {
-        String accessToken = UtilToken.get("invalid-token-teambition");
+        String key = "token:" + tbConf.getAppID();
+        String accessToken = UtilToken.get(TBConf.NS, key);
         if (StringUtils.isNotBlank(accessToken)) return accessToken;
         Algorithm algorithm = Algorithm.HMAC256(tbConf.getAppSecret());
         long timestamp = System.currentTimeMillis();
@@ -48,7 +49,7 @@ public class TBClientImpl implements TBClient {
                 .sign(algorithm);
         log.info("响应token, {}", accessToken);
         // token失效自动重置: TB传递过期时间2h, 重复调用就会刷新
-        UtilToken.put("invalid-token-teambition", accessToken, EXPIRES_IN);
+        UtilToken.put(TBConf.NS, key, accessToken, EXPIRES_IN);
         return accessToken;
     }