最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

springboot如何通過(guò)自定義注解對(duì)方法參數(shù)進(jìn)行攔截驗(yàn)證

 更新時(shí)間:2025年04月27日 16:46:39   作者:藍(lán)眸少年CY  
這篇文章主要介紹了springboot如何通過(guò)自定義注解對(duì)方法參數(shù)進(jìn)行攔截驗(yàn)證問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

springboot通過(guò)自定義注解對(duì)方法參數(shù)進(jìn)行攔截驗(yàn)證

元注解參數(shù)說(shuō)明

  • @Target 定義注解的作用目標(biāo),也就是可以定義注解具體作用在類上,方法上,還是變量上
  • @Retention 定義注解的保留策略
RetentionPolicy.SOURCE注解僅存在于源碼中在class字節(jié)碼文件中不包含
RetentionPolicy.CLASS默認(rèn)的保留策略注解會(huì)在class字節(jié)碼文件中存在但運(yùn)行時(shí)無(wú)法獲得;
RetentionPolicy.RUNTIME注解會(huì)在class字節(jié)碼文件中存在,在運(yùn)行時(shí)可以通過(guò)反射獲取到。
  • @Document 說(shuō)明該注解將被包含在javadoc中
  • @Inherited 說(shuō)明子類可以繼承父類中的該注解

@Target類型和說(shuō)明

類型說(shuō)明
ElementType.TYPE接口、類、枚舉、注解
ElementType.FIELD字段、枚舉的常量
ElementType.METHOD方法
ElementType.PARAMETER方法參數(shù)
ElementType.CONSTRUCTOR構(gòu)造函數(shù)
ElementType.LOCAL_VARIABLE局部變量
ElementType.ANNOTATION_TYPE注解
ElementType.PACKAGE

具體實(shí)現(xiàn):簡(jiǎn)單版

1、引入坐標(biāo)

<!-- 引入aop切面支持 -->
<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2、創(chuàng)建自定義注解

package com.hk.annotation;
 
import java.lang.annotation.*;
 
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ParamsIntercept {
  
}
  • @Target注解指定ElementType
  • @Inherited 說(shuō)明子類可以繼承父類中的該注解
  • @Retention注解指定RetentionPolicy

注意:

注解支持的元素類型除了上面的String之外還有以下:

  • 基本類型(int、char、byte、double、float、long、boolean)
  • 字符串String
  • 類Class
  • 枚舉enum
  • 注解Annotation
  • 上述類型的數(shù)組類型

當(dāng)使用其他類型修飾注解元素時(shí),編譯期會(huì)報(bào)錯(cuò)

Invalid type 'Integer' for annotation member

基本類型的包裝類型也是不允許在注解中修飾注解元素的;上述代碼中 subjectId 不能 定義為 Integer

3、創(chuàng)建切面進(jìn)行判斷

import com.alibaba.fastjson.JSONObject;
import com.bxm.adsmanager.model.dao.user.User;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
  
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
  
@Aspect
@Component
public class ParamsBeforeAspect {
  
    private static final Logger logger = Logger.getLogger(ParamsBeforeAspect .class);
  
    @Before("@annotation(com.hk.annotation.ParamsIntercept)")
    public void doBefore(JoinPoint point){
        try {
            long startTime = System.currentTimeMillis();//開始時(shí)間
            Method method = getMethod(point);
            if(null == method){
                if(logger.isWarnEnabled()){
                    logger.warn("method is null");
                }
                return;
            }            
 
            Object[] args = point.getArgs();//獲取請(qǐng)求參數(shù)
            
            if (ArrayUtils.isNotEmpty(args)) {
                for (Object arg : args) {
                   // 對(duì)參數(shù)進(jìn)行判斷
                }
            }
  
            long endTime = System.currentTimeMillis();//結(jié)束時(shí)間
            float excTime=(float)(endTime-startTime)/1000;
            logger.info("總耗時(shí):" + excTime+"s");
        }catch (Exception e){
            logger.error("記錄日志異常",e);
        }
    } 
 
    private Method getMethod(JoinPoint point) {
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        Class<?> targetClass = point.getTarget().getClass();
        try {
            return targetClass.getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
        } catch (NoSuchMethodException e) {
            return null;
        }
    }

4、controller使用

@Controller
@RequestMapping(value = "/")
public class UserManagerController {
    //1.傳入的是一個(gè)具體的值
	@ParamsIntercept
    @RequestMapping(value = "/getUser/{subjectId}")
    public R<String> getUserDetail(@PathVariable Integer subjectId) {
        try {
            //處理自己的業(yè)務(wù)
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(e.getMessage());
        }
        return R.error("操作失敗");
    }
   
}         

具體實(shí)現(xiàn):封裝版

1、引入坐標(biāo)

<!-- 引入aop切面支持 -->
<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2、創(chuàng)建自定義注解

package com.hk.annotation;
 
import java.lang.annotation.*;
 
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ParamsIntercept {
  String subjectId();
}

3、創(chuàng)建切面

package com.hk.aspect;
 
import com.warmer.base.enums.ReturnStatus;
import com.warmer.base.util.R;
import com.warmer.base.util.SpringUtils;
import com.warmer.base.util.StringUtil;
import com.warmer.web.annotation.AnnotationResolver;
import com.warmer.web.annotation.DomainOwner;
import com.warmer.web.entity.KgDomain;
import com.warmer.web.security.TokenService;
import com.warmer.web.service.KnowledgeGraphService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
 
import javax.servlet.http.HttpServletRequest;
import java.util.List;
 
@Aspect
@Component
public class DomainValidAspect {
 
    @Pointcut("@annotation(com.hk.annotation.ParamsIntercept)")
    public void annotationPointCut() {
 
    }
 
    @Before("annotationPointCut()")
    public void doBefore(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 獲取方法注解
        ParamsIntercept paramsIntercept = signature.getMethod().getAnnotation(ParamsIntercept.class);
        // 獲取參數(shù)
        String subjectIdCode = paramsIntercept.subjectId();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        Integer memberId = (Integer) request.getAttribute("memberId");
        AnnotationResolver annotationResolver = AnnotationResolver.newInstance();
        Integer resolver = (Integer) annotationResolver.resolver(joinPoint, subjectIdCode);
        log.info("獲取請(qǐng)求參數(shù):subjectId:{}, memberId:{}", resolver, memberId);
        // 具體業(yè)務(wù)代碼
        .......
    }
}
 

4、封裝獲取參數(shù)工具

package com.hk.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * @description:
 * @author: HK
 * @since: 2024/9/25 15:16
 */
public class AnnotationResolver {
    private static AnnotationResolver resolver ;
    public static AnnotationResolver newInstance(){
        if (resolver == null) {
            return resolver = new AnnotationResolver();
        }else{
            return resolver;
        }
    }
    
    public Object resolver(JoinPoint joinPoint, String str) {

        if (str == null) return null ;

        Object value = null;
        if (str.matches("#\\{\\D*\\}")) {
            String newStr = str.replaceAll("#\\{", "").replaceAll("\\}", "");
            if (newStr.contains(".")) { // 復(fù)雜類型
                try {
                    value = complexResolver(joinPoint, newStr);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                value = simpleResolver(joinPoint, newStr);
            }
        } else { //非變量
            value = str;
        }
        return value;
    }


    private Object complexResolver(JoinPoint joinPoint, String str) throws Exception {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        String[] names = methodSignature.getParameterNames();
        Object[] args = joinPoint.getArgs();
        String[] strs = str.split("\\.");

        for (int i = 0; i < names.length; i++) {
            if (strs[0].equals(names[i])) {
                Object obj = args[i];
                //這里處理出入?yún)?shù)為Map的邏輯
                if(obj instanceof Map){
                    Map item=(Map) obj;
                    return item.get(strs[1]);
                }
                Method dmethod = obj.getClass().getDeclaredMethod(getMethodName(strs[1]), null);
                Object value = dmethod.invoke(args[i]);
                return getValue(value, 1, strs);
            }
        }
        return null;
    }

    private Object getValue(Object obj, int index, String[] strs) {
        try {
            if (obj != null && index < strs.length - 1) {
                Method method = obj.getClass().getDeclaredMethod(getMethodName(strs[index + 1]), null);
                obj = method.invoke(obj);
                getValue(obj, index + 1, strs);
            }
            return obj;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private String getMethodName(String name) {
        return "get" + name.replaceFirst(name.substring(0, 1), name.substring(0, 1).toUpperCase());
    }
    private Object simpleResolver(JoinPoint joinPoint, String str) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        String[] names = methodSignature.getParameterNames();
        Object[] args = joinPoint.getArgs();

        for (int i = 0; i < names.length; i++) {
            if (str.equals(names[i])) {
                return args[i];
            }
        }
        return null;
    }

}

5、controller使用

@Controller
@RequestMapping(value = "/")
public class UserManagerController {
    //1.傳入的是一個(gè)具體的值
	@ParamsIntercept(subjectId= "#{userCode}")
    @RequestMapping(value = "/getUser/{subjectId}")
    public R<String> getUserDetail(@PathVariable Integer subjectId) {
        try {
            //處理自己的業(yè)務(wù)
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(e.getMessage());
        }
        return R.error("操作失敗");
    }
    //2.傳入的是一個(gè)對(duì)象
    @ParamsIntercept(subjectId= "#{userItem.subjectId}")
    
	//3.傳入的可能是一個(gè)map
 	@ParamsIntercept(subjectId= "#{params.subjectId}")
   
}         

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring Boot 中的任務(wù)執(zhí)行器基本概念及使用方法

    Spring Boot 中的任務(wù)執(zhí)行器基本概念及使用方法

    務(wù)執(zhí)行器是 Spring Boot 中的一個(gè)非常實(shí)用的模塊,它可以簡(jiǎn)化異步任務(wù)的開發(fā)和管理,在本文中,我們介紹了任務(wù)執(zhí)行器的基本概念和使用方法,以及一個(gè)完整的示例代碼,需要的朋友可以參考下
    2023-07-07
  • 郵件的組織結(jié)構(gòu)介紹 郵件實(shí)現(xiàn)詳解(三)

    郵件的組織結(jié)構(gòu)介紹 郵件實(shí)現(xiàn)詳解(三)

    這篇文章主要為大家詳細(xì)介紹了郵件的組織結(jié)構(gòu),郵件內(nèi)容的基本格式和具體細(xì)節(jié),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • 詳解Spring Data JPA中Repository的接口查詢方法

    詳解Spring Data JPA中Repository的接口查詢方法

    repository代理有兩種方式從方法名中派生出特定存儲(chǔ)查詢:通過(guò)直接從方法名派生查詢和通過(guò)使用一個(gè)手動(dòng)定義的查詢。本文將通過(guò)示例詳細(xì)講解Spring Data JPA中Repository的接口查詢方法,需要的可以參考一下
    2022-04-04
  • 深入理解Java垃圾回收機(jī)制以及內(nèi)存泄漏

    深入理解Java垃圾回收機(jī)制以及內(nèi)存泄漏

    下面小編就為大家?guī)?lái)一篇深入理解Java垃圾回收機(jī)制以及內(nèi)存泄漏。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給的大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-05-05
  • Spring事件監(jiān)聽源碼解析流程分析

    Spring事件監(jiān)聽源碼解析流程分析

    spring事件監(jiān)聽機(jī)制離不開容器IOC特性提供的支持,比如容器會(huì)自動(dòng)創(chuàng)建事件發(fā)布器,自動(dòng)識(shí)別用戶注冊(cè)的監(jiān)聽器并進(jìn)行管理,在特定的事件發(fā)布后會(huì)找到對(duì)應(yīng)的事件監(jiān)聽器并對(duì)其監(jiān)聽方法進(jìn)行回調(diào),這篇文章主要介紹了Spring事件監(jiān)聽源碼解析,需要的朋友可以參考下
    2023-08-08
  • Java8中的lambda表達(dá)式入門教程

    Java8中的lambda表達(dá)式入門教程

    lambda表達(dá)式,即帶有參數(shù)的表達(dá)式,為了更清晰地理解lambda表達(dá)式,下面通過(guò)示例代碼給大家介紹java8 lambda 表達(dá)式入門教程,感興趣的朋友一起看看吧
    2017-08-08
  • 帶你了解Java數(shù)據(jù)結(jié)構(gòu)和算法之哈希表

    帶你了解Java數(shù)據(jù)結(jié)構(gòu)和算法之哈希表

    這篇文章主要為大家介紹了Java數(shù)據(jù)結(jié)構(gòu)和算法之哈希表,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-01-01
  • 在Spring中使用JDBC和JDBC模板的講解

    在Spring中使用JDBC和JDBC模板的講解

    今天小編就為大家分享一篇關(guān)于在Spring中使用JDBC和JDBC模板的講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • Java的List集合框架之ArrayList詳解

    Java的List集合框架之ArrayList詳解

    這篇文章主要介紹了Java的List集合框架之ArrayList詳解,ArrayList默認(rèn)容量為10(構(gòu)造方法未指定初始容量為0),擴(kuò)容是利用位運(yùn)算(右移一位)和直接相加進(jìn)行1.5倍擴(kuò)容,需要的朋友可以參考下
    2023-11-11
  • Java多線程中Thread.currentThread()和this的區(qū)別詳解

    Java多線程中Thread.currentThread()和this的區(qū)別詳解

    這篇文章主要介紹了Java多線程中Thread.currentThread()和this的區(qū)別詳解,Thread.currentThread()方法返回的是對(duì)當(dāng)前正在執(zhí)行的線程對(duì)象的引用,this代表的是當(dāng)前調(diào)用它所在函數(shù)所屬的對(duì)象的引用,需要的朋友可以參考下
    2023-08-08

最新評(píng)論

连平县| 洛阳市| 乌恰县| 玉山县| 龙州县| 建水县| 海原县| 唐海县| 夏津县| 揭阳市| 天全县| 海阳市| 阿鲁科尔沁旗| 赞皇县| 卓尼县| 静海县| 六枝特区| 梁河县| 班戈县| 黄山市| 凤台县| 绥棱县| 洛浦县| 临海市| 德令哈市| 长沙县| 济阳县| 海原县| 淮南市| 贵州省| 锡林郭勒盟| 深水埗区| 齐河县| 根河市| 上犹县| 石柱| 都昌县| 和田县| 阿坝| 无锡市| 增城市|