怎么用Spring的spel获取自定义注解参数值
这篇文章主要介绍了怎么用Spring的spel获取自定义注解参数值的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么用Spring的spel获取自定义注解参数值文章都会有所收获,下面我们一起来看看吧。
spel获取自定义注解参数值1.注解类packagecom.xxx.mall.order.service.component;importjava.lang.annotation.*;/***库存不足等信息监控*Createdbyxdcon2019/4/1615:43*/@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})@Documentedpublic@interfaceStockWarnCollect{/**客户id*/StringcustomerId();/**来源*/Stringsource();/**请求类型1:详情页2:购物车去结算3:提交订单*/StringpageType();}2.注解使用
@Override@StockWarnCollect(customerId="#customerId",source="#source",pageType="2")publicMap<String,Object>validateCarts(LongcustomerId,Set<Long>userSelectedIds,Shortsource,JSONArraycouponInfo){//省略}3.aop中处理
importlombok.extern.slf4j.Slf4j;importorg.apache.commons.lang.exception.ExceptionUtils;importorg.apache.commons.lang3.StringUtils;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.Signature;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.aspectj.lang.annotation.Pointcut;importorg.aspectj.lang.reflect.MethodSignature;importorg.springframework.core.LocalVariableTableParameterNameDiscoverer;importorg.springframework.expression.EvaluationContext;importorg.springframework.expression.Expression;importorg.springframework.expression.ExpressionParser;importorg.springframework.expression.spel.standard.SpelExpressionParser;importorg.springframework.expression.spel.support.StandardEvaluationContext;importorg.springframework.stereotype.Component;importjava.lang.reflect.Method;/***下单失败、库存监控*Createdbyxdcon2019/4/1615:45*/@Aspect@Component@Slf4jpublicclassStockWarnCollectAop{@Pointcut(value="@annotation(com.xxx.mall.order.service.component.StockWarnCollect)")publicvoidcollectStockWarn(){}@Around(value="collectStockWarn()")publicObjectaround(ProceedingJoinPointpjp)throwsThrowable{MethodtargetMethod=this.getTargetMethod(pjp);StockWarnCollectstockWarnCollect=targetMethod.getAnnotation(StockWarnCollect.class);//spel信息StringcustomerIdSpel=stockWarnCollect.customerId();StringsourceSpel=stockWarnCollect.source();IntegerpageType=null;//操作类型,纯字符串if(StringUtils.isNotBlank(stockWarnCollect.pageType())){pageType=Integer.valueOf(stockWarnCollect.pageType());}//客户id、来源解析ExpressionParserparser=newSpelExpressionParser();LocalVariableTableParameterNameDiscovererdiscoverer=newLocalVariableTableParameterNameDiscoverer();String[]params=discoverer.getParameterNames(targetMethod);Object[]args=pjp.getArgs();EvaluationContextcontext=newStandardEvaluationContext();for(intlen=0;len<params.length;len++){context.setVariable(params[len],args[len]);}Expressionexpression=parser.parseExpression(customerIdSpel);LongcustomerId=expression.getValue(context,Long.class);expression=parser.parseExpression(sourceSpel);Shortsource=expression.getValue(context,Short.class);log.info("collectStockWarncustomerId:{},source:{}",customerId,source);//业务逻辑处理Objectresult=null;try{result=pjp.proceed();}catch(Throwablee){log.info("collectStockWarnwatchscreatingordererrorMsg:{}",ExceptionUtils.getStackTrace(e));if(einstanceofMallException){}else{//未知错误}throwe;}try{if(result!=null){}}catch(Exceptione){log.error("collectStockWarnprocesserror,errorMsg:{}",ExceptionUtils.getStackTrace(e));}returnresult;}/***获取目标方法*/privateMethodgetTargetMethod(ProceedingJoinPointpjp)throwsNoSuchMethodException{Signaturesignature=pjp.getSignature();MethodSignaturemethodSignature=(MethodSignature)signature;MethodagentMethod=methodSignature.getMethod();returnpjp.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("#{表达式}")publicStringarg;
2.2 <bean>配置
<beanid="xxx"class="com.java.XXXXX.xx"><!--同@Value,#{}内是表达式的值,可放在property或constructor-arg内--><propertyname="arg"value="#{表达式}"></bean>
2.3 代码块中使用
publicclassSpELTest{publicstaticvoidmain(String[]args){//创建ExpressionParser解析表达式ExpressionParserparser=newSpelExpressionParser();//表达式放置Expressionexp=parser.parseExpression("表达式");//执行表达式,默认容器是spring本身的容器:ApplicationContextObjectvalue=exp.getValue();/**如果使用其他的容器,则用下面的方法*///创建一个虚拟的容器EvaluationContextStandardEvaluationContextctx=newStandardEvaluationContext();//向容器内添加beanBeanAbeanA=newBeanA();ctx.setVariable("bean_id",beanA);//setRootObject并非必须;一个EvaluationContext只能有一个RootObject,引用它的属性时,可以不加前缀ctx.setRootObject(XXX);//getValue有参数ctx,从新的容器中根据SpEL表达式获取所需的值Objectvalue=exp.getValue(ctx);}}4 #{…}和${…}
#{…} 用于执行SpEl表达式,并将内容赋值给属性
${…} 主要用于加载外部属性文件中的值
#{…} 和${…} 可以混合使用,但是必须#{}外面,${}在里面
4.1 ${…}用法
{}里面的内容必须符合SpEL表达式,通过@Value(“${spelDefault.value}”)可以获取属性文件中对应的值,但是如果属性文件中没有这个属性,则会报错。可以通过赋予默认值解决这个问题,如@Value("${spelDefault.value:127.0.0.1}")
//如果属性文件没有spelDefault.value,则会报错//@Value("${spelDefault.value}")//privateStringspelDefault2;//使用default.value设置值,如果不存在则使用默认值@Value("${spelDefault.value:127.0.0.1}")privateStringspelDefault;
4.2 #{…}用法
这里只演示简单用法
//SpEL:调用字符串HelloWorld的concat方法@Value("#{'HelloWorld'.concat('!')}")privateStringhelloWorld;//SpEL:调用字符串的getBytes方法,然后调用length属性@Value("#{'HelloWorld'.bytes.length}")privateStringhelloWorldbytes;
4.3 ${…}和#{…}混合使用
${...}和#{...}可以混合使用,如下文代码执行顺序:通过${server.name}从属性文件中获取值并进行替换,然后就变成了 执行SpEL表达式{‘server1,server2,server3’.split(‘,’)}。
//SpEL:传入一个字符串,根据","切分后插入列表中,#{}和${}配置使用(注意单引号,注意不能反过来${}在外面,#{}在里面)@Value("#{'${server.name}'.split(',')}")privateList<String>servers;
在上文中在#{}外面,${}在里面可以执行成功,那么反过来是否可以呢${}在外面,#{}在里面,如代码
//SpEL:注意不能反过来${}在外面,#{}在里面,这个会执行失败@Value("${#{'HelloWorld'.concat('_')}}")privateList<String>servers2;
答案是不能。因为spring执行${}是时机要早于#{}。在本例中,Spring会尝试从属性中查找#{‘HelloWorld’.concat(‘_’)},那么肯定找不到,由上文已知如果找不到,然后报错。所以${}在外面,#{}在里面是非法操作
关于“怎么用Spring的spel获取自定义注解参数值”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“怎么用Spring的spel获取自定义注解参数值”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注亿速云行业资讯频道。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。