可以說幾乎所有的應用場景中填帽,參數(shù)驗證都在編寫業(yè)務邏輯前完成,嚴格確保進來的數(shù)據(jù)是合法且符合要求的。
Java Web 開發(fā)領(lǐng)域沥邻,也早有較為完善的 Bean Validation 為 Java Bean 驗證定義了相應的元數(shù)據(jù)模型和 API平项。首先赫舒,在項目中引入 web 模塊的依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Hibernate Validator 是 Bean Validation 的一種實現(xiàn) . Hibernate Validator 提供了 JSR 303 規(guī)范中所有內(nèi)置 constraint 的實現(xiàn),以及一些附加的 constraint闽瓢。如果想了解更多請查看 http://www.hibernate.org/subprojects/validator.html
具體以及常用的 constraint 包含如下:
@Data
public class Validate {
// 空和非空檢查: @Null接癌、@NotNull、@NotBlank扣讼、@NotEmpty
@Null(message = "驗證是否為 null")
private Integer isNull;
@NotNull(message = "驗證是否不為 null, 但無法查檢長度為0的空字符串")
private Integer id;
@NotBlank(message = "檢查字符串是不是為 null缺猛,以及去除空格后長度是否大于0")
private String name;
@NotEmpty(message = "檢查是否為 NULL 或者是 EMPTY")
private List<String> stringList;
// Boolean值檢查: @AssertTrue、@AssertFalse
@AssertTrue(message = " 驗證 Boolean參數(shù)是否為 true")
private Boolean isTrue;
@AssertFalse(message = "驗證 Boolean 參數(shù)是否為 false ")
private Boolean isFalse;
// 長度檢查: @Size椭符、@Length
@Size(min = 1, max = 2, message = "驗證(Array,Collection,Map,String)長度是否在給定范圍內(nèi)")
private List<Integer> integerList;
@Length(min = 8, max = 30, message = "驗證字符串長度是否在給定范圍內(nèi)")
private String address;
// 日期檢查: @Future枯夜、@FutureOrPresent、@Past艰山、@PastOrPresent
@Future(message = "驗證日期是否在當前時間之后")
private Date futureDate;
@FutureOrPresent(message = "驗證日期是否為當前時間或之后")
private Date futureOrPresentDate;
@Past(message = "驗證日期是否在當前時間之前")
private Date pastDate;
@PastOrPresent(message = "驗證日期是否為當前時間或之前")
private Date pastOrPresentDate;
// 其它檢查: @Email湖雹、@CreditCardNumber、@URL曙搬、@Pattern摔吏、@ScriptAssert、@UniqueElements
@Email(message = "校驗是否為正確的郵箱格式")
private String email;
@CreditCardNumber(message = "校驗是否為正確的信用卡號")
private String creditCardNumber;
@URL(protocol = "http", host = "127.0.0.1", port = 8080, message = "校驗是否為正確的URL地址")
private String url;
@Pattern(regexp = "^1[3|4|5|7|8][0-9]{9}$", message = "正則校驗是否為正確的手機號")
private String phone;
// 對關(guān)聯(lián)對象元素進行遞歸校驗檢查
@Valid
@UniqueElements(message = "校驗集合中的元素是否唯一")
private List<CalendarEvent> calendarEvent;
@Data
@ScriptAssert(lang = "javascript", script = "_this.startDate.before(_this.endDate)",
message = "通過腳本表達式校驗參數(shù)")
private class CalendarEvent {
private Date startDate;
private Date endDate;
}
// 數(shù)值檢查: @Min纵装、@Max征讲、@Range、@DecimalMin橡娄、@DecimalMax诗箍、@Digits
@Min(value = 0, message = "驗證數(shù)值是否大于等于指定值")
@Max(value = 100, message = "驗證數(shù)值是否小于等于指定值")
@Range(min = 0, max = 100, message = "驗證數(shù)值是否在指定值區(qū)間范圍內(nèi)")
private Integer score;
@DecimalMin(value = "10.01", inclusive = false, message = "驗證數(shù)值是否大于等于指定值")
@DecimalMax(value = "199.99", message = "驗證數(shù)值是否小于等于指定值")
@Digits(integer = 3, fraction = 2, message = "限制整數(shù)位最多為3,小數(shù)位最多為2")
private BigDecimal money;
}
常見的前后端分離開發(fā)模式挽唉,數(shù)據(jù)通信通常以 JSON 為主滤祖。針對 POST 和 PUT 請求,一般通過新建域(對象)模型來進行數(shù)據(jù)綁定和校驗瓶籽,constraint 通常附加在這些域模型的字段上(如上):
/**
* Valid注解標明要對參數(shù)對象進行數(shù)據(jù)校驗
*/
@PutMapping
@PostMapping
public Map<String, Object> test01(@RequestBody @Valid Validate validate, BindingResult bindingResult) {
Map<String, Object> map = new HashMap<>(4);
if (bindingResult.hasErrors()) {
String errorMsg = bindingResult.getFieldErrors().stream().map(FieldError::getDefaultMessage)
.collect(Collectors.joining(","));
map.put("errorMsg", errorMsg);
}
map.put("params", validate.toString());
return map;
}
此外匠童,對于 GET 和 DELETE 請求,參數(shù)通常為 key1=value1&key2=value2
這種形式塑顺。默認情況下汤求,Hibernate Validator 只能對 Object 屬性進行校驗俏险,并不能對單個參數(shù)進行校驗,Spring 在此基礎上進行了擴展扬绪,通過配置 MethodValidationPostProcessor 處理器竖独,可以實現(xiàn)對方法參數(shù)的攔截校驗。
@Configuration
public class ValidateConfig {
/**
* 配置MethodValidationPostProcessor攔截器挤牛,以實現(xiàn)對方法參數(shù)的校驗
*/
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
注意莹痢,要在 Controller 類上明確標明 @Validated
:
@Validated
@RestController
@RequestMapping("validate")
public class ValidateController {
@GetMapping
@DeleteMapping
public Map<String, Object> test02(@NotNull(message = "id不能為空") @Range(min = 1, max = 100, message = "id最小為1最大為100") Integer id,
@NotBlank(message = "email不能為空") @Email(message = "郵箱格式錯誤") String email,
@ModelAttribute @Valid Validate validate) {
Map<String, Object> map = new HashMap<>(4);
map.put("id", id);
map.put("email", email);
map.put("params", validate.toString());
return map;
}
}
上述這種形式的參數(shù)要是校驗失敗,錯誤提示明顯并不友好赊颠,通過捕獲此類異常就可以解決格二,這里就不再介紹了劈彪。
參考鏈接
JSR 303 - Bean Validation 介紹及最佳實踐
SpringBoot-服務端參數(shù)驗證-JSR-303驗證框架
文章已授權(quán)轉(zhuǎn)載竣蹦,原文鏈接:Spring Boot 項目參數(shù)校驗的常見使用場景