JavaServer Faces (JSF) 框架提供了丰富的工具来管理 Web 应用程序中的视图。理解 JSF 视图的生命周期对于开发高质量的应用程序至关重要。本文将通过一个具体的案例来探讨 JSF 视图管理的基本概念,并通过示例代码来展示视图的创建、管理和销毁过程。
首先,创建一个新的 JSF 项目。在 Eclipse 中,选择 "File" > "New" > "Dynamic Web Project",命名为 "MyJSFViewManagement",并确保选择了支持 JSF 的服务器版本。
接下来,需要添加 JSF 依赖。如果使用 Maven,可以在 pom.xml
文件中添加如下依赖:
<dependencies>
<dependency>
<groupId>javax.faces</groupId>
<artifactId>javax.faces-api</artifactId>
<version>2.3.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.3.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.1-b09</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.1-b09</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>11.0</version>
</dependency>
</dependencies>
如果你不使用 Maven,可以直接下载 JSF 和 EL 的 JAR 文件,并将它们添加到项目的 classpath 中。
在 WEB-INF
目录下创建 web.xml
文件,配置 JSF servlet。
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<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>*.jsf</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
上述配置指定了一个名为 Faces Servlet
的 servlet,该 servlet 处理所有扩展名为 .jsf
的请求,并设置了默认欢迎页面为 index.xhtml
。
接下来,创建一个简单的 Managed Bean。这个 bean 将会包含一些简单的属性和方法。
package com.example.bean;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
@ManagedBean(name = "viewBean")
@ViewScoped
public class ViewBean {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void initializeView() {
message = "Welcome to the view!";
}
public void updateMessage(ActionEvent event) {
message = "Message updated by an action!";
}
}
在上述代码中,@ManagedBean
注解表示这是一个 Managed Bean,@ViewScoped
注解指定了它的作用域为视图范围。initializeView
方法用于初始化视图,而 updateMessage
方法用于更新 message
属性的值。
接下来,创建一个 Facelets 页面 index.xhtml
,展示来自 bean 的信息,并使用 JSF 标签来实现视图管理。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>JSF View Management Example</title>
</h:head>
<h:body>
<h:form>
<h:outputText value="#{viewBean.message}" />
<h:commandButton value="Update Message" action="#{viewBean.updateMessage}">
<f:event type="preRenderView" listener="#{viewBean.initializeView}" />
</h:commandButton>
</h:form>
</h:body>
</html>
在 index.xhtml
页面中,<h:outputText>
标签用于显示 viewBean
中的 message
属性值。<h:commandButton>
标签用于创建一个按钮,当用户点击该按钮时,会触发 updateMessage
方法的执行。<f:event>
标签指定了在 preRenderView
事件发生时调用 initializeView
方法,以确保每次进入视图时都重新初始化视图数据。
为了更好地理解视图的生命周期,我们还可以在 viewBean
中添加一些日志记录。
package com.example.bean;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
import java.util.logging.Logger;
@ManagedBean(name = "viewBean")
@ViewScoped
public class ViewBean {
private static final Logger LOG = Logger.getLogger(ViewBean.class.getName());
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void initializeView() {
message = "Welcome to the view!";
LOG.info("View initialized.");
}
public void updateMessage(ActionEvent event) {
message = "Message updated by an action!";
LOG.info("Message updated.");
}
public void destroyView() {
LOG.info("View destroyed.");
}
}
在上述代码中,我们添加了一个 destroyView
方法,并在其中记录日志。为了触发视图销毁,我们需要手动销毁视图。这可以通过在 web.xml
中添加一个 view-param
参数来实现。
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<init-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Production</param-value>
</init-param>
<init-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
在 index.xhtml
页面中,我们可以添加一个链接来触发视图销毁。
<h:body>
<h:form>
<h:outputText value="#{viewBean.message}" />
<h:commandButton value="Update Message" action="#{viewBean.updateMessage}">
<f:event type="preRenderView" listener="#{viewBean.initializeView}" />
</h:commandButton>
<h:commandLink value="Destroy View" action="#{null}" immediate="true">
<f:viewParam name="viewDestroyed" value="true" />
</h:commandLink>
</h:form>
</h:body>
在上述代码中,<h:commandLink>
标签用于创建一个链接,当用户点击该链接时,会触发视图销毁。通过 immediate="true"
属性,我们确保在执行任何其他操作之前立即处理视图参数。
最后,部署并运行你的应用程序。启动应用服务器,并在浏览器中访问 http://localhost:8080/MyJSFViewManagement/index.jsf
。你应该看到一个带有 "Update Message" 按钮的页面。点击按钮后,页面会显示更新后的信息。点击 "Destroy View" 链接后,视图会被销毁,并记录相应的日志信息。
通过上述步骤,你已经成功地创建了一个简单的 JSF 应用程序,并展示了如何管理视图的生命周期。这个示例不仅介绍了如何配置 JSF 环境以支持视图管理,还包括了如何编写 Managed Bean 和 Facelets 页面,以及如何使用 JSF 标签来控制视图的生命周期。掌握了这些基础知识后,你可以进一步探索 JSF 的更多高级功能,如导航规则、状态保存方法等,逐步提高你的开发技能。