JSF bean动作方法返回字符串测试

时间:2015-03-27 10:41:47

标签: jsf navigation jsf-1.2

我试图从这个question中理解返回null和""之间的区别。在JSF行动中,但无法真实体验。

以下是OP的引用

  

根据我的理解,当一个JSF动作返回"" (空字符串)   用户停留在当前页面上但视图已刷新。然而,   当操作返回null时,用户仍然停留在当前页面上   但旧的观点被重用

我很难理解从JSF Backing bean返回""null"viewid?faces-redirect=true"之间的区别。我试图通过一个小例子来理解差异,但我无法体验到实际的差异。以下是我的示例的代码片段。

的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <display-name>Jsf Questions</display-name>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <context-param>
    <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
    <param-value>.jspx</param-value>
  </context-param>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/jsfintroapp/*</url-pattern>
  </servlet-mapping>
</web-app>

faces-config.xml中

<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xi="http://www.w3.org/2001/XInclude"
 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_1_2.xsd">
 <managed-bean>
  <managed-bean-name>userLogin</managed-bean-name>
  <managed-bean-class>com.srk.beans.UserLogin</managed-bean-class>
  <managed-bean-scope>request</managed-bean-scope>
 </managed-bean>
 <navigation-rule>
  <description>Contains list of all navigation rules here</description>
  <from-view-id>/*</from-view-id>
  <navigation-case>
   <display-name>WELCOME</display-name>
   <from-outcome>welcome</from-outcome>
   <to-view-id>/geek_examples/authorized_user.jspx</to-view-id>
  </navigation-case>
</faces-config>

我的托管bean是一个请求范围的bean,如上所述。

UserLogin.java(Backing bean)代码段

public String saveData() {
    //String returnString = "";//Case 1 : works - user stays on the same page
    //String returnString = null;//Case 2: works - user stays on the same page
    // Case 3:
    String viewId = FacesContext.getCurrentInstance().getViewRoot().getViewId();
    LOG.debug("view id = "+ viewId);
    String returnString = "?faces-redirect=true";//viewId+
    LOG.debug("return string = "+ returnString);
    LOG.debug("Username = "+ getName() + " password = "+ getPassword());
    return returnString;
}

login.jspx

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
<f:view>
<head>
<title>JSF Question</title>
</head>
<body>
    <h:form>
        <h3>User Name and Password</h3>
        <table>
            <tr>
              <td><h:outputLabel value="Name"/></td>
              <td><h:inputText value="#{userLogin.name}"/></td>
            </tr>
            <tr>
              <td><h:outputLabel value="Password"/></td>
              <td><h:inputText value="#{userLogin.password}"/></td>
            </tr>
            <tr>
              <td><h:commandButton value="Sign In" action="#{userLogin.saveData}"/></td>
            </tr>
        </table>
    </h:form>
</body>
</f:view>
</html>

此示例中使用的库

enter image description here

我尝试访问login.jspx页面,在表单字段中输入值并单击登录。我总是可以看到同一页面,无论我在saveData()方法中返回什么,它没有显示任何行为上的差异,有人可以对这个概念提出一些看法吗?

1 个答案:

答案 0 :(得分:6)

如该答案所述,返回nullvoid将重用相同的JSF视图,包括附加到其上的所有视图范围bean。

但是,JSF 1.2没有“视图范围bean”的概念。这是在JSF 2.0中引入的。而且,你有一个请求范围的bean。无论您如何导航,它都会在每个请求中重新创建。因此,通过查看bean的行为方式,这并不是很明显。如果您通过在UIViewRoot中放置一个属性然后检查请求范围bean的构造函数(如果它仍然存在)来手动模仿JSF 2.0视图范围,那么这是显而易见的。

如果您使用了JSF 2.x视图范围的bean,那么当您使用非null结果进行导航时,您已经注意到它已重新创建(即,再次调用它的(post)构造函数)。另见a.o. How to choose the right bean scope?

并且,?faces-redirect=true查询字符串也是JSF 2.x特定的,JSF 1.x无法识别。在JSF 1.x中,要实现相同的效果,请将<redirect/>添加到<navigation-case>,或使用ExternalContext#redirect()

public void saveData() throws IOException {
    // ...

    ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
    String url = ec.getRequestContextPath() + "/login.jsf";
    ec.redirect(url);
}

在此相关问题中详细说明了选择哪种导航方法:How to navigate in JSF? How to make URL reflect current page (and not previous one)。通常,在UX和SEO的角度来看,使用POST进行页面到页面导航是不好的做法。始终使用GET或在POST后执行重定向。

无论如何,在使用JSF 1.x进行开发时,您不应该关注JSF 2.x目标答案/资源。它只会导致混乱,因为JSF 2.x中的许多事情都有所不同(更好!)。 JSF 2.x已经存在了5年多,JSF 1.x几乎和EOL一样长。继续研究死技术是没有意义的。 Consider migrating