JSF bean 动作方法return 字符串测试

JSF bean action method return string test

我试图从这个question中理解 returning null 和 "" 在 JSF 动作中的区别,但无法真正体验。

以下是 OP

的引述

From what I understand, when a JSF action returns "" (empty String) the user stays on the current page but the view is refreshed. However, when the action returns null the user still stays on the current page but the old view is reused

我对理解来自 JSF Backing bean 的 returning ""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>

面孔-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(支持 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>

本例中使用的库

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

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

然而,

JSF 1.2 没有 "view scoped bean" 的概念。这是在 JSF 2.0 中引入的。此外,您有一个请求范围的 bean。无论您如何导航,它都会根据每个请求重新创建。因此,通过查看 bean 的行为方式并不能真正注意到它。如果您通过在 UIViewRoot 中放置一个属性然后检查请求作用域 bean 的构造函数(如果它仍然存在)来手动模拟 JSF 2.0 视图范围,它只会引起注意。

如果您使用过 JSF 2.x view scoped bean,您会注意到当您使用非null 结果。另见 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 进行开发时,您不应该查看针对 answers/resources 的 JSF 2.x。它只会导致混淆,因为在 JSF 2.x 中许多事情的处理方式不同(更好!)。 JSF 2.x 已经存在 5 年多了,而 JSF 1.x 停产的时间几乎一样长。继续研究死技术是没有意义的。 Consider migrating.