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

溫馨提示×

溫馨提示×

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

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

怎么用Spring的spel獲取自定義注解參數值

發布時間:2022-02-17 13:37:13 來源:億速云 閱讀:184 作者:iii 欄目:開發技術

這篇文章主要介紹了怎么用Spring的spel獲取自定義注解參數值的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇怎么用Spring的spel獲取自定義注解參數值文章都會有所收獲,下面我們一起來看看吧。

spel獲取自定義注解參數值

1.注解類

package com.xxx.mall.order.service.component; 
import java.lang.annotation.*;
 
/**
 * 庫存不足等信息監控
 * Created by xdc on 2019/4/16 15:43
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface StockWarnCollect {
 
    /** 客戶id */
    String customerId();
 
    /** 來源 */
    String source();
 
    /** 請求類型 1:詳情頁 2:購物車去結算 3:提交訂單 */
    String pageType();
}

2.注解使用

@Override
@StockWarnCollect(customerId = "#customerId", source = "#source", pageType = "2")
public Map<String, Object> validateCarts(Long customerId, Set<Long> userSelectedIds, Short source, JSONArray couponInfo){
    // 省略
}

3.aop中處理 

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
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.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component; 
import java.lang.reflect.Method;
 
/**
 * 下單失敗、庫存監控
 * Created by xdc on 2019/4/16 15:45
 */
@Aspect
@Component
@Slf4j
public class StockWarnCollectAop { 
    @Pointcut(value = "@annotation(com.xxx.mall.order.service.component.StockWarnCollect)")
    public void collectStockWarn(){}
 
    @Around(value = "collectStockWarn()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
 
        Method targetMethod = this.getTargetMethod(pjp);
        StockWarnCollect stockWarnCollect = targetMethod.getAnnotation(StockWarnCollect.class);
 
        // spel信息
        String customerIdSpel = stockWarnCollect.customerId();
        String sourceSpel = stockWarnCollect.source();
        Integer pageType = null;  // 操作類型,純字符串
        if (StringUtils.isNotBlank(stockWarnCollect.pageType())) {
            pageType = Integer.valueOf(stockWarnCollect.pageType());
        }
 
        // 客戶id、來源解析
        ExpressionParser parser = new SpelExpressionParser();
        LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
        String[] params = discoverer.getParameterNames(targetMethod); 
        Object[] args = pjp.getArgs();
 
        EvaluationContext context = new StandardEvaluationContext();
        for (int len = 0; len < params.length; len++) {
            context.setVariable(params[len], args[len]);
        }
        Expression expression = parser.parseExpression(customerIdSpel);
        Long customerId = expression.getValue(context, Long.class);
 
        expression = parser.parseExpression(sourceSpel);
        Short source = expression.getValue(context, Short.class);
        log.info("collectStockWarn customerId:{}, source:{}", customerId, source);
 
        // 業務邏輯處理
        Object result = null;
        try {
            result = pjp.proceed();
        } catch (Throwable e) {
            log.info("collectStockWarn watchs creating order errorMsg:{}", ExceptionUtils.getStackTrace(e));
            if (e instanceof MallException) {
 
            } else {    // 未知錯誤
            
            } 
            throw e;
        } 
        try {
            if (result != null) {            
            }
        } catch (Exception e) {
            log.error("collectStockWarn process error, errorMsg:{}", ExceptionUtils.getStackTrace(e));
        } 
        return result; 
    } 
    /**
     * 獲取目標方法
     */
    private Method getTargetMethod(ProceedingJoinPoint pjp) throws NoSuchMethodException {
        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature)signature;
        Method agentMethod = methodSignature.getMethod();
        return pjp.getTarget().getClass().getMethod(agentMethod.getName(),agentMethod.getParameterTypes());
    }
}

spel在注解中的使用

SpEL(Spring Expression Language),即Spring表達式語言,是比JSP的EL更強大的一種表達式語言。為什么要總結SpEL,因為它可以在運行時查詢和操作數據,尤其是數組列表型數據,因此可以縮減代碼量,優化代碼結構。個人認為很有用。

1 語法說明

1.1 SpEL 字面量:

  • 整數:#{8}

  • 小數:#{8.8}

  • 科學計數法:#{1e4}

  • String:可以使用單引號或者雙引號作為字符串的定界符號。

  • Boolean:#{true}

1.2 SpEL引用bean , 屬性和方法:

  • 引用其他對象:#{car}

  • 引用其他對象的屬性:#{car.brand}

  • 調用其它方法 , 還可以鏈式操作:#{car.toString()}

  • 調用靜態方法靜態屬性:#{T(java.lang.Math).PI}

1.3 SpEL支持的運算符號:

  • 算術運算符:+,-,*,/,%,^(加號還可以用作字符串連接)

  • 比較運算符:< , > , == , >= , <= , lt , gt , eg , le , ge

  • 邏輯運算符:and , or , not , |

  • if-else 運算符(類似三目運算符):?:(temary), ?:(Elvis)

  • 正則表達式:#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}'}

2. 基本用法

SpEL有三種用法:

1. 是在注解@Value中;

2. 在XML配置中;

3. 代碼塊中使用Expression。

2.1 @Value

    //@Value能修飾成員變量和方法形參
    //#{}內就是表達式的內容
    @Value("#{表達式}")
    public String arg;

2.2 <bean>配置

<bean id="xxx" class="com.java.XXXXX.xx">
    <!-- 同@Value,#{}內是表達式的值,可放在property或constructor-arg內 -->
    <property name="arg" value="#{表達式}">
</bean>

2.3 代碼塊中使用

public class SpELTest { 
    public static void main(String[] args) {
 
        //創建ExpressionParser解析表達式
        ExpressionParser parser = new SpelExpressionParser();
        //表達式放置
        Expression exp = parser.parseExpression("表達式");
        //執行表達式,默認容器是spring本身的容器:ApplicationContext
        Object value = exp.getValue();
        
        /**如果使用其他的容器,則用下面的方法*/
        //創建一個虛擬的容器EvaluationContext
        StandardEvaluationContext ctx = new StandardEvaluationContext();
        //向容器內添加bean
        BeanA beanA = new BeanA();
        ctx.setVariable("bean_id", beanA);
        
        //setRootObject并非必須;一個EvaluationContext只能有一個RootObject,引用它的屬性時,可以不加前綴
        ctx.setRootObject(XXX);
        
        //getValue有參數ctx,從新的容器中根據SpEL表達式獲取所需的值
        Object value = exp.getValue(ctx);
    }
}

4 #{&hellip;}和${&hellip;}

  • #{&hellip;} 用于執行SpEl表達式,并將內容賦值給屬性

  • ${&hellip;} 主要用于加載外部屬性文件中的值

  • #{&hellip;} 和${&hellip;} 可以混合使用,但是必須#{}外面,${}在里面

4.1 ${&hellip;}用法 

{}里面的內容必須符合SpEL表達式,通過@Value(“${spelDefault.value}”)可以獲取屬性文件中對應的值,但是如果屬性文件中沒有這個屬性,則會報錯。可以通過賦予默認值解決這個問題,如@Value("${spelDefault.value:127.0.0.1}")

// 如果屬性文件沒有spelDefault.value,則會報錯
    //  @Value("${spelDefault.value}")
    //  private String spelDefault2;
 
    // 使用default.value設置值,如果不存在則使用默認值
    @Value("${spelDefault.value:127.0.0.1}")
    private String spelDefault;

4.2 #{&hellip;}用法 

這里只演示簡單用法

    // SpEL:調用字符串Hello World的concat方法
    @Value("#{'Hello World'.concat('!')}")
    private String helloWorld;
 
    // SpEL: 調用字符串的getBytes方法,然后調用length屬性
    @Value("#{'Hello World'.bytes.length}")
    private String helloWorldbytes;

4.3 ${&hellip;}和#{&hellip;}混合使用 

${...}和#{...}可以混合使用,如下文代碼執行順序:通過${server.name}從屬性文件中獲取值并進行替換,然后就變成了 執行SpEL表達式{&lsquo;server1,server2,server3&rsquo;.split(&lsquo;,&rsquo;)}。

// SpEL: 傳入一個字符串,根據","切分后插入列表中, #{}和${}配置使用(注意單引號,注意不能反過來${}在外面,#{}在里面)
    @Value("#{'${server.name}'.split(',')}")
    private List<String> servers;

在上文中在#{}外面,${}在里面可以執行成功,那么反過來是否可以呢${}在外面,#{}在里面,如代碼

// SpEL: 注意不能反過來${}在外面,#{}在里面,這個會執行失敗
    @Value("${#{'HelloWorld'.concat('_')}}")
    private List<String> servers2;

答案是不能。因為spring執行${}是時機要早于#{}。在本例中,Spring會嘗試從屬性中查找#{&lsquo;HelloWorld&rsquo;.concat(&lsquo;_&rsquo;)},那么肯定找不到,由上文已知如果找不到,然后報錯。所以${}在外面,#{}在里面是非法操作 

關于“怎么用Spring的spel獲取自定義注解參數值”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“怎么用Spring的spel獲取自定義注解參數值”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

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

AI

巧家县| 留坝县| 余姚市| 古交市| 平湖市| 连云港市| 吴江市| 化州市| 上饶市| 朝阳市| 三河市| 古蔺县| 万载县| 凤山市| 蕲春县| 乌拉特后旗| 南乐县| 卓尼县| 丰都县| 孟连| 柘荣县| 綦江县| 黎城县| 石台县| 广汉市| 和政县| 南涧| 商都县| 兰考县| 肥东县| 如东县| 日照市| 南通市| 黄骅市| 若羌县| 田阳县| 东阿县| 平谷区| 雅安市| 图们市| 任丘市|