JSF本身對於Bean的管理有依賴注入的功能,不過Spring的IoC容器提供更多的功能,另一方面Spring還有AOP框架,在事務處理上也可以幫的上忙。
JSF與Spring的結合,主要目的就是讓Spring的Bean名稱可以被JSF視作為<managed-bean-name>標籤上的
名稱來使用,也就是當您在JSF定義檔中根據一個名稱要求一個Bean實例時,若JSF在自己的
Context中找不到名稱,可以嘗試到Spring的Context中去尋找。
來改寫一下 第一個 JSF 程式,以示範JSF與Spring是如何結合運作的,首先設計一個簡單的UserChanger類別:
package onlyfun.caterpillar;
public class UserChanger { public String getChangedName(String name) { return name.toUpperCase(); } }
這個類別會將傳入的名稱改成大寫,用來模擬商務層的一個物件,接著來改寫一下User類別:
package onlyfun.caterpillar;
public class User { private String name; private UserChanger userChanger; public void setName(String name) { this.name = getUserChanger().getChangedName(name); } public String getName() { return name; } public void setUserChanger(UserChanger userChanger) { this.userChanger = userChanger; } public UserChanger getUserChanger() { return userChanger; } }
User類別中接受UserChecker類別的實例注入,使用者送出的名稱會被UserChecker類別的實例改為大寫,您可以使用
org.springframework.web.jsf.DelegatingVariableResolver類別讓Spring的Bean名稱可以
在JSF中曝光,您可以在JSF的faces-config.xml中設定:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN" "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
<faces-config> <application> <variable-resolver> org.springframework.web.jsf.DelegatingVariableResolver </variable-resolver> </application> <navigation-rule> <from-view-id>/pages/index.jsp</from-view-id> <navigation-case> <from-outcome>login</from-outcome> <to-view-id>/pages/welcome.jsp</to-view-id> </navigation-case> </navigation-rule> <managed-bean> <managed-bean-name>user</managed-bean-name> <managed-bean-class> onlyfun.caterpillar.User </managed-bean-class> <managed-bean-scope>session</managed-bean-scope> <managed-property> <property-name>userChanger</property-name> <value>#{userChanger}</value> </managed-property> </managed-bean> </faces-config>
實際上在JSF的定義檔中並沒有定義userChanger的Bean實例,當JSF找不到userChanger時,會使用
DelegatingVariableResolver物件於Spring的Context中尋找同名的Bean實例,假設您的Bean定義檔是這麼撰寫
的:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="userChanger" class="onlyfun.caterpillar.UserChanger"/> </beans>
為了讓DelegatingVariableResolver物件知道Bean定義檔的名稱與位置,您必須在web.xml中使用
org.springframework.web.context.ContextLoaderListener類別,並使用<context-
param>標籤指定Bean定義檔的名稱與位置,例如:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee → http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <session-config> <session-timeout> 30 </session-timeout> </session-config>
<listener> <listener-class> org.springframework.web. → context.ContextLoaderListener </listener-class> </listener>
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/beans-config.xml</param-value> </context-param> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class> javax.faces.webapp.FacesServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.faces</url-pattern> </servlet-mapping> </web-app>
在不支援Listener設定的容器上(例如Servlet 2.2以更早的版本),您可以使用org.springframework.web.context.ContextLoaderServlet來取代上面的Listener設定,例如:
...
<servlet>
<servlet-name>demoConfig</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
</servlet>
...
現在您可以運作一下程式,看一下執行的結果中,在送出使用者的名稱之後,是否會被改寫為大字。
|