当前位置: 首页 > news >正文

自定义注解实现服务分处理-策略模式

路由:请求标识→匹配 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 {@Overridepublic 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\"}");}@Overridepublic String[] getSupportBusinessCodes() {// 与@BusinessServiceMapping的value保持一致(便于校验)return new String[]{"DC"};}
}// 示例2:订单业务Service(标识ORD)
@BusinessServiceMapping(value = "ORD", // 业务标识:ORD=订单desc = "订单相关业务处理(创建订单/取消订单)"
)
public class OrderBusinessService implements BusinessProcessService {@Overridepublic BusinessResponseDTO process(BusinessRequestDTO requestDTO) {// 订单业务逻辑处理(类似客户Service)String orderData = requestDTO.getBusinessData();System.out.println("订单Service处理业务,数据:" + orderData);return BusinessResponseDTO.success("订单业务处理成功", "{\"orderId\":2001,\"orderStatus\":\"PAID\"}");}@Overridepublic 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,初始化映射*/@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {// 1. 扫描Spring容器中所有实现BusinessProcessService接口的BeanMap<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获取ServiceBusinessProcessService 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 {@Autowiredprivate BusinessServiceRouter businessServiceRouter;/*** 统一业务处理接口* @param requestDTO 业务请求(包含businessCode和业务数据)* @return 业务处理结果*/@PostMapping("/process")public BusinessResponseDTO processBusiness(@RequestBody BusinessRequestDTO requestDTO) {// 直接委托路由服务处理,无需硬编码分支return businessServiceRouter.routeAndProcess(requestDTO);}
}

三、核心流程说明

  1. 启动初始化:
    Spring 启动时,BusinessServiceRouter 通过 ApplicationContextAware 扫描所有实现 BusinessProcessService 且带 @BusinessServiceMapping 的 Service,建立 “业务标识→Service” 的映射(如 DC→CustomerBusinessServiceORD→OrderBusinessService)。
  2. 请求处理:
    • 前端发送请求(如客户业务),businessCode=DCbusinessData={"customerName":"张三","phone":"13800138000"}
    • BusinessController 接收请求,调用 BusinessServiceRouter.routeAndProcess
    • 路由服务根据 businessCode=DC 找到 CustomerBusinessService,调用其 process 方法;
    • 处理完成后,返回统一格式的 BusinessResponseDTO

四、扩展与优势

  1. 新增业务:
    若需新增 “产品业务”(标识 PROD),只需:
    • 新建 ProductBusinessService 实现 BusinessProcessService
    • 用 @BusinessServiceMapping(value = "PROD", desc = "产品业务") 标记;
    • 无需修改 Controller 或路由服务,实现 “开闭原则”。
  2. 避免硬编码:
    传统写法需用 if (businessCode.equals("DC")) { 客户Service } else if (...),新增业务需修改代码;此方案通过注解 + 路由,彻底消除硬编码分支。
  3. 便于维护:
    每个业务 Service 职责单一,通过注解清晰标识业务范围,后续维护只需定位到对应 Service 即可。

五、依赖与配置

需确保 Spring 能扫描到注解标记的类,在 Spring Boot 启动类添加扫描路径(默认扫描启动类所在包及子包,若 Service 在其他包需手动指定):
 
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);}
}

 

 

http://www.sczhlp.com/news/115598/

相关文章:

  • 网站制作教程宁波网站推广哪家公司好
  • 海珠网站建设公司如何建一个公司的网站
  • 无锡企业网站seo排名优化软件
  • 简述一个网站设计的主要步骤阿里云域名注册优惠口令
  • 一个人做公司管理网站广告效果图用什么软件做
  • iOS26正式版全新风格!一文汇总实用新功能!
  • 远程控制应用的中的全球节点功能如何开启?插件类型、并发数量怎么选?
  • 借助Aspose.HTML控件,使用 Python 将 HTML 转换为 DOCX
  • 网站备案验证码错误高端网站开发平台
  • 网站建设的公司开发中山建网站咨询电话
  • 清远建设网站wordpress 公众号 采集器
  • appcms程序怎么做网站高端定制网站建设
  • 网站内容包括哪些上海网站建设润滋
  • 赣州热门网站安卓手机软件开发
  • 网站建设后的优势深圳外贸公司网站
  • 帮我写一篇网站打开网站代码怎么写
  • 遵义交通建设网站到那里找做网站的兼职
  • openEuler 24.03 (LTS-SP2)安装mysql 8.0.41
  • 7.数据库归档异常检查与处理
  • Gitlab 关键字
  • 8.listener日志占用过大处理方法
  • 马建仓AI助手完成全链路升级:三十余项新能力重塑研发工作流
  • 大连网站快速建设推荐合肥企业网站建设公司哪家好
  • 微商城手机网站制作阿里指数查询
  • 人社局网站建设步骤大连建设网联合收费
  • 网站后端性能优化措施企业网站模板 网页模板
  • 中山网站建设开发me wordpress
  • 手机卡盟网站建设阿里云控制台登录入口
  • 专业深圳网站建设公司哪里网站备案
  • 漯河企业网站开发迁移WordPress后无法访问