Spring学习笔记--在SpEL中筛选集合

Posted 月光诗人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring学习笔记--在SpEL中筛选集合相关的知识,希望对你有一定的参考价值。

要用到Spring的util(包括util:list等),xml文件中的beans中需要添加一些有关util的信息:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <!-- bean definitions here -->

</beans>

首先定义一个City类。

package com.moonlit.myspring;

public class City {
    private String name;
    private String state;
    private int population;
    @Override
    public String toString() {
        return String.format("[%s,%s,%d]", name, state, population);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
    public int getPopulation() {
        return population;
    }
    public void setPopulation(int population) {
        this.population = population;
    }
}

使用<util:list>元素在Spring里配置一个包含City对象的List集合。

  <util:list id="cities">
    <bean class="com.moonlit.myspring.City"
      p:name="Beijing" p:state="BJ" p:population="215213241" />
    <bean class="com.moonlit.myspring.City"
      p:name="Shanghai" p:state="SH" p:population="242612378" />
    <bean class="com.moonlit.myspring.City"
      p:name="Guangzhou" p:state="GD" p:population="12700812" />
    <bean class="com.moonlit.myspring.City"
      p:name="Hangzhou" p:state="HZ" p:population="8700420" />
    <bean class="com.moonlit.myspring.City"
      p:name="Baoding" p:state="BD" p:population="11194443" />
    <bean class="com.moonlit.myspring.City"
      p:name="Harbin" p:state="HRB" p:population="10636003" />
    <bean class="com.moonlit.myspring.City"
      p:name="Shuzhou" p:state="SZ" p:population="10466092" />
    <bean class="com.moonlit.myspring.City"
      p:name="Xian" p:state="XA" p:population="8467821" />
  </util:list>

<util:list>元素是由Spring的util命名空间所定义的。它创建了一个java.util.List类型的Bean,这个集合里包含了所有以上配置的Bean。
<util:list>对象也是一个Bean,我们可以通过以下方式获得cities:

List<City> cities = (List<City>) context.getBean("cities");

可以通过如下方式访问集合成员:

    <property name="chosenCity" value="#{cities[2]}" />
    <property name="randomChosenCity" value="#{cities[T(java.lang.Math).random() * cities.size()]}" />

中括号([])运算符会始终通过索引访问集合中的成员。
[]运算符同样可以用来获取java.util.Map集合中的成员。例如,假设City对象以其名字作为键放入Map集合中。在这种场景下,我们可以像下面展示的那样获取键为Dallas的entry:

<property name="choseCity" value="#{cities[\'Dallas\']}" />

[]运算符还可以从java.util.Properties集合中获取值。例如,假设我们需要通过<util:properties>元素在Spring中加载一个properties配置文件:

<util:properties id="settings" location="classpath:setting.properties" />

这里定义的settings Bean是一个java.util.Propertes类,夹在了一个名为名为settings.properties的文件。我们可以使用SpEL获得settings Bean中名为twitter.accessTokend的对象:

<properties name="accessToken" value="#{settings[\'twitter.accessToken\']}" />

除了访问<util:properties>所生命的集合中的属性,Spring还为SpEL选择了两种特殊的选择属性的方式:systemEnvironment和systemProperties。
systemEnvironment包含了应用程序所在机器上的所有环境变量。

<property name="homePath" value="${systemEnvironment[\'HOME\']}" />

systemPropreties包含了Java应用程序启动时所设置的所有属性(通常通过-D参数)。例如,如果使用-Dapplication.home=/etc/myapp,来启动JVM,那么你就可以通过以下SpEL表达式将该值注入homePath属性中:

<property name="homePath" value="#{systemProperties[\'application.home\']}" />

[]运算符同样可以通过索引来得到字符串的某个字符。例如,下面的表达式返回“s”:

\'This is a test\'[3]

查询集合成员 —— 查询运算符(.?[])

<property name="bigCities" value="#{cities.?[population gt 2e7]}" />

查询运算符会创建一个新的集合,新的集合中只存放符合中括号内的表达式的成员。这里,bigCIties属性被注入了人口多于20000000的城市集合。
SpEL还提供了两种其他查询运算符:
“.^[]”:从集合中查询第一个匹配项。
“.$[]”:从集合中查询最后一个匹配项。
例如:

<property name="aBigCity" value="#{cities.^[population gt 2e7]}" />
<property name="aBigCity" value="#{cities.$[population gt 2e7]}" />

投影集合 —— 投影运算符(.![])
集合投影是从集合的每一个元素中选择特定的属性放入一个新的集合中。
例如,从cities中获得所有的name:

<property name="cityNames" value="#{cities.![name]}" />

查询运算符.?[]和投影运算符.![]可以混合使用。

<property name="sityNames" value="#{cities.?[population gt 2e7].![name + \',\' + state]}" />

演示上面部分效果的程序:

package com.moonlit.myspring;

import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Hero {
    private City chosenCity;
    private City randomChosenCity;
    private String homePath; 
    private List<City> bigCities;
    private List<String> cityNames;
    public void perform() {
        System.out.println("chosen city = " + chosenCity);
        System.out.println("random chosen city = " + randomChosenCity);
        System.out.println("home path = " + homePath);
        System.out.println("big cities:");
        for (City city : bigCities)
            System.out.println("\\t" + city);
        System.out.println("city names :");
        for (String cityName : cityNames)
            System.out.println("\\t" + cityName);
    }
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "spring-util-idol.xml");
        // util:list is also a bean
        List<City> cities = (List<City>) context.getBean("cities");
        for (City city : cities)
            System.out.println(city);
        Hero hero = (Hero) context.getBean("hero");
        hero.perform();
        
        
    }
    public City getChosenCity() {
        return chosenCity;
    }
    public void setChosenCity(City chosenCity) {
        this.chosenCity = chosenCity;
    }
    public City getRandomChosenCity() {
        return randomChosenCity;
    }
    public void setRandomChosenCity(City randomChosenCity) {
        this.randomChosenCity = randomChosenCity;
    }
    public String getHomePath() {
        return homePath;
    }
    public void setHomePath(String homePath) {
        this.homePath = homePath;
    }
    public List<City> getBigCities() {
        return bigCities;
    }
    public void setBigCities(List<City> bigCities) {
        this.bigCities = bigCities;
    }
    public List<String> getCityNames() {
        return cityNames;
    }
    public void setCityNames(List<String> cityNames) {
        this.cityNames = cityNames;
    }
    
}
Hero.java
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <!-- bean definitions here -->

  <util:list id="cities">
    <bean class="com.moonlit.myspring.City"
      p:name="Beijing" p:state="BJ" p:population="21521324" />
    <bean class="com.moonlit.myspring.City"
      p:name="Shanghai" p:state="SH" p:population="24261237" />
    <bean class="com.moonlit.myspring.City"
      p:name="Guangzhou" p:state="GD" p:population="12700812" />
    <bean class="com.moonlit.myspring.City"
      p:name="Hangzhou" p:state="HZ" p:population="8700420" />
    <bean class="com.moonlit.myspring.City"
      p:name="Baoding" p:state="BD" p:population="11194443" />
    <bean class="com.moonlit.myspring.City"
      p:name="Harbin" p:state="HRB" p:population="10636003" />
    <bean class="com.moonlit.myspring.City"
      p:name="Shuzhou" p:state="SZ" p:population="10466092" />
    <bean class="com.moonlit.myspring.City"
      p:name="Xian" p:state="XA" p:population="8467821" />
  </util:list>
  
  <bean id="hero" class="com.moonlit.myspring.Hero">
    <property name="chosenCity" value="#{cities[2]}" />
    <property name="randomChosenCity" value="#{cities[T(java.lang.Math).random() * cities.size()]}" />
    <property name="homePath" value="#{systemEnvironment[\'HOME\']}" />
    <property name="bigCities" value="#{cities.?[population gt 2e7]}" />
    <property name="cityNames" value="#{cities.![name]}" />
  </bean>

</beans>
spring-util-idol.xml

扩展阅读(Spring4.0.x doc里面的xml配置信息和很多例子):http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/xsd-config.html

理解:
<util:list>,<util:map>,<util:properties>可以装配集合,使用前请声明util命名空间。
通过<util:properties id="XX" location="classpath:YY.properties">读取YY.properties文件。
查询运算符:
.?[]:查询所有匹配项
.^[]:查询第一个匹配项
.$[]:查询最后一个匹配项
投影运算符:
.![]

以上是关于Spring学习笔记--在SpEL中筛选集合的主要内容,如果未能解决你的问题,请参考以下文章

Spring学习笔记--Spring表达式语言SpEL

无法在 SpEL 中为 Spring Data MongoDB 集合名称解析 bean

Spring 可缓存 - 使用 SpEL 过滤掉空集合

从头认识Spring-1.16 SpEl对集合的操作-查询集合以及投影元素集合

从头认识Spring-1.16 SpEl对集合的操作-建立集合以及访问集合的元素,以<util:list/>为例

SPRING IN ACTION 第4版笔记-第三章ADVANCING WIRING-008-SpEL介绍