Spring --- SpEL

一)什么是SpEL 
  SpEL -- Spring Expression Language. Spring的表达式语言。举个最简单的例子: 
Java代码   收藏代码
  1. ExpressionParser parser =new SpelExpressionParser();  
  2. Expression exp = parser.parseExpression("'Hello World'");  
  3. String message = (String) exp.getValue();  

    最后 message的值就是 Hello World, 表达式中的单引号''就是表达String类型的一种格式。另外值得注意的一点时,当表达式不符合规范时, parser.parseExpression语句会抛出ParseException;而exp.getValue会抛出EvaluationException 
    而为了避免最后的类型转换,我们还可以这样写: 
Java代码   收藏代码
  1. String message = exp.getValue(String.class);  


二)SpEL举例中需要使用到的类 
    以下是本文介绍SpEL过程中需要使用到的类,在此列出,以供后续介绍中使用参考: 
Inventor.java 
Java代码   收藏代码
  1. package org.spring.samples.spel.inventor;  
  2. import java.util.Date;  
  3. import java.util.GregorianCalendar;  
  4.   
  5. public class Inventor {  
  6.   private String name;  
  7.   private String nationality;  
  8.   private String[] inventions;  
  9.   private Date birthdate;  
  10.   private PlaceOfBirth placeOfBirth;  
  11.   
  12.   public Inventor(String name, String nationality){  
  13.     GregorianCalendar c= new GregorianCalendar();  
  14.     this.name = name;  
  15.     this.nationality = nationality;  
  16.     this.birthdate = c.getTime();  
  17.   }  
  18.   public Inventor(String name, Date birthdate, String nationality) {  
  19.     this.name = name;  
  20.     this.nationality = nationality;  
  21.     this.birthdate = birthdate;  
  22.   }  
  23.   public Inventor() {}  
  24.   
  25.   public String getName() { return name;}  
  26.   public void setName(String name) { this.name = name;}  
  27.   
  28.   public String getNationality() { return nationality;}  
  29.   public void setNationality(String nationality) { this.nationality = nationality; }  
  30.   
  31.   public Date getBirthdate() { return birthdate;}  
  32.   public void setBirthdate(Date birthdate) { this.birthdate = birthdate;}  
  33.   
  34.   public PlaceOfBirth getPlaceOfBirth() { return placeOfBirth;}  
  35.   public void setPlaceOfBirth(PlaceOfBirth placeOfBirth) { this.placeOfBirth = placeOfBirth;}  
  36.   
  37.   public void setInventions(String[] inventions) { this.inventions = inventions; }  
  38.   public String[] getInventions() { return inventions;}  
  39. }  

PlaceOfBirth.java 
Java代码   收藏代码
  1. package org.spring.samples.spel.inventor;  
  2.   
  3. public class PlaceOfBirth {  
  4.   private String city;  
  5.   private String country;  
  6.   
  7.   public PlaceOfBirth(String city) {this.city=city;}  
  8.   public PlaceOfBirth(String city, String country){  
  9.     this(city);  
  10.     this.country = country;  
  11.   }  
  12.   
  13.   public String getCity() {return city;}  
  14.   public void setCity(String s) {this.city = s;}  
  15.   
  16.   public String getCountry() {return country;}  
  17.   public void setCountry(String country) {this.country = country;}  
  18. }  

Society.java 
Java代码   收藏代码
  1. package org.spring.samples.spel.inventor;  
  2. import java.util.*;  
  3.   
  4. public class Society {  
  5.   private String name;  
  6.   public static String Advisors = "advisors";  
  7.   public static String President = "president";  
  8.   private List<Inventor> members = new ArrayList<Inventor>();  
  9.   private Map officers = new HashMap();  
  10.   
  11.   public List getMembers() {return members;}  
  12.   public Map getOfficers() {return officers;}  
  13.   public String getName() {return name;}  
  14.   public void setName(String name) {this.name = name;}  
  15.   public boolean isMember(String name){  
  16.     boolean found = false;  
  17.     for (Inventor inventor : members) {  
  18.       if (inventor.getName().equals(name)){  
  19.         found = true;  
  20.         break;  
  21.       }  
  22.     }  
  23.     return found;  
  24.   }  
  25. }  


三)EvaluationContext接口 
    当在使用表达式的过程中有遇到类型转换时,我们需要EvaluationContext接口加以辅助: 
Java代码   收藏代码
  1. class Simple {  
  2.   public List<Boolean> booleanList = new ArrayList<Boolean>();  
  3. }  
  4.   
  5. Simple simple = new Simple();  
  6. simple.booleanList.add(true);  
  7. EvaluationContext simpleContext = new StandardEvaluationContext(simple);  
  8. // false is passed in here as a string. SpEL and the conversion service will  
  9. // correctly recognize that it needs to be a Boolean and convert it  
  10. parser.parseExpression("booleanList[0]").setValue(simpleContext, "false");  
  11. // b will be false  
  12. Boolean b = simple.booleanList.get(0);  

注:EvaluationContext开销较大,所以多用于数据变化较少的情况。如果数据变化频繁,我们可以考虑直接引用对象(比如上例中的simple)以减小开销。 

四)SpEL 
  下面正式开始介绍SpEL。 
1'Literal expressions 基本类的表达式 
Java代码   收藏代码
  1. ExpressionParser parser = new SpelExpressionParser();  
  2. // evals to "Hello World"  
  3. String helloWorld = (String) parser.parseExpression("'Hello World'").getValue();  
  4. double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue();  
  5.   
  6. // evals to 2147483647  
  7. int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue();  
  8. boolean trueValue = (Boolean) parser.parseExpression("true").getValue();  
  9. Object nullValue = parser.parseExpression("null").getValue();  


2' Properties, Arrays, Lists, Maps, Indexers 属性、集合的表示 
    Properties: 
Java代码   收藏代码
  1. // evals to 1856  
  2. int year = (Integer) parser.parseExpression("Birthdate.Year + 1900").getValue(context);  
  3. String city = (String) parser.parseExpression("placeOfBirth.City").getValue(context);  

    arrays and lists: 
Java代码   收藏代码
  1. ExpressionParser parser = new SpelExpressionParser();  
  2. // Inventions Array  
  3. StandardEvaluationContext teslaContext = new StandardEvaluationContext(tesla);  
  4. // evaluates to "Induction motor"  
  5. String invention = parser.parseExpression("inventions[3]").getValue(teslaContext,String.class);  
  6.   
  7. // Members List  
  8. StandardEvaluationContext societyContext = new StandardEvaluationContext(ieee);  
  9. // evaluates to "Nikola Tesla"  
  10. String name = parser.parseExpression("Members[0].Name").getValue(societyContext, String.class);  
  11.   
  12. // List and Array navigation  
  13. // evaluates to "Wireless communication"  
  14. String invention = parser.parseExpression("Members[0].Inventions[6]").getValue(societyContext,String.class);  

   Map: 
Java代码   收藏代码
  1. // Officer's Dictionary  
  2. Inventor pupin = parser.parseExpression("Officers['president']").getValue(societyContext,Inventor.class);  
  3. // evaluates to "Idvor"  
  4. String city =  
  5. parser.parseExpression("Officers['president'].PlaceOfBirth.City").getValue(societyContext,String.class);  
  6. // setting values  
  7. parser.parseExpression("Officers['advisors'][0].PlaceOfBirth.Country").setValue(societyContext,"Croatia");  


3' construction 
    lists: 
Java代码   收藏代码
  1. // evaluates to a Java list containing the four numbers  
  2. List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue(context);  
  3. List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context);  

    arrays: 
Java代码   收藏代码
  1. int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue(context);  
  2. // Array with initializer  
  3. int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(context);  
  4. // Multi dimensional array  
  5. int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context);  


4' Methods 
Java代码   收藏代码
  1. // string literal, evaluates to "bc"  
  2. String c = parser.parseExpression("'abc'.substring(2, 3)").getValue(String.class);  
  3. // evaluates to true  
  4. boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(societyContext,  
  5. Boolean.class);  


5' Operators 
    Relational operators: 
Java代码   收藏代码
  1. // evaluates to true  
  2. boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class);  
  3. // evaluates to false  
  4. boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class);  
  5. // evaluates to true  
  6. boolean trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);  
  7. // evaluates to false  
  8. boolean falseValue = parser.parseExpression("'xyz' instanceof T(int)").getValue(Boolean.class);  
  9. // evaluates to true  
  10. boolean trueValue =  
  11. parser.parseExpression("'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);  
  12. //evaluates to false  
  13. boolean falseValue =  
  14. parser.parseExpression("'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);  

注意关键字:instanceof、matches 

    Logical operators: 
Java代码   收藏代码
  1. // evaluates to false  
  2. boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.class);  
  3. // evaluates to true  
  4. String expression = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')";  
  5. boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);  
  6. // -- OR -//  
  7. evaluates to true  
  8. boolean trueValue = parser.parseExpression("true or false").getValue(Boolean.class);  
  9. // evaluates to true  
  10. String expression = "isMember('Nikola Tesla') or isMember('Albert Einstien')";  
  11. boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);  
  12. // -- NOT -//  
  13. evaluates to false  
  14. boolean falseValue = parser.parseExpression("!true").getValue(Boolean.class);  
  15. // -- AND and NOT -String  
  16. expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";  
  17. boolean falseValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);  


    Mathematical operators: 
Java代码   收藏代码
  1. // Addition  
  2. int two = parser.parseExpression("1 + 1").getValue(Integer.class); // 2  
  3. String testString =  
  4. parser.parseExpression("'test' + ' ' + 'string'").getValue(String.class); // 'test string'  
  5. // Subtraction  
  6. int four = parser.parseExpression("1 - -3").getValue(Integer.class); // 4  
  7. double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class); // -9000  
  8. // Multiplication  
  9. int six = parser.parseExpression("-2 * -3").getValue(Integer.class); // 6  
  10. double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class); // 24.0  
  11. // Division  
  12. int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class); // -2  
  13. double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class); // 1.0  
  14. // Modulus  
  15. int three = parser.parseExpression("7 % 4").getValue(Integer.class); // 3  
  16. int one = parser.parseExpression("8 / 5 % 2").getValue(Integer.class); // 1  
  17. // Operator precedence  
  18. int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class); // -21  


6' Assignment 
Java代码   收藏代码
  1. Inventor inventor = new Inventor();  
  2. StandardEvaluationContext inventorContext = new StandardEvaluationContext(inventor);  
  3. parser.parseExpression("Name").setValue(inventorContext, "Alexander Seovic2");  
  4. // alternatively  
  5. String aleks = parser.parseExpression("Name = 'Alexandar Seovic'").getValue(inventorContext,String.class);  


7' Types 
Java代码   收藏代码
  1. Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class);  
  2. Class stringClass = parser.parseExpression("T(String)").getValue(Class.class);  
  3. boolean trueValue =  
  4. parser.parseExpression("T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR")  
  5. .getValue(Boolean.class);  

注: 在java.lang中的类不需要全路径。 

8' Constructors 
Java代码   收藏代码
  1. Inventor einstein =  
  2. p.parseExpression("new org.spring.samples.spel.inventor.Inventor('Albert Einstein','German')").getValue(Inventor.class);  
  3. //create new inventor instance within add method of List  
  4. p.parseExpression("Members.add(new org.spring.samples.spel.inventor.Inventor('Albert Einstein','German'))").getValue(societyContext);  


9' Variables 
Java代码   收藏代码
  1. Inventor tesla = new Inventor("Nikola Tesla""Serbian");  
  2. StandardEvaluationContext context = new StandardEvaluationContext(tesla);  
  3. context.setVariable("newName""Mike Tesla");  
  4. parser.parseExpression("Name = #newName").getValue(context);  
  5. System.out.println(tesla.getName()) // "Mike Tesla"  

注: Spring还有两个预留的variables: #this #root   #this表示集合中的当前元素,#root表示根对象,即载入context的对象。 

10' Functions 
    Function的使用略微复杂。首先是调用StandardEvaluationContext的方法 
Java代码   收藏代码
  1. public void registerFunction(String name, Method m)  
进行注册,而后才能在expression中进行调用: 
Java代码   收藏代码
  1. public abstract class StringUtils {  
  2.   public static String reverseString(String input) {  
  3.     StringBuilder backwards = new StringBuilder();  
  4.     for (int i = 0; i < input.length(); i++)  
  5.       backwards.append(input.charAt(input.length() - 1 - i));  
  6.     }  
  7.     return backwards.toString();  
  8.   }  
  9. }  
  10.   
  11.   
  12. ExpressionParser parser = new SpelExpressionParser();  
  13. StandardEvaluationContext context = new StandardEvaluationContext();  
  14. //先注册方法  
  15. context.registerFunction("reverseString",StringUtils.class.getDeclaredMethod("reverseString",new Class[] { String.class }));  
  16. //而后才能调用  
  17. String helloWorldReversed =  
  18. parser.parseExpression("#reverseString('hello')").getValue(context,String.class);  


11'Bean references 
Java代码   收藏代码
  1. ExpressionParser parser = new SpelExpressionParser();  
  2. StandardEvaluationContext context = new StandardEvaluationContext();  
  3. context.setBeanResolver(new MyBeanResolver());  
  4. // This will end up calling resolve(context,"foo") on MyBeanResolver during evaluation  
  5. Object bean = parser.parseExpression("@foo").getValue(context);  

没啥好多说的,知道用@就可以了~~ 

12'Ternary Operator 
Java代码   收藏代码
  1. String falseString = parser.parseExpression("false ? 'trueExp' : 'falseExp'").getValue(String.class);  

结果是: falseExp 

13'The Elvis Operator 
这是一种对三重操作符的简化写法。比如用三重操作符我们可以这样: 
Java代码   收藏代码
  1. String name = "Elvis Presley";  
  2. String displayName = name != null ? name : "Unknown";  

等效的用Elvis操作符实现的话就是这样: 
Java代码   收藏代码
  1. ExpressionParser parser = new SpelExpressionParser();  
  2. String name = parser.parseExpression("null?:'Unknown'").getValue(String.class);  
  3. System.out.println(name); // 'Unknown'  

省略了name的显示表达! 

14'Safe Navigation operator 
用?.取代. 当代码会抛出NullPointerException时,采用?.的操作仅仅会简单的返回一个null。 
Java代码   收藏代码
  1. ExpressionParser parser = new SpelExpressionParser();  
  2. Inventor tesla = new Inventor("Nikola Tesla""Serbian");  
  3. tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));  
  4. StandardEvaluationContext context = new StandardEvaluationContext(tesla);  
  5. String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class);  
  6. System.out.println(city); // Smiljan  
  7. tesla.setPlaceOfBirth(null);  
  8. city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class);  
  9. System.out.println(city); // null - does not throw NullPointerException!!!  


15' Collection Selection 
如果你要在集合内挑选符合某些条件的元素,你可以采用这样格式的表达式?[selectionExpression] 
Java代码   收藏代码
  1. List<Inventor> list = (List<Inventor>)  
  2. parser.parseExpression("Members.?[Nationality == 'Serbian']").getValue(societyContext);  
  3. Map newMap = parser.parseExpression("map.?[value<27]").getValue();  

而如果你只需要获得第一个满足条件的元素,你可以用:^[...] 
而如果你只需要获得最后一个满足条件的元素,你可以用:$[...] 

16' Collection Projection 
那么我需要便利某些元素以组成新的集合,我们可以采用这样的表达式![projectionExpression]: 
Java代码   收藏代码
  1. // returns [ 'Smiljan', 'Idvor' ]  
  2. List placesOfBirth = (List)parser.parseExpression("Members.![placeOfBirth.city]");  


17' Expression templating 
   template的作用便是在表达式内再嵌套表达式。比如: 
Java代码   收藏代码
  1. String randomPhrase =  
  2. parser.parseExpression("random number is #{T(java.lang.Math).random()}",new TemplateParserContext()).getValue(String.class);  
  3. // evaluates to "random number is 0.7038186818312008"  

而要实现内部嵌套的T(java.lang.Math).random()表达式。我们需要实现接口ParserContext: 
Java代码   收藏代码
  1. public class TemplateParserContext implements ParserContext {  
  2.   public String getExpressionPrefix() {  
  3.     return "#{";  
  4.   }  
  5.   public String getExpressionSuffix() {  
  6.     return "}";  
  7.   }  
  8.   public boolean isTemplate() {  
  9.     return true;  
  10.   }  
  11. }  


五)SpEL在配置中的使用 
  同样的语法,SpEL还能在配置文件和annotation中使用!!强大吧 ^.^ 它们的格式是#{ <expression string> } 
  在配置文件中: 
Java代码   收藏代码
  1. <bean id="numberGuess" class="org.spring.samples.NumberGuess">  
  2.   <property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/>  
  3.   <!-- other properties -->  
  4. </bean>  
  5. <bean id="taxCalculator" class="org.spring.samples.TaxCalculator">  
  6.   <property name="defaultLocale" value="#{ systemProperties['user.region'] }"/>  
  7.   <!-- other properties -->  
  8. </bean>  
  9. <bean id="numberGuess" class="org.spring.samples.NumberGuess">  
  10.   <property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/>  
  11.   <!-- other properties -->  
  12. </bean>  
  13. <bean id="shapeGuess" class="org.spring.samples.ShapeGuess">  
  14.   <property name="initialShapeSeed" value="#{numberGuess.randomNumber }"/>  
  15.   <!-- other properties -->  
  16. </bean>  

  在annotation中使用: 
Java代码   收藏代码
  1. public static class FieldValueTestBean{  
  2.   @Value("#{ systemProperties['user.region'] }")  
  3.   private String defaultLocale;  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值