Spring表達式語言

Spring表達式語言

Spring表達式是一個支持查詢和操作運行時對象de強大表達式語言,預發類似EL,提供額外的功能,函數調用和簡單字符串的模板函數。別的java表達式語言還有 OGNL, MVEL,JBoss EL 等等。
SpEL不依賴於Spring,可以獨立使用,當然也可以在Spring中使用。下邊是使用官網的例子作爲演示:
https://docs.spring.io/spring/docs/4.2.9.RELEASE/spring-framework-reference/html/expressions.html

簡單的表達式

準備需要的測試類

package com.jd.spel.bean;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author
 * @date 2018/10/16 14:33
 */
public  class Inventor {
    public List<Boolean> booleanList = new ArrayList<Boolean>();
    public List<String> list;
    private String name;
    private Date brithday;
    private String nationality;
    private String[] inventions;
    private PlaceOfBirth placeOfBirth;

    public Inventor() {
        this.brithday = new Date();
    }

    public Inventor(String name, Date brithday, String nationality) {
        this.name = name;
        this.brithday = brithday;
        this.nationality = nationality;
    }

    public String getName() {
        return name;
    }

    public Date getBrithday() {
        return brithday;
    }

    public String getNationality() {
        return nationality;
    }

    public String[] getInventions() {
        return inventions;
    }

    public PlaceOfBirth getPlaceOfBirth() {
        return placeOfBirth;
    }

    public void setInventions(String[] inventions) {
        this.inventions = inventions;
    }

    public void setPlaceOfBirth(PlaceOfBirth placeOfBirth) {
        this.placeOfBirth = placeOfBirth;
    }

    public void setBooleanList(List<Boolean> booleanList) {
        this.booleanList = booleanList;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setBrithday(Date brithday) {
        this.brithday = brithday;
    }

    public void setNationality(String nationality) {
        this.nationality = nationality;
    }
}

package com.jd.spel.bean;

/**
 *
 * @date 2018/10/16 14:32
 */
public class PlaceOfBirth {
    private String city;
    private String country;

    public PlaceOfBirth(String city) {
        this.city=city;
    }

    public PlaceOfBirth(String city, String country) {
        this(city);
        this.country = country;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String s) {
        this.city = s;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }
}
package com.jd.spel.bean;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @date 2018/10/16 14:31
 */
public class Society {

    private String name;

    public static String Advisors = "advisors";
    public static String President = "president";

    private List<Inventor> members = new ArrayList<Inventor>();
    private Map officers = new HashMap();

    public List getMembers() {
        return members;
    }

    public Map getOfficers() {
        return officers;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isMember(String name) {
        for (Inventor inventor : members) {
            if (inventor.getName().equals(name)) {
                return true;
            }
        }
        return false;
    }
}

/**
* 該類官網例子中沒有,我這邊建立的,有個認識就好
*/
class Ieee {
        private List<Inventor> members;

        public Ieee() {
            members = new ArrayList<>();
            for (int i = 0; i < 4; i++) {
                members.add(new Inventor("" + i, new Date(), "" + i));
            }
            members.get(0).setInventions(new String[]{"1212","12121"});
        }

        public List<Inventor> getMembers() {
            return members;
        }

        public void setMembers(List<Inventor> members) {
            this.members = members;
        }
    }

使用基本的表達式處理

ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello World'");
String message = (String) exp.getValue();
System.out.println("使用簡單的Expression解析表達式 " + message);


System.out.println("使用簡單的Expression解析使用concat表達式 " + message);

exp = parser.parseExpression("'Hello World'.concat('!')");
System.out.println("concat !" + (String) exp.getValue());

// invokes 'getBytes()'
exp = parser.parseExpression("'Hello World'.bytes");
byte[] bytes = (byte[]) exp.getValue();
System.out.println("bytes " + bytes);

// invokes 'getBytes().length'
exp = parser.parseExpression("'Hello World'.bytes.length");
int length = (Integer) exp.getValue();
System.out.println("bytes.length " + length);

exp = parser.parseExpression("new String('hello world').toUpperCase()");
message = exp.getValue(String.class);
System.out.println("toUpperCase " + message);

//執行後的結果-=---============
使用簡單的Expression解析表達式 Hello World
使用簡單的Expression解析使用concat表達式 Hello World
concat !Hello World!
bytes [B@1553973
bytes.length 11
toUpperCase HELLO WORLD

使用簡單對象處理

// Create and set a calendar
 GregorianCalendar c = new GregorianCalendar();
 c.set(1856, 7, 9);
 ExpressionParser parser = new SpelExpressionParser();
 Expression exp = parser.parseExpression("name");
 Inventor inventor = new Inventor("Nikola Tesla", c.getTime(), "Serbian");
 //
 Inventor inventor1 = new Inventor("222", c.getTime(), "Serbian");
 EvaluationContext context = new StandardEvaluationContext(inventor1);
 String name = (String) exp.getValue(context);  //獲得標準容器
 System.out.println("context: Inventor.name ->" + name);
 // The constructor arguments are name, birthday, and nationality.

 name = (String) exp.getValue(inventor);
 System.out.println("auto: Inventor.name ->" + name);


 exp = parser.parseExpression("name == 'Nikola Tesla'");
 boolean result = exp.getValue(context, Boolean.class); // evaluates to true
 System.out.println("evaluates boolean :" + result);

//運行後的結構-========
context: Inventor.name ->222
auto: Inventor.name ->Nikola Tesla
evaluates boolean :false

類型裝換

ExpressionParser parser = new SpelExpressionParser();
Inventor simple = new Inventor();
simple.booleanList.add(false);
StandardEvaluationContext simpleContext = new StandardEvaluationContext(simple);
parser.parseExpression("booleanList[0]").setValue(simpleContext, "false");
// b will be false
Boolean b = simple.booleanList.get(0);
System.out.println("Type Conversion " + b);

//運行後的結構-========
Type Conversion false

重構解析器配置

// 打開配置:
// - 引用值動態設置爲null
// - 自動增加集合的大小
SpelParserConfiguration config = new SpelParserConfiguration(true, true);
ExpressionParser parser = new SpelExpressionParser(config);
Expression expression = parser.parseExpression("list[3]");
Inventor demo = new Inventor();
Object o = expression.getValue(demo);
System.out.println("ParserConfiguration " + o);


//運行結果=====================
ParserConfiguration  //這裏的o什麼也沒有輸出

//設置使用立即編譯模式 有三種模式,
SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE,
             this.getClass().getClassLoader());
SpelExpressionParser parser = new SpelExpressionParser(config);
Expression expr = parser.parseExpression("name");
Inventor message = new Inventor();
Object payload = expr.getValue(message);
System.out.println(payload);  //輸入位null

properties, arrays, lists, maps

這裏就不寫例子了。在我們的系統配置文件上下文用過。

屬性引用

 Inventor simple = new Inventor();
 simple.setPlaceOfBirth(new PlaceOfBirth("北京"));

 StandardEvaluationContext context = new StandardEvaluationContext(simple);
 // evals to 2018
 int year = (Integer) parser.parseExpression("Brithday.Year + 1900").getValue(context);
 String city = (String) parser.parseExpression("placeOfBirth.City").getValue(context);
 System.out.println("year " + year + "; city " + city);


 String[] strings = new String[]{"32", "233", "3333"};
 simple.setInventions(strings);
 // Inventions Array
 StandardEvaluationContext teslaContext = new StandardEvaluationContext(simple);
 // evaluates to "Induction motor"
 String invention = parser.parseExpression("inventions[2]").getValue(
         teslaContext, String.class);
 System.out.println("Inventions Array " + invention);


 Ieee ieee = new Ieee();
 // Members List
 StandardEvaluationContext societyContext = new StandardEvaluationContext(ieee);
 // evaluates to "Nikola Tesla"
 String name = parser.parseExpression("Members[0].Name").getValue(
         societyContext, String.class);
 // List and Array navigation
 // evaluates to "Wireless communication"
 invention = parser.parseExpression("Members[0].Inventions[1]").getValue(
         societyContext, String.class);

 System.out.println("Members List of Members[0].Name :" + name  +"; Members[0].Inventions[1] :"+invention);

//運行結果
year 2018; city 北京
Inventions Array 3333
Members List of Members[0].Name :0; Members[0].Inventions[1] :12121

源碼分析

入口代碼

public class SpelExpressionParser extends TemplateAwareExpressionParser {
	private final SpelParserConfiguration configuration;
	/**
	 * Create a parser with default settings.
	 */
	public SpelExpressionParser() {
		this.configuration = new SpelParserConfiguration();
	}

	/**
	 * Create a parser with the specified configuration.
	 * @param configuration custom configuration options
	 */
	public SpelExpressionParser(SpelParserConfiguration configuration) {
		Assert.notNull(configuration, "SpelParserConfiguration must not be null");
		this.configuration = configuration;
	}
	public SpelExpression parseRaw(String expressionString) throws ParseException {
		return doParseExpression(expressionString, null);
	}

	@Override
	protected SpelExpression doParseExpression(String expressionString, ParserContext context) throws ParseException {
	//這裏主要是doParseExpression執行,可以看見主要實現在nternalSpelExpressionParser中
		return new InternalSpelExpressionParser(this.configuration).doParseExpression(expressionString, context);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章