10. 示例应用-06:rdvmedecins-pfm-spring
10.1. 移植
现在我们将前一个应用程序移植到 Spring / Tomcat 环境中:
![]() |
我们将基于两个已编写的应用程序。我们将使用:
- 02 版本的 [DAO] 和 [JPA] 层JSF / Spring,
- 来自 05 版 PFM / EJB 的 [web] / Primefaces mobile 层,
- Spring 配置文件(版本 02)
此处我们进行的工作与之前将 JSF2 / EJB / Glassfish 应用程序移植到 JSF2 / Spring Tomcat 环境时类似。因此我们将减少说明。 如有需要,读者可参考该移植案例。
我们将移植所需的所有项目都放在了一个新的文件夹 [rdvmedecins-pfm-spring] [1] 中:
![]() |
- [mv-rdvmedecins-spring-dao-jpa]:02版[DAO]和[JPA]的层,以及JSF / Spring,
- [mv-rdvmedecins-spring-metier]:02版[métier]的层,JSF / Spring,
- [mv-rdvmedecins-pfmobile]:05版Primefaces mobile的[web]层 / EJB,
- 在 [2] 中,我们将它们导入 NetBeans,
- 在 [3] 中,Web 项目的依赖关系不再正确:
- 针对 [DAO]、[JPA]、[métier] 层的依赖关系必须修改,使其现在指向 Spring 项目;
- Glassfish 服务器曾提供 JSF 的库。但在 Tomcat 服务器上已不再提供。因此必须将其添加到依赖项中。
[web] 项目的变更如下:
![]() |
[web] 层中的 [pom.xml] 文件现具有以下依赖项:
<dependencies>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>3.2</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>mobile</artifactId>
<version>0.9.1</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.1.8</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.1.8</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mv-rdvmedecins-spring-dao-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mv-rdvmedecins-spring-metier</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
出现了错误。这些错误是由 [web] 层中的 EJB 引用引起的。首先让我们研究一下 [Application] Bean:
![]() |
我们移除所有因缺少包而报错的行,将 [IMetier](这是它在 Spring 层 [métier] 中的名称)重命名为接口 [IMetierLocal],并使用 Spring 对其进行实例化:
package beans;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import rdvmedecins.metier.service.IMetier;
public class Application {
// 业务层
private IMetier metier;
// 错误
private List<Erreur> erreurs = new ArrayList<Erreur>();
private Boolean erreur = false;
public Application() {
try {
// 实例化 [métier] 层
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config-metier-dao.xml");
metier = (IMetier) ctx.getBean("metier");
} catch (Throwable th) {
// 记录错误
erreur = true;
erreurs.add(new Erreur(th.getClass().getName(), th.getMessage()));
while (th.getCause() != null) {
th = th.getCause();
erreurs.add(new Erreur(th.getClass().getName(), th.getMessage()));
}
return;
}
}
// 获取器
public Boolean getErreur() {
return erreur;
}
public List<Erreur> getErreurs() {
return erreurs;
}
public IMetier getMetier() {
return metier;
}
}
- 第 20-21 行:根据 Spring 配置文件实例化 [métier] 层。该配置文件即 [métier] 和 [1] 层所使用的配置文件。 我们将该文件复制到 Web 项目 [2] 中:
![]() |
- 第 22-31 行:我们处理可能出现的异常,并将异常堆栈记录在第 14 行的字段中。
完成上述操作后,Bean [Application] 已无错误。现在我们来看 Bean [Form]、[1] 和 [2]:
![]() |
|
由于缺少包,我们删除了所有出错的行(import 和注解),并将 [IMetier] 重命名为接口 [ImetierLocal]。这样就足以消除所有 [3] 的错误。
此外,需在 [Form] Bean 的代码中,为字段
// Application bean
private Application application;
在 [Application] 和 [Form] bean 中删除的某些注解,曾将类声明为具有特定作用域的 bean。 现在,此配置在以下文件中进行:
<?xml version='1.0' encoding='UTF-8'?>
<!-- =========== FULL CONFIGURATION FILE ================================== -->
<faces-config version="2.0"
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/web-facesconfig_2_0.xsd">
<application>
<!-- 消息文件 -->
<resource-bundle>
<base-name>
messages
</base-name>
<var>msg</var>
</resource-bundle>
<message-bundle>messages</message-bundle>
<default-render-kit-id>PRIMEFACES_MOBILE</default-render-kit-id>
</application>
<!-- applicationBean Bean -->
<managed-bean>
<managed-bean-name>applicationBean</managed-bean-name>
<managed-bean-class>beans.Application</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
<!-- 表单 Bean -->
<managed-bean>
<managed-bean-name>form</managed-bean-name>
<managed-bean-class>beans.Form</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>application</property-name>
<value>#{applicationBean}</value>
</managed-property>
</managed-bean>
</faces-config>
移植工作已完成。我们可以尝试运行该 Web 应用程序。
![]() |
我们将留给读者自行测试这个新应用程序。我们可以对其进行微调,以处理 [Application] Bean 初始化失败的情况。已知在此情况下,以下字段已被初始化:
// 错误
private List<Erreur> erreurs = new ArrayList<Erreur>();
private Boolean erreur = false;
可以在 Bean [Form] 的 init 方法中预先处理这种情况:
@PostConstruct
private void init() {
// 初始化是否成功?
if (application.getErreur()) {
// 获取错误列表
erreurs = application.getErreurs();
// 显示错误视图
setForms(false, false, true);
}
// 将医生和客户数据缓存
...
}
- 第 5 行:如果 Bean [Application] 初始化失败,
- 第7行:获取错误列表,
- 第 9 行:并显示错误页面。
因此,如果停止 SGBD 和 MySQL,然后重新启动应用程序,现在将显示以下页面:

10.2. 结论
将 Primefaces mobile/EJB/Glassfish 应用程序迁移至 Primefaces mobile/Spring/Tomcat 环境的过程十分简单。 在 JSF / Spring / Tomcat 应用程序研究中报告的内存泄漏问题(第 4.3.5 节)仍然存在。我们将采用相同的方法解决该问题。
10.3. 使用 Eclipse 进行测试
我们将 Maven 项目导入 Eclipse [1]:
![]() |
我们运行 Web 项目 [2]。
![]() |
我们选择 Tomcat 服务器 [3]。随后,应用程序的首页将在 Eclipse 的内置浏览器中显示 [4]。
10.4. 移动端测试
要在移动设备上测试应用程序,请按照第 8.5.6 节中的说明进行操作。以下是应用程序的截图:
![]() | ![]() |
![]() | ![]() |














