在任什麼時候候,當你要處理一個應用程序的業務邏輯,數據校驗是你必需要考慮和麪對的事情。應用程序必須經過某種手段來確保輸入進來的數據從語義上來說是正確的。java
在一般的狀況下,應用程序是分層的,不一樣的層由不一樣的開發人員來完成。git
不少時候一樣的數據驗證邏輯會出如今不一樣的層,這樣就會致使代碼冗餘和一些管理的問題,好比說語義的一致性等。正則表達式
爲了不這樣的狀況發生,最好是將驗證邏輯與相應的域模型進行綁定。spring
因而 JSR 303 - Bean Validation
應運而生。api
在Maven的pom.xml
中引入validation-api
bash
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
複製代碼
validation-api
的一個很好的補充來源於hibernate
,雖然hibernate
已經遠去,可是其留存下來了不少精髓。app
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
複製代碼
@Null 被註釋的元素必須爲 null
@NotNull 被註釋的元素必須不爲 null
@AssertTrue 被註釋的元素必須爲 true
@AssertFalse 被註釋的元素必須爲 false
@Min(value) 被註釋的元素必須是一個數字,其值必須大於等於指定的最小值
@Max(value) 被註釋的元素必須是一個數字,其值必須小於等於指定的最大值
@DecimalMin(value) 被註釋的元素必須是一個數字,其值必須大於等於指定的最小值
@DecimalMax(value) 被註釋的元素必須是一個數字,其值必須小於等於指定的最大值
@Size(max, min) 被註釋的元素的大小必須在指定的範圍內
@Digits (integer, fraction) 被註釋的元素必須是一個數字,其值必須在可接受的範圍內
@Past 被註釋的元素必須是一個過去的日期
@Future 被註釋的元素必須是一個未來的日期
@Pattern(value) 被註釋的元素必須符合指定的正則表達式
複製代碼
@Email 被註釋的元素必須是電子郵箱地址
@Length 被註釋的字符串的大小必須在指定的範圍內
@NotEmpty 被註釋的字符串的必須非空
@Range 被註釋的元素必須在合適的範圍內
複製代碼
經過實現ConstraintValidator
能夠自定義參數註解。ide
@Target( {
METHOD,
FIELD,
ANNOTATION_TYPE,
CONSTRUCTOR,
PARAMETER
})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {MobileValidator.class})
public @interface Mobile {
String regexp() default "";
String message() default "手機號碼格式不正確";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
複製代碼
public class MobileValidator implements ConstraintValidator<Mobile, String> {
/** * 手機號的正則表達式. */
private static Pattern pattern = Pattern.compile(
"^0?(13[0-9]|14[0-9]|15[0-9]|16[0-9]|17[0-9]|18[0-9]|19[0-9])[0-9]{8}$");
@Override
public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
Matcher m = pattern.matcher(value);
return m.matches();
}
@Override
public void initialize(Mobile constraintAnnotation) {}
}
複製代碼
如此,咱們就能夠在Bean中使用註解@Mobile
了。ui
@Data
public class User {
@NotBlank
private String userName;
@Mobile
private String mobile;
}
複製代碼
@Configuration
public class ValidateConfig {
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor(){
return new MethodValidationPostProcessor();
}
}
複製代碼
@Valid
進行參數校驗@RequestMapping(value = "/book", method = RequestMethod.POST)
public void addBook(@RequestBody @Valid Book book) {
System.out.println(book.toString());
}
複製代碼
@Validated
進行參數校驗@RestController
@Validated
public class ValidateController {
// ...
}
複製代碼
針對參數異常BindException
進行全局異常攔截。spa
@ControllerAdvice
public class GlobalWebExceptionHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalWebExceptionHandler.class);
/** * 定義參數異常處理器. * * @param e 當前平臺異常參數對象. * @return org.springframework.http.ResponseEntity */
@ExceptionHandler(BindException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<Map<String, Object>> validateErrorHandler(BindException e) {
Map<String, Object> errorMap = new HashMap<>(2);
BindingResult bindingResult = e.getBindingResult();
if (bindingResult.hasErrors()) {
List<FieldError> errorList = bindingResult.getFieldErrors();
String errorMsg = "[字段:" + errorList.get(0).getField() + "]錯誤,緣由:" + errorList.get(0).getDefaultMessage();
errorMap.put("message", errorMsg);
errorMap.put("code", EnumError.PARAMS_ERROR.getCode());
return new ResponseEntity<>(errorMap, HttpStatus.BAD_REQUEST);
}
LOGGER.error("[服務] - [捕獲參數異常。異常信息:{}]", JSON.toJSONString(bindingResult));
return new ResponseEntity<>(errorMap, HttpStatus.BAD_REQUEST);
}
}
複製代碼