feat(user): 添加用户数据同步到 websopy 功能

- 新增 websopyUrl 配置项用于指定同步服务地址
- 创建 UserSyncService 服务实现用户数据同步逻辑
- 在 UserController 中添加用户新增时同步到 websopy 的功能
- 在 WxLoginController 和 WxOfficialController 中集成用户同步
- 实现单个用户同步和批量用户同步的功能
- 添加同步状态日志记录和错误处理机制
This commit is contained in:
2026-04-04 04:02:35 +08:00
parent 808766eeac
commit 2303f46fca
5 changed files with 168 additions and 0 deletions

View File

@@ -92,6 +92,11 @@ public class ConfigProperties {
*/
private String serverUrl;
/**
* websopy 服务地址(用于同步用户数据)
*/
private String websopyUrl;
/**
* 阿里云存储 OSS
* Endpoint

View File

@@ -66,6 +66,8 @@ public class UserController extends BaseController {
private ConfigProperties configProperties;
@Resource
private LoginRecordService loginRecordService;
@Resource
private UserSyncService userSyncService;
@PreAuthorize("hasAuthority('sys:auth:user')")
@Operation(summary = "分页查询用户")
@@ -142,6 +144,8 @@ public class UserController extends BaseController {
return fail("该手机号码已存在");
}
if (userService.saveUser(user)) {
// 同步到 websopy
userSyncService.syncUserToWebsopy(user);
return success("添加成功", user.getUserId());
}
return fail("添加失败");
@@ -159,6 +163,8 @@ public class UserController extends BaseController {
return fail("该手机号码已存在");
}
if (userService.saveUser(user)) {
// 同步到 websopy
userSyncService.syncUserToWebsopy(user);
return success("添加成功", user.getUserId());
}
return fail("添加失败");
@@ -181,6 +187,8 @@ public class UserController extends BaseController {
userList.removeIf(d -> phoneCollect.containsKey(d.getPhone()));
if (userService.saveBatch(userList)) {
// 同步到 websopy异步处理不阻塞响应
userList.forEach(user -> userSyncService.syncUserToWebsopy(user));
return success("添加成功");
}
return fail("添加失败");
@@ -201,6 +209,8 @@ public class UserController extends BaseController {
userParam.setLimit(500L);
final PageResult<User> result = userService.pageRel(userParam);
final Set<Integer> collect = result.getList().stream().map(User::getUserId).collect(Collectors.toSet());
// 同步到 websopy异步处理不阻塞响应
userList.forEach(user -> userSyncService.syncUserToWebsopy(user));
return success("添加成功", collect);
}
return fail("添加失败");
@@ -511,6 +521,7 @@ public class UserController extends BaseController {
// 保存新用户(逐个保存以处理角色关系)
int successCount = 0;
List<String> failedUsers = new ArrayList<>();
List<User> successUsers = new ArrayList<>();
for (User user : users) {
try {
@@ -524,6 +535,7 @@ public class UserController extends BaseController {
userRoleService.saveBatch(user.getUserId(), roleIds);
}
successCount++;
successUsers.add(user);
} else {
failedUsers.add(user.getUsername());
}
@@ -534,6 +546,11 @@ public class UserController extends BaseController {
}
}
// 同步成功导入的用户到 websopy
for (User successUser : successUsers) {
userSyncService.syncUserToWebsopy(successUser);
}
// 构建返回消息
StringBuilder message = new StringBuilder();
if (successCount > 0) {

View File

@@ -65,6 +65,8 @@ public class WxLoginController extends BaseController {
private ConfigProperties config;
@Resource
private UserRefereeService userRefereeService;
@Resource
private UserSyncService userSyncService;
public WxLoginController(StringRedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
@@ -473,6 +475,8 @@ public class WxLoginController extends BaseController {
userRole.setTenantId(addUser.getTenantId());
userRole.setRoleId(addUser.getRoleId());
userRoleService.save(userRole);
// 同步到 websopy
userSyncService.syncUserToWebsopy(addUser);
}
// 绑定关系
if (userParam.getSceneType() != null && userParam.getSceneType().equals("save_referee") && userParam.getRefereeId() != null && userParam.getRefereeId() != 0) {

View File

@@ -22,6 +22,7 @@ import com.gxwebsoft.common.system.service.RoleService;
import com.gxwebsoft.common.system.service.UserOauthService;
import com.gxwebsoft.common.system.service.UserRoleService;
import com.gxwebsoft.common.system.service.UserService;
import com.gxwebsoft.common.system.service.UserSyncService;
import com.gxwebsoft.common.system.vo.WxOfficialButton;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
@@ -69,6 +70,8 @@ public class WxOfficialController extends BaseController {
@Resource
private UserRoleService userRoleService;
@Resource
private UserSyncService userSyncService;
@Resource
private UserOauthService userOauthService;
@Resource
private RedisUtil redisUtil;
@@ -155,6 +158,8 @@ public class WxOfficialController extends BaseController {
userRole.setTenantId(user.getTenantId());
userRole.setRoleId(user.getRoleId());
userRoleService.save(userRole);
// 同步到 websopy
userSyncService.syncUserToWebsopy(user);
}
System.out.println("新微信公众号用户 = " + userId);
}

View File

@@ -0,0 +1,137 @@
package com.gxwebsoft.common.system.service;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.utils.HttpUtils;
import com.gxwebsoft.common.system.entity.User;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
/**
* 用户同步服务(同步到 websopy
*
* @author WebSoft
* @since 2026-04-04
*/
@Slf4j
@Service
public class UserSyncService {
@Resource
private ConfigProperties configProperties;
private String websopyBaseUrl;
@PostConstruct
public void init() {
websopyBaseUrl = configProperties.getWebsopyUrl();
if (websopyBaseUrl == null || websopyBaseUrl.isEmpty()) {
log.warn("websopyUrl 未配置,用户同步功能将不可用");
} else {
log.info("用户同步服务初始化完成websopy地址: {}", websopyBaseUrl);
}
}
/**
* 同步单个用户到 websopy
*
* @param user 用户信息
*/
public void syncUserToWebsopy(User user) {
if (websopyBaseUrl == null || websopyBaseUrl.isEmpty()) {
log.warn("websopyUrl 未配置,跳过用户同步: userId={}", user.getUserId());
return;
}
if (user == null || user.getUserId() == null) {
log.warn("用户信息为空,跳过同步");
return;
}
try {
// 构建请求体
JSONObject userCache = new JSONObject();
userCache.put("userId", user.getUserId());
userCache.put("username", user.getUsername());
userCache.put("nickname", user.getNickname());
userCache.put("avatar", user.getAvatar());
userCache.put("phone", user.getPhone());
userCache.put("status", user.getStatus());
userCache.put("updateTime", System.currentTimeMillis());
String url = websopyBaseUrl + "/api/app/user-sync/single";
String body = userCache.toJSONString();
log.info("同步用户到 websopy: userId={}, url={}", user.getUserId(), url);
// 发送 HTTP POST 请求
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
HttpResponse response = HttpUtils.doPost(url, "", "POST", headers, null, body);
String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
log.debug("websopy 响应: {}", responseBody);
// 解析响应
JSONObject result = JSON.parseObject(responseBody);
if (result != null && result.getIntValue("code") == 0) {
log.info("用户同步成功: userId={}", user.getUserId());
} else {
String message = result != null ? result.getString("message") : "未知错误";
log.error("用户同步失败: userId={}, message={}", user.getUserId(), message);
}
} catch (Exception e) {
log.error("用户同步异常: userId={}, error={}", user.getUserId(), e.getMessage(), e);
}
}
/**
* 刷新 websopy 端的用户缓存
* 只传 userIdwebsopy 端会通过 API 回查获取完整信息
*
* @param userId 用户ID
*/
public void refreshUserCache(Integer userId) {
if (websopyBaseUrl == null || websopyBaseUrl.isEmpty()) {
log.warn("websopyUrl 未配置,跳过刷新缓存: userId={}", userId);
return;
}
if (userId == null) {
log.warn("userId 为空,跳过刷新");
return;
}
try {
String url = websopyBaseUrl + "/api/app/user-sync/refresh/" + userId;
log.info("刷新用户缓存: userId={}, url={}", userId, url);
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
HttpResponse response = HttpUtils.doPost(url, "", "POST", headers, null, "");
String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
JSONObject result = JSON.parseObject(responseBody);
if (result != null && result.getIntValue("code") == 0) {
log.info("刷新缓存成功: userId={}", userId);
} else {
String message = result != null ? result.getString("message") : "未知错误";
log.error("刷新缓存失败: userId={}, message={}", userId, message);
}
} catch (Exception e) {
log.error("刷新缓存异常: userId={}, error={}", userId, e.getMessage(), e);
}
}
}