从JSF 1.2迁移到JSF 2.0

141

我正在处理一个使用 JSF 1.2编写的相当大的应用程序。 JSF 1.2已经发布了大约6年。我需要升级到JSF 2.0。这会有多麻烦?我注意到一些自定义标签中的属性已经改变了等等。

我需要升级所使用的JSF版本,从JSF 1.2升级到JSF 2.0可能会比较困难。因为新版本中某些自定义标签的属性已经更改,这可能导致代码不兼容。然而,升级也会带来一些好处,例如更好的性能和更好的安全性。建议在进行升级前,进行充分的测试以确保应用程序的稳定性。

5个回答

258

痛苦

将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文件(如果有的话)。

  • 将JSF 2.0 JAR文件放入/WEB-INF/lib中(如果JSF 1.2是由servlet容器提供的,您可能需要更改类加载策略,以便在加载servlet容器库之前先加载Web应用程序库,另请参阅应用服务器中的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的根声明至少符合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并希望继续使用它,那么基本上您不需要改变任何其他东西。

逐步升级

如果您已经在FacesServleturl-pattern中使用后缀,例如*.jsf,那么很好知道FacesServlet将首先扫描*.xhtml文件,如果不存在,则扫描*.jsp文件。这为您提供了在幕后逐步从JSP转换为Facelets而无需更改URL的空间。

但是,如果您使用前缀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相关的<context-param>值,因为这些值在Facelets 2.0中已经是默认值,例如javax.faces.DEFAULT_SUFFIX的值为*.xhtml

  • 更新现有Facelet标签库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片段中始终使用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片段中使用http://xmlns.jcp.org命名空间域,而不是http://java.sun.com

包含页面更改

如果您现有的JSP页面设计良好,则不应该有任何一行脚本代码,并且您还应该只有<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

自定义组件更改

您需要按照Mojarra迁移指南中的说明将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可用。如果省略@ManagedBeanname属性,则默认为类名的第一个字符小写化。
@ManagedBean
@RequestScoped
public class SomeBean {}

在这个特定的例子中,它将是#{someBean}
任何<managed-property>都可以使用@ManagedProperty进行注释。
@ManagedProperty("#{otherBean}")
private OtherBean otherBean;

任何都可以使用@FacesValidator进行注释:
@FacesValidator("someValidator")
public class SomeValidator implements Validator {}

任何<转换器>都可以使用@FacesConverter进行注释。
@FacesConverter("someConverter")
public class SomeConverter implements Converter {}

任何<renderer>都可以使用@FacesRenderer进行注释。
@FacesRenderer(componentFamily="someComponentFamily", rendererType="someRendererType")
public class SomeRenderer extends Renderer {}

任何使用XHTML页面的文件名作为和的都可以被删除,因为这将会被隐式地完成。可以逐步通过将所有结果值更改为目标视图的文件名来实现此目标。
最后,任何在会话中放置的会话范围的bean,其唯一目的是在同一标签页/窗口中保留bean数据以供后续请求使用,最好将其标记为@ViewScoped,因为这样当最终用户在不同的标签页/窗口中打开相同页面时,该bean不会受到影响。

组件库

请注意,本答案不考虑任何第三方组件库,如PrimeFaces/RichFaces/IceFaces,因为这基本上归结为"视情况而定",所以很难给出可靠的答案。一般来说,只需根据他们的说明将组件库升级到符合JSF 2.0标准的版本即可。最好编写单元测试,在升级前后运行并修复任何个别问题。

以下至少是一些与特定组件库迁移相关的有用链接:

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(或更高版本)。Tomahawk也没有迁移指南。基本上,您只需要更改JAR文件,并在必要时通过将bean的作用域更改为视图作用域来摆脱所有<t:saveState>引用。

@ManagedBean(name="managedBeanName") @RequestScoped没问题 :) - Daniel Szalay
很好的答案。在我的情况下,我还必须将javax.faces.VALIDATE_EMPTY_FIELDS参数设置为false才能使验证正常工作。另请参阅:https://dev59.com/d1fUa4cB1Zd3GeqPI4dE - Jasper de Vries
2
我也可以推荐每个人阅读http://balusc.blogspot.nl/2011/09/communication-in-jsf-20.html。 - Jasper de Vries
我正在尝试更改TLD文件,但是Mojarra迁移指南已经消失了。有什么建议吗? - Xtopher
1
@Cfold:我修复了链接。 - BalusC
显示剩余2条评论

7

2
注意:此适用于从Facelets 1.x迁移到2.x的情况。 - BalusC
而对于2.2及以上版本,请参阅https://dev59.com/hl0Z5IYBdhLWcg3wyyx1 - Kukeltje

6
JSF 2.0有许多新功能和组件,我认为迁移不会很痛苦。唯一你可能觉得困难的是使用第三方库。如果你的应用程序严重依赖于像Richfaces这样的库,那么你将会遇到问题。并非所有来自Richfaces 3的组件都被移植到Richfaces 4中。
这也可能有所帮助:JSF 1.2应用程序迁移到JSF 2.0 还要检查一下这个:JSF 2中有什么新东西?

1
当您使用JSF 1.x与Richfaces时,情况是相同的-您需要经历所有“痛苦”才能找出如何将第三方组件与JSF集成。对于JSF 2.x的方法也没有什么不同。这就是编程的“乐趣”,不是吗? :) - ChuongPham

4

Web.xml

 Add the jars
    1. jsf-api-2.0.jar 
    2. jsf-impl.2.0.2.jar

第一步:修改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>

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

0
如果您正在使用Apache Trinidad,您还需要将其升级到2.0版本,以便支持JSF 2.0。有更多信息可在Hacker's Valhalla找到。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接