package com.ruoyi.service.impl; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.entity.SysMenu; import com.ruoyi.domain.ModuleSearchResult; import com.ruoyi.service.ModuleSearchable; import lombok.extern.slf4j.Slf4j; import org.apache.commons.logging.Log; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.function.Function; import java.util.stream.Collectors; @Service @Slf4j public class InterfaceBasedSearchRouter { private final Map moduleSearchMap; /** * 自动收集所有实现ModuleSearchable接口的Bean */ @Autowired public InterfaceBasedSearchRouter(List searchServices) { this.moduleSearchMap = searchServices.stream() .collect(Collectors.toMap( ModuleSearchable::getModuleCode, Function.identity(), (existing, replacement) -> { log.warn("发现重复的模块编码: {}, 使用先注册的服务", existing.getModuleCode()); return existing; } )); log.info("已注册搜索模块: {}", moduleSearchMap.keySet()); } @Async // 声明此方法异步执行,将使用我们上面配置的Executor public CompletableFuture searchModuleAsync(String moduleCode, ModuleSearchable service, String companion, Date startTime, Date endTime) { // 将原来在lambda表达式中的搜索逻辑移到这里 long start = System.currentTimeMillis(); try { List data = service.search(companion, startTime, endTime); long searchTime = System.currentTimeMillis() - start; ModuleSearchResult result = ModuleSearchResult.success(moduleCode, service.getModuleName(), data, data.size(), searchTime); return CompletableFuture.completedFuture(result); } catch (Exception e) { log.error("模块[{}]搜索失败: {}", moduleCode, e.getMessage()); ModuleSearchResult result = ModuleSearchResult.error(moduleCode, e.getMessage()); return CompletableFuture.completedFuture(result); } } /** * 通用的路由搜索请求(支持不同参数类型) */ /** * 通用的路由搜索请求 */ public AjaxResult routeSearch(String moduleCode, Object... args) { log.info("路由搜索: moduleCode={}, args={}", moduleCode, Arrays.toString(args)); // 全模块搜索:当moduleCode为空或特定标识时 if (moduleCode == null || moduleCode.isEmpty() || "all".equalsIgnoreCase(moduleCode)) { return searchAllModules(args); } // 单个模块搜索(原有逻辑) ModuleSearchable searchService = moduleSearchMap.get(moduleCode); if (searchService == null) { String availableModules = String.join(", ", moduleSearchMap.keySet()); return AjaxResult.error("不支持的搜索模块: " + moduleCode + "。可用模块: [" + availableModules + "]"); } try { if (args.length == 3) { return handleFourArgs(searchService, args); } else { return AjaxResult.error("不支持的参数数量,需要3个参数,实际收到: " + args.length); } } catch (Exception e) { log.error("搜索执行失败: moduleCode={}", moduleCode, e); return AjaxResult.error("搜索执行失败: " + e.getMessage()); } } private AjaxResult handleFourArgs(ModuleSearchable searchService, Object[] args) { String companion = null; Date happenStartTime = null; Date happenEndTime = null; // 处理companion参数 if (args[0] instanceof String) { companion = (String) args[0]; } else if (args[0] != null) { companion = args[0].toString(); } // 处理时间参数 if (args[1] instanceof Date) { happenStartTime = (Date) args[1]; } if (args[2] instanceof Date) { happenEndTime = (Date) args[2]; } // 判断搜索类型 boolean hasTimeRange = happenStartTime != null && happenEndTime != null; List result; if (hasTimeRange) { // 有时间范围:执行时间范围搜索 log.info("执行时间范围搜索: companion={}, startTime={}, endTime={}", companion, happenStartTime, happenEndTime); result = searchService.search(companion, happenStartTime, happenEndTime); } else { // 无时间范围:只按companion搜索 log.info("执行companion搜索: companion={}, 时间范围为空", companion); result = searchService.search(companion, null, null); } return AjaxResult.success("搜索成功", result); } /** * 全模块搜索:获取所有模块的数据并分类 */ private AjaxResult searchAllModules(Object[] args) { log.info("执行全模块搜索,参数数量: {}", args.length); try { Map result = new LinkedHashMap<>(); int totalCount = 0; int successCount = 0; // 处理搜索参数 String companion = extractCompanion(args); Date happenStartTime = extractStartTime(args); Date happenEndTime = extractEndTime(args); System.out.println("全模块搜索 ------ 同伴: " + companion); System.out.println("全模块搜索 ------ 开始时间: " + happenStartTime); System.out.println("全模块搜索 ------ 结束时间: " + happenEndTime); // 并行处理所有模块搜索(提高性能) List> futures = moduleSearchMap.entrySet().stream().map(entry -> searchModuleAsync(entry.getKey(), entry.getValue(), companion, happenStartTime, happenEndTime)) .collect(Collectors.toList()); // 等待所有搜索完成 CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); // 收集结果 for (CompletableFuture future : futures) { ModuleSearchResult moduleResult = future.get(); if (moduleResult.isSuccess()) { // 创建一个可变的HashMap并填入数据 Map resultMap = new HashMap<>(); resultMap.put("data", moduleResult.getData()); resultMap.put("count", moduleResult.getCount()); resultMap.put("searchTime", moduleResult.getSearchTime()); // 将构建好的Map放入最终结果中 result.put(moduleResult.getModuleCode(), resultMap); successCount++; totalCount += moduleResult.getCount(); } else { Map errorInfo = new HashMap<>(); errorInfo.put("error", moduleResult.getErrorMessage()); errorInfo.put("success", false); result.put(moduleResult.getModuleCode(), errorInfo); } } // 构建返回结果 Map finalResult = new LinkedHashMap<>(); finalResult.put("totalModules", moduleSearchMap.size()); finalResult.put("successModules", successCount); finalResult.put("totalRecords", totalCount); finalResult.put("searchTime", new Date()); finalResult.put("modules", result); log.info("全模块搜索完成: 成功{}/{}个模块,总计{}条记录", successCount, moduleSearchMap.size(), totalCount); return AjaxResult.success("全模块搜索成功", finalResult); } catch (Exception e) { log.error("全模块搜索执行失败", e); return AjaxResult.error("全模块搜索失败: " + e.getMessage()); } } /** * 单个模块搜索包装方法 */ private ModuleSearchResult searchSingleModule(String moduleCode, ModuleSearchable service, String companion, Date startTime, Date endTime) { long start = System.currentTimeMillis(); try { List data = service.search(companion, startTime, endTime); long searchTime = System.currentTimeMillis() - start; return ModuleSearchResult.success(moduleCode, service.getModuleName(), data, data.size(), searchTime); } catch (Exception e) { log.error("模块[{}]搜索失败: {}", moduleCode, e.getMessage()); return ModuleSearchResult.error(moduleCode, e.getMessage()); } } // // /** // * 获取所有可搜索的模块信息 // */ // public List getAvailableModules() { // return moduleSearchMap.values().stream() // .map(service -> SysMenu.builder() // .moduleCode(service.getModuleCode()) // .moduleName(service.getModuleName()) // .build()) // .collect(Collectors.toList()); // } /** * 参数提取辅助方法 */ private String extractCompanion(Object[] args) { if (args.length > 0 && args[0] instanceof String) { return (String) args[0]; } else if (args.length > 0 && args[0] != null) { return args[0].toString(); } return null; } private Date extractStartTime(Object[] args) { return (args.length > 1 && args[1] instanceof Date) ? (Date) args[1] : null; } private Date extractEndTime(Object[] args) { return (args.length > 2 && args[2] instanceof Date) ? (Date) args[2] : null; } }