【发布时间】:2026-01-07 18:20:03
【问题描述】:
我正在使用一个用 JSF 1.2 编写的相当大的应用程序。 JSF 1.2 现在大约 6 岁了。我需要升级到 JSF 2.0。这会有多痛苦?我注意到自定义标签中的某些属性已更改等。
【问题讨论】:
我正在使用一个用 JSF 1.2 编写的相当大的应用程序。 JSF 1.2 现在大约 6 岁了。我需要升级到 JSF 2.0。这会有多痛苦?我注意到自定义标签中的某些属性已更改等。
【问题讨论】:
将 JSF 1.2 升级到 2.0 的痛苦取决于您当前使用的视图技术以及您想要使用的视图技术。
不管视图技术切换,至少应该做以下步骤:
/WEB-INF/lib 中删除 JSF 1.2 JAR(如果有)。/WEB-INF/lib 中删除 JSF 2.0 JAR(如果 JSF 1.2 是 servletcontainer-supplied,您可能需要更改类加载策略以先加载 webapp 库,然后再加载 servletcontainer 库,另请参见 JSF2 classloading issues in application servers)。更新 faces-config.xml 的根声明以符合 JSF 2.0 规范。
<faces-config
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"
version="2.0">
注意:当您使用 JSF 2.2 或更新版本时,请在上述 XML sn-p 中使用 http://xmlns.jcp.org 命名空间域而不是 http://java.sun.com。
确保web.xml 的根声明已经至少符合 Servlet 2.5。 JSF 2.0 无法在 2.4 或更低版本上运行 (although it's hackable)。
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
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-app_2_5.xsd"
id="YourWebappID"
version="2.5">
注意:当您使用 Servlet 3.0 或更新版本时,请在上述 XML sn-p 中使用 http://xmlns.jcp.org 命名空间域而不是 http://java.sun.com。
如果您正在使用 JSP 2.x 并希望继续使用它,那么您基本上不需要更改任何其他内容。
如果您已经为FacesServlet 使用了后缀url-pattern,例如*.jsf,那么很高兴知道FacesServlet 将首先扫描*.xhtml 文件,如果它不存在,然后扫描*.jsp 文件。这为您提供了在不更改 URL 的情况下在后台逐渐从 JSP 转换为 Facelets 的空间。
但是如果你使用前缀url-pattern,比如/faces/*,并且你想从JSP逐步升级到Facelets,那么你真的必须把它改成*.jsf,可能还有现有JSP中的所有链接页面。
您只需要记住,新的 JSF 2.0 提供的隐式导航不会扫描文件的存在,它无论如何都会转到outcome.xhtml。所以如果你想来自或去*.jsp,那么你仍然需要将它包含在 JSF 1.x 的 viewid 中。
如果您使用 Facelets 1.x 作为视图技术并希望使用 JSF 2.0 提供的 Facelets 2.0,那么您需要执行以下附加步骤:
/WEB-INF/lib 中删除 Facelets 1.x JAR。faces-config.xml 中删除 Facelets 1.x FaceletViewHandler。FaceletViewHandler 实现都需要更新以扩展 ViewHandlerWrapper。web.xml 中删除任何与 Facelets 1.x 相关的 <context-param> 值,这些值在 Facelets 2.0 中已经是默认值,例如值为 *.xhtml 的 javax.faces.DEFAULT_SUFFIX。更新现有 Facelet taglib XML 的根声明以符合 Facelets 2.0。
<facelet-taglib
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-facelettaglibrary_2_0.xsd"
version="2.0">
注意:当您使用 JSF 2.2 或更新版本时,请在上述 XML sn-p 中使用 http://xmlns.jcp.org 命名空间域而不是 http://java.sun.com。
基本上应该是这样的。
如果您使用 JSP 2.x 作为视图技术,并且想立即升级到 Facelets 2.0,那么您需要在网站可以上线。你基本上改变了这里的视图技术。
在每个母版页上,您需要更改以下基本 JSP 模板..
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<!DOCTYPE html>
<f:view>
<html lang="en">
<head>
<title>JSP page</title>
</head>
<body>
<h:outputText value="JSF components here." />
</body>
</html>
</f:view>
..到以下基本 Facelets 模板:
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>XHTML page</title>
</h:head>
<h:body>
<h:outputText value="JSF components here." />
</h:body>
</html>
注意:当您使用 JSF 2.2 或更高版本时,请在上述 XHTML sn-ps 中使用 http://xmlns.jcp.org 命名空间域而不是 http://java.sun.com。
如果您现有的 JSP 页面设计得很好,那么您不应该有任何 scriptlet 代码行,并且您也应该只有 <jsp:include> 作为唯一的 JSP 特定标记。其中任何一个都需要更改:
<jsp:include page="include.jsp" />
到
<ui:include src="include.xhtml" />
基本的JSP包含页面模板..
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<f:subview id="include">
<h:outputText value="JSF components here." />
</f:subview>
..应更改为以下基本 Facelets 包含页面模板:
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:outputText value="JSF components here." />
</ui:composition>
注意:当您使用 JSF 2.2 或更新版本时,请在上述 XHTML sn-ps 中使用 http://xmlns.jcp.org 命名空间域而不是 http://java.sun.com。
您需要按照Mojarra Migration Guide 中的说明将 JSP TLD 文件更改为 Facelets TLD 文件。
无论迁移方法如何,您都可以通过新的 JSF 2.0 注释甚至CDI 逐步消除faces-config.xml。任何<managed-bean>都可以被@ManagedBean注解:
@ManagedBean(name="managedBeanName")
@RequestScoped
public class SomeBean {}
在@RequestScoped 旁边,还有@ViewScoped、@SessionScoped 和@ApplicationScoped 可用。如果您省略@ManagedBean 的name 属性,那么它将默认为第一个字符小写的类名。
@ManagedBean
@RequestScoped
public class SomeBean {}
在这个特定的例子中,它将是#{someBean}。
任何<managed-property>都可以使用@ManagedProperty注解:
@ManagedProperty("#{otherBean}")
private OtherBean otherBean;
任何<validator>都可以使用@FacesValidator注解:
@FacesValidator("someValidator")
public class SomeValidator implements Validator {}
任何<converter> 都可以使用@FacesConverter 进行注释
@FacesConverter("someConverter")
public class SomeConverter implements Converter {}
任何<renderer> 都可以使用@FacesRenderer 进行注释
@FacesRenderer(componentFamily="someComponentFamily", rendererType="someRendererType")
public class SomeRenderer extends Renderer {}
任何<navigation-case> 使用XHTML 页面的文件名作为<from-outcome> 和<to-view-id> 都可以删除,因为这将是implicitly 完成。这可以通过更改所有结果值以匹配目标视图的文件名来逐步完成。
最后,任何被放入会话中的会话范围 bean 的唯一原因是在同一选项卡/窗口中的后续请求中保留 bean 数据,可以更好地标记@ViewScoped,因为这样 bean 不会当最终用户在不同的选项卡/窗口中打开同一页面时会受到影响。
请注意,我在此答案中没有考虑任何第三方组件库,例如 PrimeFaces/RichFaces/IceFaces,因此不可能写出可靠的答案,因为它基本上归结为“它取决于”。一般来说,只需按照他们的说明将组件库升级到一个由他们自己验证的 JSF 2.0 兼容版本就足够了。最好只编写单元测试,在升级前后运行它们并单独修复任何问题。
这里至少有一些关于特定组件库迁移的有用链接:
PrimeFaces 没有针对 PrimeFaces 1.x 到 2.x 的迁移指南,因为 PrimeFaces 1.x 已经需要 Facelets 1.x,因此您只需遵循 Facelets 1.x 到 2.x 的迁移步骤。但是,有一个 PrimeFaces 2.x to 3.x (and higher) migration guide 也可能适用于从 PrimeFaces 1.x 迁移到 3.x(或更高版本)。 Tomahawk 也没有迁移指南。基本上,您唯一需要更改的是 JAR,如有必要,通过将 bean 视图设置为范围来摆脱请求范围 bean 上的所有 <t:saveState> 引用。
【讨论】:
javax.faces.VALIDATE_EMPTY_FIELDS 参数设置为 false 才能对验证进行排序。另见:*.com/questions/6113935/…
要提一提的是,如果有人在 JSF 1.2 中使用 JSTL,那么在升级到 JSF2 时,您应该更改命名空间:
到:
【讨论】:
JSF 2.0 有许多新特性和组件,我不觉得迁移会很痛苦。您会发现困难的唯一领域是使用第三方库。如果您的应用程序严重依赖 Richfaces 等库,那么您将面临问题。并非 Richfaces 3 中的所有组件都移植到 Richfaces 4。
【讨论】:
Web.xml
Add the jars
1. jsf-api-2.0.jar
2. jsf-impl.2.0.2.jar
第 1 步:更改 web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<servlet>
<servlet-name>facesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
第二步:webmvc-config.xml
<!-- Handles requests mapped to the Spring Web Flow system -->
<bean id="flowController" class="org.springframework.webflow.mvc.servlet.FlowController">
<property name="flowExecutor" ref="flowExecutor" />
<property name="ajaxHandler">
<bean class="org.springframework.faces.webflow.JsfAjaxHandler" />
</property>
</bean>
第三步:facess-config.xml
<faces-config 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" version="2.0">
【讨论】:
如果您使用的是 Apache Trinidad,您还必须将其升级到 2.0 版,以便支持 JSF 2.0。 Hacker's Valhalla 有更多信息。
【讨论】: