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

Spring MVC 異步發送微信消息:Thread 實現模式

     編輯:Java 綜合教學

業務場景

訂單狀態從「支付成功」變更為「已發貨」時,需異步推送微信模板消息給用戶,避免阻塞主線程影響響應速度。

控制器層異步調用

@RequestMapping("order/updateOrder.do")
public String updateOrder(HttpServletRequest request, HttpServletResponse response) {
    // ... 參數獲取與訂單更新 ...
    try {
        shopService.updateOrder(order);
        if (Integer.parseInt(stats) == 3) { // 已發貨
            // 匿名內部類啟動新線程
            new Thread(() -> {
                message.sendWxMessage(openId, tranNum, logisticCompany, logisticNum);
            }).start();
        }
    } catch (Exception e) { e.printStackTrace(); }
    return "redirect:/order/orderlist.do?currPage=1";
}

服務接口定義

public interface Message {
    void sendWxMessage(String openId, String tranNum, String logisticCompany, String logisticNum);
}

實現類核心邏輯

@Service("Message")
public class MessageImpl implements Message {
    @Override
    public void sendWxMessage(String openId, String tranNum, String logisticCompany, String logisticNum) {
        // 1. 組裝模板消息 JSON
        JSONObject params = JSONObject.fromObject(MsgTemplateBean.getMsgTemplateBean(tranNum, logisticCompany, logisticNum));
        params.put("touser", openId);

        // 2. 獲取 access_token
        String token = getAccessToken();
        if (token == null) {
            Loger.logtxt("WxMessage", "獲取 access_token 失敗");
            return;
        }

        // 3. 發送 POST 請求
        String url = Constant.SEND_MESSAGE_URL + "?access_token=" + token;
        String result = ConnectionUrlUtil.sendPost(url, params.toString());

        // 4. 解析結果
        JSONObject resp = JSONObject.fromObject(result);
        if (resp.getInt("errcode") == 0) {
            Loger.logtxt("WxMessage", "發送成功: " + params);
        } else {
            Loger.logtxt("WxMessage", "發送失敗: " + params + " 原因: " + resp.get("errmsg"));
        }
    }

    private String getAccessToken() {
        String url = Constant.TOKEN_URL + "?grant_type=client_credential&appid=" + Constant.APP_ID + "&secret=" + Constant.APP_SECRET;
        String json = ConnectionUrlUtil.sendPost(url, "");
        if (Tools.isNotEmpty(json)) {
            JSONObject obj = JSONObject.fromObject(json);
            return obj.optString("access_token", null);
        }
        return null;
    }
}

優化建議

  • 線程池替換: 生產環境應使用 @Async + ThreadPoolTaskExecutor,避免頻繁創建銷毀線程。
  • 消息隊列: 引入 RabbitMQ/Kafka 實現可靠異步,支援重試、死信、監控。
  • Token 緩存: access_token 有效期 2 小時,應用 Redis 緩存並定時刷新,減少 HTTP 請求。
  • 異常重試: 發送失敗時採用指數退避重試策略,記錄失敗日誌供人工補發。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved