spring 參數(shù)校驗

  • 概述

在日常應用中,存在大量需要針對輸入數(shù)據進行驗證的應用場景,例如字符串的大小,ip地址驗證,email格式驗證等等各類情況。
值得開心的是Spring Boot將這類場景進行了集成抽象,提供一個完整而且靈活的機制簡化開發(fā)者在進行相關操作時的重復工作量。

  • Maven引用

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

springboot需要引入spring-boot-starter-validation(使用Hibernate Validator 框架提供驗證功能) 依賴進行參數(shù)校驗,由于本項目中已經引入了spring-boot-starter-web 依賴(包含spring-boot-starter-validation依賴),就不需要重復引用了。

@Valid是使用Hibernate validation的時候使用
@Validated是只用Spring Validator校驗機制使用
說明:java的JSR303聲明了@Valid這類接口,而Hibernate-validator對其進行了實現(xiàn)
@Validation對@Valid進行了二次封裝,在使用上并沒有區(qū)別,但在分組、注解位置、嵌套驗證等功能上有所不同,這里主要就這幾種情況進行說明。

  • 基本注解介紹
@NotEmpty:作用在String、collection、map、數(shù)組上,不能為null,size > 0
@NotBlank: 只能用于String,不能為null,也不可以是" ",即trim()后長度大于0
@NotNull:作用于任何類型,不能為null,可以為空
@AssertTrue:必須為true
@AssertFalse:必須為false
@Min(value):必須為一個數(shù)字,且值大于等于指定的值
@Max(value):必須為一個數(shù)字,且值小于等于指定的值
@Size(max,min):限制參數(shù)大小范圍
@Future:必須是一個將來的日期
@Past:必須是一個過去的日期
@Pattern(value):指定正則
  • 注解的使用范圍
    @Validated:用在類型、方法和方法參數(shù)上。但不能用于成員屬性(field)
    代碼詳情
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {
    Class<?>[] value() default {};
}

@Valid:可以用在方法、構造函數(shù)、方法參數(shù)和成員屬性(field)上
代碼詳情

@Target({ METHOD, FIELD, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
public @interface Valid {
}

注意事項:

  • 在Spring MVC應用中,允許使用上述各類的@Valid 和@Validated注解去驗證@RequestParam和@PathVariable中定義的各類params。(兩個可以混用)但是使用@Validated來修飾整個類,表示其中方法需要在method這個級別使用validation邏輯進行驗證。
  • 嵌套校驗:一個待驗證的pojo類,其中還包含了待驗證的對象,需要在待驗證對象上注解@Valid,才能驗證待驗證對象中的成員屬性,這里不能使用@Validated。
    @Valid
    @NotNull(message = "任課老師不能為空")
    @Size(min = 1, message = "至少有一個老師")
    private List<TeacherBean> teacherBeans;
  • 基本使用
  1. 作用在參數(shù)上
@RestController
@Validated
public class xxxxController {
……
   @RequestMapping("/validationStudent")
    public Object validationStudent(@Validated @NotEmpty @Size(min = 2, max = 45,message = "xxxx") @RequestParam("name") String name,
                                    @RequestParam("sex") boolean sex,
                                    @Valid @Max(value = 100,message = "xxxx") @Min(value=0,message = "xxx") @RequestParam("age") int age,
                                    @Valid @NotEmpty @Length(min = 12, max = 12,message = "長度不合法") @RequestParam("stuno") String stuno)  {
        Student student = new Student();
        student.setAge(age);
        student.setName(name);
        student.setSex(sex);
        student.setStuno(stuno);
        return student;
    }

異常信息類似:javax.validation.ConstraintViolationException: validationStudent.name: 個數(shù)必須在2和45之間, validationStudent.stuno: 長度不合法

  1. 作用在jsonbean上

public class TeacherBean {
    @NotEmpty(message = "老師姓名不能為空")
    private String teacherName;
    @Min(value = 1, message = "學科類型從1開始計算")
    private int type;
}


public class StudentBean implements Serializable{
    @NotBlank(message = "用戶名不能為空")
    private String name;
    @Min(value = 18, message = "年齡不能小于18歲")
    private Integer age;
    @Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手機號格式錯誤")
    private String phoneNum;
    @Email(message = "郵箱格式錯誤")
    private String email;
    @MyConstraint
    private String className;
 
    @Valid
    @NotNull(message = "任課老師不能為空")
    @Size(min = 1, message = "至少有一個老師")
    private List<TeacherBean> teacherBeans;
}


@RestController
public class CheckController {
    @PostMapping("stu")
    public String addStu(@Valid  @RequestBody StudentBean studentBean){
        return "add student success";
    }
}

異常信息類似:
MethodArgumentNotValidException:xxxx
如果缺少@RequestBody 注解會報錯:BindException:xxx

3.統(tǒng)一的異常處理類來處理不同的錯誤:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public Object ExceptionHandler(Exception ex) {
        ex.printStackTrace();
        return "Exception: " + ex.getMessage();
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public Object ConstraintViolationExceptionHandler(ConstraintViolationException ex) {
        ex.printStackTrace();
        return "ConstraintViolationException: " + ex.getMessage();
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex) {
        ex.printStackTrace();
        return "MethodArgumentNotValidException: " + ex.getMessage();
    }

    @ExceptionHandler(BindException.class)
    public Object BindExceptionHandler(BindException ex) {
        ex.printStackTrace();
        return "BindException: " + ex.getMessage();
    }
}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容