当前位置: 首页 > news >正文

国外包装设计网站在线一键建站系统

国外包装设计网站,在线一键建站系统,如何建b2b网站,wordpress 屏蔽插件更新0. 我只是个普通码农,不值得挽留 Spring SpEL表达式的使用 常见的应用场景:分布式锁的切面借助SpEL来构建key 比较另类的的应用场景:动态校验 个人感觉可以用作控制程序的走向,除此之外,spring的一些模块的自动配置类,也会在Cond…

0. 我只是个普通码农,不值得挽留

Spring SpEL表达式的使用
常见的应用场景:分布式锁的切面借助SpEL来构建key
比较另类的的应用场景:动态校验


个人感觉可以用作控制程序的走向,除此之外,spring的一些模块的自动配置类,也会在@Conditional注解中使用SpEL来实现有条件的加载特定的bean.

1. UML

1.1 ExpressionParser

解释器设计模式的体现了
在这里插入图片描述
单纯的(非模板表达式)spel表达式将通过 SpelExpressionParser 创建 InternalSpelExpressionParser, 来实现 parseExpression() 的底层逻辑.

	// org.springframework.expression.spel.standard.InternalSpelExpressionParser#doParseExpression@Overrideprotected SpelExpression doParseExpression(String expressionString, @Nullable ParserContext context)throws ParseException {try {this.expressionString = expressionString;// 1.对相关的符号进行分词Tokenizer tokenizer = new Tokenizer(expressionString);this.tokenStream = tokenizer.process();this.tokenStreamLength = this.tokenStream.size();this.tokenStreamPointer = 0;this.constructedNodes.clear();// 2.构建 ASTSpelNodeImpl ast = eatExpression();Assert.state(ast != null, "No node");Token t = peekToken();if (t != null) {throw new SpelParseException(t.startPos, SpelMessage.MORE_INPUT, toString(nextToken()));}Assert.isTrue(this.constructedNodes.isEmpty(), "At least one node expected");// 3. 返回创建好的表达式实例return new SpelExpression(expressionString, ast, this.configuration);}catch (InternalParseException ex) {throw ex.getCause();}}

1.2 ParserContext

在这里插入图片描述

  • 这里前后缀例如:支持模板表达式的实现类TemplateParserContext使用了#{}
  • TemplateAwareExpressionParser(支持模板的ExpressionParser实现类),根据 ParserContext.isTemplate()来决定处理流程
  • 有必要给出模板表达式的定义: 可以理解为多个、多种表达式的组合
	// org.springframework.expression.common.TemplateAwareExpressionParser#parseExpression(java.lang.String, org.springframework.expression.ParserContext)@Overridepublic Expression parseExpression(String expressionString, @Nullable ParserContext context) throws ParseException {if (context != null && context.isTemplate()) {return parseTemplate(expressionString, context);}else {return doParseExpression(expressionString, context);}}

1.3 Expression

在这里插入图片描述

转换并获取表达式对应的数值

1.4 EvaluateContext

  • 支持间接的关联 beanFactory ,来注入spring bean
  • 该功能很好的体现了 spring-expression 的独立性
  • 支持往该上下文中加入静态方法、java bean
  • 与 Expression.getValue() 有较大的关系
    在这里插入图片描述

在这里插入图片描述

2. test-classes

因为要debug beanFactory关联的 parser,便懒得构造applicationContext,直接@SpringbootTest 启动容器了

@DisplayName("Spring Expression Language")
@SpringBootTest
public class SpELTest {@Value("#{testBean.value}")String value;@AutowiredApplicationContext appCtx;SpelExpressionParser parser;StandardEvaluationContext stdEvaCtx;@PostConstructprivate void postConstruct() throws NoSuchMethodException {parser = new SpelExpressionParser();// rootObjectstdEvaCtx = new StandardEvaluationContext(new TestBean("rootValue", null));// variablestdEvaCtx.setVariable("testBean", this.appCtx.getBean("testBean"));Method parseInt = Integer.class.getDeclaredMethod("valueOf", String.class);stdEvaCtx.registerFunction("doValueOf", parseInt);stdEvaCtx.setBeanResolver(new BeanFactoryResolver(this.appCtx));}@DisplayName("注解方式")@Testvoid t0() {// 这个上下文其实就是表达式、变量的容器(缓存)System.err.println(this.value);}@DisplayName("编码方式")@Testvoid t1() {// 不需要 {}// spring security 中也使用编码的方式解析权限注解 @PrePreAuthorizeExpression expression = parser.parseExpression("#testBean.value");System.err.println(expression.getValue(this.stdEvaCtx));}@DisplayName("运算")@Nestedclass Count {@DisplayName("字面量")@Testvoid t0() {// 上下文中找不到这个变量,报错:// spel.SpelEvaluationException: EL1007E: Property or field 'test' cannot be found on null// System.err.println("找不到变量="+parser.parseExpression("test").getValue(String.class));// 字符串System.err.println("字符串1=" + parser.parseExpression("'test'").getValue(String.class));System.err.println("字符串2=" + parser.parseExpression("\"test\"").getValue(String.class));// 数字System.err.println("int=" + parser.parseExpression("1").getValue(Integer.class));System.err.println("long=" + parser.parseExpression("1L").getValue(long.class));System.err.println("float=" + parser.parseExpression("1.1").getValue(Float.class));System.err.println("double=" + parser.parseExpression("1.1E+1").getValue(double.class));System.err.println("hex=" + parser.parseExpression("0xf").getValue(int.class));// 布尔System.err.println("bool=" + parser.parseExpression("false").getValue(boolean.class));// nullSystem.err.println(parser.parseExpression("null").getValue());}@DisplayName("算数")@Testvoid t1() {System.err.println("3+2=" + parser.parseExpression("3+2").getValue(Integer.class));System.err.println("3-2=" + parser.parseExpression("3-2").getValue(Integer.class));System.err.println("3*2=" + parser.parseExpression("3*2").getValue(Integer.class));System.err.println("3/2=" + parser.parseExpression("3/2").getValue(Integer.class));System.err.println("3%2=" + parser.parseExpression("3%2").getValue(Integer.class));System.err.println("3^2=" + parser.parseExpression("3^2").getValue(Integer.class));}@DisplayName("关系运算")@Testvoid t2() {System.err.println("3==2=" + parser.parseExpression("3==2").getValue(Boolean.class));System.err.println("3 == 2=" + parser.parseExpression("3 == 2").getValue(Boolean.class));System.err.println("3 ge 2 =" + parser.parseExpression("3 ge 2").getValue(boolean.class));System.err.println("3 LT 2 = " + parser.parseExpression("3 LT 2").getValue(boolean.class));// SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'NE2'// System.err.println("3NE2 = "+parser.parseExpression("3NE2").getValue(boolean.class));// 并不能返回 int:0、1,会抛出异常System.err.println("2 between {1, 2}=" + parser.parseExpression("2 between {1, 2}").getValue(Boolean.class));// SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'le(<=)'// System.err.println("1<2<=2="+parser.parseExpression("1<2<=3").getValue(Boolean.class));}@DisplayName("逻辑运算")@Testvoid t3() {System.err.println("2>1 and false = " + parser.parseExpression("2>1 and false").getValue(boolean.class));System.err.println("2>1 && false = " + parser.parseExpression("2>1 && false").getValue(Boolean.class));// SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'factory_bean_ref(&)'// System.err.println("2>1 & false = "+parser.parseExpression("2>1 & false").getValue(Boolean.class));System.err.println("2>1 or NOT false and (! NOT false || 1==1) = " + parser.parseExpression("2>1 or NOT false and (! NOT false || 1==1)").getValue(Boolean.class));}@DisplayName("三目运算")@Testvoid t4() {System.err.println("3 > 2 ? true : false = " + parser.parseExpression("3 > 2 ? true : false").getValue(boolean.class));}@DisplayName("elivis")@Testvoid t5() {System.err.println("null ?: 'false' = " + parser.parseExpression("null ?: 'false'").getValue(Boolean.class));System.err.println("null ?: 'false' = " + parser.parseExpression("null ?: 'false'").getValue(String.class));}@DisplayName("正则")@Testvoid t6() {System.err.println("" + parser.parseExpression("'123' matches '\\d{3}'").getValue(boolean.class));System.err.println("" + parser.parseExpression("123 matches '\\d{3}'").getValue(Boolean.class));}@DisplayName("instanceof")@Testvoid t7() {System.err.println("'123' instanceof T(String) = " + parser.parseExpression("'123' instanceof T(String)").getValue(Boolean.class));System.err.println("123 instanceof T(String) = " + parser.parseExpression("123 instanceof T(java.lang.String)").getValue(Boolean.class));}}@DisplayName("类型")@Nestedclass Type {@DisplayName("class")@Testvoid t0() {// java.lang 以外的类均需要全限定名System.err.println(parser.parseExpression("T(String)").getValue(Class.class));System.err.println(parser.parseExpression("T(java.util.Map)").getValue(Class.class));// 访问 静态的属性、方法System.err.println(parser.parseExpression("T(Integer).MAX_VALUE").getValue(int.class));System.err.println(parser.parseExpression("T(Integer).parseInt(3)").getValue(Integer.class));}@DisplayName("instance")@Testvoid t1() {// java.lang 包 同理System.err.println(parser.parseExpression("new String('苹果一样的甜')").getValue(String.class));System.err.println(parser.parseExpression("new java.util.Date()").getValue(Date.class));}@DisplayName("reference")@Testvoid t2() {System.err.println("#testBean.value=" + parser.parseExpression("#testBean.value").getValue(stdEvaCtx, String.class));System.err.println("#this.value=" + parser.parseExpression("#this.value").getValue(stdEvaCtx, String.class));System.err.println("#root.value=" + parser.parseExpression("#root.value").getValue(stdEvaCtx, String.class));// rootObject缺省时,访问其属性,不能加#前缀System.err.println("(root属性可以省略#root)value=" + parser.parseExpression("value").getValue(stdEvaCtx, String.class));}@DisplayName("assign")@Testvoid t3() {System.err.println("#testBean.value=newValue --> " + parser.parseExpression("#testBean.value='newValue'").getValue(stdEvaCtx, String.class));System.err.println("#this.value=newThisValue --> " + parser.parseExpression("#this.value='newThisValue'").getValue(stdEvaCtx, String.class));System.err.println("#root.value=newRootValue --> " + parser.parseExpression("#root.value='newRootValue'").getValue(stdEvaCtx, String.class));System.err.println("value=newValue --> " + parser.parseExpression("value='newValue'").getValue(stdEvaCtx, String.class));}@DisplayName("func")@Testvoid t4() {System.err.println(parser.parseExpression("#doValueOf('20').byteValue()").getValue(stdEvaCtx, Byte.class));}@DisplayName("对象属性获取 及 安全导航")@Testvoid t5() {System.err.println(parser.parseExpression("value").getValue(stdEvaCtx, String.class));// Value 可以,Value 不得行(首字母不敏感)System.err.println(parser.parseExpression("Value").getValue(stdEvaCtx, String.class));// 支持groovy的elivis表达式// 安全导航运算符前面的#root可以省略,但后面的#root不可省略System.err.println(parser.parseExpression("#root?.#root").getValue(stdEvaCtx, TestBean.class));System.err.println(parser.parseExpression("value?.#root.value").getValue(stdEvaCtx, String.class));// SpelParseException: Expression [username?.'核弹拉链'] @8: EL1049E: Unexpected data after '.': ''核弹拉链''// SpEL引入了Groovy语言中的安全导航运算符"(对象|属性)?.属性"// 常量显然不得行// System.err.println(parser.parseExpression("username?.'核弹拉链'").getValue(stdEvaCtx, String.class));}@DisplayName("对象方法调用")@Testvoid t6() {System.err.println(parser.parseExpression("value.substring(1, 6).toUpperCase()").getValue(stdEvaCtx, String.class));System.err.println(parser.parseExpression("toString()").getValue(stdEvaCtx, String.class));}@DisplayName("bean引用(BeanFactoryResolver)")@Testvoid t7() {// @BeanName// EvaluationContext.setBeanResolver() 需要借助 beanFactorySystem.err.println(Jsons.NO_OP.stringify(parser.parseExpression("@systemProperties").getValue(stdEvaCtx, Properties.class)));System.err.println(Jsons.NO_OP.stringify(parser.parseExpression("@testBean").getValue(stdEvaCtx, TestBean.class)));}}@DisplayName("集合")@Nestedclass Collect {@DisplayName("内联数组")@Testvoid t0() {System.err.println(Arrays.toString(parser.parseExpression("new int[2]{1, 2}").getValue(int[].class)));System.err.println(Arrays.toString(parser.parseExpression("new String[2][2]").getValue(String[][].class)));// 不支持多维数组创建同时,做初始化System.err.println(Arrays.toString(parser.parseExpression("new String[2][2]{'1','2'},{'3','4'}").getValue(String[][].class)));}@DisplayName("内联集合")@Testvoid t1() {System.err.println(parser.parseExpression("{}").getValue(List.class));// java.util.Collections$UnmodifiableRandomAccessListSystem.err.println(parser.parseExpression("{1, 2,3}").getValue(List.class).getClass().getName());// 此时的 List<List> .class = java.util.ArrayList// 存在非字面量表达式时,集合类型将转为原始类型(可修改的集合)System.err.println(parser.parseExpression("{{1+2,2+4},{3,4+4}}").getValue(List.class).getClass().getName());}@DisplayName("数组、集合、字典元素访问")@Testvoid t2() {System.err.println(parser.parseExpression("[0]").getValue(new int[]{1, 2, 3}, Integer.class));System.err.println(parser.parseExpression("{1, 2, 3}[0]").getValue(int.class));System.err.println(parser.parseExpression("[0]").getValue(Lists.newArrayList(1, 2, 3), int.class));Map<String, Integer> map = Maps.newHashMap();map.put("weng", 4);map.put("chong", 5);map.put("yu", 2);System.err.println(parser.parseExpression("['chong']").getValue(map, int.class));}// 很像 streamApi.peek().collect(toList())@DisplayName("数组、集合、字典 转换")@Testvoid t3() {// array|list|map.![表达式]System.err.println(Arrays.toString(parser.parseExpression("#root.![#this+1]").getValue(new int[]{1, 2, 3}, int[].class)));System.err.println(parser.parseExpression("#root.![#this+1]").getValue(Lists.newArrayList(1, 2, 3), List.class));Map<String, Integer> map = Maps.newHashMap();map.put("weng", 4);map.put("chong", 5);map.put("yu", 2);System.err.println(Jsons.NO_OP.stringify(parser.parseExpression("#root.![#this.key+1]").getValue(map, List.class)));System.err.println(Jsons.NO_OP.stringify(parser.parseExpression("#root.![#this.value+1]").getValue(map, List.class)));// 报错: cannot convert from java.util.ArrayList<?> to java.util.Map<?, ?>// 集合、数组之间可以随意转换// System.err.println(Jsons.NO_OP.stringify(parser.parseExpression("#root.![#this.value+1]").getValue(map, Map.class)));}// 相当于 streamApi.filter.collect(toList)@DisplayName("数组、集合、字典 选择")@Testvoid t4() {// array|list|map.?[表达式]System.err.println(Arrays.toString(parser.parseExpression("#root.?[#this>=2]").getValue(new int[]{1, 2, 3}, int[].class)));System.err.println(Arrays.toString(parser.parseExpression("#root.?[#this>=2]").getValue(Lists.newArrayList(1, 2, 3), int[].class)));Map<String, Integer> map = Maps.newHashMap();map.put("weng", 4);map.put("chong", 5);map.put("yu", 2);// {"weng":4,"yu":2}System.err.println(Jsons.NO_OP.stringify(parser.parseExpression("#root.?[#this.key!='chong']").getValue(map, Map.class)));// 这里转的集合,有些怪异// [{"weng":4,"yu":2}]System.err.println(Jsons.NO_OP.stringify(parser.parseExpression("#root.?[#this.key!='chong']").getValue(map, List.class)));System.err.println(Jsons.NO_OP.stringify(parser.parseExpression("#root.?[#this.value<=2]").getValue(map, Map.class)));}}
}

附上相关的类

@Component("testBean")
@AllArgsConstructor
@NoArgsConstructor
@Data
public class TestBean {@Value("${angel.spel.key}")public String value;private String username;
}
http://www.dt0577.cn/news/21086.html

相关文章:

  • 淘宝客怎么做网站seo推广排名重要吗
  • 做网站可以用微软雅黑字体么查域名备案信息查询
  • 网站开发中的3p技术如何注册网站怎么注册
  • 广州公司注册流程及费用seo网站推广免费
  • 知了网站后台学历提升
  • 百度不收录我的网站seo快速排名服务
  • 企业信用信息查询公示系统天津seo营销推广全程实例
  • 网站建设教程软件手机cpu性能增强软件
  • 建设银行积分兑换网站长沙seo优化哪家好
  • 网站建设优化及推广广告投放运营主要做什么
  • java做房屋拍卖网站网络热词缩写
  • 做论坛网站靠什么营利排名优化方案
  • 怎么查询企业注册信息西安seo王
  • 目前做的最好的电子烟网站免费营销培训
  • 网站开发平台的定义免费隐私网站推广app
  • 织梦后台怎么建设网站百度关键词推广公司哪家好
  • wordpress 爆破用户名seo好学吗
  • 开公司如何做网站推广长沙seo优化公司
  • 网站开发技术知识企业关键词大全
  • 石家庄建站费用成品视频直播软件推荐哪个好用
  • 胶州企业网站设计北京网站定制公司
  • wordpress完美迁站教程优化关键词快速排名
  • 网站表单提交到qq邮箱市场营销专业
  • 自己做商务网站有什么利弊搜索引擎优化是指什么
  • j2ee网站开发教程网站综合排名信息查询
  • seo免费网站建设即刻搜索
  • 做网站一个月20g流量够吗百度百科创建
  • 政府单位门户网站开发文档精准获客
  • 重庆seo整站优化方案范文上海疫情最新情况
  • 广州网络营销品牌百度seo推广计划类型包括