1、首先創建兩個自定義校驗註解類
package com.example.demo.annotation;
import com.example.demo.interface2.CreateAction;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 自定義校驗註解
*/
@Constraint(validatedBy = {Name.NameUtil.class})
@Documented
@Retention(RUNTIME)
@Target({ElementType.ANNOTATION_TYPE, METHOD, ElementType.FIELD})
public @interface Name {
// 真坑,以下三個參數的名稱必須爲這三個,不能爲其他
String message() default "姓名必須爲小黑";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Documented
@interface List{
Name [] value();
}
class NameUtil implements ConstraintValidator<Name,String>, CreateAction {
@Override
public void initialize(Name constraintAnnotation) {
// TODO 可以用以初始化數據
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
if("小黑".equals(s)){
return true;
}else{
return false;
}
}
}
}
package com.example.demo.annotation;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.*;
/**
* 自定義校驗註解
*/
@Constraint(validatedBy = {Sex.SexUtil.class})
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
public @interface Sex {
// 真坑,以下三個參數的名稱必須爲這三個,不能爲其他
String message() default "性別必須爲女";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
class SexUtil implements ConstraintValidator<Sex, Object> {
@Override
public void initialize(Sex constraintAnnotation) {
// TODO 可以用以初始化數據
}
@Override
public boolean isValid(Object s, ConstraintValidatorContext constraintValidatorContext) {
// System.out.println(s.toString());
// System.out.println(s.getClass().getName());
if("女".equals(s)){
return true;
}else{
return false;
}
}
}
}
package com.example.demo.entity;
import com.example.demo.annotation.Name;
import com.example.demo.annotation.Sex;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Sex(message = "性別必須爲女2")
public class E {
private int id;
@Name(message = "姓名必須爲小黑2")
@NotNull
private String name;
private String age;
@NotNull
private String sex;
}
2、校驗註解的使用
1>、controller中的使用
@RequestMapping(value = "/pAnnotation",method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
@ApiOperation(value = "測試自定義校驗註解controller層")
public void pAnnotation(@Valid E e ,BindingResult bindingResult){
p1.pAnnotation(e,bindingResult);
}
public void pAnnotation(E e , BindingResult bindingResult) {
if (bindingResult.hasErrors()){
bindingResult.getAllErrors().forEach(s-> {
System.out.println(s.getDefaultMessage());
});
}else{
System.out.println("沒有報錯");
}
}
2>、方法中觸發註解
package com.example.demo.util;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;
@Component
public class AnnotationCheck<T> {
private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
public void checkAnnotation(T t){
//執行驗證
Set<ConstraintViolation<T>> constraintViolations = validator.validate(t);
//打印校驗信息
if (!CollectionUtils.isEmpty(constraintViolations)) {
for (ConstraintViolation<T> constraintViolation : constraintViolations) {
System.out.println(constraintViolation.getPropertyPath().toString() + ": " + constraintViolation.getMessage());
}
}
}
}
調用:
annotationCheck.checkAnnotation(e);
3>分組的使用
定義兩個空接口,分別代表E對象的增加校驗規則和修改校驗規則
/**
* 可以在一個Model上面添加多套參數驗證規則,此接口定義添加Person模型新增時的參數校驗規則
*/
public interface CreateAction {
}
/**
* 可以在一個Model上面添加多套參數驗證規則,此接口定義添加Person模型修改時的參數校驗規則
*/
public interface UpdateAction {
}
修改實體中的註解
package com.example.demo.entity;
import com.example.demo.annotation.Name;
import com.example.demo.annotation.Sex;
import com.example.demo.interface2.CreateAction;
import com.example.demo.interface2.UpdateAction;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Sex(message = "性別必須爲女2")
public class E {
private int id;
@Name.List({
@Name(groups = CreateAction.class ,message = "創建時姓名必須爲小黑2"),
@Name(groups = UpdateAction.class ,message = "修改時姓名必須爲小黑2")
})
@NotNull
private String name;
private String age;
@NotNull
private String sex;
}
使用:
@RequestMapping(value = "/pAnnotation3",method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
@ApiOperation(value = "測試自定義校驗註解-groups分組")
public void pAnnotation3( @Validated({CreateAction.class}) E e,BindingResult bindingResult){
if (bindingResult.hasErrors()){
bindingResult.getAllErrors().forEach(s-> {
System.out.println(s.getDefaultMessage());
});
}else{
System.out.println("沒有報錯");
}
}
結果
創建時姓名必須爲小黑2
此時只會對標註了‘CreateAction.classd的註解生效,
分組用在方法上---待實現
註解用在方法上
1、實例化MethodValidationPostProcessor
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
2、在所要實現方法參數校驗的類上面添加@Validated,如下
@RestController
@Validated
public class ValidateController {
}
3、在方法上面添加校驗規則:
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String paramCheck(@Length(min = 10) @RequestParam String name) {
System.out.println(name);
return null;
}
當方法上面的參數校驗失敗,spring 框架就回拋出異常
{
"timestamp": "2020-05-07T11:51:00.141+0000",
"status": 500,
"error": "Internal Server Error",
"message": "An Errors/BindingResult argument is expected to be declared immediately after the model attribute, the @RequestBody or the @RequestPart arguments to which they apply: public void com.example.demo.controller.PracticeController.pAnnotation4(java.lang.String,org.springframework.validation.BindingResult)",
"path": "/practice/pAnnotation4"
}
自定義註解是BindException錯誤,其他組件的註解是ConstraintViolationException
想辦法集中處理TODO
--TODO 待實現,使用攔截器攔截並返回業務錯誤---
@AssertFalse 驗證註解的元素值是false
@AssertTrue 驗證註解的元素值是true
@DecimalMax(value=x) 驗證註解的元素值小於等於@ DecimalMax指定的value值
@DecimalMin(value=x) 驗證註解的元素值小於等於@ DecimalMin指定的value值
@Digits(integer=整數位數, fraction=小數位數) 驗證註解的元素值的整數位數和小數位數上限
@Future 驗證註解的元素值(日期類型)比當前時間晚
@Max(value=x) 驗證註解的元素值小於等於@Max指定的value值
@Min(value=x) 驗證註解的元素值大於等於@Min指定的value值
@NotNull 驗證註解的元素值不是null
@Null 驗證註解的元素值是null
@Past 驗證註解的元素值(日期類型)比當前時間早
@Pattern(regex=正則表達式, flag=) 驗證註解的元素值與指定的正則表達式匹配
@Size(min=最小值, max=最大值) 驗證註解的元素值的在min和max(包含)指定區間之內,如字符長度、集合大小
@Valid 驗證關聯的對象,如賬戶對象裏有一個訂單對象,指定驗證訂單對象
@NotEmpty 驗證註解的元素值不爲null且不爲空(字符串長度不爲0、集合大小不爲0)
@Range(min=最小值, max=最大值) 驗證註解的元素值在最小值和最大值之間
@NotBlank 驗證註解的元素值不爲空(不爲null、去除首位空格後長度爲0),不同於@NotEmpty,@NotBlank只應用於字符串且在比較時會去除字符串的空格
@Length(min=下限, max=上限) 驗證註解的元素值長度在min和max區間內
@Email 驗證註解的元素值是Email,也可以通過正則表達式和flag指定自定義的email格式