使用自定義注解+springAop實(shí)現(xiàn)參數(shù)非空校驗(yàn)方式
自定義注解+springAop參數(shù)非空校驗(yàn)
自定義注解,來對對應(yīng)的方法進(jìn)行入?yún)⑿r?yàn),為空返回參數(shù)錯(cuò)誤
新建注解類@interface ParamsVerify
@Target(ElementType.METHOD)//枚舉,表示注解可能出現(xiàn)在的地方
@Retention(RetentionPolicy.RUNTIME)//運(yùn)行時(shí)保留注解
@Documented//生成api文檔時(shí)會看到此注解,可加可不加
public @Interface ParamsVerify(){
//注解類修飾符必須是public 如果不寫會默認(rèn)public
String[] params() default "";//傳入方法的參數(shù)
}
利用springAop來實(shí)現(xiàn)切面
利用springAop,我們可以把除業(yè)務(wù)核心代碼以外的,需要重復(fù)進(jìn)行的操作來統(tǒng)一處理,例如打印日志,參數(shù)校驗(yàn)等等,以切面的方式來進(jìn)行,一個(gè)切面,由切點(diǎn)、通知(增強(qiáng))來組成
增強(qiáng)就是對Aop管理的代碼來通過動態(tài)代理來添加額外的邏輯(代碼),動態(tài)代理有兩種實(shí)現(xiàn)方式,一種是通過jdk,一種是通過cglib,springboot中默認(rèn)是使用cglib來進(jìn)行動態(tài)代理的;而切點(diǎn)(ponitCut),是多個(gè)連接點(diǎn)組成的一個(gè)切點(diǎn),通常通過表達(dá)式來指向程序中一個(gè)定義的位置,來告知springAop啟動的范圍
//這個(gè)切點(diǎn)定義為使用該注解的方法都可以執(zhí)行該切面類里的通知
@Pointcut("@annotation(com.xy.utlis.annotations.TestA)")
新建一個(gè)切面類
通知方法執(zhí)行順序
環(huán)繞–前置—后置
@Aspect//聲明該類是一個(gè)切面類
@Component//聲明該類交由spring管理
public class testAImpl {
/** 定義切點(diǎn),使用該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í)行方法
}
}
寫一個(gè)接口來測試是否成功
@PostMapping("test")
@TestA(params={"name","age","sex"})//表明這三個(gè)參數(shù)是必填的
public void test(String name,String age,String sex){
System.out.println("ok");
}
發(fā)送post請求,只攜帶name

檢測到參數(shù)為null,打印錯(cuò)誤信息

這里可以自定義返回異常值或者其他處理了
帶上完整參數(shù)請求接口

成功放行

使用注解統(tǒng)一校驗(yàn)參數(shù)非空
可修改做工具類
代碼:
1. 待校驗(yàn)類
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. 校驗(yàn)
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ù)校驗(yàn)通過=========");
}
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校驗(yàn)失敗=========");
throw new IllegalArgumentException("[" + annotation.content() + "]為null");
}
if (getMethodResult instanceof String) {
if (StringUtils.isBlank(String.valueOf(getMethodResult))) {
System.out.println("==========非空校驗(yàn)失敗=========");
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ù)校驗(yàn)通過=========
name長度:2
==========長度小于指定范圍=========
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBootWeb?入門了解?Swagger?的具體使用
這篇文章主要介紹了SpringBootWeb?入門了解?Swagger?的具體使用,Swagger?框架可以根據(jù)已經(jīng)實(shí)現(xiàn)的方法或者類,通過頁面的方式直觀清晰的查看或者進(jìn)行測試該方法,需要的朋友可以參考下2024-08-08
SpringBoot配置使Mybatis打印SQL執(zhí)行時(shí)的實(shí)際參數(shù)值操作
這篇文章主要介紹了SpringBoot配置使Mybatis打印SQL執(zhí)行時(shí)的實(shí)際參數(shù)值操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
利用idea生成webservice客戶端超詳解步驟(wsdl文件的使用)
這篇文章主要給大家介紹了關(guān)于利用idea生成webservice客戶端超詳解步驟,第一次接觸webservice,從采坑到采坑,算是了解了一些,明白了一些,文中通過代碼以及圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
macOS上使用gperftools定位Java內(nèi)存泄漏問題及解決方案
這篇文章主要介紹了macOS上使用gperftools定位Java內(nèi)存泄漏問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
Intellij IDEA創(chuàng)建spring-boot項(xiàng)目的圖文教程
本文通過圖文并茂的形式給大家介紹了Intellij IDEA創(chuàng)建spring-boot項(xiàng)目的教程,本文給大家介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友參考下吧2018-01-01
Java實(shí)現(xiàn)一個(gè)小說采集程序的簡單實(shí)例
下面小編就為大家?guī)硪黄狫ava實(shí)現(xiàn)一個(gè)小說采集程序的簡單實(shí)例。小編覺得挺不錯(cuò)的, 現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06

