fix:优化查询用户关键词匹配
This commit is contained in:
@@ -71,26 +71,84 @@ public class UserNameCacheService {
|
||||
*/
|
||||
@Cacheable(value = "allUsers", key = "'userList'")
|
||||
public List<CIDUserResp> getAllUsers() {
|
||||
log.info("缓存未命中,从用户系统加载全量数据...");
|
||||
log.info("缓存未命中,从用户系统分批加载全量数据...");
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// 存储所有分批查询到的用户数据
|
||||
List<CIDUserResp> allUsers = new ArrayList<>();
|
||||
// 分页参数:当前页从1开始,单页size CID允许的最大值1000
|
||||
int current = 1;
|
||||
final int pageSize = 1000;
|
||||
// 总数据条数(从接口返回的total字段获取)
|
||||
Long totalCount = null;
|
||||
|
||||
final int MAX_QUERY_TIMES = 10; // 最大查询次数
|
||||
int queryTimes = 0; // 已查询次数
|
||||
|
||||
try {
|
||||
UserListReq userListReq = new UserListReq();
|
||||
userListReq.setTenantId(ThreadLocalContext.getTenantId());
|
||||
userListReq.setCurrent(1);
|
||||
userListReq.setSize(9999);
|
||||
SdmResponse<PageDataResp<List<CIDUserResp>>> pageDataRespSdmResponse = sysUserFeignClient.listUser(userListReq);
|
||||
if (pageDataRespSdmResponse.isSuccess() && pageDataRespSdmResponse.getData() != null) {
|
||||
List<CIDUserResp> users = pageDataRespSdmResponse.getData().getData();
|
||||
if (CollectionUtils.isNotEmpty(users)) {
|
||||
log.info("加载完成,用户数:{},耗时:{}ms", users.size(), System.currentTimeMillis() - startTime);
|
||||
return users;
|
||||
while (true) {
|
||||
// 超过最大查询次数终止
|
||||
queryTimes++;
|
||||
if (queryTimes > MAX_QUERY_TIMES) {
|
||||
log.error("超过最大查询次数({}),终止查询", MAX_QUERY_TIMES);
|
||||
break;
|
||||
}
|
||||
|
||||
// 1. 构建分页请求参数
|
||||
UserListReq userListReq = new UserListReq();
|
||||
userListReq.setTenantId(ThreadLocalContext.getTenantId());
|
||||
userListReq.setCurrent(current);
|
||||
userListReq.setSize(pageSize);
|
||||
|
||||
// 2. 调用用户系统接口
|
||||
SdmResponse<PageDataResp<List<CIDUserResp>>> pageDataRespSdmResponse = sysUserFeignClient.listUser(userListReq);
|
||||
|
||||
// 3. 处理响应结果:失败则终止循环
|
||||
if (!pageDataRespSdmResponse.isSuccess() || pageDataRespSdmResponse.getData() == null) {
|
||||
log.error("第{}页用户数据查询失败,终止分批查询", current);
|
||||
break;
|
||||
}
|
||||
|
||||
PageDataResp<List<CIDUserResp>> pageData = pageDataRespSdmResponse.getData();
|
||||
List<CIDUserResp> currentPageUsers = pageData.getData();
|
||||
|
||||
// 4. 首次查询时获取总数据条数(仅需获取一次)
|
||||
if (totalCount == null) {
|
||||
totalCount = pageData.getTotal(); // total是总数据条数(比如1200)
|
||||
log.info("获取到用户总数据条数:{}", totalCount);
|
||||
}
|
||||
|
||||
// 5. 新增当前页数据到总列表
|
||||
if (CollectionUtils.isNotEmpty(currentPageUsers)) {
|
||||
allUsers.addAll(currentPageUsers);
|
||||
log.info("第{}页加载完成,新增用户数:{},累计用户数:{}", current, currentPageUsers.size(), allUsers.size());
|
||||
}
|
||||
|
||||
// 6. 核心判断:是否还有下一页(基于总条数计算)
|
||||
// 逻辑1:累计数据 >= 总条数 → 已加载完所有数据,终止
|
||||
if (totalCount != null && allUsers.size() >= totalCount) {
|
||||
log.info("累计加载数据量({}) >= 总条数({}),终止分批查询", allUsers.size(), totalCount);
|
||||
break;
|
||||
}
|
||||
// 逻辑2:当前页数据量 < 单页size → 已是最后一页,终止(兜底判断)
|
||||
if (currentPageUsers.size() < pageSize) {
|
||||
log.info("第{}页数据量({}) < 单页size({}),已是最后一页,终止分批查询", current, currentPageUsers.size(), pageSize);
|
||||
break;
|
||||
}
|
||||
|
||||
// 7. 当前页+1,准备下一次查询
|
||||
current++;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
|
||||
// 最终统计
|
||||
log.info("全量用户加载完成,实际加载用户数:{},总数据条数:{},分批查询次数:{},耗时:{}ms",
|
||||
allUsers.size(), totalCount, current - 1, System.currentTimeMillis() - startTime);
|
||||
return allUsers;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("加载用户列表失败", e);
|
||||
return Collections.emptyList(); // 返回空列表,避免缓存null
|
||||
log.error("加载用户列表失败(已加载{}条数据)", allUsers.size(), e);
|
||||
// 即使部分失败,也返回已加载的数据(业务可根据需求调整为返回空列表)
|
||||
return CollectionUtils.isEmpty(allUsers) ? Collections.emptyList() : allUsers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +173,7 @@ public class UserNameCacheService {
|
||||
}
|
||||
|
||||
// 3. 根据关键词过滤
|
||||
String lowerKeyword = keyword.trim().toLowerCase();
|
||||
String lowerKeyword = keyword.trim();
|
||||
List<String> keywordList = splitKeyword(lowerKeyword);
|
||||
|
||||
List<CIDUserResp> result = allUsers.parallelStream()
|
||||
@@ -167,29 +225,39 @@ public class UserNameCacheService {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 预处理用户字段:去空格、判空
|
||||
String username = user.getUsername() == null ? "" : user.getUsername().trim();
|
||||
String nickname = user.getNickname() == null ? "" : user.getNickname().trim();
|
||||
Long userId = user.getUserId();
|
||||
|
||||
// 遍历所有分割后的关键词,只要匹配一个就返回true
|
||||
for (String keyword : keywordList) {
|
||||
// 场景1:关键词是数字,尝试匹配userId(精确匹配)
|
||||
// 场景1:关键词是数字,尝试匹配userId
|
||||
if (keyword.matches("\\d+")) {
|
||||
try {
|
||||
Long userId = Long.parseLong(keyword);
|
||||
if (Objects.equals(user.getUserId(), userId)) {
|
||||
Long targetUserId = Long.parseLong(keyword);
|
||||
if (Objects.equals(userId, targetUserId)) {
|
||||
log.debug("用户{}匹配到userId关键词{}", username, keyword);
|
||||
return true;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// 理论上不会走到这里,因为已经通过数字正则校验
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 场景2:关键词是非数字,匹配username/nickname
|
||||
if (user.getUsername() != null && user.getUsername().toLowerCase().contains(keyword)) {
|
||||
return true;
|
||||
}
|
||||
if (user.getNickname() != null && user.getNickname().toLowerCase().contains(keyword)) {
|
||||
boolean usernameMatch = StringUtils.isNotEmpty(username) && username.contains(keyword);
|
||||
boolean nicknameMatch = StringUtils.isNotEmpty(nickname) && nickname.contains(keyword);
|
||||
|
||||
if (usernameMatch || nicknameMatch) {
|
||||
log.debug("用户{}匹配到关键词{}(username匹配:{},nickname匹配:{})",
|
||||
username, keyword, usernameMatch, nicknameMatch);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("用户{}未匹配到任何关键词{}(username:{},nickname:{})",
|
||||
username, keywordList, username, nickname);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user