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

Java增加自定義注解進(jìn)行校驗(yàn)入?yún)⒃斀?/h1>
 更新時(shí)間:2023年04月13日 09:46:45   作者:奔跑的毛球  
這篇文章主要為大家詳細(xì)介紹了Java如何通過(guò)增加自定義注解實(shí)現(xiàn)校驗(yàn)入?yún)⒐δ?,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下

背景

客戶使用我們系統(tǒng)的時(shí)候,查詢不帶任何查詢條件,查詢就返回全部數(shù)據(jù),500多萬(wàn)條數(shù)據(jù)啊,然后直接導(dǎo)出,數(shù)據(jù)量龐大,接口超時(shí),這可苦了我們這些開(kāi)發(fā)人員,一邊優(yōu)化,一邊挨噴。這么多數(shù)據(jù)就算導(dǎo)成功了,Excel也打不開(kāi)呀。迫不得已,決定強(qiáng)制讓客戶至少傳入一個(gè)參數(shù)進(jìn)行查詢來(lái)緩解服務(wù)器以及開(kāi)發(fā)人員的壓力。

首先想到的,最簡(jiǎn)單的,就是增加一個(gè)靜態(tài)方法,在每個(gè)方法入口調(diào)一下,來(lái)校驗(yàn)以及拋出錯(cuò)誤。但是轉(zhuǎn)念一想,更優(yōu)美的解決方案是在調(diào)用的方法上加一個(gè)注解,使用注解來(lái)完成這個(gè)功能,這豈不是很棒。

再一句話說(shuō)下需求:

增加注解對(duì)入?yún)⑦M(jìn)行校驗(yàn),保證至少有一個(gè)參數(shù)不為空,若是有時(shí)間參數(shù),則起始時(shí)間和結(jié)束時(shí)間之間的距離不能超過(guò)30天。

接下來(lái),Show Time

注解類(lèi)

這里有三個(gè)參數(shù),分別是三個(gè)參數(shù)名稱(chēng),起始時(shí)間參數(shù)名稱(chēng),結(jié)束時(shí)間參數(shù)名稱(chēng),需要校驗(yàn)的參數(shù)名稱(chēng)

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface VerifyParameters {
    /**
     * 起始時(shí)間參數(shù)名稱(chēng)
     */
    String startTimeParamName() default "startTime";
    /**
     * 結(jié)束時(shí)間參數(shù)名稱(chēng)
     */
    String endTimeParamName() default "endTime";

    /**
     * 需要校驗(yàn)的參數(shù)名稱(chēng)
     */
    String paramName() default "";
}

注解的Aspect類(lèi)

這里貼一個(gè)完整的,目的是有的小伙伴想用的話,貼過(guò)去就能用。

@Component
@Aspect
public class VerifyParametersAspect {

    private static final Logger logger = LoggerFactory.getLogger(VerifyParametersAspect.class);

    /**
     * 切點(diǎn)
     */
    @Pointcut("@annotation(com.guava.mall.app.annotation.VerifyParameters)")
    public void serviceAspect() {
    }


    /**
     * service 方法前調(diào)用
     *
     * @param joinPoint
     */
    @Before("serviceAspect()")
    public void doBeforeService(JoinPoint joinPoint) {
        try {

            //獲取方法參數(shù)名
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            //獲取方法
            Method method = signature.getMethod();
            //獲取參數(shù)名
            LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
            String[] parameterNames = u.getParameterNames(method);
            Map<String, Object> params = new HashMap<>(8);
            params = getParamMap(joinPoint, method, parameterNames, params);
            //獲取注解
            VerifyParameters verifyParameters = method.getAnnotation(VerifyParameters.class);

            //參數(shù)名
            String paramName = verifyParameters.paramName();
            Object o = params.get(paramName);
            ValidationUtils.validate(o == null, "參數(shù)不能為空");
            ValidationUtils.validate(!atLeastOnePropertyNotNull(o), "請(qǐng)至少輸入一個(gè)查詢條件進(jìn)行查詢和導(dǎo)出");
            //開(kāi)始時(shí)間和結(jié)束時(shí)間的參數(shù)名
            String s = verifyParameters.startTimeParamName();
            String e = verifyParameters.endTimeParamName();
            Map<?, ?> map = JSONUtils.bean2Map(o);
            Object startTime = map.get(s);
            Object endTime = map.get(e);
            if (startTime != null || endTime != null) {
                ValidationUtils.validate(startTime == null || endTime == null, "開(kāi)始時(shí)間和結(jié)束時(shí)間必須同時(shí)存在");
                ValidationUtils.validate(Integer.parseInt(String.valueOf(endTime)) - Integer.parseInt(String.valueOf(startTime)) > 30 * 24 * 60 * 60, "時(shí)間間隔不能超過(guò)一個(gè)月");
            }
        } catch (NumberFormatException ex) {
            logger.error(ex.getMessage(), ex);
        }

    }

    private Map<String, Object> getParamMap(JoinPoint joinPoint, Method method, String[] parameterNames, Map<String, Object> params) {

        int i = 0;
        if (parameterNames != null && parameterNames.length > 0) {
            for (String parameterName : parameterNames) {
                params.put(parameterName, joinPoint.getArgs()[i]);
                i++;
            }
        }
        return params;
    }

    public static boolean atLeastOnePropertyNotNull(Object obj) {
        for (Field field : obj.getClass().getDeclaredFields()) {
            //忽略serialVersionUID
            if ("serialVersionUID".equals(field.getName())) {
                continue;
            }
            field.setAccessible(true);
            try {
                if (field.get(obj) != null && !field.get(obj).toString().isEmpty()) {
                    return true;
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return false;
    }
    /**
     * 方法后調(diào)用
     */
    @After("serviceAspect()")
    public void doAfterInService(JoinPoint joinPoint) {
    }

}

然后,解釋一下

MethodSignature signature = (MethodSignature) joinPoint.getSignature();

這是我們的第一行代碼,這里的joinPoint對(duì)象表示應(yīng)用建議的程序執(zhí)行點(diǎn),getSignature()方法則會(huì)返回正在執(zhí)行的方法的方法簽名,簽名里就包含了該方法名稱(chēng)、返回類(lèi)型參數(shù)類(lèi)型。然后再?gòu)?qiáng)制轉(zhuǎn)換成MethodSignature對(duì)象,便于訪問(wèn)方法相關(guān)的信息。

MethodSignature是一個(gè)對(duì)象,它表示正在執(zhí)行的方法的簽名,包括方法名稱(chēng)、返回類(lèi)型和參數(shù)類(lèi)型。它是Spring AOP框架中的一個(gè)類(lèi),用于在切面中獲取方法的信息。

Method method = signature.getMethod();獲取方法

這個(gè)則是從MethodSignature中獲取到了正在執(zhí)行的方法信息。

LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();

LocalVariableTableParameterNameDiscoverer是一個(gè)類(lèi),它可以用于在運(yùn)行時(shí)獲取方法參數(shù)的名稱(chēng)。它是Spring框架中的一個(gè)類(lèi),通常與反射一起使用,以便在運(yùn)行時(shí)獲取有關(guān)方法參數(shù)的信息。

通過(guò) String[] parameterNames = u.getParameterNames(method); 可以獲取到目前方法的入?yún)⒚Q(chēng)。

getParamMap(); 方法則會(huì)返回一個(gè)key是參數(shù)名稱(chēng),value是參數(shù)本身的map對(duì)象。 我們可以從中取出我們需要的那個(gè)參數(shù)對(duì)象。

VerifyParameters verifyParameters = method.getAnnotation(VerifyParameters.class);

上邊這行代碼則會(huì)獲取到方法上注解的注解對(duì)象本身,和我們傳入的參數(shù)值,因?yàn)槊總€(gè)方法的入?yún)⒉槐M相同,里邊時(shí)間的字段也不盡相同,需要主動(dòng)傳入來(lái)做處理。

這里再解釋下atLeastOnePropertyNotNull()方法,這個(gè)方法的作用是判斷參數(shù)內(nèi)的屬性是否至少有一個(gè)不為空,這里我們忽略了serialVersionUID

serialVersionUID是Java中的一個(gè)序列化機(jī)制,用于在反序列化期間驗(yàn)證發(fā)送方和接收方的對(duì)象是否具有兼容的序列化版本。如果發(fā)送方和接收方的serialVersionUID不同,則反序列化將失敗。如果未指定serialVersionUID,則Java運(yùn)行時(shí)將根據(jù)類(lèi)的特定方面自動(dòng)生成它。

之后的方法就很簡(jiǎn)單了,拿出值根據(jù)我們的需要做處理即可

controller

再看看是如何使用的吧,添加@VerifyParameters注解,傳入時(shí)間的屬性名稱(chēng),和需要校驗(yàn)的參數(shù)名稱(chēng),這里傳入?yún)?shù)名稱(chēng)的原因是,可能和我這里一樣還有其他的參數(shù)影響,而我們只想校驗(yàn)我們需要的參數(shù)。

@ApiOperation(value = "查詢列表")
@GetMapping("/test")
@VerifyParameters(startTimeParamName = "beginTime", endTimeParamName = "endTime",paramName = "orderRequest")
public Page<Map<String, Object>> findOrderTestList(Pageable pageable, ERPOrderRequest orderRequest) {
    log.info("模擬邏輯處理");
    return null;
}

這樣我們就實(shí)現(xiàn)了通過(guò)一個(gè)自定義注解對(duì)方法的入?yún)⑦M(jìn)行了校驗(yàn),在取到入?yún)⒑头椒ǖ母鱾€(gè)值之后,我們其實(shí)可以做各種各樣的操作,各位小伙伴可以任意發(fā)揮。

到此這篇關(guān)于Java增加自定義注解進(jìn)行校驗(yàn)入?yún)⒃斀獾奈恼戮徒榻B到這了,更多相關(guān)Java自定義注解校驗(yàn)入?yún)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot?Profile多環(huán)境配置方式

    SpringBoot?Profile多環(huán)境配置方式

    這篇文章主要介紹了SpringBoot?Profile多環(huán)境配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java方法的參數(shù)傳遞機(jī)制實(shí)例詳解

    Java方法的參數(shù)傳遞機(jī)制實(shí)例詳解

    這篇文章主要介紹了Java方法的參數(shù)傳遞機(jī)制,結(jié)合實(shí)例形式詳細(xì)分析了java方法參數(shù)傳遞機(jī)制原理、實(shí)現(xiàn)方法及操作注意事項(xiàng),需要的朋友可以參考下
    2019-09-09
  • Springboot接收POST請(qǐng)求,數(shù)據(jù)為json類(lèi)型問(wèn)題

    Springboot接收POST請(qǐng)求,數(shù)據(jù)為json類(lèi)型問(wèn)題

    在使用Spring框架中,當(dāng)處理POST請(qǐng)求且內(nèi)容為JSON類(lèi)型時(shí),應(yīng)使用@RequestBody注解而非@RequestParam,通過(guò)@RequestBody可以將JSON數(shù)據(jù)綁定到一個(gè)Map對(duì)象中,然后通過(guò)Map的get方法來(lái)獲取需要的參數(shù)
    2022-10-10
  • springboot版本升級(jí)以及解決springsecurity漏洞的問(wèn)題

    springboot版本升級(jí)以及解決springsecurity漏洞的問(wèn)題

    這篇文章主要介紹了springboot版本升級(jí)以及解決springsecurity漏洞的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Java實(shí)現(xiàn)簡(jiǎn)易的洗牌和發(fā)牌功能

    Java實(shí)現(xiàn)簡(jiǎn)易的洗牌和發(fā)牌功能

    本文主要介紹了Java實(shí)現(xiàn)簡(jiǎn)易的洗牌和發(fā)牌功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Spring-data-JPA使用時(shí)碰到的問(wèn)題以及解決方案

    Spring-data-JPA使用時(shí)碰到的問(wèn)題以及解決方案

    這篇文章主要介紹了Spring-data-JPA使用時(shí)碰到的問(wèn)題以及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • SpringBoot集成Druid監(jiān)控頁(yè)面最小化配置操作

    SpringBoot集成Druid監(jiān)控頁(yè)面最小化配置操作

    這篇文章主要介紹了SpringBoot集成Druid監(jiān)控頁(yè)面最小化配置操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • Java中channel用法總結(jié)

    Java中channel用法總結(jié)

    這篇文章主要介紹了Java中channel用法,較為詳細(xì)的總結(jié)了channel的定義、類(lèi)型及使用技巧,需要的朋友可以參考下
    2015-06-06
  • jackson json序列化實(shí)現(xiàn)首字母大寫(xiě),第二個(gè)字母需小寫(xiě)

    jackson json序列化實(shí)現(xiàn)首字母大寫(xiě),第二個(gè)字母需小寫(xiě)

    這篇文章主要介紹了jackson json序列化實(shí)現(xiàn)首字母大寫(xiě),第二個(gè)字母需小寫(xiě)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • SpringBoot配置Access-Control-Allow-Origin教程

    SpringBoot配置Access-Control-Allow-Origin教程

    文章介紹了三種配置Spring Boot跨域訪問(wèn)的方法:1. 使用過(guò)濾器;2. 在WebConfig配置文件中設(shè)置;3. 通過(guò)注解配置,作者分享了個(gè)人經(jīng)驗(yàn),并鼓勵(lì)讀者支持腳本之家
    2025-03-03

最新評(píng)論

敦化市| 平武县| 宁南县| 五华县| 铁岭县| 高要市| 清流县| 金山区| 东港市| 武穴市| 禄丰县| 泸西县| 宁强县| 乌什县| 浠水县| 巴塘县| 姚安县| 石渠县| 铁岭县| 呼图壁县| 深州市| 镇赉县| 永靖县| 阿鲁科尔沁旗| 特克斯县| 黄平县| 黄梅县| 邮箱| 中超| 石屏县| 昌图县| 广东省| 体育| 江津市| 平原县| 鹤岗市| 休宁县| 海淀区| 瓦房店市| 淮安市| 兰州市|