91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2021-10-20 10:33:36 來源:億速云 閱讀:174 作者:柒染 欄目:大數據

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

設計的過程中參考一下幾個原則:

  • 代碼無侵入

  • 按需加載

  • 配置多樣化

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

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

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

    String value() default "";

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

}

通過定義aop的切面來解析當前這個注解,核心實現如下

@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<String,String> httpParams = ForeignUtils.builtParams(methodSignature.getParameterNames(), request);
        result = CompletableFuture.supplyAsync(() -> {
            //重定向相關操作
            return redirectUrl(cacheKey,request,httpParams,ForeignUtils.getRequestBody(method,joinPoint));
        }, LocalThreadPool.FOREIGN_EXEC_CACHE).whenComplete((serviceData, ex) -> {
            if (ex == null) {
                //本地緩存的業務處理
                notice.onSuccess(globalCache, httpParams, serviceData);
            } else {
                notice.onError(ex, serviceData);
                throw new ForeignInvokeException("current request was deny...");
            }
        }).join();
        return result;
    }

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

    /**
     * 組裝緩存key
     * 格式: 方法名:參數值1:參數值2
     * 自動解析格式
     *
     * @param functionName 當前操作對應的名稱
     * @param args         所有變量對應的參數
     * @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;
    }

    /**
     * 請求參數的參數名稱和參數對應的值   key參數:value參數變量
     * title:test-123,subtitle:test-subtitle-123
     *
     * @param params
     * @param request
     * @return
     */
    public static Map<String, String> builtParams(String[] params, HttpServletRequest request) {
        Map<String, String> 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后請求參數,占位符的方式
     * title={title}&subtitle={subtitle}
     * 可以使用queryString()替代
     *
     * @param httpParams
     * @return
     */
    public static String builtHttpParams(Map<String, String> 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;
    }

    /**
     * 獲取當前請求中的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的參數對
     * @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表達式 緩存對應key信息
     *
     * @param params
     * @param args
     * @param spel
     * @param clazz
     * @param defaultResult
     * @return
     */
    public static <T> T combineParam(String[] params, Object[] args, String spel, Class<T> 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;
        }
    }

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

以上就是如何通過spring-aop的方式自定義注解來實現spring-cache的功能,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

耒阳市| 沂水县| 宜昌市| 辉南县| 天峻县| 融水| 襄樊市| 乾安县| 银川市| 肇东市| 平定县| 陆良县| 固原市| 福安市| 东阿县| 泸西县| 岗巴县| 吉木乃县| 滁州市| 长泰县| 隆安县| 潜江市| 淮滨县| 龙山县| 武夷山市| 新绛县| 裕民县| 洪江市| 临安市| 五台县| 浪卡子县| 淄博市| 呼图壁县| 福鼎市| 德保县| 东海县| 彝良县| 涿州市| 舞阳县| 营山县| 平凉市|