真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何通過spring-aop的方式自定義注解來實現(xiàn)spring-cache的功能

本篇文章給大家分享的是有關(guān)如何通過spring-aop的方式自定義注解來實現(xiàn)spring-cache的功能,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

創(chuàng)新互聯(lián)服務(wù)項目包括隴西網(wǎng)站建設(shè)、隴西網(wǎng)站制作、隴西網(wǎng)頁制作以及隴西網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,隴西網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到隴西省份的部分城市,未來相信會繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

設(shè)計的過程中參考一下幾個原則:

  • 代碼無侵入

  • 按需加載

  • 配置多樣化

首先自定義注解:只能作用于方法上,運(yùn)行期有效,key支持spel表達(dá)式,其中FunctionEnum是根據(jù)業(yè)務(wù)自定義的一個枚舉

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GlobalCache {

    /**
     * SPEL表達(dá)式,緩存key
     * @return
     */
    String key() default "";

    String value() default "";

    /**
     * 當(dāng)前具體的操作
     * eg:信息新增,刪除等
     *
     * @return
     */
    FunctionEnum functionEnum() default FunctionEnum.DEFAULT;

}

通過定義aop的切面來解析當(dāng)前這個注解,核心實現(xiàn)如下

@Around("@annotation(com.xxx.xxxx.core.foreign.annotation.GlobalCache)")
    public Object globalCacheAround(ProceedingJoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        ServiceData result;
        GlobalCache globalCache = method.getAnnotation(GlobalCache.class);
        String cacheKey = globalCache.functionEnum().name() + ":" + ForeignUtils.combineParam(methodSignature.getParameterNames(),joinPoint.getArgs(),globalCache.key(),String.class,"test-spel-123");
        if ("GET".equals(request.getMethod())) {
            result = defaultredisTemplate.opsForValue().get(cacheKey);
            if (result != null) {
                log.info("命中緩存,緩存的key:{}", cacheKey);
                return result;
            }
        }
        Map httpParams = ForeignUtils.builtParams(methodSignature.getParameterNames(), request);
        result = CompletableFuture.supplyAsync(() -> {
            //重定向相關(guān)操作
            return redirectUrl(cacheKey,request,httpParams,ForeignUtils.getRequestBody(method,joinPoint));
        }, LocalThreadPool.FOREIGN_EXEC_CACHE).whenComplete((serviceData, ex) -> {
            if (ex == null) {
                //本地緩存的業(yè)務(wù)處理
                notice.onSuccess(globalCache, httpParams, serviceData);
            } else {
                notice.onError(ex, serviceData);
                throw new ForeignInvokeException("current request was deny...");
            }
        }).join();
        return result;
    }

在構(gòu)造的過程中遇到很多小的零碎的問題,其中涉及到如何解析PUT請求中的body等等,下面附上ForeignUtils工具類的代碼

    /**
     * 組裝緩存key
     * 格式: 方法名:參數(shù)值1:參數(shù)值2
     * 自動解析格式
     *
     * @param functionName 當(dāng)前操作對應(yīng)的名稱
     * @param args         所有變量對應(yīng)的參數(shù)
     * @return
     */
    public static String combineParameter(String functionName, Method method, Object[] args) {
        Class[] classArr = method.getParameterTypes();
        for (int index = 0; index < classArr.length; index++) {
            if (classArr[index] == HttpServletRequest.class) {
                //是否存在其他待忽略的?
                continue;
            }
            functionName += ":" + args[index];
        }
        return functionName;
    }

    /**
     * 請求參數(shù)的參數(shù)名稱和參數(shù)對應(yīng)的值   key參數(shù):value參數(shù)變量
     * title:test-123,subtitle:test-subtitle-123
     *
     * @param params
     * @param request
     * @return
     */
    public static Map builtParams(String[] params, HttpServletRequest request) {
        Map keyMap = Maps.newHashMap();
        for (int i = 0; i < params.length; i++) {
            String value = request.getParameter(params[i]);
            if (StringUtils.isNotBlank(value)) {
                keyMap.put(params[i], value);
            }
        }
        return keyMap;
    }


    /**
     * 拼裝http后請求參數(shù),占位符的方式
     * title={title}&subtitle={subtitle}
     * 可以使用queryString()替代
     *
     * @param httpParams
     * @return
     */
    public static String builtHttpParams(Map httpParams) {
        String result = "";
        for (Map.Entry entry : httpParams.entrySet()) {
            result += entry.getKey() + "= {" + entry.getKey() + "}&";
        }
        if (result.endsWith("&")) {
            return result.substring(0, result.length() - 1);
        }
        return result;
    }

    /**
     * 獲取當(dāng)前請求中的body值
     *
     * @param method
     * @param joinPoint
     * @return
     */
    public static Object getRequestBody(Method method, ProceedingJoinPoint joinPoint) {
        Annotation[][] currentAnnotionArr = method.getParameterAnnotations();
        Object body = null;
        for (int index = 0; index < currentAnnotionArr.length; index++) {
            try {
                if (currentAnnotionArr[index][0].annotationType() == RequestBody.class) {
                    body = joinPoint.getArgs()[index];
                    break;
                }
            } catch (Exception e) {

            }
        }
        return body;
    }

    /**
     * 獲取請求中path的參數(shù)對
     * @param method
     * @param joinPoint
     * @return
     */
    public static String getPathArgs(Method method, ProceedingJoinPoint joinPoint) {
        Annotation[][] currentAnnotionArr = method.getParameterAnnotations();
        String pathValue = null;
        for (int index = 0; index < currentAnnotionArr.length; index++) {
            try {
                if (currentAnnotionArr[index][0].annotationType() == PathVariable.class) {
                    pathValue = String.valueOf(joinPoint.getArgs()[index]);
                    break;
                }
            } catch (Exception e) {

            }
        }
        return pathValue;
    }


    private static ExpressionParser parser = new SpelExpressionParser();


    /**
     * 解析SPEL表達(dá)式 緩存對應(yīng)key信息
     *
     * @param params
     * @param args
     * @param spel
     * @param clazz
     * @param defaultResult
     * @return
     */
    public static  T combineParam(String[] params, Object[] args, String spel, Class clazz, T defaultResult) {
        EvaluationContext context = new StandardEvaluationContext();
        for (int index = 0; index < params.length; index++) {
            context.setVariable(params[index], args[index]);
        }
        try {
            Expression expression = parser.parseExpression(spel);
            return expression.getValue(context, clazz);
        } catch (Exception e) {
            return defaultResult;
        }
    }

上面的工具類主要涉及到參數(shù)的組裝,解析等;

以上就是如何通過spring-aop的方式自定義注解來實現(xiàn)spring-cache的功能,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


本文題目:如何通過spring-aop的方式自定義注解來實現(xiàn)spring-cache的功能
網(wǎng)站地址:http://weahome.cn/article/jgshho.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部