您好,登錄后才能下訂單哦!
這篇文章主要講解了“如何使用自定義注解+springAop實現(xiàn)參數(shù)非空校驗”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何使用自定義注解+springAop實現(xiàn)參數(shù)非空校驗”吧!
自定義注解+springAop參數(shù)非空校驗
新建注解類@interface ParamsVerify
利用springAop來實現(xiàn)切面
新建一個切面類
使用注解統(tǒng)一校驗參數(shù)非空
1. 待校驗類
2. 注解類
3. 校驗
自定義注解,來對對應的方法進行入參校驗,為空返回參數(shù)錯誤
@Target(ElementType.METHOD)//枚舉,表示注解可能出現(xiàn)在的地方 @Retention(RetentionPolicy.RUNTIME)//運行時保留注解 @Documented//生成api文檔時會看到此注解,可加可不加 public @Interface ParamsVerify(){ //注解類修飾符必須是public 如果不寫會默認public String[] params() default "";//傳入方法的參數(shù) }
利用springAop,我們可以把除業(yè)務核心代碼以外的,需要重復進行的操作來統(tǒng)一處理,例如打印日志,參數(shù)校驗等等,以切面的方式來進行,一個切面,由切點、通知(增強)來組成
增強就是對Aop管理的代碼來通過動態(tài)代理來添加額外的邏輯(代碼),動態(tài)代理有兩種實現(xiàn)方式,一種是通過jdk,一種是通過cglib,springboot中默認是使用cglib來進行動態(tài)代理的;而切點(ponitCut),是多個連接點組成的一個切點,通常通過表達式來指向程序中一個定義的位置,來告知springAop啟動的范圍
//這個切點定義為使用該注解的方法都可以執(zhí)行該切面類里的通知 @Pointcut("@annotation(com.xy.utlis.annotations.TestA)")
通知方法執(zhí)行順序
環(huán)繞–前置—后置
@Aspect//聲明該類是一個切面類 @Component//聲明該類交由spring管理 public class testAImpl { /** 定義切點,使用該TestA注解的方法 */ @Pointcut("@annotation(com.xy.utlis.annotations.TestA)") public void addAdvice(){ } @Aroud("addAdvice")//環(huán)繞通知 另外還有@Before @After public Object test(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("環(huán)繞方法開始執(zhí)行...."); //獲取所有參數(shù)名 String[] parameterNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames(); //獲取所有參數(shù)值 Object[] args = joinPoint.getArgs(); //獲取當前注解下的方法 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); //根據(jù)當前方法獲取注解 TestA annotation = signature.getMethod().getAnnotation(TestA.class); String[] names = annotation.params();//獲得注解參數(shù) Map<String, Object> params = params(joinPoint); for (String name : names) { Object o = params.get(name); if(null==o||"".equals(o)){ System.err.println(MessageFormat.format("參數(shù)名為{0}的值為null",name)); return false; } } System.out.println("環(huán)繞方法結束執(zhí)行...."); return joinPoint.proceed();//繼續(xù)正常執(zhí)行方法 } }
寫一個接口來測試是否成功
@PostMapping("test") @TestA(params={"name","age","sex"})//表明這三個參數(shù)是必填的 public void test(String name,String age,String sex){ System.out.println("ok"); }
發(fā)送post請求,只攜帶name
檢測到參數(shù)為null,打印錯誤信息
這里可以自定義返回異常值或者其他處理了
帶上完整參數(shù)請求接口
成功放行
可修改做工具類
代碼:
public class User { @NonNull(content = "姓名不能為空", minLen = 2, maxLen = 100) private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
@Documented @Target(value = ElementType.FIELD) @Retention(value = RetentionPolicy.RUNTIME) public @interface NonNull { String name() default ""; String content() default ""; int maxLen() default 50; int minLen() default 1; }
public void test() { User user = new User(); user.setName("老王"); try { valid(user); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } private <T> void valid(T user) throws IllegalAccessException, InvocationTargetException { Class<?> clazz = user.getClass(); Field[] declaredFields = clazz.getDeclaredFields(); Method[] methods = clazz.getMethods(); for (Field field : declaredFields) { validParams(user, methods, field); } System.out.println("==========參數(shù)校驗通過========="); } private <T> void validParams(T user, Method[] methods, Field field) throws IllegalAccessException, InvocationTargetException { NonNull annotation = field.getAnnotation(NonNull.class); String fieldName; if (StringUtils.isNotBlank(annotation.name())) { fieldName = annotation.name(); } else { fieldName = field.getName(); } for (Method method : methods) { if (("get" + fieldName).toLowerCase().equals(method.getName().toLowerCase())) { Object getMethodResult = method.invoke(user, null); if (getMethodResult == null) { System.out.println("==========非Null校驗失敗========="); throw new IllegalArgumentException("[" + annotation.content() + "]為null"); } if (getMethodResult instanceof String) { if (StringUtils.isBlank(String.valueOf(getMethodResult))) { System.out.println("==========非空校驗失敗========="); throw new IllegalArgumentException("[" + annotation.content() + "]為空"); } System.out.println(fieldName + "長度:" + String.valueOf(getMethodResult).length()); if (String.valueOf(getMethodResult).length() > annotation.maxLen()) { System.out.println("==========長度超出指定范圍========="); throw new IllegalArgumentException("[" + fieldName + "]長度超出"); } if (String.valueOf(getMethodResult).length() < annotation.minLen()) { System.out.println("==========長度小于指定范圍========="); throw new IllegalArgumentException("[" + fieldName + "]長度不夠"); } } } } }
結果參考:
name長度:2
==========參數(shù)校驗通過=========
name長度:2
==========長度小于指定范圍=========
感謝各位的閱讀,以上就是“如何使用自定義注解+springAop實現(xiàn)參數(shù)非空校驗”的內容了,經過本文的學習后,相信大家對如何使用自定義注解+springAop實現(xiàn)參數(shù)非空校驗這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。