需求:对用户名以及密码进行参数验证,使用自定义注解的方式
使用预编译的Pattern对字段进行校验
public class ValidationUtils {
// 字段验证的正则表达式
private static final String usernameRegex = "^[A-Za-z].{5,19}$";
private static final String passwordRegx = "^[A-Za-z].{7,19}$";
private static final Pattern usernamePattern;
private static final Pattern passwordPattern;
// 静态代码块只执行一次
static {
usernamePattern = Pattern.compile(usernameRegex);
passwordPattern = Pattern.compile(passwordRegx);
}
// 检验方法
public static boolean checkUsername(String username) {
return username != null && usernamePattern.matcher(username).matches();
}
public static boolean checkPassword(String password) {
return password != null && passwordPattern.matcher(password).matches();
}
}
定义注解
@Documented
// 说明使用哪个类进行参数校验
@Constraint(validatedBy = UsernameValidator.class)
@Retention(RetentionPolicy.RUNTIME)
// 注解的作用范围,参数检验一般为字段域
@Target({ElementType.FIELD})
public @interface VerifyUsername {
String regexp() default "";
String message() default "用户名不正确";
// 一定要存在的方法
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
实现ConstraintValidator接口中的isValid方法来执行检验方法
// VerifyUsername : 自定义注解名
public class UsernameValidator implements ConstraintValidator<VerifyUsername,String> {
@Override
public void initialize(VerifyUsername constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return ValidationUtils.checkUsername(value);
}
}
在DTO中使用自定义注解
public class UserCreateDTO {
@VerifyUsername
private String username;
@VerifyPassword
private String password;
}
对controller中接收的字段进行验证
一定要在接收类前加@Valid注解,自定义注解才生效
@PostMapping("/create")
public String createUser(@RequestBody @Valid UserCreateDTO userCreateDTO) {
// TODO
return "success";
}
参数检验失败后的异常处理
@RestControllerAdvice("com.example")
public class DefaultExceptionHandler {
/**
* 参数缺失异常处理
*/
@ExceptionHandler(MissingServletRequestParameterException.class)
public Response<?> handleMissingParameterException(MissingServletRequestParameterException e) {
return createFailureResponse("缺少参数: " + e.getParameterName());
}
/**
* 参数验证失败时的响应
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Response<?> handleBindException(MethodArgumentNotValidException e) {
return createFailureResponse("参数校验失败:"
+ e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
}
/**
* 全局异常处理
*/
@ExceptionHandler(Exception.class)
public Response<?> handleAllException(Exception e) {
String msg = "服务器异常: " + e.getMessage();
return createFailureResponse(msg);
}
/**
* 创建请求失败时的响应
*/
private Response<Object> createFailureResponse(String errorMsg) {
Response<Object> response = new Response<>();
response.setVerboseMsg(errorMsg);
return response;
}
}