1. 程式人生 > >自定義註解+springAop實現引數的分組驗證

自定義註解+springAop實現引數的分組驗證

廢話:一個同事寫的,感覺很實用,然後我從中整理出來的一個小demo。

問題引入

在日常開發中免不了對傳入的引數進行校驗,例如更新資料的時候id不能為空,新增資料的時候某個元素不能為空等。我們不得不寫類似於下面的程式碼:

@RequestMapping("/createStudent")
    public Object createStudent( Student student) {
       String name = student.getName();
       if ( StringUtils.isEmpty( name ) ){
         return
"姓名不能為空"; } return student; } @RequestMapping("/updateStudent") public Object updateStudent( Student student) { String id = student.getId(); if ( StringUtils.isEmpty( id ) ){ return "id不能為空"; } return student; }

這樣確實有很多重複的程式碼,於是就想著去解決,我把問題簡化為下面的小demo,以供參考。

專案結構

這裡寫圖片描述

定義註解用於分組

@Target({ElementType.PARAMETER,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validate
{
    Class<?>[] groups() default { };
}

定義兩個組

public interface Create { }
public interface Update { }

具體邏輯實現(重點)

@Component // 加入到IoC容器
@Aspect // 指定當前類為切面類 public class Aop { @Autowired protected Validator validator; //@Pointcut("@annotation(springboot.Validate)") @Pointcut("execution(* springboot.*.*(..))") public void pointCut() { } @Around("pointCut()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); // 獲取當前方法 Parameter[] parameters = method.getParameters(); if (parameters != null && parameters.length > 0) { for (int j = 0; j < parameters.length; j++) { Parameter parameter = parameters[j]; Validate validate = parameter.getAnnotation(Validate.class);// 獲取引數的註解 if (validate != null) { Object arg = joinPoint.getArgs()[j];// 獲取到引數 Class<?>[] groups = validate.groups();// 獲取註解引數,驗證組 List<ViolationMessage> violationErrors =groups.length!=0?beanValidator(arg, groups):beanValidator(arg);// 引數有效性驗證 if (violationErrors != null) { return violationErrors;// 驗證不通過,返回結果 } } } } return joinPoint.proceed(); } public List<ViolationMessage> beanValidator(Object object, Class<?>... groups) { Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups); if (!constraintViolations.isEmpty()) { List<ViolationMessage> list = new ArrayList<>(); ViolationMessage vm = new ViolationMessage(); for (ConstraintViolation<Object> cv : constraintViolations) { vm = new ViolationMessage(); vm.setProperty(cv.getPropertyPath().toString()); vm.setMessage(cv.getMessageTemplate()); list.add(vm); } return list; } return null; } }

原理,利用aop獲取獲取註解上的分組資訊與當前引數,然後用validator進行校驗。

實體類

public class Student {
   @NotNull(message="id:不能為空",groups={Update.class})
    @Size(min = 3, max = 20, message = "id長度只能在3-20之間", groups = { Update.class})
    private String id;
    @NotNull(message = "姓名不能為空", groups = {Create.class})
    private String name;
    private String age;
    /**get set省略**/
}

錯誤資訊封裝

public class ViolationMessage implements Serializable{

    private static final long serialVersionUID = 1L;

    private String property;
    private String message;
    /**get set省略**/
    }

controller類

@RestController
public class TestController {
    @RequestMapping("/createChack")
    public Object createChack(@Validate(groups={Create.class}) Student student) {
        return student;
    }

    @RequestMapping("/updateChack")
    public Object updateChack(@Validate(groups={Update.class}) Student student) {
        return student;
    }

}

執行SpringbootFirstApplication啟動專案進行測試

具體專案見碼雲:

參考部落格: