2016年1月5日 星期二

SpEL2 (Spring3.x 十六)

※操作集合

※XML設定

XXX.java和Book.java

public class XXX {
    public List<String> l = new ArrayList<>(3);
    public Map<String, String> m = new HashMap<>(3);
    // setter/getter...
    
    public XXX() {
        l.add("a");
        l.add("b");
        l.add("c");
    
        m.put("A", "1");
        m.put("B", "2");
        m.put("C", "3");
    }
}
    
public class Book {
    private String cList;
    private String cMap;
    private Map<String, String> map;
    // setter/getter...
}



applicationContext.xml

<bean id="xxx" class="vo.XXX" />
    
<bean id="bo" class="vo.Book" p:map="#{xxx.m}">
    <property name="cList" value="#{xxx.l[1]}" />
    <property name="cMap" value="#{xxx.m['C']}" />
</bean>



測試類

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    
System.out.println(ctx.getBeanDefinitionCount());
for (String s : ctx.getBeanDefinitionNames()) {
    System.out.println(s);
}
    
Book book = ctx.getBean("bo", Book.class);
System.out.println(book.getcList());
System.out.println(book.getcMap());
System.out.println(book.getMap());
    
((ClassPathXmlApplicationContext) ctx).close();



※Annotation設定 

XXX.java只要在最上面加上@Component("xxx"),如果不想「()」,那就是大寫的「XXX」,xml要開啟

如果打錯spring就起不來了,可以將xxx相關的都註解掉,然後將測試類的bo全註解掉,看run起來時是抓到什麼bean


Book.java

@Component("bo")
public class Book {
    @Value("#{xxx.l[1]}")
    private String cList;
    
    @Value("#{xxx.m['C']}")
    private String cMap;
    
    @Value("#{xxx.m}")
    private Map<String, String> map;
    
    // setter/getter...
}



※三元運算子

xxx != null ? xxx:"ooo";
這是一般的寫法,xxx會重覆,所以SpEL又增加一種如下的寫法
xxx ?: "ooo"
原本的三元運算子還是可以用



※安全導航操作

foo.bar,這樣子寫有可能會導致NullPoint Exception,所以SpEL用一種特殊的寫法可以將它變成字串null,如下:
foo?.bar




※建構子

public class XXX {
    private String a;
    
    public XXX() {
    }
    
    public XXX(String a) {
        this.a = a;
    }
    
    public String getA() {
        return a;
    }
}
    
    
ExpressionParser parser = new SpelExpressionParser();
XXX xxx = parser.parseExpression("new vo.XXX('aaa')").getValue(XXX.class);
System.out.println(xxx.getA());



※#this和#root

ExpressionParser parser = new SpelExpressionParser();
EvaluationContext ctx = new StandardEvaluationContext();
    
ctx.setVariable("v", "A");
ctx.setVariable("v", "B");
    
String rtn1 = parser.parseExpression("#v").getValue(ctx, String.class);
System.out.println(rtn1);
    
ctx = new StandardEvaluationContext("C");
String rtn2 = parser.parseExpression("#root").getValue(ctx, String.class);
System.out.println(rtn2);
    
String rtn3 = parser.parseExpression("#this").getValue(ctx, String.class);
System.out.println(rtn3);
    
System.out.println(parser.parseExpression("#root='D'").getValue(ctx, String.class));
System.out.println(parser.parseExpression("#this='E'").getValue(ctx, String.class));

※結果:
B
C
C
D
E

※兩者看起來差不多,再看一個例子

List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17);
ExpressionParser parser = new SpelExpressionParser();
    
// #this
EvaluationContext ctx = new StandardEvaluationContext();
ctx.setVariable("primes", primes);
    
@SuppressWarnings("unchecked")
List<Integer> rtn = parser.parseExpression("#primes.?[#this gt 10]").getValue(ctx, List.class);
    
// #root
// EvaluationContext ctx = new StandardEvaluationContext(primes);
// @SuppressWarnings("unchecked")
// List<Integer> rtn = parser.parseExpression("#root.?[#this gt 10]").getValue(ctx, List.class);
// --------------------------------------
    
System.out.println(parser.parseExpression("#root").getValue(ctx, String.class));
System.out.println(parser.parseExpression("#this").getValue(ctx, String.class));
    
for (Integer i : rtn) {
    System.out.println(i);
}

※「.?」是選集合的意思,和安全導航操作的「?.」剛好相反,不要搞錯了

※結果:
null
null
11
13
17

※如果#this註解,#root打開的結果如下:
2,3,5,7,11,13,17
2,3,5,7,11,13,17
11
13
17

※看結果也是很像,但表達式裡使用#this不能使用root; 而使用#root不能使用primes(廢話)
要使用root時,必須在StandardEvaluationContext()參數裡塞值才有東西



※集合投影(.!)

就是迭代集合後,做一些操作
XXX.java和上面一樣



XXX xxx = new XXX();
List<String> ls = xxx.getL();
Map<String, String> ms = xxx.getM();
    
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext ctx = new StandardEvaluationContext();
ctx.setVariable("l", ls);
ctx.setVariable("m", ms);
    
@SuppressWarnings("unchecked")
List<String> rtnList = parser.parseExpression("#l.![#this+1]").getValue(ctx, List.class);
System.out.println(rtnList.iterator().next());
System.out.println("-----");
    
@SuppressWarnings("unchecked")
List<String> rtnMap1 = parser.parseExpression("#m.![#this.key + 1]").getValue(ctx, List.class);
Iterator<String> it1 = rtnMap1.iterator();
while (it1.hasNext()) {
    System.out.println(it1.next());
}
System.out.println("-----");
    
@SuppressWarnings("unchecked")
List<String> rtnMap2 = parser.parseExpression("#m.![#this.value+1]").getValue(ctx, List.class);
Iterator<String> it2 = rtnMap2.iterator();
while (it2.hasNext()) {
    System.out.println(it2.next());
}

※取map時,可以取key或value,用#this.key和#this.value,但#this可以不打,變成key+1和value+1


沒有留言:

張貼留言