參數校驗在日常開發時是很常用的操作。爲了避免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的卑微碼農🐶,覺得好用記得點贊收藏!!!