本文目录导读:

在Java中,校验模块的复用是提升开发效率和代码质量的关键,以下我会从设计模式和实际案例两个维度,为你提供几种成熟的复用方案。
核心复用思路:分层解耦 + 策略化
基于注解的校验(JSR-380 / Bean Validation)
这是最标准的复用方式,适合简单字段校验。
// 1. 定义可复用的校验注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneValidator.class)
public @interface ValidPhone {
String message() default "手机号格式错误";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
// 2. 校验逻辑实现(可复用)
public class PhoneValidator implements ConstraintValidator<ValidPhone, String> {
private static final String PHONE_REGEX = "^1[3-9]\\d{9}$";
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null || value.isEmpty()) {
return true; // 允许空值,用@NotNull配合
}
return value.matches(PHONE_REGEX);
}
}
// 3. 在任意实体中复用
public class UserDTO {
@ValidPhone
private String phone;
@ValidPhone(groups = {Admin.class}) // 分组校验
private String adminPhone;
}
复用方式:一个注解全局使用,业务代码无需重复写if判断。
策略模式 + 工厂模式(复杂业务校验)
当校验规则复杂且经常变动时,使用策略模式实现可插拔的校验单元。
// 1. 定义校验策略接口
public interface ValidationStrategy<T> {
ValidationResult validate(T target);
}
// 2. 实现具体策略(每个策略独立可复用)
public class OrderAmountStrategy implements ValidationStrategy<Order> {
@Override
public ValidationResult validate(Order order) {
if (order.getAmount() <= 0) {
return ValidationResult.fail("订单金额必须大于0");
}
return ValidationResult.success();
}
}
public class UserAgeStrategy implements ValidationStrategy<User> {
@Override
public ValidationResult validate(User user) {
if (user.getAge() < 0 || user.getAge() > 150) {
return ValidationResult.fail("年龄不合法");
}
return ValidationResult.success();
}
}
// 3. 策略工厂(管理校验规则组合)
public class ValidationFactory {
private static final Map<String, List<ValidationStrategy>> rules = new HashMap<>();
static {
rules.put("order", Arrays.asList(new OrderAmountStrategy(),
new OrderStatusStrategy()));
rules.put("user", Arrays.asList(new UserAgeStrategy(),
new UserNameStrategy()));
}
public static List<ValidationStrategy> getStrategies(String type) {
return rules.getOrDefault(type, Collections.emptyList());
}
}
// 4. 校验执行器(统一复用入口)
public class ValidationExecutor {
public static <T> ValidationResult execute(String type, T target) {
List<ValidationStrategy> strategies = ValidationFactory.getStrategies(type);
for (ValidationStrategy strategy : strategies) {
ValidationResult result = strategy.validate(target);
if (result.isFail()) {
return result;
}
}
return ValidationResult.success();
}
}
// 使用示例
Order order = new Order();
ValidationResult result = ValidationExecutor.execute("order", order);
复用方式:任意业务逻辑只要调用ValidationExecutor.execute("user", user)即可复用所有用户校验规则。
责任链模式(流水线式校验)
适合需要顺序执行且可动态组装的场景。
// 1. 抽象校验节点
public abstract class ValidationHandler {
protected ValidationHandler next;
public ValidationHandler setNext(ValidationHandler next) {
this.next = next;
return next;
}
public abstract boolean handle(Request request);
protected boolean handleNext(Request request) {
if (next == null) return true;
return next.handle(request);
}
}
// 2. 具体节点(可独立复用)
public class TokenValidationHandler extends ValidationHandler {
@Override
public boolean handle(Request request) {
if (request.getToken() == null || request.getToken().isEmpty()) {
System.out.println("Token校验失败");
return false;
}
System.out.println("Token校验通过");
return handleNext(request);
}
}
public class PermissionValidationHandler extends ValidationHandler {
@Override
public boolean handle(Request request) {
if (!"admin".equals(request.getRole())) {
System.out.println("权限不足");
return false;
}
System.out.println("权限校验通过");
return handleNext(request);
}
}
// 3. 动态组装校验链(复用点)
public class ValidationChainBuilder {
public static ValidationHandler buildDefaultChain() {
ValidationHandler tokenHandler = new TokenValidationHandler();
ValidationHandler permissionHandler = new PermissionValidationHandler();
tokenHandler.setNext(permissionHandler);
return tokenHandler; // 返回链头
}
}
// 使用
Request request = new Request();
ValidationHandler chain = ValidationChainBuilder.buildDefaultChain();
boolean pass = chain.handle(request);
复用方式:通过buildDefaultChain()轻松组装可复用的校验流水线,也可通过配置文件动态修改。
模板方法模式(固定校验骨架)
适合校验流程通用但具体校验逻辑不同的场景。
// 1. 抽象校验模板
public abstract class AbstractValidator<T> {
// 模板方法:定义校验的固定骨架
public final ValidationResult validate(T target) {
// 步骤1:基础非空校验
if (target == null) {
return ValidationResult.fail("目标对象不能为空");
}
// 步骤2:具体校验(子类实现)
ValidationResult specificResult = doValidate(target);
if (specificResult.isFail()) {
return specificResult;
}
// 步骤3:后置处理(可选)
postValidate(target);
return ValidationResult.success();
}
protected abstract ValidationResult doValidate(T target);
protected void postValidate(T target) {
// 默认空实现,子类可选覆盖
}
}
// 2. 具体实现类
public class UserValidator extends AbstractValidator<User> {
@Override
protected ValidationResult doValidate(User user) {
if (user.getName() == null || user.getName().length() < 2) {
return ValidationResult.fail("用户名至少2个字符");
}
return ValidationResult.success();
}
}
// 使用
UserValidator validator = new UserValidator();
ValidationResult result = validator.validate(user);
复用方式:所有校验器继承AbstractValidator,自动获得非空校验等通用逻辑。
企业级最佳实践:组合使用
实际项目中通常将上述模式组合:
校验架构分层:
├── 表现层(Controller)
│ ├── @Valid / @Validated 注解(处理基础字段校验)
│ └── 自定义注解(@Phone、@Email等)
├── 业务层(Service)
│ ├── 策略模式校验器(处理复杂业务规则)
│ └── 责任链校验器(处理流程化校验)
└── 基础设施层(Infrastructure)
├── 校验结果封装(ValidationResult)
├── 校验异常统一处理
└── 校验规则配置中心(规则可配置化)
关键复用技巧:
- 将校验逻辑剥离到独立模块(如
validation-common),所有微服务依赖 - 使用SPI或Spring Factories实现校验器的自动发现
- 规则配置化:将校验规则放入数据库或配置中心,运行时动态加载
选择哪种复用方式取决于你的业务复杂度:简单校验用注解,复杂校验用策略模式,流程校验用责任链,固定骨架用模板方法。