• Spring Framework学习小记


    Spring Expression Language(SpEL)

    The Spring Expression Language (“SpEL” for short) is a powerful expression language that supports querying and manipulating an object graph at runtime. The language syntax is similar to Unified EL but offers additional features, most notably method invocation and basic string templating functionality.

    详情参阅:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#expressions

    模式配置(SpelCompilerMode):解释执行模式(OFF)、编译模式(IMMEDIATE)、混合模式(MIXED)

    使用示例:

    Bean中使用(Expressions in Bean Definitions):

     1 //1
     2 public class FieldValueTestBean {
     3 
     4     @Value("#{ systemProperties['user.region'] }")
     5     private String defaultLocale;
     6 
     7     public void setDefaultLocale(String defaultLocale) {
     8         this.defaultLocale = defaultLocale;
     9     }
    10 
    11     public String getDefaultLocale() {
    12         return this.defaultLocale;
    13     }
    14 }
    15 
    16 
    17 //2
    18 public class PropertyValueTestBean {
    19 
    20     private String defaultLocale;
    21 
    22     @Value("#{ systemProperties['user.region'] }")
    23     public void setDefaultLocale(String defaultLocale) {
    24         this.defaultLocale = defaultLocale;
    25     }
    26 
    27     public String getDefaultLocale() {
    28         return this.defaultLocale;
    29     }
    30 }
    31 
    32 //3
    33 public class SimpleMovieLister {
    34 
    35     private MovieFinder movieFinder;
    36     private String defaultLocale;
    37 
    38     @Autowired
    39     public void configure(MovieFinder movieFinder,
    40             @Value("#{ systemProperties['user.region'] }") String defaultLocale) {
    41         this.movieFinder = movieFinder;
    42         this.defaultLocale = defaultLocale;
    43     }
    44 
    45     // ...
    46 }
    View Code

    代码路径中动态使用SpEL:(参阅:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#expressions-language-ref

      1 package com.sensetime.sensestudy.exptool.web;
      2 
      3 import java.util.ArrayList;
      4 import java.util.Arrays;
      5 import java.util.HashMap;
      6 import java.util.List;
      7 import java.util.Map;
      8 
      9 import org.springframework.expression.EvaluationContext;
     10 import org.springframework.expression.ExpressionParser;
     11 import org.springframework.expression.common.TemplateParserContext;
     12 import org.springframework.expression.spel.SpelParserConfiguration;
     13 import org.springframework.expression.spel.standard.SpelExpressionParser;
     14 import org.springframework.expression.spel.support.SimpleEvaluationContext;
     15 
     16 import lombok.Data;
     17 
     18 /**
     19  * @see <a href=
     20  *      'https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#expressions-language-ref'>https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#expressions-language-ref</a>
     21  */
     22 public class SpELTest {
     23     @Data
     24     public static class Person {
     25         private String name;
     26         private List<Boolean> booleans = new ArrayList<>();
     27         private List<String> nickNames;
     28         private Map<String, Integer> friendAge = new HashMap<>();
     29     }
     30 
     31     public static void main(String[] args) throws NoSuchMethodException, SecurityException {
     32 
     33         ExpressionParser parser = new SpelExpressionParser();
     34 
     35         // 1 Literal Expressions
     36         System.err.println(parser.parseExpression("1+7").getValue());// 8
     37         System.err.println(parser.parseExpression("-6.0221415E+23").getValue(Double.class));// -6.0221415E23
     38         System.err.println(parser.parseExpression("0x7FFFFFFF").getValue(Integer.class));// 2147483647
     39         System.err.println(parser.parseExpression("true").getValue(Boolean.class));// true
     40         System.err.println(parser.parseExpression("null").getValue(Double.class));// null
     41 
     42         System.err.println(parser.parseExpression("'Hello World'").getValue());// Hello World
     43         System.err.println(parser.parseExpression("'Hello World'").getValue(String.class));// Hello World
     44         System.err.println();
     45 
     46         Person p = new Person();
     47         p.setName("张三丰");
     48         p.getBooleans().add(true);
     49         p.getFriendAge().put("小李", 10);
     50 
     51         System.err.println(parser.parseExpression("name").getValue(p));// 张三丰
     52         System.err.println(parser.parseExpression("getName()").getValue(p));// 张三丰
     53         System.err.println(parser.parseExpression("name").getValue(p, String.class));// 张三丰
     54         System.err.println();
     55 
     56         // 2 Properties, Arrays, Lists, Maps, and Indexers
     57         System.err.println(parser.parseExpression("getBooleans()[0]").getValue(p));// true
     58         System.err.println(parser.parseExpression("getFriendAge()['小李']").getValue(p));// 10
     59 
     60         parser.parseExpression("booleans[0]").setValue(SimpleEvaluationContext.forReadOnlyDataBinding().build(), p, "false");// 会自动进行类型转换
     61         System.err.println(p.getBooleans().get(0));// false
     62 
     63         new SpelExpressionParser(new SpelParserConfiguration(true, true)).parseExpression("nickNames[3]").getValue(p);// 通过SpelParserConfiguration配置自动对Array或Collection进行容量扩展和元素初始化
     64         System.err.println(p.getNickNames().size());// 4
     65         System.err.println();
     66 
     67         // 3 Inline lists, Inline Maps
     68         Object val1 = parser.parseExpression("{1,2,3,4}").getValue();
     69         System.err.println(val1);// [1, 2, 3, 4]
     70         System.err.println(val1.getClass());// class java.util.Collections$UnmodifiableRandomAccessList
     71         System.err.println(parser.parseExpression("{{1,2},{3,4}}").getValue());// [[1, 2], [3, 4]]
     72 
     73         Object val2 = parser.parseExpression("{name:'zhangsan', age:20}").getValue();
     74         System.err.println(val2);// {name=zhangsan, age=20}
     75         System.err.println(val2.getClass());// class java.util.Collections$UnmodifiableMap
     76         System.err.println(parser.parseExpression("{p1:{1,2}, p2:{3,4}}").getValue());// {p1=[1, 2], p2=[3, 4]}
     77         System.err.println();
     78 
     79         // 4 Array Construction
     80         int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue();
     81         int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue();
     82         int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue();
     83         System.err.println();
     84 
     85         // 5 Methods
     86         System.err.println(parser.parseExpression("'Hello World'.concat('!')").getValue());// Hello World!
     87         System.err.println(parser.parseExpression("'Hello World'.bytes.length").getValue());// 11
     88         System.err.println();
     89 
     90         // 6 Operators: Relational Operators, Logical Operators, Mathematical Operators
     91         System.err.println(parser.parseExpression("name=='张三丰'").getValue(p));// true
     92         System.err.println(parser.parseExpression("1 < 2").getValue());// true
     93         System.err.println(parser.parseExpression("1 lt 2").getValue());// true
     94         System.err.println(parser.parseExpression("'a' < 'b'").getValue());// true
     95         System.err.println(parser.parseExpression("2 instanceof T(Integer)").getValue());// true
     96         System.err.println(parser.parseExpression("'5.00' matches '^-?\d+(\.\d{2})?$'").getValue());// true
     97 
     98         System.err.println(parser.parseExpression("true and false").getValue(Boolean.class));// false
     99         System.err.println(parser.parseExpression("true or false").getValue(Boolean.class));// true
    100         System.err.println(parser.parseExpression("not false").getValue(Boolean.class));// true
    101         System.err.println(parser.parseExpression("! false").getValue(Boolean.class));// true
    102 
    103         System.err.println(parser.parseExpression(" 1 + -1*8 + 7%4 +8/3 - -1").getValue());// -1
    104         System.err.println();
    105 
    106         // 7 Types
    107         System.err.println(parser.parseExpression("T(System).getProperty('user.dir')").getValue());/// Users/zhangsan/software/eclipse-workspace/CourseDesignServer
    108         System.err.println(parser.parseExpression("T(java.util.Date)").getValue(Class.class));// class java.util.Date
    109         System.err.println(parser.parseExpression("T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR").getValue());// true
    110         System.err.println();
    111 
    112         // 8 Variables
    113         EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();// new StandardEvaluationContext();
    114         context.setVariable("newName", "张君宝");
    115         System.err.println(parser.parseExpression("name = #newName").getValue(context, p)); // 张君宝
    116         System.err.println(p.getName());// 张君宝
    117 
    118         context.setVariable("primes", Arrays.asList(2, 3, 5, 7, 11, 13, 17));
    119         System.err.println(parser.parseExpression("#primes.?[#this>10]").getValue(context));// [11, 13, 17]
    120         System.err.println(parser.parseExpression("#primes.#this").getValue(context, p));// [2, 3, 5, 7, 11, 13, 17]
    121         System.err.println(parser.parseExpression("#primes.#root").getValue(context, p));// SpELTest.Person(name=张君宝, booleans=[false], nickNames=[, , , ],
    122                                                                                             // friendAge={小李=10})
    123         System.err.println(parser.parseExpression("#this").getValue(context, p));// SpELTest.Person(name=张君宝, booleans=[false], nickNames=[, , , ],
    124                                                                                     // friendAge={小李=10})
    125         System.err.println(parser.parseExpression("#root").getValue(context, p));// SpELTest.Person(name=张君宝, booleans=[false], nickNames=[, , , ],
    126                                                                                     // friendAge={小李=10})
    127         // The #this variable is always defined and refers to the current evaluation
    128         // object, The #root variable is always defined and refers to the root context
    129         // object.
    130         System.err.println();
    131 
    132         // 9 Register Functions
    133         context.setVariable("myReverseString", SpELTest.class.getDeclaredMethod("reverseString", String.class));
    134         System.err.println(parser.parseExpression("#myReverseString('hello')").getValue(context));// olleh
    135         System.err.println();
    136 
    137         // 10 Ternary Operator (If-Then-Else), Elvis Operator
    138         System.err.println(parser.parseExpression("name?:'Unknown'").getValue(p));// 张君宝
    139         System.err.println(parser.parseExpression("1>0?'yes':'no' ").getValue());// yes
    140         System.err.println(parser.parseExpression("1>0?:'no' ").getValue());// true
    141         System.err.println();
    142 
    143         // 11 Collection Selection. Selection is possible upon both lists and maps.
    144         // .?[selectionExpression] all matched elements
    145         // .^[selectionExpression] first matched elements
    146         // .$[selectionExpression] last matched elements
    147 
    148 //        System.err.println(parser.parseExpression("booleans.?[#this=true]").getValue(p));//
    149 
    150         p.getFriendAge().put("小张", 20);
    151         System.err.println(parser.parseExpression("friendAge.?[value>10] ").getValue(p));// {小张=20}
    152         System.err.println(parser.parseExpression("friendAge.?[key!=null] ").getValue(p));// {小李=10, 小张=20}
    153         System.err.println(parser.parseExpression("friendAge.^[key!=null] ").getValue(p));// {小李=10}
    154         System.err.println(parser.parseExpression("friendAge.$[key!=null] ").getValue(p));// {小张=20}
    155         System.err.println();
    156 
    157         // 12 Collection Projection. .![projectionExpression]
    158         System.err.println(parser.parseExpression("friendAge.![key+value] ").getValue(p));// [小李10, 小张20]
    159         System.err.println();
    160 
    161         // 13 Expression templating
    162         System.err.println(parser.parseExpression("random number is #{T(java.lang.Math).random()}", new TemplateParserContext()).getValue());// random number is 0.7043883689415746
    163         System.err.println();
    164 
    165     }
    166 
    167     public static String reverseString(String input) {
    168         StringBuilder backwards = new StringBuilder(input.length());
    169         for (int i = 0; i < input.length(); i++) {
    170             backwards.append(input.charAt(input.length() - 1 - i));
    171         }
    172         return backwards.toString();
    173     }
    174 }
    View Code

    String类型自动转换

    强烈推荐阅读下面列出的各文章,写得深入易懂。

    Spring Framework中的String类型转换器、格式化器经过了多个发展阶段,概述如下(详情参阅:Spring类型转换-框架设计的基石):

    1 PropertyEditor: (名字的由来:早期JDK AWT中为了解析GUI界面用户输入的值而引入,故叫ProperEditor,Spring基于PropertyEditor做增强)

    Spring PropertyEditor及其各种实现:ProperyEditor、ProperyEditorSupport

    Spring对PropertyEditor的注册和管理机制:PropertyEditorRegistry、PropertyEditorRegistrySupport、PropertyEditorRegistrar。

    PropertyEditorRegistrar在Spring内的唯一实现为ResourceEditorRegistrar,配置文件转为Resource(如配置classpath:xxx.xml用来启动Spring容器的配置文件,String -> Resource转换)就是它的功劳。

    2 新一代类型转换器:Spring 新一代类型转换机制。Spring中对HTTP请求参数的自动解析转换、@Value参数的解析等都是基于此。

    转换器接口及其实现:

    Converter<S, T>:  Source -> Target类型转换接口,适用于1:1转换

    ConverterFactory<S, R>:  Source -> R类型转换接口,适用于1:N转换

    GenericConverter:  更为通用的类型转换接口,适用于N:N转换

    ConditionalConverter:  可跟上面3个接口搭配组合使用,提供前置条件判断验证

    3 ConversionService:上述转换器的注册和管理,见 注册中心服务

    ConverterRegistry、ConversionService、DefaultConversionService、ConversionServiceFactoryBean

    4 JDK的format(java.text.format):DateFormat、NumberFormat、MessageFormat。详情参阅 JDK 格式化器

    DateFormat:日期时间格式化——日期字符串与Java日期类型间的解析或格式化

    NumberFormat:数值格式化

    DecimalFormat:数值的有效位保留、科学技术法、分组分隔、百分数表示、货币符表示

    ChoiceFormat:维护数字与字符串间的对应关系。用的很少。

    MessageFormat:字符串格式——用于在字符串中插入参数

    缺点:设计上存在一定缺陷,过于底层无法标准化对使用者不够友好等。

     、

    5 大一统的Spring Format

    Spring格式化器:org.springframework.format.Formatter,进行了应用层面的封装,更友好易用,内部还是借助 java.text.Format、java.time下的format 、java.text.NumberFormat 等实现。

    Spring格式化器的注册中心:FormatterRegistry,此接口继承自类型转换器注册中心 ConverterRegistry,所以格式化注册中心是转换器注册中心的加强版,是其超集,功能更多更强大。

    FormatterRegistry、FormattingConversionService、DefaultFormattingConversionService

      、  

     

     

     

     

  • 相关阅读:
    $.unique()去重问题
    js判断中文
    js URL中文传参乱码
    zabbix添加nginx监控
    TCP/IP与OSI参考模型原理
    100个linux系统常用指令
    read指令使用方法
    grep与正则表达式使用
    shell脚本中case的用法
    shell脚本:变量,文件判断,逻辑运算等纪要
  • 原文地址:https://www.cnblogs.com/z-sm/p/14353819.html
Copyright © 2020-2023  润新知