Skip to content

7. 示例应用-04:rdvmedecins-pf-spring

7.1. 移植

现在我们将前一个应用程序移植到 Spring / Tomcat 环境中:

我们将基于两个已编写好的应用程序。我们将使用:

  • 02 版 JSF / Spring 中的 [DAO] 和 [JPA] 层,
  • 来自 03 版 PF / EJB 的 [web] / Primefaces 层,
  • Spring 配置文件(版本 02)

此处我们进行的工作与之前将 JSF2 / EJB / Glassfish 应用程序移植到 JSF2 / Spring Tomcat 环境时类似。因此我们将减少说明。 如有需要,读者可参考该移植案例。

我们将移植所需的所有项目都放在了一个新的文件夹 [rdvmedecins-pf-spring] [1] 中:

  • [mv-rdvmedecins-spring-dao-jpa]:02版JSF / Spring中的[DAO]和[JPA]层,
  • [mv-rdvmedecins-spring-metier]:版本 02 JSF / Spring 中的 [métier] 层,
  • [mv-rdvmedecins-pf]:来自版本 03 Primefaces / EJB 的 [web] 层,
  • 在 [2] 中,我们将它们加载到 NetBeans 中,
  • 在 [3] 中,Web 项目的依赖关系不再正确:
    • 对 [DAO]、[JPA]、[métier] 层的依赖关系必须修改,使其现在指向 Spring 项目;
    • Glassfish 服务器曾提供 JSF 的库。但在 Tomcat 服务器上已不再提供。因此必须将其添加到依赖项中。

[web] 项目的变更如下:

[web] 层中的 [pom.xml] 文件现具有以下依赖项:


<dependencies>    
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>mv-rdvmedecins-spring-metier</artifactId>
      <version>${project.version}</version>
    </dependency>
    <dependency>
      <groupId>com.sun.faces</groupId>
      <artifactId>jsf-api</artifactId>
      <version>2.1.7</version>
    </dependency>
    <dependency>
      <groupId>com.sun.faces</groupId>
      <artifactId>jsf-impl</artifactId>
      <version>2.1.7</version>
    </dependency>
    <dependency>  
      <groupId>org.primefaces</groupId>  
      <artifactId>primefaces</artifactId>  
      <version>3.3</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 行:我们处理可能出现的异常并记录其调用堆栈。

完成上述操作后,Bean [Application] 已无错误。现在我们来看 Bean [Form]、[1] 和 [2]:

我们将因缺少包而导致的所有错误行(import 和注解)删除。这样就足以消除所有 [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>
  </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,然后重新启动应用程序,现在将显示以下页面:

Image

7.2. 结论

将 Primefaces / EJB / Glassfish 应用程序迁移至 Primefaces / Spring / Tomcat 环境的过程十分简单。但在 JSF / Spring / Tomcat 应用程序研究中(第 4.3.5 节)提到的内存泄漏问题依然存在。

该问题将采用相同的方法解决。

7.3. 使用 Eclipse 进行测试

我们将 Maven 项目导入 Eclipse [1]:

我们运行 Web 项目 [2]。

我们选择Tomcat服务器[3]。随后,应用程序的首页将在Eclipse的内置浏览器[4]中显示。