Springboot中Controller层数据校验,自定义注解@Valid校验枚举参数值
在日常业务开发中,使用valid做参数校验时,很多时候默认的注解,例如@Min、@Max、@NotBlank等不能满足业务对数据的校验,不吐不想写大量的if-else,这时候就需要自定义注解来配合 @vaild,对前端的数据进行校验
1、业务场景
import lombok. RequiredArgsConstructor;
import javax. validation. Valid;
import static org. springframework. http. HttpStatus. OK;
@RestController
@RequestMapping ( "/api/ticket" )
@RequiredArgsConstructor
public class TicketController {
private final TicketService ticketService;
@PatchMapping ( "/{ticketId}" )
@ResponseStatus ( OK)
public void rejectTicket ( @Valid @RequestBody UpdateTicketStatusCommand command,
@PathVariable ( "ticketId" ) String ticketId) {
usageAppealService. updateTicket ( ticketId, command) ;
}
}
前端发送一下 Request Json对应的 Command
@Getter
@Setter
public class UpdateTicketStatusCommand {
private TicketStatus previousStatus;
private TicketStatus currentStatus;
private String reviewComments;
}
public enum TicketStatus {
CREATE,
APPEALING,
DONE
}
需要校验工单的状态,假如:
previousStatus 取值范围为 CREATE、APPEALING两种 currentStatus 的取值范围为 APPEALING、DONE 此时需要做严格的校验
2、定义注解类
import javax. validation. Constraint;
import javax. validation. Payload;
import java. lang. annotation. *;
@Target ( { ElementType. FIELD, ElementType. METHOD, ElementType. ANNOTATION_TYPE} )
@Retention ( RetentionPolicy. RUNTIME)
@Documented
@Constraint ( validatedBy = { TicketStatusValidator. class } )
public @interface TicketStatusValid {
String message ( ) default "" ;
Class< ? > [ ] groups ( ) default { } ;
Class< ? extends Payload > [ ] payload ( ) default { } ;
TicketStatus[ ] ticketStatuses ( ) ;
}
该注解类作用在枚举类上 TicketStatus[] ticketStatuses() 用于传入参数字段的取值范围
3、实现注解
import javax. validation. ConstraintValidator;
import javax. validation. ConstraintValidatorContext;
import java. util. Arrays;
import java. util. List;
public class TicketStatusValidator implements ConstraintValidator < AppealResultValid, AppealTicketStatus> {
private List< TicketStatus> ticketStatuses;
@Override
public void initialize ( TicketStatusValid constraintAnnotation) {
ConstraintValidator. super . initialize ( constraintAnnotation) ;
ticketStatuses = Arrays. asList ( constraintAnnotation. ticketStatuses ( ) ) ;
}
@Override
public boolean isValid ( TicketStatus value, ConstraintValidatorContext context) {
return ticketStatuses. contains ( value) ;
}
}
public boolean isValid(TicketStatus value, ConstraintValidatorContext context) 方法用于校验 枚举值是否被包含在数据内
4、注解类的使用
@Getter
@Setter
public class UpdateTicketStatusCommand {
@TicketStatusValid (
ticketStatuses = { CREATE, APPEALING} ,
message = "The value range of previousResult is CREATE, APPEALING"
)
private AppealTicketStatus previousResult;
@TicketStatusValid (
ticketStatuses = { APPEALING, DONE} ,
message = "The value range of currentResult is APPEALING, DONE"
)
private AppealTicketStatus currentResult;
@NotBlank
@Size ( min = 1 , max = 120 , message = "The length of reviewComments is limited to 120" )
private String reviewComments;
}