🎉🎉《Spring Boot实战案例合集》目前已更新153个案例,我们将持续不断的更新。文末有电子书目录。
💪💪永久更新承诺
我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务。
💌💌如何获取
订阅我们的合集《点我订阅》,并通过私信联系我们,我们将第一时间将电子书发送给您。
环境:SpringBoot3.4.2
1. 简介
在复杂业务系统开发中,校验逻辑与业务代码混杂的问题普遍存在。大量 if-else 判断导致代码臃肿、可读性差,且规则变更需频繁修改业务代码,违背开闭原则。尤其在电商、金融等领域,订单创建、交易处理等场景涉及时间限制、库存状态、用户权限等多维度校验,传统硬编码方式易引发漏判、误判,且难以复用校验逻辑。
本篇文章将基于 AOP 实现动态业务规则校验,通过将校验逻辑抽离为独立规则组件,实现业务与校验的解耦。借助注解灵活组合规则,支持快速失败与全量校验模式,可动态适配规则变化,大幅提升代码可维护性与系统扩展性,成为复杂业务场景的高效解决方案。
如下最终效果:
@BusinessValidation(rules = {OrderAmountValidation.class,OrderAddressValidation.class}, failFast = false)public void createOrder(Order order) {System.err.println("订单创建成功") ;}
输出结果
2.1 自定义注解
public BusinessValidation {/**需要执行的校验规则类数组*/Class<? extends ValidationRule>[] rules() ;/**是否快速失败(遇到第一个校验失败就抛出异常)*/boolean failFast() default true;/**校验失败时是否抛出异常*/boolean throwException() default true;/**校验失败时的错误消息模板*/String message() default "规则校验失败";}
2.2 规则接口定义
/**业务校验规则接口,所有具体校验规则需实现此接口*/public interface ValidationRule {ValidationResult validate(Object target, Method method, Object[] args);}// 校验结果public class ValidationResult {/**校验是否通过*/private final boolean valid ;/**错误消息*/private final String message ;private ValidationResult(boolean valid, String message) {this.valid = valid;this.message = message;}/**创建校验通过的结果*/public static ValidationResult valid() {return new ValidationResult(true, null);}/**创建校验失败的结果*/public static ValidationResult invalid(String message) {return new ValidationResult(false, message);}public boolean isValid() {return valid;}public String getMessage() {return message;}}
接下来,我们先定义几个不同规则的实现
// 校验订单金额public class OrderAmountValidation implements ValidationRule {// 最大订单金额限制private static final BigDecimal MAX_AMOUNT = new BigDecimal("100000") ;public ValidationResult validate(Object target, Method method, Object[] args) {// 假设第1个参数Order对象(实际可以考虑通过注解方式?)BigDecimal amount = ((Order) args[0]).getAmount() ;if (amount.compareTo(BigDecimal.ZERO) <= 0) {return ValidationResult.invalid("订单金额必须大于0");}if (amount.compareTo(MAX_AMOUNT) > 0) {return ValidationResult.invalid("订单金额超过最大限制: " + MAX_AMOUNT);}return ValidationResult.valid() ;}}// 校验订单邮寄地址public class OrderAddressValidation implements ValidationRule {private static final Set<String> NO_SUPPORT = Set.of("新疆", "西藏") ;public ValidationResult validate(Object target, Method method, Object[] args) {// 假设第1个参数Order对象(实际可以考虑通过注解方式?)String address = ((Order) args[0]).getAddress() ;if (NO_SUPPORT.contains(address)) {return ValidationResult.invalid(String.format("【%s】不支持的邮寄地址", address));}return ValidationResult.valid() ;}}
2.3 规则校验切面
public class BusinessValidationAspect implements ApplicationContextAware {private ApplicationContext context;public Object validateBusinessRules(ProceedingJoinPoint pjp, BusinessValidation validation)throws Throwable {Object target = pjp.getTarget() ;Method method = ((MethodSignature) pjp.getSignature()).getMethod();Object[] args = pjp.getArgs();// 1.获取需要执行的校验规则类Class<? extends ValidationRule>[] ruleClasses = validation.rules();List<ValidationRule> rules = new ArrayList<>();// 2.获取所有的校验规则(如果不是bean对象则进行创建)for (Class<? extends ValidationRule> clazz : ruleClasses) {try {ValidationRule rule = context.getBean(clazz) ;rules.add(rule) ;} catch (Exception e) {// 创建实例Objenesis obj = new ObjenesisStd() ;ValidationRule rule = obj.newInstance(clazz) ;rules.add(rule) ;}}List<String> errors = new ArrayList<>() ;// 3.执行所有校验规则for (ValidationRule rule : rules) {ValidationResult result = rule.validate(target, method, args) ;if (!result.isValid()) {// 校验失败,根据注解配置决定抛出异常或继续执行if (validation.failFast()) {errors.add(result.getMessage()) ;break ;} else {// 非快速失败模式,收集所有错误信息errors.add(result.getMessage()) ;}}}// 4.错误信息处理if (!errors.isEmpty() && validation.throwException()) {throw new BusinessValidationException(errors) ;} else {System.err.println(errors) ;}// 5.继续向下执行return pjp.proceed();}public void setApplicationContext(ApplicationContext context) throws BeansException {this.context = context ;}}
在该切面中,我们通过 Objenesis 创建规则实例对象,你在应用此方法时,你需要了解下它创建对象的规则,详细请查看下面文章:
2.4 异常处理
public class GlobalExceptionHandler {()public ResponseEntity<?> businessValidationException(BusinessValidationException e) {return ResponseEntity.ok(e.getErrors()) ;}}// 异常对象public class BusinessValidationException extends RuntimeException {private List<String> errors = new ArrayList<>() ;public BusinessValidationException(List<String> errors) {super("") ;this.errors = errors ;}}
2.5 测试
public class OrderService {(rules = {OrderAmountValidation.class,OrderAddressValidation.class}, failFast = false)public void createOrder(Order order) {System.err.println("订单创建成功") ;}}
Controller接口
private final OrderService orderService ;public OrderController(OrderService orderService) {this.orderService = orderService;}public ResponseEntity<?> create( Order order) {this.orderService.createOrder(order) ;return ResponseEntity.ok(order) ;}
以上就完成了基于注解的动态规则校验。
推荐文章
Spring Boot + JobRunr 后台任务执行神器,太强大了
强大!借助Spring Boot内置动态刷新功能,实时更新组件
性能优化!3种方案优化Controller接口调用,性能提升N倍
重磅!Spring Cloud Gateway 全面支持 Servlet 技术栈,简单多了
性能优化!7个策略,让Spring Boot 处理每秒百万请求
Spring Boot自定义注解+参数解析器,构建灵活的安全认证机制
必学!Spring Boot结合MDC全方位的日志跟踪(支持跨线程)


