ITEEDU

在 JSF 中整合 Spring

JSF本身对于Bean的管理有依赖注入的功能,不过Spring的IoC容器提供更多的功能,另一方面 Spring还有AOP框架,在事务处理上也可以帮的上忙。

JSF与Spring的结合,主要目的就是让Spring的Bean名称可以被JSF视作为<managed‐bean‐name>标 签上的 名称来使用,也就是当您在JSF定义档中根据一个名称要求一个Bean实例时,若JSF在自己 的 Context中找不到名称,可以尝试到Spring的Context中去寻找。

来改写一下 第一个 JSF   程式,以示范JSF与Spring是如何结合运作的,首先设计一个简单的 UserChanger类别:

•      UserChanger.java
package onlyfun.caterpillar;
public class UserChanger {
	public String getChangedName(String name) {
		return name.toUpperCase();
	}
}

这个类别会将传入的名称改成大写,用来模拟商务层的一个物件,接着来改写一下 User 类别:

•      User.java
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 中设定:

•      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 定义档是这么撰写 的:

•      beans‐config.xml
<?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 定义档的名称与位置,例如:

•      web.xml
<?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>
...

现在您可以运作一下程式,看一下执行的结果中,在送出使用者的名称之后,是否会被改写为大 字。