@SessionScoped bean 作为 @ViewScoped 的 @ManagedProperty 注入,其行为类似于 MyFaces 中的 @RequestScoped,在 Mojarra 中工作正常

2024-01-15

这是我的简单例子:

Index.xhtml在根中:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Title</title>
    </h:head>
    <h:body>
        <h:form>
            <h:inputText value="#{index.variable}"></h:inputText>
            <h:commandButton action="#{index.submit()}" type="submit"></h:commandButton>
        </h:form>
    </h:body>
</html>

它的托管Bean:

import java.io.IOException;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

@ManagedBean
@ViewScoped
public class Index implements Serializable {

    @ManagedProperty("#{sessionBean}")
    private SessionBean sessionBean; /*getter&setter*/
    private String variable; /*getter&setter*/

    public void submit() {
        sessionBean.setAsd(variable);
        ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
        try {
            context.redirect("next");
        } catch (IOException ex) {
        }
    }
}

/next/index.xhtml:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Check variable</title>
    </h:head>
    <h:body>
        #{sessionBean.asd}
    </h:body>
</html>

SessionBean.java:

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class SessionBean implements Serializable {

    private String asd;

    public String getAsd() {
        return asd;
    }

    public void setAsd(String asd) {
        this.asd = asd;
    }
}

如果我使用 mojarra 实现,一切都会按预期工作:提交表单后,用户被重定向到root/并查看以以下形式打印的值index.xhtml.

但如果我用我的脸,asd提交现有表单后立即变为空。SessionScoped豆的行为就像RequestScoped

Why?


这是我的web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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-app_3_0.xsd">
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
    <listener>
        <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
        <!--listener-class>com.sun.faces.config.ConfigureListener</listener-class-->
    </listener>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <welcome-file-list>
        <welcome-file>index.xhtml</welcome-file>
    </welcome-file-list>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
</web-app>

服务器:Apache Tomcat 7.0.34

UPDATE:如果我们改变它就可以了ViewScoped的注释Index.java bean to RequestScoped or SessionScoped。但为什么?


我目前有一个在 Mojarra 的帮助下编写的 JSF 2.1 项目。只是为了进行实验,我将实现更改为 MyFaces 并运行该应用程序,结果仅看到与您类似的问题(我注入的所有 @ManagedProperty 变量在 POST 提交后最终都为 null)。我切换回 Mojarra,该应用程序运行良好。因此,MyFaces 实现基本上有些不同。

一些谷歌搜索让我发现了这个未解决的问题 -MYFACES-3656 https://issues.apache.org/jira/browse/MYFACES-3656。以下是问题记者关于如何解决该问题的摘录:

如果您设置org.apache.myfaces.SERIALIZE_STATE_IN_SESSION http://myfaces.apache.org/core20/myfaces-impl/webconfig.html#org_apache_myfaces_SERIALIZE_STATE_IN_SESSION to false并重新部署应用程序,然后一切都按预期进行。

这有什么帮助?答案就在:

我认为所描述的行为是预期的(不同的是 所描述的行为是期望的或有意以这种方式完成的)。

这里发生的事情是在 MyFaces 序列化中设置为 true 默认(JSF 1.0 规范中的一些旧行是这样说的,即使 RI 不 以这种方式实现)。在 JSF 2.2 规范中,SERIALIZE_STATE_IN_SESSION param 将被标准化并默认设置为 false。

序列化导致视图范围内的所有 bean 实际上都是 “重新创造”。如果参数设置为 false,则 bean 会存储到 会话和进一步的请求被使用,看起来一切都是 好吧,但事实并非如此,因为在集群配置中 相同的应用程序将失败.

仅当第一次创建视图作用域 bean 时,引用 来自托管属性生效,但如果 bean 是 序列化/反序列化,引用不会恢复回来,因为 在序列化步骤上,甚至应用程序和会话范围 beans 也是序列化的。

.....

怎么解决呢?我还没有找到解决这个问题的合适方法。一 可以考虑恢复视图范围 bean 并重新应用 @ManagedProperty 注释或在 faces-config.xml 中找到的条目,但是 问题是视图范围 bean 仍然存储以下信息 不应该从一开始就存在(仅将字段标记为瞬态 会成功的)。可以定义一个特殊模式 hack 或一些变体已经完成,但它只会出现在 myfaces 中,而且它 默认情况下无法启用。

已报告类似问题并回复了上述解释邮件列表存档 http://mail-archives.apache.org/mod_mbox/myfaces-users/201108.mbox/%3CCAGJtJfFsME4VhXEjjdJ6bS76_avPmHz_yh0jLDH8=1P8_RDqGA@mail.gmail.com%3E

现在,因为在您的情况下您没有明确设置STATE_SAVING_METHOD,默认为服务器。最后,SERIALIZE_STATE_IN_SESSION生效并默认为true。

我在 Tomcat 上使用 MyFaces 尝试了您的代码,并将 SERIALIZE_STATE_IN_SESSION 设置为 false 并且它有效。但是,在这种情况下,您将 STATE_SAVING_METHOD 设置为client,什么都不起作用,您将收到视图状态未找到错误。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

@SessionScoped bean 作为 @ViewScoped 的 @ManagedProperty 注入,其行为类似于 MyFaces 中的 @RequestScoped,在 Mojarra 中工作正常 的相关文章

随机推荐