Queue + ThreadLocal丟失
將資料寫入數據庫時發現丟MQ 的 ThreadLocal.get 不到 因為是新的進程了所以要重set 於是將 userId 丟進MQ,在MQ重set 就能拿得到了
-
filter
@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { try { String userId = request.getHeader("X-User-Id"); log.info("Processing request for userId: {}", userId); // 設置到 ThreadLocal UserContext.setUserId(userId); if(ipService.getClientIp(request) == null) { log.info("未取得公網IP..."); } //RabbitTemplate 默认使用 SimpleMessageConverter,它能够处理基本类型和 Serializable 接口的对象。 rabbitTemplate.convertAndSend("userLogQueue", userId); // 1. 這個 chain.doFilter(request, response); } finally { // 清理 ThreadLocal UserContext.clear(); } } -
MQ
@RabbitListener(queues = "${rabbitmq.user-log-queue}") public void handlUserLog(String userId) { try { UserContext.setUserId(userId); // 2. 補上這句 log.info("開始取得當前公網IP loc..."); String redisLocation = ipService.getRedisLocation(); if(redisLocation == null){ log.info("未取得公網IP loc..."); ipService.saveUserLog(); } } catch (Exception e) { log.error("公網IP loc任務失敗...", e); } } -
Service
@Service @Transactional public class IpService { public String getRedisLocation() { String userId = UserContext.getUserId(); // 3. 這個原本拿不到 是null String key = RedisConstants.USERLOG_IP_KEY + userId; HashOperations<String, String, String> hashOps = stringRedisTemplate.opsForHash(); return hashOps.get(key, "loc"); } }