一看就懂!三分鐘搞定Springboot+validation整合,輕鬆驗證用戶輸入

參數校驗在日常開發時是很常用的操作。爲了避免null指針、非法數據存入數據庫,我們通常要進行參數校驗。我們來看一個參數校驗的例子:

    @PostMapping("/save")
    public Object save(@RequestBody UserVO userVO) {
        String mobile = userVO.getMobile();

        //手動逐個 參數校驗~ 寫法
        if (StringUtils.isBlank(mobile)) {
            return R.bulid(ResultEnum.PARAM_FAIL_CODE,"mobile:手機號碼不能爲空");
        } else if (!Pattern.matches("^[1][3,4,5,6,7,8,9][0-9]{9}$", mobile)) {
            return R.bulid(ResultEnum.PARAM_FAIL_CODE,"mobile:手機號碼格式不對");
        }

        //拋出自定義異常等~寫法
        if (StringUtils.isBlank(userVO.getUsername())) {
            throw new ParamException(ResultEnum.PARAM_FAIL_CODE, "用戶名不能爲空");
        }

        // 比如寫一個map返回
        if (StringUtils.isBlank(userVO.getSex())) {
            Map<String, Object> result = new HashMap<>(5);
            result.put("code", Constant.PARAM_FAIL_CODE);
            result.put("msg", "性別不能爲空");
            return result;
        }
        //.........各種寫法 ...
        userService.save(userVO);
        return R.success();
    }

都0202年了,還這麼寫參數校驗?

validation相信大家都聽說過,Spring又怎麼會放過這個好東西。傳統的validation用起來還挺費勁,但是Springboot他來了~輕鬆幾步搞定參數校驗。

先上步驟

1.導包,只需要spring-boot-starter-validation和web即可

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.13.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>validation-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>validation-demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- validation  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <!-- web 測試 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.寫DTO

public class TestDTO {

    @NotNull(message = "姓名不能爲空")
    private String name;

    @NotNull(message = "年齡不能爲空")
    @Max(value = 120, message = "最大值不能大於120")
    @Min(value = 0, message = "最小值不能低於0")
    private Integer age;

    //get set省略
}

這裏給你們一份說明 

 

第三步:編寫Controller

@RestController
@RequestMapping("/test")
public class TestController {
    /**
     * 測試
     * `@Valid` 表示對這個對象校驗
     * `BindingResult` 獲取的是校驗的結果,這個對象有許多方法獲取校驗信息,可以自定義返回信息
     * 
     *
     * @param dto
     * @param bindingResult
     * @return
     */
    @PostMapping("/post")
    public Map<Object, Object> test(@Validated @RequestBody TestDTO dto, BindingResult bindingResult) {
        Map<Object, Object> res = new HashMap<>();
        if (bindingResult.hasErrors()) {
            res.put("status", 400);
            res.put("msg", bindingResult.getFieldError().getDefaultMessage());
            return res;
        } else {
            res.put("status", 200);
            res.put("msg", "ok");
            res.put("data", dto);
            return res;
        }

    }
}

 

好了,結束。測試一下,這裏使用IDEA插件RestfulToolkit測試。

所有強大的東西在於可以自定義,接下來我們看看如何自定義校驗註解。

這裏我們用比較常見的標誌位校驗需求來做示例

1.創建自定義註解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Constraint(validatedBy = FlagValidatorClass.class) // 綁定對應校驗器
public @interface FlagValidator {
    String[] value() default {};

    String message() default "flag is not found";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

2.編寫對應校驗器

/**
 * 標誌位校驗器
 */
public class FlagValidatorClass implements ConstraintValidator<FlagValidator, Integer> {
    private String[] values;

    /**
     * 初始化
     *
     * @param flagValidator 註解上設置的值
     */
    @Override
    public void initialize(FlagValidator flagValidator) {
        this.values = flagValidator.value();
    }

    /**
     * 校驗
     *
     * @param value  被校驗的值,即輸入
     * @param constraintValidatorContext 校驗上下文
     * @return 返回true證明校驗通過,false校驗失敗
     */
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) {
        boolean isValid = false;
        // 當value爲null,校驗失敗
        if (value == null) {
            return false;
        }
        //遍歷校驗
        for (int i = 0; i < values.length; i++) {
            if (values[i].equals(String.valueOf(value))) {
                isValid = true;
                break;
            }
        }
        return isValid;
    }
}

這樣子就完成了自定義參數校驗。當然了,我們可以在isValid方法中添加更加複雜的校驗邏輯,如正則匹配等方法,這裏就不展開了。

測試一下,先在DTO中添加flag屬性,標上註解。

    @NotNull(message = "標識位不能爲空")
    @FlagValidator(value = {"0", "1"}, message = "標誌位有誤")
    private Integer flag;

效果:

接着我們來看看BindResult有什麼內容。

我們輸出一下這個對象

   System.out.println(bindingResult);
// 成功時,這沒什麼好說的
org.springframework.validation.BeanPropertyBindingResult: 0 errors

// 失敗時
org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'testDTO' on field 'flag': rejected value [12]; 
codes [FlagValidator.testDTO.flag,FlagValidator.flag,FlagValidator.java.lang.Integer,FlagValidator]; 
arguments 
[org.springframework.context.support.DefaultMessageSourceResolvable: codes [testDTO.flag,flag]; 
arguments []; 
default message [flag],[Ljava.lang.String;@1017351]; 
default message [標誌位有誤]

我們可以看到一些屬性,Field、Default message、Rejected value。

我們可以通過他的方法獲取對應的值。

獲取Error,getFieldError默認返回第一個錯誤。getAllErrors返回錯誤列表。

獲取對應的屬性。 

構造我們自己的校驗返回內容。

通過Java8的stream方法我們可以簡單的獲取到報錯信息並返回前端;

   Object[] objects =  bindingResult.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).toArray();

 

 

這次Springboot+validation整合就講到這裏。

代碼比較簡單,源碼就不奉上來,有需要的可以私信我。

 


有什麼問題可以評論或者私信我,每日在線解(LIAO)疑(SAO)。

我是大誌,一位準備996的卑微碼農🐶,覺得好用記得點贊收藏!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章