@Vaild注解使用及擴展
一、@Vaild注解介紹
使用@Vaild注解可以簡化入參的校驗,配合統一異常實現簡單快捷的入參校驗,具體使用參照以下
二、@Vaild具體使用
1、引入jar包
如果你是springboot項目,此依賴內已經引入,無需再次引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
如果沒有,將依賴jar包引入到自己的項目中,maven依賴如下
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.3.5.Final</version>
</dependency>
2、在入參請求類中添加限制注解
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserReq implements Serializable {
private Integer id;
@NotBlank(message = "用戶名不能為空")
@Length(message = "用戶名最大為{max}個字符", max = 20)
private String username;
@NotBlank(message = "密碼不能為空")
@Length(message = "密碼長度限制為{min}-{max}", min = 8, max = 16)
private String password;
@NotNull(message = "性別不能為空")
private Byte sex;
@Range(message = "年齡范圍為{min}-{max}", min = 0, max = 120)
private Integer age;
}
3、控制器中使用@Vaild
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@Slf4j
@RestController
@RequestMapping("/user/post")
public class PostController {
@PostMapping("/create")
public String createUser(@Valid @RequestBody UserReq req){
log.info(JSON.toJSONString(req));
return "成功";
}
}
4、請求進行測試


雖然攔截成功,但錯誤出參不知道所以然,一頭霧水,需進行優化
三、優化出參
1、修改控制器
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@Slf4j
@RestController
@RequestMapping("/user/post")
public class PostController {
@PostMapping("/create")
public String createUser(@Valid @RequestBody UserReq req, BindingResult result){
// 如果發生錯誤,則返回第一個錯誤信息,這里也可以自定義返回信息
if(result.hasErrors()){
String message = result.getAllErrors().get(0).getDefaultMessage();
log.error(message);
return message;
}
log.info(JSON.toJSONString(req));
return "成功";
}
}
2、請求進行測試

四、使用統一異常
1、創建統一異常捕獲類
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@Slf4j
@ControllerAdvice
public class MyExceptionHandler {
@ResponseBody
@ExceptionHandler(Exception.class)
public ResultData exceptionHandler(Exception exception){
log.error("統一異常", exception);
// 捕獲對應異常進行處理,默認返回第一個錯誤信息,這里也可以自定義返回信息
if(exception instanceof MethodArgumentNotValidException){
MethodArgumentNotValidException ex = (MethodArgumentNotValidException) exception;
String message = ex.getBindingResult().getAllErrors().get(0).getDefaultMessage();
return ResultData.getFailResult(message);
}
return ResultData.getFailResult("服務器繁忙,請稍后再試!");
}
}
2、此時控制器不需要做額外處理
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@Slf4j
@RestController
@RequestMapping("/user/post")
public class PostController {
@PostMapping("/create")
public String createUser(@Valid @RequestBody UserReq req){
log.info(JSON.toJSONString(req));
return "成功";
}
}
3、請求進行測試


五、驗證注解
1、官方的驗證注解
| 驗證注解 | 說明 |
|---|---|
| @Null | 只能為null |
| @NotNull | 不能為null |
| @NotEmpty | 不為null、不能為空字符串(字符串長度不為0、集合大小不為0) |
| @NotBlank | 不為null、不能為空字符串,不同於@NotEmpty,@NotBlank會去掉空格再判斷 |
| @AssertFalse | 必須為false |
| @AssertTrue | 必須為true |
| @DecimalMax(value) | 必須為一個不大於指定值的數字 |
| @DecimalMin(value) | 必須為一個不小於指定值的數字 |
| @Max(value) | 必須為一個不大於指定值的數字 |
| @Min(value) | 必須為一個不小於指定值的數字 |
| @Digits(integer,fraction) | 必須為一個小數,且整數部分的位數不能超過integer,小數部分的位數不能超過fraction |
| @Future | 必須是一個將來的日期 |
| @Past | 必須是一個過去的日期 |
| @Pattern(value) | 必須符合指定的正則表達式 |
| @Length(max,min) | 字符長度必須在min到max之間 |
| 驗證注解的元素值是Email |
2、自定義驗證注解
1)定義注解
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Constraint(validatedBy = {SexConstraintValidator.class})
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SexConstraint {
String message() default "性別有誤,請確認";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
2)定義校驗器
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class SexConstraintValidator implements ConstraintValidator<SexConstraint, Byte> {
@Override
public void initialize(SexConstraint sexConstraint) {
System.out.println("初始化信息");
}
@Override
public boolean isValid(Byte sex, ConstraintValidatorContext constraintValidatorContext) {
if(sex==null)
return false;
if(sex!=0 && sex!=1 && sex!=2)
return false;
return true;
}
}
3)使用注解
import com.banmoon.lol.config.annotation.SexConstraint;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.Range;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserReq implements Serializable {
private Integer id;
@NotBlank(message = "用戶名不能為空")
@Length(message = "用戶名最大為{max}個字符", max = 20)
private String username;
@NotBlank(message = "密碼不能為空")
@Length(message = "密碼長度限制為{min}-{max}", min = 8, max = 16)
private String password;
@SexConstraint
private Byte sex;
@Range(message = "年齡范圍為{min}-{max}", min = 0, max = 120)
private Integer age;
}
4)請求進行測試


