自定义注解实现服务分处理-策略模式
路由:请求标识→匹配 Service→调用 process 方法
通过自定义注解 @BusinessServiceMapping
标记具体业务 Service,注解值(如 DC 代表客户、ORD
代表订单)与请求参数中的业务标识关联;再通过 Spring 容器扫描 + 策略模式,实现 “请求标识→匹配 Service→调用 process 方法” 的自动路由,避免硬编码分支判断。
根据条件动态选择执行,解耦 “选择逻辑” 和 “业务实现”
自定义注解:@BusinessServiceMapping
(标记业务 Service)
import org.springframework.stereotype.Component; import java.lang.annotation.*; /** * 自定义业务Service映射注解:标记Service对应的业务标识(如DC=客户、ORD=订单) */ @Target({ElementType.TYPE}) // 仅用于类(Service实现类) @Retention(RetentionPolicy.RUNTIME) // 运行时保留,便于反射获取 @Documented @Component // 让Spring自动扫描该注解标记的类 public @interface BusinessServiceMapping { /** * 业务标识(如DC=客户、ORD=订单),支持多标识(如一个Service处理多个相关业务) */ String[] value(); /** * 业务描述(可选,用于文档说明) */ String desc() default ""; }
2. 业务 Service 接口:BusinessProcessService
(定义统一方法)
import com.yourproject.dto.BusinessRequestDTO; import com.yourproject.dto.BusinessResponseDTO; /** * 业务Service统一接口:所有业务Service需实现此接口 */ public interface BusinessProcessService { /** * 统一业务处理方法 * @param requestDTO 业务请求参数(封装请求标识、业务数据等) * @return 业务处理结果 */ BusinessResponseDTO process(BusinessRequestDTO requestDTO); /** * 获取当前Service支持的业务标识(与@BusinessServiceMapping的value对应,便于校验) */ String[] getSupportBusinessCodes(); }
3. 业务请求 / 响应 DTO:封装参数与结果
// 业务请求DTO:请求需携带业务标识(如dc、ord) public class BusinessRequestDTO { /** * 业务标识(与@BusinessServiceMapping的value对应,如DC=客户、ORD=订单) */ private String businessCode; /** * 具体业务数据(JSON字符串,根据业务类型解析) */ private String businessData; // getter + setter } // 业务响应DTO:统一返回格式 public class BusinessResponseDTO { /** * 处理状态(SUCCESS/FAIL) */ private String status; /** * 响应消息 */ private String message; /** * 业务结果数据(JSON字符串) */ private String resultData; // 静态工厂方法:简化创建 public static BusinessResponseDTO success(String message, String resultData) { BusinessResponseDTO dto = new BusinessResponseDTO(); dto.setStatus("SUCCESS"); dto.setMessage(message); dto.setResultData(resultData); return dto; } public static BusinessResponseDTO fail(String message) { BusinessResponseDTO dto = new BusinessResponseDTO(); dto.setStatus("FAIL"); dto.setMessage(message); return dto; } // getter + setter }
4. 业务 Service 实现类(示例:客户 Service + 订单 Service)
// 示例1:客户业务Service(标识DC) @BusinessServiceMapping( value = "DC", // 业务标识:DC=客户 desc = "客户相关业务处理(新增/编辑/查询客户)" ) public class CustomerBusinessService implements BusinessProcessService { @Override public BusinessResponseDTO process(BusinessRequestDTO requestDTO) { // 1. 解析客户业务数据(requestDTO.getBusinessData()为JSON字符串) String customerData = requestDTO.getBusinessData(); // 示例:假设业务数据是客户新增参数(实际项目用JSON工具解析为实体类) // CustomerAddDTO addDTO = JSON.parseObject(customerData, CustomerAddDTO.class); // 2. 处理客户业务逻辑(如调用DAO新增客户) System.out.println("客户Service处理业务,数据:" + customerData); // 3. 返回结果 return BusinessResponseDTO.success("客户业务处理成功", "{\"customerId\":1001,\"status\":\"ACTIVE\"}"); } @Override public String[] getSupportBusinessCodes() { // 与@BusinessServiceMapping的value保持一致(便于校验) return new String[]{"DC"}; } } // 示例2:订单业务Service(标识ORD) @BusinessServiceMapping( value = "ORD", // 业务标识:ORD=订单 desc = "订单相关业务处理(创建订单/取消订单)" ) public class OrderBusinessService implements BusinessProcessService { @Override public BusinessResponseDTO process(BusinessRequestDTO requestDTO) { // 订单业务逻辑处理(类似客户Service) String orderData = requestDTO.getBusinessData(); System.out.println("订单Service处理业务,数据:" + orderData); return BusinessResponseDTO.success("订单业务处理成功", "{\"orderId\":2001,\"orderStatus\":\"PAID\"}"); } @Override public String[] getSupportBusinessCodes() { return new String[]{"ORD"}; } }
5. 路由服务:BusinessServiceRouter
(核心:匹配请求与 Service)
import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.Map; /** * 业务Service路由:根据请求的businessCode匹配对应的Service */ @Component public class BusinessServiceRouter implements ApplicationContextAware { /** * 业务标识→Service的映射缓存(key:businessCode,value:对应的BusinessProcessService) */ private final Map<String, BusinessProcessService> businessServiceMap = new HashMap<>(); /** * Spring启动时,扫描所有带@BusinessServiceMapping的Service,初始化映射 */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { // 1. 扫描Spring容器中所有实现BusinessProcessService接口的Bean Map<String, BusinessProcessService> serviceBeans = applicationContext.getBeansOfType(BusinessProcessService.class); // 2. 遍历Service,解析@BusinessServiceMapping注解,建立映射 for (BusinessProcessService service : serviceBeans.values()) { BusinessServiceMapping mapping = service.getClass().getAnnotation(BusinessServiceMapping.class); if (mapping == null) { continue; // 跳过未标记注解的Service } // 3. 为每个业务标识绑定Service(支持一个Service对应多个标识) for (String businessCode : mapping.value()) { if (businessServiceMap.containsKey(businessCode)) { throw new RuntimeException("业务标识[" + businessCode + "]重复绑定Service,请检查@BusinessServiceMapping注解"); } businessServiceMap.put(businessCode, service); System.out.println("业务标识[" + businessCode + "]绑定Service:" + service.getClass().getSimpleName()); } } // 4. 打印映射结果(便于调试) System.out.println("业务Service映射初始化完成,共" + businessServiceMap.size() + "个标识:" + businessServiceMap.keySet()); } /** * 核心方法:根据业务标识获取对应的Service * @param businessCode 业务标识(如DC、ORD) * @return 匹配的BusinessProcessService * @throws RuntimeException 无匹配Service时抛出异常 */ public BusinessProcessService getServiceByBusinessCode(String businessCode) { BusinessProcessService service = businessServiceMap.get(businessCode); if (service == null) { throw new RuntimeException("未找到业务标识[" + businessCode + "]对应的Service,请检查配置"); } return service; } /** * 统一业务处理入口:路由到对应Service并调用process方法 */ public BusinessResponseDTO routeAndProcess(BusinessRequestDTO requestDTO) { if (requestDTO == null || requestDTO.getBusinessCode() == null) { return BusinessResponseDTO.fail("请求参数错误:businessCode不能为空"); } try { // 1. 根据businessCode获取Service BusinessProcessService service = getServiceByBusinessCode(requestDTO.getBusinessCode()); // 2. 调用Service的process方法处理业务 return service.process(requestDTO); } catch (RuntimeException e) { // 3. 捕获异常,返回统一错误格式 return BusinessResponseDTO.fail("业务处理失败:" + e.getMessage()); } } }
6. 控制层:BusinessController
(接收请求,调用路由服务)
import com.yourproject.dto.BusinessRequestDTO; import com.yourproject.dto.BusinessResponseDTO; import com.yourproject.service.BusinessServiceRouter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * 统一业务入口Controller:所有业务请求通过此接口进入,由路由服务分发 */ @RestController @RequestMapping("/api/business") public class BusinessController { @Autowired private BusinessServiceRouter businessServiceRouter; /** * 统一业务处理接口 * @param requestDTO 业务请求(包含businessCode和业务数据) * @return 业务处理结果 */ @PostMapping("/process") public BusinessResponseDTO processBusiness(@RequestBody BusinessRequestDTO requestDTO) { // 直接委托路由服务处理,无需硬编码分支 return businessServiceRouter.routeAndProcess(requestDTO); } }
三、核心流程说明
四、扩展与优势
五、依赖与配置
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; @SpringBootApplication // 若Service在com.yourproject.service包下,默认会扫描,无需额外配置;若路径不同需添加: // @ComponentScan(basePackages = {"com.yourproject.controller", "com.yourproject.service"}) public class BusinessApplication { public static void main(String[] args) { SpringApplication.run(BusinessApplication.class, args); } }