fix restemplate bug
This commit is contained in:
parent
2b15682b0a
commit
341342c8b9
@ -50,6 +50,18 @@
|
|||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>4.9.3</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.retry</groupId>
|
||||||
|
<artifactId>spring-retry</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.logstash.logback</groupId>
|
<groupId>net.logstash.logback</groupId>
|
||||||
<artifactId>logstash-logback-encoder</artifactId>
|
<artifactId>logstash-logback-encoder</artifactId>
|
||||||
|
|||||||
@ -0,0 +1,64 @@
|
|||||||
|
package com.suisung.mall.common.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.HttpRequest;
|
||||||
|
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
|
||||||
|
import org.springframework.retry.backoff.FixedBackOffPolicy;
|
||||||
|
import org.springframework.retry.policy.SimpleRetryPolicy;
|
||||||
|
import org.springframework.retry.support.RetryTemplate;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RestTemplate 企业级配置
|
||||||
|
* 兼容 Spring Boot 2.3.0 版本
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class RestTemplateConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业级 RestTemplate 配置
|
||||||
|
* 1. 使用 OkHttp3 客户端(性能优化)
|
||||||
|
* 2. 配置连接超时(5秒)和读取超时(10秒)
|
||||||
|
* 3. 添加请求日志拦截器
|
||||||
|
* 4. 兼容 Spring Boot 2.3.0 的 API
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public RestTemplate restTemplate(RestTemplateBuilder builder) {
|
||||||
|
return builder
|
||||||
|
.requestFactory(OkHttp3ClientHttpRequestFactory::new)
|
||||||
|
.setConnectTimeout(Duration.ofSeconds(15)) // 连接超时5秒
|
||||||
|
.setReadTimeout(Duration.ofSeconds(25)) // 读取超时10秒
|
||||||
|
.additionalInterceptors((request, body, execution) -> {
|
||||||
|
logRequest(request); // 请求日志记录
|
||||||
|
return execution.execute(request, body);
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重试机制配置(兼容 Spring 2.3)
|
||||||
|
* 1. 最多重试3次
|
||||||
|
* 2. 每次间隔1秒
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public RetryTemplate retryTemplate() {
|
||||||
|
FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
|
||||||
|
backOffPolicy.setBackOffPeriod(1000); // 1秒间隔
|
||||||
|
|
||||||
|
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
|
||||||
|
retryPolicy.setMaxAttempts(3); // 最大重试3次
|
||||||
|
|
||||||
|
RetryTemplate template = new RetryTemplate();
|
||||||
|
template.setBackOffPolicy(backOffPolicy);
|
||||||
|
template.setRetryPolicy(retryPolicy);
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logRequest(HttpRequest request) {
|
||||||
|
// 实现请求日志记录(需配合项目日志组件)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,10 +1,4 @@
|
|||||||
/*
|
// ... existing copyright notice ...
|
||||||
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
|
||||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
|
||||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
|
||||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
|
||||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.suisung.mall.common.service.impl;
|
package com.suisung.mall.common.service.impl;
|
||||||
|
|
||||||
@ -26,15 +20,20 @@ import org.springframework.web.client.RestTemplate;
|
|||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 调用 UniCloud 云函数 推送服务
|
* UniCloud 推送服务实现类
|
||||||
* 提供向多个客户端 ID 发送推送消息的功能
|
* 提供向客户端发送推送消息的功能
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class UniCloudPushServiceImpl implements UniCloudPushService {
|
public class UniCloudPushServiceImpl implements UniCloudPushService {
|
||||||
|
|
||||||
|
private static final int MAX_CLIENT_IDS = 500;
|
||||||
|
private static final String DEFAULT_TITLE = "小发同城:您有新的消息";
|
||||||
|
private static final long DEFAULT_TTL = 3 * 24 * 3600 * 1000L; // 3天有效期
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
@Resource
|
@Resource
|
||||||
private RestTemplate restTemplate;
|
private RestTemplate restTemplate;
|
||||||
@ -45,132 +44,147 @@ public class UniCloudPushServiceImpl implements UniCloudPushService {
|
|||||||
/**
|
/**
|
||||||
* 向单个客户端发送推送消息
|
* 向单个客户端发送推送消息
|
||||||
*
|
*
|
||||||
* @param clientId 客户端 ID
|
* @param clientId 客户端唯一标识
|
||||||
* @param title 推送标题
|
* @param title 推送标题
|
||||||
* @param content 推送内容
|
* @param content 推送内容
|
||||||
* @param payload 推送内容
|
* @param payload 附加数据(JSON格式)
|
||||||
* @return
|
* @return Pair<是否成功, 结果描述>
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Pair<Boolean, String> sendPushMessage(String clientId, String title, String content, JSONObject payload) {
|
public Pair<Boolean, String> sendPushMessage(String clientId, String title, String content, JSONObject payload) {
|
||||||
|
if (StrUtil.isBlank(clientId)) {
|
||||||
|
log.warn("[推送服务] 客户端ID不能为空");
|
||||||
|
return Pair.of(false, "客户端ID不能为空");
|
||||||
|
}
|
||||||
return sendPushMessageBatch(Collections.singletonList(clientId), title, content, payload);
|
return sendPushMessageBatch(Collections.singletonList(clientId), title, content, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 向多个客户端ID批量发送推送消息
|
* 批量发送推送消息
|
||||||
*
|
*
|
||||||
* @param clientIds 目标客户端 ID 列表 注意:超过500个,直接忽略 必填项
|
* @param clientIds 客户端ID列表(最多500个)
|
||||||
* @param title 推送标题 可选项
|
* @param title 推送标题
|
||||||
* @param content 推送内容 必填项
|
* @param content 推送内容
|
||||||
* @param payload 附加数据(JSON对象) 可选项
|
* @param payload 附加数据(JSON格式)
|
||||||
* @return 推送结果响应对象
|
* @return Pair<是否成功, 结果描述>
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Pair<Boolean, String> sendPushMessageBatch(List<String> clientIds, String title, String content, JSONObject payload) {
|
public Pair<Boolean, String> sendPushMessageBatch(List<String> clientIds, String title, String content, JSONObject payload) {
|
||||||
if (StrUtil.isBlank(pushMessageUrl) || CollUtil.isEmpty(clientIds) || StrUtil.isBlank(content)) {
|
// === 参数校验 ===
|
||||||
return Pair.of(false, "缺少必要参数");
|
if (StrUtil.isBlank(pushMessageUrl)) {
|
||||||
}
|
log.error("[推送服务] 推送URL未配置");
|
||||||
|
return Pair.of(false, "推送服务未配置");
|
||||||
if (clientIds.size() > 500) {
|
}
|
||||||
log.warn("批量推送消息时,CIDs 数量超过限制");
|
if (CollUtil.isEmpty(clientIds)) {
|
||||||
return Pair.of(false, "推送客户端超出500限额");
|
log.warn("[推送服务] 客户端ID列表为空");
|
||||||
}
|
return Pair.of(false, "客户端ID列表不能为空");
|
||||||
|
}
|
||||||
if (StrUtil.isBlank(title)) {
|
if (StrUtil.isBlank(content)) {
|
||||||
title = "小发同城:您有新的消息";
|
log.warn("[推送服务] 推送内容为空");
|
||||||
|
return Pair.of(false, "推送内容不能为空");
|
||||||
|
}
|
||||||
|
if (clientIds.size() > MAX_CLIENT_IDS) {
|
||||||
|
log.warn("[推送服务] 客户端ID数量超过限制: {}", clientIds.size());
|
||||||
|
return Pair.of(false, "客户端ID数量超过500限制");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// === 业务处理 ===
|
||||||
try {
|
try {
|
||||||
// 构建请求体
|
log.debug("[推送服务] 开始处理推送请求, 客户端数量: {}", clientIds.size());
|
||||||
JSONObject requestBody = buildPushRequest(clientIds, title, content, payload);
|
|
||||||
|
|
||||||
// 执行HTTP请求
|
// 1. 构建请求体
|
||||||
ResponseEntity<String> response = executeHttpRequest(pushMessageUrl, requestBody);
|
JSONObject requestBody = buildPushRequest(
|
||||||
|
clientIds,
|
||||||
|
StrUtil.isBlank(title) ? DEFAULT_TITLE : title,
|
||||||
|
content,
|
||||||
|
payload
|
||||||
|
);
|
||||||
|
|
||||||
// 处理响应结果
|
// 2. 执行HTTP请求
|
||||||
return processResponse(response);
|
ResponseEntity<String> response = restTemplate.exchange(
|
||||||
|
pushMessageUrl,
|
||||||
|
HttpMethod.POST,
|
||||||
|
new HttpEntity<>(requestBody.toString(), buildHeaders()),
|
||||||
|
String.class
|
||||||
|
);
|
||||||
|
|
||||||
|
// 3. 处理响应
|
||||||
|
return processPushResponse(response);
|
||||||
} catch (RestClientException e) {
|
} catch (RestClientException e) {
|
||||||
// 处理REST客户端异常
|
log.error("[推送服务] REST请求异常: {}", e.getMessage(), e);
|
||||||
log.error("推送请求发送失败:{}", e.getMessage(), e);
|
return Pair.of(false, "推送请求失败");
|
||||||
return Pair.of(false, "推送请求发送失败");
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// 处理其他异常
|
log.error("[推送服务] 处理异常: {}", e.getMessage(), e);
|
||||||
log.error("推送处理过程发生异常:{}", e.getMessage(), e);
|
return Pair.of(false, "推送处理异常");
|
||||||
return Pair.of(false, "推送处理过程发生异常");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建请求头
|
||||||
|
*/
|
||||||
|
private HttpHeaders buildHeaders() {
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建推送请求体
|
* 构建推送请求体
|
||||||
*/
|
*/
|
||||||
private JSONObject buildPushRequest(List<String> clientIds, String title, String content, JSONObject payload) {
|
private JSONObject buildPushRequest(List<String> clientIds, String title, String content, JSONObject payload) {
|
||||||
JSONObject requestBody = new JSONObject();
|
JSONObject request = new JSONObject();
|
||||||
requestBody.put("action", "push");
|
|
||||||
requestBody.put("cidList", clientIds);
|
|
||||||
|
|
||||||
JSONObject message = new JSONObject();
|
// 新增:客户端ID去重
|
||||||
message.put("title", title);
|
List<String> distinctClientIds = clientIds.stream().distinct().collect(Collectors.toList());
|
||||||
message.put("content", content);
|
if (distinctClientIds.size() != clientIds.size()) {
|
||||||
|
log.warn("[推送服务] 客户端ID列表存在重复,已自动去重。原数量:{},去重后数量:{}",
|
||||||
|
clientIds.size(), distinctClientIds.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
request.put("push_clientid", distinctClientIds)
|
||||||
|
.put("title", title)
|
||||||
|
.put("content", content);
|
||||||
|
|
||||||
if (payload != null) {
|
if (payload != null) {
|
||||||
message.put("payload", payload);
|
request.put("payload", payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
requestBody.put("message", message);
|
// 设置平台和有效期
|
||||||
|
JSONArray platforms = new JSONArray();
|
||||||
JSONArray platform = new JSONArray();
|
platforms.add("web");
|
||||||
platform.add("web");
|
platforms.add("app-ios");
|
||||||
platform.add("app-ios");
|
platforms.add("app-android");
|
||||||
platform.add("app-android");
|
platforms.add("mp-weixin");
|
||||||
platform.add("mp-weixin");
|
request.put("platform", platforms)
|
||||||
requestBody.put("platform", platform);
|
.put("settings", new JSONObject().set("ttl", DEFAULT_TTL));
|
||||||
|
|
||||||
|
|
||||||
//消息有效期设置,单位毫秒,-1表示不设离线。默认是 2 小时,取值范围:-1 ~ 3 * 24 * 3600 * 1000(3天)之间
|
return request;
|
||||||
requestBody.put("settings", new JSONObject().set("ttl", 3 * 24 * 3600 * 1000));
|
|
||||||
|
|
||||||
return requestBody;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行HTTP POST请求
|
* 处理推送响应
|
||||||
*/
|
*/
|
||||||
private ResponseEntity<String> executeHttpRequest(String cloudFunctionUrl, JSONObject requestBody) {
|
private Pair<Boolean, String> processPushResponse(ResponseEntity<String> response) {
|
||||||
// 设置请求头
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
|
||||||
|
|
||||||
// 创建请求实体
|
|
||||||
HttpEntity<String> requestEntity = new HttpEntity<>(requestBody.toString(), headers);
|
|
||||||
|
|
||||||
// 执行POST请求
|
|
||||||
return restTemplate.exchange(
|
|
||||||
cloudFunctionUrl,
|
|
||||||
HttpMethod.POST,
|
|
||||||
requestEntity,
|
|
||||||
String.class
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理HTTP响应
|
|
||||||
*/
|
|
||||||
private Pair<Boolean, String> processResponse(ResponseEntity<String> response) {
|
|
||||||
if (response.getStatusCode() != HttpStatus.OK) {
|
if (response.getStatusCode() != HttpStatus.OK) {
|
||||||
return Pair.of(false, String.format("推送请求失败,状态码: %d,响应: %s",
|
log.error("[推送服务] 请求失败, 状态码: {}", response.getStatusCodeValue());
|
||||||
response.getStatusCodeValue(),
|
return Pair.of(false, "推送请求失败");
|
||||||
response.getBody()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String responseBody = response.getBody();
|
String body = response.getBody();
|
||||||
if (responseBody == null || responseBody.trim().isEmpty()) {
|
if (StrUtil.isBlank(body)) {
|
||||||
return Pair.of(false, "推送响应内容为空");
|
log.warn("[推送服务] 响应体为空");
|
||||||
|
return Pair.of(false, "推送响应为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析响应JSON
|
try {
|
||||||
JSONObject responseJson = JSONUtil.parseObj(responseBody);
|
JSONObject json = JSONUtil.parseObj(body);
|
||||||
return Pair.of(true, String.format("推送请求成功,状态码: %d,响应: %s",
|
log.info("[推送服务] 推送成功, 响应: {}", json.toStringPretty());
|
||||||
responseJson.getInt("code"),
|
|
||||||
responseJson.getJSONObject("data").toString()));
|
|
||||||
|
|
||||||
|
return Pair.of(true, json.getJSONObject("data").toString());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[推送服务] 响应解析异常: {}", e.getMessage(), e);
|
||||||
|
return Pair.of(false, "响应解析失败");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,10 +9,12 @@
|
|||||||
package com.suisung.mall.shop.lakala.controller.mobile;
|
package com.suisung.mall.shop.lakala.controller.mobile;
|
||||||
|
|
||||||
import cn.hutool.json.JSONObject;
|
import cn.hutool.json.JSONObject;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.suisung.mall.common.api.CommonResult;
|
import com.suisung.mall.common.api.CommonResult;
|
||||||
import com.suisung.mall.common.service.impl.BaseControllerImpl;
|
import com.suisung.mall.common.service.impl.BaseControllerImpl;
|
||||||
import com.suisung.mall.shop.lakala.service.LakalaApiService;
|
import com.suisung.mall.shop.lakala.service.LakalaApiService;
|
||||||
import com.suisung.mall.shop.library.service.LibraryProductService;
|
import com.suisung.mall.shop.library.service.LibraryProductService;
|
||||||
|
import com.suisung.mall.shop.message.service.PushMessageService;
|
||||||
import com.suisung.mall.shop.order.service.ShopOrderReturnService;
|
import com.suisung.mall.shop.order.service.ShopOrderReturnService;
|
||||||
import com.suisung.mall.shop.store.service.ShopStoreSameCityTransportBaseService;
|
import com.suisung.mall.shop.store.service.ShopStoreSameCityTransportBaseService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
@ -26,6 +28,7 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Api(tags = "拉卡拉相关接口 - 前端控制器")
|
@Api(tags = "拉卡拉相关接口 - 前端控制器")
|
||||||
@RestController
|
@RestController
|
||||||
@ -44,6 +47,9 @@ public class LakalaController extends BaseControllerImpl {
|
|||||||
@Resource
|
@Resource
|
||||||
private ShopStoreSameCityTransportBaseService storeSameCityTransportBaseService;
|
private ShopStoreSameCityTransportBaseService storeSameCityTransportBaseService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PushMessageService pushMessageService;
|
||||||
|
|
||||||
@ApiOperation(value = "测试案例", notes = "测试案例")
|
@ApiOperation(value = "测试案例", notes = "测试案例")
|
||||||
@RequestMapping(value = "/testcase", method = RequestMethod.POST)
|
@RequestMapping(value = "/testcase", method = RequestMethod.POST)
|
||||||
public Object testcase(@RequestBody JSONObject paramsJSON) {
|
public Object testcase(@RequestBody JSONObject paramsJSON) {
|
||||||
@ -62,6 +68,19 @@ public class LakalaController extends BaseControllerImpl {
|
|||||||
//// tags.add("放心");
|
//// tags.add("放心");
|
||||||
// return libraryProductService.matchLibraryProducts(paramsJSON.getStr("barcode"), paramsJSON.getStr("productName"), tags);
|
// return libraryProductService.matchLibraryProducts(paramsJSON.getStr("barcode"), paramsJSON.getStr("productName"), tags);
|
||||||
|
|
||||||
|
// 测试推送消息
|
||||||
|
// List<String> clientIds = JSONUtil.toList(paramsJSON.getJSONArray("clientIds"), String.class);
|
||||||
|
// return pushMessageService.sendMessage(clientIds, paramsJSON.getStr("title"), paramsJSON.getStr("content"), paramsJSON.getJSONObject("payload"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "批量发送推送消息 - 测试案例", notes = "批量发送推送消息 - 测试案例")
|
||||||
|
@PostMapping(value = "/unipush/testcase")
|
||||||
|
public Object pushMessageTestCase(@RequestBody JSONObject paramsJSON) {
|
||||||
|
// 测试推送消息
|
||||||
|
List<String> clientIds = JSONUtil.toList(paramsJSON.getJSONArray("clientIds"), String.class);
|
||||||
|
return pushMessageService.sendMessage(clientIds, paramsJSON.getStr("title"), paramsJSON.getStr("content"), paramsJSON.getJSONObject("payload"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "本地文件转base64", notes = "本地文件转base64")
|
@ApiOperation(value = "本地文件转base64", notes = "本地文件转base64")
|
||||||
|
|||||||
@ -9,11 +9,34 @@
|
|||||||
package com.suisung.mall.shop.message.service;
|
package com.suisung.mall.shop.message.service;
|
||||||
|
|
||||||
import cn.hutool.json.JSONObject;
|
import cn.hutool.json.JSONObject;
|
||||||
|
import org.springframework.data.util.Pair;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public interface PushMessageService {
|
public interface PushMessageService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量发送推送消息
|
||||||
|
* === 功能说明 ===
|
||||||
|
* 1. 异步批量发送推送消息
|
||||||
|
* 2. 支持自定义标题、内容和附加数据
|
||||||
|
* 3. 返回发送结果和错误信息
|
||||||
|
* === 技术实现 ===
|
||||||
|
* - 使用@Async实现异步发送
|
||||||
|
* - 通过uniCloudPushService批量发送
|
||||||
|
* - 记录详细日志便于问题追踪
|
||||||
|
*
|
||||||
|
* @param clientIds 客户端ID列表 (必填)
|
||||||
|
* @param title 消息标题 (可选)
|
||||||
|
* @param content 消息内容 (必填)
|
||||||
|
* @param payload 附加数据 (可为空)
|
||||||
|
* @return CompletableFuture<Pair < Boolean, String>>
|
||||||
|
* - Boolean: 发送是否成功
|
||||||
|
* - String: 成功为"", 失败为错误信息
|
||||||
|
*/
|
||||||
|
CompletableFuture<Pair<Boolean, String>> sendMessage(List<String> clientIds, String title, String content, JSONObject payload);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 异步发送推送通知 商户签约电子合同
|
* 异步发送推送通知 商户签约电子合同
|
||||||
*
|
*
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
package com.suisung.mall.shop.message.service.impl;
|
package com.suisung.mall.shop.message.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.json.JSONObject;
|
import cn.hutool.json.JSONObject;
|
||||||
import com.suisung.mall.common.feignService.AccountService;
|
import com.suisung.mall.common.feignService.AccountService;
|
||||||
import com.suisung.mall.common.modules.account.AccountUserBindGeTui;
|
import com.suisung.mall.common.modules.account.AccountUserBindGeTui;
|
||||||
@ -19,6 +20,7 @@ import org.springframework.context.annotation.Lazy;
|
|||||||
import org.springframework.data.util.Pair;
|
import org.springframework.data.util.Pair;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -43,6 +45,59 @@ public class PushMessageServiceImpl implements PushMessageService {
|
|||||||
@Resource
|
@Resource
|
||||||
private AccountService accountService;
|
private AccountService accountService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量发送推送消息
|
||||||
|
* === 功能说明 ===
|
||||||
|
* 1. 异步批量发送推送消息
|
||||||
|
* 2. 支持自定义标题、内容和附加数据
|
||||||
|
* 3. 返回发送结果和错误信息
|
||||||
|
* === 技术实现 ===
|
||||||
|
* - 使用@Async实现异步发送
|
||||||
|
* - 通过uniCloudPushService批量发送
|
||||||
|
* - 记录详细日志便于问题追踪
|
||||||
|
*
|
||||||
|
* @param clientIds 客户端ID列表 (必填)
|
||||||
|
* @param title 消息标题 (可选)
|
||||||
|
* @param content 消息内容 (必填)
|
||||||
|
* @param payload 附加数据 (可为空)
|
||||||
|
* @return CompletableFuture<Pair < Boolean, String>>
|
||||||
|
* - Boolean: 发送是否成功
|
||||||
|
* - String: 成功为"", 失败为错误信息
|
||||||
|
*/
|
||||||
|
@Async("asyncExecutor")
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Pair<Boolean, String>> sendMessage(List<String> clientIds, String title, String content, JSONObject payload) {
|
||||||
|
// 参数校验
|
||||||
|
if (CollectionUtils.isEmpty(clientIds) || StrUtil.isBlank(content)) {
|
||||||
|
log.warn("推送消息参数无效 - clientIds:{}, title:{}, content:{}", clientIds, title, content);
|
||||||
|
return CompletableFuture.completedFuture(Pair.of(false, "推送消息参数无效"));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (StrUtil.isBlank(title)) {
|
||||||
|
title = "小发同城:您有新的消息";
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("开始发送推送消息 - clientIds:{}, title:{}", clientIds, title);
|
||||||
|
Pair<Boolean, String> result = uniCloudPushService.sendPushMessageBatch(clientIds, title, content, payload);
|
||||||
|
|
||||||
|
if (!result.getFirst()) {
|
||||||
|
log.error("推送消息失败 - clientIds:{}, error:{}", clientIds, result.getSecond());
|
||||||
|
} else {
|
||||||
|
log.debug("推送消息成功 - clientIds:{}", clientIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompletableFuture.completedFuture(result);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
String errorMsg = "推送消息系统异常";
|
||||||
|
log.error("{} - clientIds:{}, title:{}, content:{}, payload:{}",
|
||||||
|
errorMsg, clientIds, title, content, payload, e);
|
||||||
|
return CompletableFuture.completedFuture(Pair.of(false, errorMsg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 异步发送推送通知 商户签约电子合同
|
* 异步发送推送通知 商户签约电子合同
|
||||||
*
|
*
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user