【问题标题】:Migrating from JSF 1.2 to JSF 2.0从 JSF 1.2 迁移到 JSF 2.0
【发布时间】:2026-01-07 18:20:03
【问题描述】:

我正在使用一个用 JSF 1.2 编写的相当大的应用程序。 JSF 1.2 现在大约 6 岁了。我需要升级到 JSF 2.0。这会有多痛苦?我注意到自定义标签中的某些属性已更改等。

【问题讨论】:

    标签: java jsf migration jsf-2


    【解决方案1】:

    痛苦

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

    • JSP 2.x 到 JSP 2.x = 几乎不费吹灰之力。
    • Facelets 1.x 到 Facelets 2.0 = 不费吹灰之力。
    • JSP 2.x 到 Facelets 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 到 JSP 2.x

    如果您正在使用 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 到 Facelets 2.0

    如果您使用 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 相关的 &lt;context-param&gt; 值,这些值在 Facelets 2.0 中已经是默认值,例如值为 *.xhtmljavax.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 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 代码行,并且您也应该只有 &lt;jsp:include&gt; 作为唯一的 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。任何&lt;managed-bean&gt;都可以被@ManagedBean注解:

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

    @RequestScoped 旁边,还有@ViewScoped@SessionScoped@ApplicationScoped 可用。如果您省略@ManagedBeanname 属性,那么它将默认为第一个字符小写的类名。

    @ManagedBean
    @RequestScoped
    public class SomeBean {}
    

    在这个特定的例子中,它将是#{someBean}

    任何&lt;managed-property&gt;都可以使用@ManagedProperty注解:

    @ManagedProperty("#{otherBean}")
    private OtherBean otherBean;
    

    任何&lt;validator&gt;都可以使用@FacesValidator注解:

    @FacesValidator("someValidator")
    public class SomeValidator implements Validator {}
    

    任何&lt;converter&gt; 都可以使用@FacesConverter 进行注释

    @FacesConverter("someConverter")
    public class SomeConverter implements Converter {}
    

    任何&lt;renderer&gt; 都可以使用@FacesRenderer 进行注释

    @FacesRenderer(componentFamily="someComponentFamily", rendererType="someRendererType")
    public class SomeRenderer extends Renderer {}
    

    任何&lt;navigation-case&gt; 使用XHTML 页面的文件名作为&lt;from-outcome&gt;&lt;to-view-id&gt; 都可以删除,因为这将是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 上的所有 &lt;t:saveState&gt; 引用。

    【讨论】:

    • @ManagedBean(name="managedBeanName") @RequestScoped 是:)
    • 很棒的帖子,对我帮助很大。需要注意的一点:当从 jsf 1.2 迁移到 jsf 2 时,您几乎可以肯定有人使用的是来自 richfaces 3.3.x 的 a4j。我决定将richfaces 3.3.3 和jsf 2 一起使用,因为升级到richfaces 4.x 似乎是一个平庸的改变。所以我做了你的指南(在 faces-config 中撤消了所有与 facelets 相关的东西(激活的 viewhandler 删除了 taglig 注释),然后跟着community.jboss.org/wiki/RichFaces333AndJSF20 最后不得不这样做*.com/questions/85532/…
    • 很好的答案。就我而言,我还必须将 javax.faces.VALIDATE_EMPTY_FIELDS 参数设置为 false 才能对验证进行排序。另见:*.com/questions/6113935/…
    • @Cfold:我修复了链接。
    【解决方案2】:

    要提一提的是,如果有人在 JSF 1.2 中使用 JSTL,那么在升级到 JSF2 时,您应该更改命名空间:

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

    到:

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

    【讨论】:

    【解决方案3】:

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

    这也可能有帮助 JSF 1.2 application migration to JSF 2.0

    也可以查看What is new in JSF 2?

    【讨论】:

    • 当您将 Richfaces 与 JSF 1.x 一起使用时,情况也是如此——您经历了所有“痛苦”以了解如何将第三方组件与 JSF 集成。 JSF 2.x 的方法没有区别。这就是编程的“乐趣”,不是吗? :)
    【解决方案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">
    

    【讨论】:

      【解决方案5】:

      如果您使用的是 Apache Trinidad,您还必须将其升级到 2.0 版,以便支持 JSF 2.0。 Hacker's Valhalla 有更多信息。

      【讨论】:

        最近更新 更多