从 JSF 1.2迁移到 JSF 2.0

我的工作与一个相当大的应用程序写在 JSF 1.2。 JSF 1.2现在已经有6年的历史了。我需要升级到 JSF 2.0。这会有多痛苦?我注意到自定义标记中的一些属性已经被更改等等。

102755 次浏览

JSF 2.0有许多新的特性和组件,我不认为迁移会很痛苦。你会发现唯一困难的地方是在使用第三方库。如果您的应用程序严重依赖于 Richfaces 这样的库,那么您将面临问题。并非 Richfaces 3中的所有组件都移植到 Richfaces 4中。

这也许会有帮助 将 JSF 1.2应用程序迁移到 JSF 2.0

再看看这个 JSF 2中有什么新内容?

痛苦

将 JSF 1.2升级到2.0的痛苦取决于您当前使用的视图技术和您想要使用的视图技术。

  • 从 JSP 2.x 到 JSP 2.x = 几乎不费吹灰之力。
  • Faclets 1.x 到 Faclets 2.0 = 少量工作。
  • JSP 2.x to Facelets 2.0 = 大量工作,如果您还有自定义组件,那么需要加倍努力。

基本的改变

无论视图技术如何切换,至少都应该执行以下步骤:

  • /WEB-INF/lib中删除 JSF 1.2 JAR (如果有的话)。
  • /WEB-INF/lib中删除 JSF 2.0 JAR (如果 JSF 1.2是 servlet 容器提供的,那么您可能需要更改类加载策略,以便在 servlet 容器库之前首先加载 webapp 库,另请参阅 应用服务器中的 JSF2类加载问题)。
  • 更新 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 片段中使用 http://xmlns.jcp.org名称空间域而不是 http://java.sun.com

  • 确保 web.xml的 root 声明已经符合 至少 Servlet 2.5. JSF 2.0不能在2.4或更低版本(虽然它是可以被黑客攻击的)上工作。

    <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 片段中使用 http://xmlns.jcp.org名称空间域而不是 http://java.sun.com


JSP 2.x 到 JSP 2. x

如果您正在使用 JSP 2. x并希望 留着使用它,那么基本上不需要更改任何其他内容。

逐渐升级

如果您已经为 FacesServlet使用了后缀 url-pattern,如 *.jsf,那么最好知道 FacesServlet将首先扫描 *.xhtml文件,如果它不存在,然后扫描 *.jsp文件。这为您提供了空间,可以在不改变 URL 的情况下,在幕后逐步从 JSP 转换到 Facelets。

但是如果使用前缀 url-pattern,比如 /faces/*,并且希望逐步从 JSP 升级到 Faclets,那么就必须将其更改为 *.jsf,可能还要更改现有 JSP 页面中的所有链接。

您只需要记住,新的 JSF 2.0提供的隐式导航不会扫描文件的存在,它无论如何都会转到 outcome.xhtml。因此,如果您想从 *.jsp或者转到 *.jsp,那么您仍然需要以 JSF 1.x 的方式将它包含在 viewid 中。


Faclets 1.x 到 Faclets 2.0

如果您使用 1. x作为视图技术,并希望使用 JSF 2.0提供的 Faclets 2.0,那么您需要执行以下附加步骤:

  • /WEB-INF/lib中删除 Faclets 1.x JAR。
  • faces-config.xml中删除 Faclets 1.x FaceletViewHandler
  • 任何自定义的 FaceletViewHandler实现都需要更新以扩展 ViewHandlerWrapper
  • 没有必要,但只是为了清理,从 web.xml中删除任何已经在 Faclets 2.0中默认的与 Faclets 1.x 相关的 <context-param>值,比如值为 *.xhtmljavax.faces.DEFAULT_SUFFIX
  • 更新现有 Faclet taglib XML 的根声明以符合 Faclets 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 片段中使用 http://xmlns.jcp.org名称空间域而不是 http://java.sun.com

基本上就是这样了。


JSP 2.x 到 Facelets 2.0

如果您使用 JSP 2. x作为视图技术,并且您想立即升级到 Faclets 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 片段中使用 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 片段中使用 http://xmlns.jcp.org名称空间域而不是 http://java.sun.com

自定义组件更改

您需要将 JSPTLD 文件更改为如此 摩加拉移民指南中所述的 FaclettLD 文件。


后果

无论采用何种迁移方法,您都可以通过新的 JSF 2.0注释甚至 CDI逐渐消除 faces-config.xml。任何 <managed-bean>都可以由 @ManagedBean注释:

@ManagedBean(name="managedBeanName")
@RequestScoped
public class SomeBean {}

除了 @RequestScoped,还有 @ViewScoped@SessionScoped@ApplicationScoped。如果省略 @ManagedBeanname属性,那么它将默认为 classname,第一个字符小写。

@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 {}

任何使用 XHTML 页面的文件名作为 <from-outcome><to-view-id><navigation-case>都可以删除,因为这将是 毫无疑问完成的。这可以通过更改所有结果值以匹配目标视图的文件名来逐步实现。

最后,将任何会话范围内的 bean 放在会话中的唯一原因是为了在同一个选项卡/窗口中的后续请求中保留 bean 数据,这样可以更好地标记为 @ViewScoped,因为这样,当 enduser 在不同的选项卡/窗口中打开同一页面时,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 到3.x (及更高版本)的迁移指南可能也适用于从 PrimeFaces 1.x 到3.x (或更高版本)的迁移。战斧也没有迁徙向导。基本上,您需要更改的只有 JAR,如果有必要,可以通过设置 bean 视图的作用域来消除请求范围内 bean 上的所有 <t:saveState>引用。

如果您正在使用 Apache Trinidad,那么您还必须将其升级到2.0版,以便支持 JSF 2.0。黑客的瓦尔哈拉有更多信息。

值得一提的是,如果有人在 JSF 1.2中使用 JSTL,那么在升级到 JSF2时,您应该将名称空间从:

Http://java.sun.com/jstl/core

致:

Http://java.sun.com/jsp/jstl/core

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>

步骤2: 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>

Step3: 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">