自定義注解+springAop參數(shù)非空校驗
自定義注解,來對對應(yīng)的方法進行入?yún)⑿r灒瑸榭辗祷貐?shù)錯誤
新建注解類@interface ParamsVerify
@Target(ElementType.METHOD)//枚舉,表示注解可能出現(xiàn)在的地方 @Retention(RetentionPolicy.RUNTIME)//運行時保留注解 @Documented//生成api文檔時會看到此注解,可加可不加 public @Interface ParamsVerify(){ //注解類修飾符必須是public 如果不寫會默認(rèn)public String[] params() default "";//傳入方法的參數(shù) }
利用springAop來實現(xiàn)切面
利用springAop,我們可以把除業(yè)務(wù)核心代碼以外的,需要重復(fù)進行的操作來統(tǒng)一處理,例如打印日志,參數(shù)校驗等等,以切面的方式來進行,一個切面,由切點、通知(增強)來組成
增強就是對Aop管理的代碼來通過動態(tài)代理來添加額外的邏輯(代碼),動態(tài)代理有兩種實現(xiàn)方式,一種是通過jdk,一種是通過cglib,springboot中默認(rèn)是使用cglib來進行動態(tài)代理的;而切點(ponitCut),是多個連接點組成的一個切點,通常通過表達(dá)式來指向程序中一個定義的位置,來告知springAop啟動的范圍
//這個切點定義為使用該注解的方法都可以執(zhí)行該切面類里的通知 @Pointcut("@annotation(com.xy.utlis.annotations.TestA)")
新建一個切面類
通知方法執(zhí)行順序
環(huán)繞C前置―后置
@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(); //獲取當(dāng)前注解下的方法 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); //根據(jù)當(dāng)前方法獲取注解 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)繞方法結(jié)束執(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ù)請求接口
成功放行
使用注解統(tǒng)一校驗參數(shù)非空
可修改做工具類
代碼:
1. 待校驗類
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; } }
2. 注解類
@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; }
3. 校驗
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 + "]長度不夠"); } } } } }
結(jié)果參考:
name長度:2
==========參數(shù)校驗通過=========
name長度:2
==========長度小于指定范圍=========
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://blog.csdn.net/DRNB666/article/details/110454228