而如果輸入錯誤的用戶註冊信息,Bean validation 規範會檢出輸入錯誤,AccountCreate.jsp 中顯示錯誤提示。如圖 20 所示。
利用 CDI 和 JSF2.0 簡化 Account Login 程序開發
JSR299 Contexts and Dependency Injection (CDI) 進一步提高了 Java EE 開發平台的易用性,提供了包括上下文管理,類型安全的依賴注入,攔截器綁定,與 JSF 的集成等服務。詳情參考”Dependency Injection in Java EE 6 系列文章”
JSF314 JSF2.0 則關注與 Web 應用的開發,以提高 Web 應用開發效率、降低維護複雜度為目標,並加入 Ajax 支持,Bean Validation 支持。詳情參考”JSF2 簡介系列文章“。
在 JSF2.0 中,通過 Expression Language (EL) 表達式語言與 @ManagedBean 注釋,將 Web 頁面與 Backing Bean 關聯在一起,參考清單 10。
JSF 表單: <h:inputText styleClass=”inputText” id=”username” value=”#{account.username}”> ManagedBean @ManagedBean(name=”account”) Public class Accountbean { Private String username …. } |
藉助 CDI 服務,我們可以用 @Named 注釋替代 @ManagedBean,將 CDI 引入 JSF backing bean 中,從而實現 JSF 與 CDI 的集成。
在本章中,我們將採用 CDI+JSF 的方式重寫 Account Login 程序,用 JSF 替代原有的 JSP 和 Servlet 實現表現層,並利用 CDI 特性更新原有的 EJB session bean。涉及的主要步驟為:
啟用 CDI 服務
CDI 上下文管理 @..Scoped
CDI 依賴注入 @Inject
JSF 2.0 Facelets 開發
CDI 與 JSF 集成
依照 JSR299 規範,開發人員必須在 .war 歸檔文件的 WEB-INF/ 目錄下或者其他類型歸檔文件的 META-INF/ 目錄下,放置 beans.xml 文件。參考清單 11:
<?xml version=”1.0″ encoding=”UTF-8″?> <beans xmlns=”http://java.sun.com/xml/ns/javaee” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd”> </beans> |
此外,CDI Bean 必須包含一個無參數的構造函數,或者其構造函數用 @Injection 修飾;CDI Bean 不能是抽象類(@Decorator CDI bean 除外);CDI Bean 不能是非靜態內部類。使用 CDI 服務時,請儘可能保證您的 bean 是可序列化的(implements Serializable)。
CDI 上下文管理 @..Scoped 服務
CDI 管理的每個對象的 Scope 和生命周期都被綁定到特定的上下文中。表 1 列出了 CDI 支持的上下文。
範圍 |
描述 |
Dependent | CDI 默認範圍,任何注入對象都默認依賴於其被注入的上下文 |
ApplicationScoped | 在應用程序範圍內存儲對象;例如,當數據在 Application 級別共享時,可以用 @ApplicationScoped 描述 |
RequestScoped | 在請求範圍內存儲對象;例如,當數據用於將 HTTP 請求傳遞到 JSF backing bean 中,可以用 @RequestScoped 描述 |
SessionScoped | 在會話範圍內存儲對象;例如,當用戶登錄憑據需要在整個 session 級別共享,可以用 @SessionScoped |
ConversationScoped | 當請求和會話範圍皆不適用,可以利用 ConversationScoped 自定義上下文。 |
在 Accout Login 程序中,EJB session bean AccountService 用於存儲用戶登陸憑信,因此我們可以用 @SessionScoped 描述 AccountService session bean,參考清單 12:
清單 12. SessionScoped EJB session bean
@Stateful @Named @SessionScoped public class AccountService implements Serializable { …. } |
用戶在登錄界面中會輸入用戶名 username、密碼信息 password,這兩個數據會傳遞到 JSF backing bean 中,用於觸發後續操作。由於 username 和 password 僅出現在 HTTP request 中,用 @RequestScoped 描述更適當。我們新建一個名為 Credentials.java 的 POJO 對象,存儲 username 和 password,參考清單 13。
清單 13. RequestScoped Credentials.java
@Named @RequestScoped public class Credentials implements Serializable { private static final long serialVersionUID = 1375763091581287708L; private String username; private String password; public Credentials() { super(); } Getters & Setters …. } |
在 CDI Bean 中,我們不僅可以通過 @Resource 等注釋將資源注入到 Java Bean,還可以通過 @Injection 注釋將任何 Java Bean 注入。
在 AccountService bean 中,我們將 Usertab 對象注入,用於存儲用戶登錄憑信,將 Credentials 對象注入,用於用戶登錄信息的驗證。通過 @Inject,我們不需要關心對象的創建、銷毀等額外工作。參考清單 14:
@Stateful @Named @SessionScoped public class AccountService implements Serializable { private static final long serialVersionUID = 7103565672729007156L; @PersistenceContext(unitName = “AccountManagementEJB”) EntityManager em; @Inject private Usertab user; @Inject private Credentials credential; …. public AccountService() { super(); }
public String login() { user = this.loginUser(credential.getUsername(),credential.getPassword()); if (user != null) return (“AccountInfo.jsf”); else return (“AccountLogin.jsf”); } public Usertab loginUser(String username, String password) { …. }
Getters() & Setters()…
} |
以下文章點擊率最高
Loading…