CDI Features

1、EL/SpELhtml

一、EL語言(CDI與表達式語言(EL)集成,容許在JavaServer Faces頁面或JavaServer Pages頁面中直接使用任何組件)java

1)概述;
EL是JSP內置的表達式語言,用以訪問頁面的上下文以及不一樣做用域中的對象 ,
取得對象屬性的值,或執行簡單的運算或判斷操做。EL在獲得某個數據時,會自動進行數據類型的轉換。
使用EL表達式輸出數據時,若是有則輸出數據,若是爲null則什麼也不輸出。正則表達式

2)語法:
a.EL表達式老是放在{}中,並且前邊有一個:做爲前綴::{}
b.獲取對象的屬性值能夠直接經過「對象.屬性名」:user.name;getsetc.[]:{user.name};注意:這裏的屬性名是get和set方法對應的屬性值,並非對象中的變量名。c.獲取對象的屬性也能夠經過「對象[「屬性名」]」:user.name;getsetc.[]:{user[「name」]}
d.獲取Map中屬性時能夠以直接經過屬性的key:map.key,{map.key},map.key,{map[key]}
e.在指定域中獲取屬性:
在EL表達式中若是咱們直接使用屬性名如:${user},它將會在四個域中由小到大依次查找。
順序:pageScope、requestScope、sessionScope、applicationScope。
也能夠指定從哪一個域中獲取:
${ pageScope .user }:當前頁面
${requestScope.user}:當前請求
${sessionScope.user}:當前會話
${sessionScope.user}:當前應用
數組

3)EL中包含11個隱含對象,這些對象能夠在EL表達式中直接使用:
a.pageContext,和JSP中的pageContext功能同樣
b.請求域:pageScope/requestScope/sessionScope/applicationScope
c.請求參數,參數對象主要用於獲取get或post請求中的參數:
param:獲取指定的請求參數,param.usernameparamValues:{param.username}paramValues:獲取請求參數數組,如:param.usernameparamValues::{paramValues.sport[1]}
d.其餘:header/headerValues/initParam/cookie
安全

4)EL支持數學運算和邏輯運算:
a.加減乘除:17+5=>22b.{17+5} => 22b.取餘%或mod:17+5=>22b.餘{17%5} => 2
c.比較運算符>,<,==,!=,<=,>=,eq,ne,lt,gt,le,ge:3>5{3&gt;5}或3>5或{3 gt 5} =>false
d.邏輯比較 &&或and,!或not,||或or,empty:${!true} => false
cookie

2.SpELsession

1)Spring框架的表達式語言(簡稱SpEL):是一個支持運行時查詢和操做對象圖的強大的表達式語言。
SpEL 爲 bean 的屬性進行動態賦值提供了便利.app

2)語法:SpEL 使用 #{…} 做爲定界符,全部在大框號中的字符都將被認爲是 SpEL。框架

3)運用範圍:
a. 對 bean 進行引用,調用屬性值:#{book.name}
b.調用方法以及引用對象中的屬性
引用方法:#{dog.run()},引用靜態方法:#{T(java.lang.Math).PI}
引用對象的屬性:#{user.name}
c.計算表達式的值
加減乘除:#{counter.total + 40},#{T(java.lang.Math).PI * 2}
加號做爲字符串鏈接符:#{user.name + ’ ’ + user.address}
比較運算符(>,<,=,>=,<=,,lt,gt,eq,le,ge):
#{counter.total == 100},#{counter.total le 1000}
if-else條件判斷,三元運算符:
#{user.name’Tom’ ? ‘Jess’}async

d.正則表達式的匹配(matches)
#{user.name matches ‘1{4,16}$’}
e.字面量的表示:
#{5},#{89.7},#{1e4},#{false}
可以使用單/雙引號做爲字符串表達符號:#{‘Chuck’},#{「Chuck」}

2、Decorator(裝飾注入組件的能力)

@Decorator

功能:修飾器,橫向
註冊一個修飾器類PaintedDecorator.java

@Decorator
public class PaintedDecorator implements Room {

@Inject
@Delegate
Room roomToBeDecorated; //註冊被修飾的房子,這裏是BlankRoom

public String showRoom() {
doPainting();
return roomToBeDecorated.showRoom() + 「刷牆漆」;
}

@Decorator
public class FlooredDecorator implements Room {

@Inject
@Delegate
Room roomToBeDecorated; //註冊被修飾的房子,這裏是BlankRoom

public String showRoom() {
doFlooring();
return roomToBeDecorated.showRoom() + 「鋪地板」;
}
// 鋪地板
private void doFlooring() {
System.out.print(「裝飾地板」);
}
}
註冊兩個被修飾類BlankRoom.java,修飾的基礎

public class BlankRoom implements Room {

public String showRoom() {
return 「毛胚房」;
}
}

激活修飾器,執行順序由下至上

cn.edu.sdut.softlab.FlooredDecorator cn.edu.sdut.softlab.PaintedDecorator 具體實現

@Named(「room」)
public class RoomController {

@Inject
Room room;

public String showRoom() {
return room.showRoom();
}
}
輸出

毛胚房刷牆漆鋪地板

3、Interceptor(使用類型安全攔截器綁定將攔截器與組件相關聯的能力)

@Interceptor

攔截器

功能:斷開邏輯插入功能,好比Logger
定義一個攔截器LoggedInterceptor.java
@Logged
@Interceptor
public class LoggedInterceptor implements Serializable {

public LoggedInterceptor(){}

// 攔截以後具體實現
@AroundInvoke
public Object logMethod(InvocationContext ctx) throws Exception {
System.out.println(「Entering method:」 + ctx.getMethod().getName()

  • " in class: " + ctx.getMethod().getDeclaringClass().getName());
    return ctx.proceed();
    }
    }
    調用攔截器

@Logged
public void checkin(){
System.out.println(「checkin room…」);
}
固然攔截器須要在beans.xml上激活



cn.edu.sdut.r314.AuditInterceptor
cn.edu.sdut.r314.LoggedInterceptor


固然攔截器也能夠修飾一整個組件,這樣只要調用這個組件的時候就會執行攔截器的內容

@Named
@Audit
public class RoomController {

/**

  • 訂房
  • @return
    */
    public void checkin(){
    System.out.println(「checkin room…」);
    }

/**

  • 退房
  • @return
    */
    public void checkout(){
    System.out.println(「checkout room…」);
    }

4、Producer(動態注入)

@Produces

功能: 製造組件,自定義組件分配

咱們先定義好一個接口Tasks.java以及他的實現類AsyncTask.java , SyncTask.java。以及一個枚舉類TaskType.java

public enum TaskType {
ASYNC,SYNC;
}
而後看一下@Produces是怎麼調用的

@RequestScoped
public class TaskProducers implements Serializable {

TaskType taskType = TaskType.ASYNC;
public TaskProducers() {
System.out.println(「TaskProducers constructor called」);
}

/**

  • change from @RequestScoped to @ApplicationScoped to see what happened.
  • @TODO why @SessionScoped failed here?
  • @param asyncTask async task
  • @param syncTask sync task
  • @return Task according to TaskType
    */
    @Produces
    @Preferred
    @SessionScoped
    public Task getTask(AsyncTask asyncTask, SyncTask syncTask) {
    System.out.println(「getTask called…」);
    switch (taskType) {
    case ASYNC:
    return asyncTask;
    case SYNC:
    return syncTask;
    default:
    return null;
    }
    }
    }
    你們看到這裏@Produces修飾Task類型的getTask()方法,而且添加一個Qualifter: @Preferred,也就是說produces 也能夠經過qualifter來區分。並且你們都知道在CDI中名字並不重要,重要的是組件類型。也就是說getTask()方法能夠修改成任意名字。還有就是可被申請的組件須要同過參數的形式注入。

調用組件TaskController.java

@Model
public class TaskController {

@Inject
@Preferred
Task task;

public String sayHello() {
return 「hello task:」 + task.getName();
}

@PostConstruct
public void init() {
System.out.println(「GreetingController post construct…」);
}

@PreDestroy
public void destroy() {
System.out.println(「GreetingController pre destroy…」);
}
}
這樣調用的就是Async組件;

介紹其餘幾個註解:

@Model = @Name + @RequestScope@PostConstruct:初始化組件,功能至關於構造器@PreDestory:銷燬組件

相關文章
相關標籤/搜索