先来展示一个传统校验方式
以购票请求校验为例:
public class TicketServiceImpl implements TicketService {
@Autowired
//....Mapper层
public void Query(TicketRequest request) {
// 基础校验
if (request.getUserId() == null) {
throw new ValidationException("用户ID不能为空");
}
if (StringUtils.isEmpty(request.getTrainNumber())) {
throw new ValidationException("车次不能为空");
}
// 查询专用校验
if (request.getDepartureDate() == null) {
throw new ValidationException("出发日期不能为空");
}
if (request.getDepartureDate().isBefore(LocalDate.now())) {
throw new ValidationException("不能查询历史日期车票");
}
....查询逻辑
}
public void Order(OrderRequest request) {
// 基础校验重复代码...
if (request.getUserId() == null) {
throw new ValidationException("用户ID不能为空");
}
// 下单专用校验
if (request.getSeats() == null || request.getSeats().isEmpty()) {
throw new ValidationException("至少选择一个座位");
}
if (request.getTotalPrice().compareTo(BigDecimal.ZERO) <= 0) {
throw new ValidationException("金额必须大于0");
}
....下单逻辑
}
}
这种校验模式有几大问题:
- 校验逻辑重复(如用户ID校验)
- 业务耦合度高
- 难以扩展新校验规则
责任链模式改造
1、改造完的Service
@Service
public class TicketServiceImpl implements TicketService {
@Autowired
private ValidationService validationService;
public Ticket queryTickets(QueryRequest request) {
validator.validate(request); // 自动走基础+查询校验
// 查询逻辑...
}
public void createOrder(OrderRequest request) {
validator.validate(request); // 自动走基础+订单校验
// 下单逻辑...
}
}
2、请求对象结构
// 基础请求
public class TicketRequest {
private Long userId;
private String trainNumber;
// getters/setters...
}
// 查询请求
public class QueryRequest extends TicketRequest {
private LocalDate departureDate;
// 扩展字段...
}
// 订单请求
public class OrderRequest extends TicketRequest {
private List<String> seats;
private BigDecimal totalPrice;
// 扩展字段...
}
3、Validation层(校验层)
3.1、校验服务接口Service
public interface ValidationService {
void validateQuery(QueryRequest request);
void validateOrder(OrderRequest request);
}
3.2、校验服务实现ServiceImpl
@Service
public class ValidationServiceImpl implements ValidationService {
@Autowired
@Qualifier("queryValidatorChain")
private ValidationHandler<QueryRequest> queryValidator;
@Autowired
@Qualifier("orderValidatorChain")
private ValidationHandler<OrderRequest> orderValidator;
@Override
public void validateQuery(QueryRequest request) {
queryValidator.handle(request);
}
@Override
public void validateOrder(OrderRequest request) {
orderValidator.handle(request);
}
}
4、Validator配置层
校验器配置类
@Configuration
public class ValidatorConfig {
@Bean
@Qualifier("basicValidator")
public BasicValidator basicValidator() {
return new BasicValidator();
}
@Bean
@Qualifier("queryValidator")
public QueryValidator queryValidator() {
return new QueryValidator();
}
@Bean
@Qualifier("orderValidator")
public OrderValidator orderValidator() {
return new OrderValidator();
}
@Bean
@Qualifier("queryValidatorChain")
public ValidationHandler<QueryRequest> queryValidatorChain(
@Qualifier("basicValidator") BasicValidator basic,
@Qualifier("queryValidator") QueryValidator query) {
basic.setNext(query);
return basic;
}
@Bean
@Qualifier("orderValidatorChain")
public ValidationHandler<OrderRequest> orderValidatorChain(
@Qualifier("basicValidator") BasicValidator basic,
@Qualifier("orderValidator") OrderValidator order) {
basic.setNext(order);
return basic;
}
}
5、Validator实现层
5.1、抽象验证处理器
public abstract class AbstractValidationHandler<T> implements ValidationHandler<T> {
private ValidationHandler<T> next;
@Override
public void setNext(ValidationHandler<T> next) {
this.next = next;
}
@Override
public void handle(T request) throws ValidationException {
doValidate(request);
if (next != null) {
next.handle(request);
}
}
protected abstract void doValidate(T request) throws ValidationException;
}
5.2、具体验证器实现
@Component
public class BasicValidator extends AbstractValidationHandler<TicketRequest> {
@Override
protected void doValidate(TicketRequest request) throws ValidationException {
if (request.getUserId() == null) {
throw new ValidationException("USER_ID_REQUIRED", "用户ID不能为空");
}
if (StringUtils.isEmpty(request.getTrainNumber())) {
throw new ValidationException("TRAIN_NUMBER_REQUIRED", "车次不能为空");
}
}
}
@Component
public class QueryValidator extends AbstractValidationHandler<QueryRequest> {
@Override
protected void doValidate(QueryRequest request) throws ValidationException {
if (request.getDepartureDate() == null) {
throw new ValidationException("DEPARTURE_DATE_REQUIRED", "出发日期必须指定");
}
if (request.getDepartureDate().isBefore(LocalDate.now())) {
throw new ValidationException("INVALID_DEPARTURE_DATE", "不能查询历史日期车票");
}
}
}
@Component
public class OrderValidator extends AbstractValidationHandler<OrderRequest> {
@Override
protected void doValidate(OrderRequest request) throws ValidationException {
if (request.getSeats() == null || request.getSeats().isEmpty()) {
throw new ValidationException("SEAT_SELECTION_REQUIRED", "至少选择一个座位");
}
if (request.getSeats().size() > 5) {
throw new ValidationException("MAX_SEAT_LIMIT", "单次最多购买5张票");
}
}
}
改造优势对比
维度 | 传统方式 | 责任链模式 |
---|---|---|
代码复用 | 重复校验逻辑 | 共用基础校验链 |
扩展性 | 需修改原类 | 添加新Handler即可 |
可读性 | 方法臃肿 | 每个校验器职责单一 |
维护性 | 牵一发而动全身 | 独立修改不影响其他 |
灵活性 | 固定校验顺序 | 动态调整链条顺序 |
典型场景:
当系统需要支持新的校验规则(如疫情防控期间限制购票地区),责任链模式只需新增一个EpidemicValidator
即可,而传统方式需要修改所有校验方法。
示例
新增疫情校验器:
@Component
public class EpidemicValidator extends AbstractValidationHandler<OrderRequest> {
@Override
protected void doValidate(OrderRequest request) {
if (isHighRiskArea(request.getDepartureStation())) {
throw new ValidationException("HIGH_RISK_AREA", "高风险地区暂不支持购票");
}
}
private boolean isHighRiskArea(String station) {
// 调用疫情API检查
return false;
}
}
配置更新:
@Bean
@Qualifier("orderValidatorChain")
public ValidationHandler<OrderRequest> orderValidatorChain(
@Qualifier("basicValidator") BasicValidator basic,
@Qualifier("orderValidator") OrderValidator order,
@Qualifier("epidemicValidator") EpidemicValidator epidemic) {
basic.setNext(order).setNext(epidemic);
return basic;
}
代码粗糙,有错误请指明,感谢!