Java JSF2-使用视图范围管理bean在导航之间传递值

Java JSF2-使用视图范围管理bean在导航之间传递值,java,jsf,jsf-2,Java,Jsf,Jsf 2,我正在解决如何在不使用会话范围管理bean的情况下将值从一个页面传递到另一个页面。对于大多数托管bean,我希望只有请求范围 我创建了一个非常非常简单的计算器示例,它将第五阶段请求bean(CalculatorRequestBean)上的操作产生的结果对象作为在下一阶段生命周期中初始化的请求bean的新实例的初始化值 事实上,在生产环境中,我们需要传递更复杂的数据对象,它不像下面定义的结果那样原始 您对这个考虑了两种可能性的解决方案有什么看法?我们保持相同的观点,或者我们导航到新的观点。但在这两

我正在解决如何在不使用会话范围管理bean的情况下将值从一个页面传递到另一个页面。对于大多数托管bean,我希望只有请求范围

我创建了一个非常非常简单的计算器示例,它将第五阶段请求bean(CalculatorRequestBean)上的操作产生的结果对象作为在下一阶段生命周期中初始化的请求bean的新实例的初始化值

事实上,在生产环境中,我们需要传递更复杂的数据对象,它不像下面定义的结果那样原始

您对这个考虑了两种可能性的解决方案有什么看法?我们保持相同的观点,或者我们导航到新的观点。但在这两种情况下,我都可以使用视图作用域的托管bean获得先前存储的值

计算器页面:

<?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>Calculator</title>
</h:head>
<h:body>
    <h:form>
        <h:panelGrid columns="2">
            <h:outputText value="Value to use:"/>
            <h:inputText value="#{calculatorBeanRequest.valueToAdd}"/>

            <h:outputText value="Navigate to new view:"/>
            <h:selectBooleanCheckbox value="#{calculatorBeanRequest.navigateToNewView}"/>

            <h:commandButton value="Add" action="#{calculatorBeanRequest.add}"/>
            <h:commandButton value="Subtract" action="#{calculatorBeanRequest.subtract}"/>

            <h:outputText value="Result:"/>
            <h:outputText value="#{calculatorBeanRequest.result.value}"/>

            <h:commandButton value="Calculator2" action="calculator2"/>

            <h:outputText value="DUMMY" rendered="#{resultBeanView.dummy}"/>
        </h:panelGrid>
    </h:form>
</h:body>
在视图“calculator.xhtml”上使用的请求范围的托管bean,带有操作add和subtract

package cz.test.calculator;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;


@ManagedBean
@RequestScoped
public class CalculatorBeanRequest {

    @ManagedProperty(value="#{resultBeanView}")
    ResultBeanView resultBeanView;

    private Result result;

    private int valueToAdd;

    /**
     *  Should perform navigation to 
     */
    private boolean navigateToNewView;

    /** Creates a new instance of CalculatorBeanRequest */
    public CalculatorBeanRequest() {        
    }


    @PostConstruct
    public void init() {       
        // Remember already saved result from view scoped bean
        result = resultBeanView.getResult();
    }

    // Dependency injections
    public void setResultBeanView(ResultBeanView resultBeanView) {
        this.resultBeanView = resultBeanView;
    }

    public ResultBeanView getResultBeanView() {
        return resultBeanView;
    }

    // Getters, setter
    public void setValueToAdd(int valueToAdd) {
        this.valueToAdd = valueToAdd;
    }

    public int getValueToAdd() {
        return valueToAdd;
    }

    public boolean isNavigateToNewView() {
        return navigateToNewView;
    }

    public void setNavigateToNewView(boolean navigateToNewView) {
        this.navigateToNewView = navigateToNewView;
    }

    public Result getResult() {
        return result;
    }

    // Actions
    public String add() {        
        result.setValue(result.getValue() + valueToAdd);
        return isNavigateToNewView() ? "calculator" : null;
    }    

    public String subtract() {        
        result.setValue(result.getValue() - valueToAdd);
        return isNavigateToNewView() ? "calculator" : null;
    }
}
在视图“calculator2.xhtml”上使用请求范围的托管bean,操作为除法和乘法:

package cz.test.calculator;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;


@ManagedBean
@RequestScoped
public class CalculatorBeanRequest2 {

    @ManagedProperty(value="#{resultBeanView}")
    ResultBeanView resultBeanView;

    private Result result;

    private int valueToUse;

    /**
     *  Should perform navigation to
     */
    private boolean navigateToNewView;

    /** Creates a new instance of CalculatorBeanRequest2 */
    public CalculatorBeanRequest2() {
    }


    @PostConstruct
    public void init() {
        result = resultBeanView.getResult();
    }

    // Dependency injections
    public void setResultBeanView(ResultBeanView resultBeanView) {
        this.resultBeanView = resultBeanView;
    }

    public ResultBeanView getResultBeanView() {
        return resultBeanView;
    }

    // Getters, setter
    public void setValueToAdd(int valueToAdd) {
        this.valueToUse = valueToAdd;
    }

    public int getValueToAdd() {
        return valueToUse;
    }

    public boolean isNavigateToNewView() {
        return navigateToNewView;
    }

    public void setNavigateToNewView(boolean navigateToNewView) {
        this.navigateToNewView = navigateToNewView;
    }

    public Result getResult() {
        return result;
    }

    // Actions
    public String multiply() {
        result.setValue(result.getValue() * valueToUse);
        return isNavigateToNewView() ? "calculator2" : null;
    }

    public String divide() {
        result.setValue(result.getValue() / valueToUse);
        return isNavigateToNewView() ? "calculator2" : null;
    }    
}
最后查看作用域托管bean,以将结果变量传递到新页面:

package cz.test.calculator;

import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;


@ManagedBean
@ViewScoped
public class ResultBeanView implements Serializable {    

    private Result result = new Result();

    /** Creates a new instance of ResultBeanView */
    public ResultBeanView() {        
    }

    @PostConstruct
    public void init() {
        // Try to find request bean ManagedBeanRequest and reset result value
        CalculatorBeanRequest calculatorBeanRequest =  (CalculatorBeanRequest)FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get("calculatorBeanRequest");
        if(calculatorBeanRequest != null) {
            setResult(calculatorBeanRequest.getResult());
        }
        CalculatorBeanRequest2 calculatorBeanRequest2 =  (CalculatorBeanRequest2)FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get("calculatorBeanRequest2");
        if(calculatorBeanRequest2 != null) {
            setResult(calculatorBeanRequest2.getResult());
        }
    }
    /** No need to have public modifier as not used on view
     *  but only in managed bean within the same package
     */
    void setResult(Result result) {
        this.result = result;
    }

    /** No need to have public modifier as not used on view
     *  but only in managed bean within the same package
     */
    Result getResult() {
      return result;
    }

    /**
     * To be called on page to instantiate ResultBeanView in Render view phase
     */
    public boolean isDummy() {
        return false;
    }

}
您的问题询问如何在不使用会话范围管理bean的情况下将值从一个页面传递到另一个页面,但在您的示例中,我实际上没有看到不同的页面

您始终停留在同一页面(视图)上。JSF组件会自动将它们的值保留在所谓的视图状态中,因此不需要在这里手动传递任何内容

如果您真的想在完全不同的页面之间传递信息(例如,从calculator.xthml到result_overview.xhtml),那么一个可能的解决方案是使用Java EE 6中的
对话范围
。如果您仅在例如Tomcat上使用JSF2.0 libs,则不能使用此范围,但是如果您添加了CDI实现或部署到完整的JavaEE,如Glassfish V3或Jboss AS 6,则可以使用此范围


对话范围实际上在页面之间工作,但有一个小问题,您必须将托管bean从@ManagedBean更改为@Named,并且必须意识到您将使用CDIBeans而不是JSF托管bean。它们基本上是互操作的,但有许多注意事项。

是的,您是对的,在本例中,我没有导航到新页面。对不起,我误用了“页面”这个词。无论如何,我导航到新的“视图”,它是垃圾视图范围的bean(这就是为什么我让它使用重新实例化的原因。我可能会添加新的页面calculator2.xhtml,其中包含操作除法和乘法,这可能会使用以前操作产生的结果。我是否应该这样编写示例?关于对话范围,我会看一下,但现在我们只有Tomcat和Mojarra。我将示例更改为包含两个共享相同结果数据的页面对象。它似乎应该可以工作;)但请注意,您会患上一页落后综合症(浏览器的地址栏仍然显示“Calculator”的URL,而实际上它显示的是“Calculator2”)。您已经创建了一个简单的解决方法,也可以通过
Flash
作用域在JSF中完成,或者通过前面提到的对话作用域在javaee中完成。事实上,我尝试了Flash作用域,但只能使用一次。重复使用是不可能的,因为Flash scope“stuff”只经历了一轮生命周期:-(如果您对如何在我的示例中使用它有任何线索,请向我展示。我阅读了文章是的,这是我想要的,但如何在没有应用服务器的情况下实现这一点?
package cz.test.calculator;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;


@ManagedBean
@RequestScoped
public class CalculatorBeanRequest2 {

    @ManagedProperty(value="#{resultBeanView}")
    ResultBeanView resultBeanView;

    private Result result;

    private int valueToUse;

    /**
     *  Should perform navigation to
     */
    private boolean navigateToNewView;

    /** Creates a new instance of CalculatorBeanRequest2 */
    public CalculatorBeanRequest2() {
    }


    @PostConstruct
    public void init() {
        result = resultBeanView.getResult();
    }

    // Dependency injections
    public void setResultBeanView(ResultBeanView resultBeanView) {
        this.resultBeanView = resultBeanView;
    }

    public ResultBeanView getResultBeanView() {
        return resultBeanView;
    }

    // Getters, setter
    public void setValueToAdd(int valueToAdd) {
        this.valueToUse = valueToAdd;
    }

    public int getValueToAdd() {
        return valueToUse;
    }

    public boolean isNavigateToNewView() {
        return navigateToNewView;
    }

    public void setNavigateToNewView(boolean navigateToNewView) {
        this.navigateToNewView = navigateToNewView;
    }

    public Result getResult() {
        return result;
    }

    // Actions
    public String multiply() {
        result.setValue(result.getValue() * valueToUse);
        return isNavigateToNewView() ? "calculator2" : null;
    }

    public String divide() {
        result.setValue(result.getValue() / valueToUse);
        return isNavigateToNewView() ? "calculator2" : null;
    }    
}
package cz.test.calculator;

import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;


@ManagedBean
@ViewScoped
public class ResultBeanView implements Serializable {    

    private Result result = new Result();

    /** Creates a new instance of ResultBeanView */
    public ResultBeanView() {        
    }

    @PostConstruct
    public void init() {
        // Try to find request bean ManagedBeanRequest and reset result value
        CalculatorBeanRequest calculatorBeanRequest =  (CalculatorBeanRequest)FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get("calculatorBeanRequest");
        if(calculatorBeanRequest != null) {
            setResult(calculatorBeanRequest.getResult());
        }
        CalculatorBeanRequest2 calculatorBeanRequest2 =  (CalculatorBeanRequest2)FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get("calculatorBeanRequest2");
        if(calculatorBeanRequest2 != null) {
            setResult(calculatorBeanRequest2.getResult());
        }
    }
    /** No need to have public modifier as not used on view
     *  but only in managed bean within the same package
     */
    void setResult(Result result) {
        this.result = result;
    }

    /** No need to have public modifier as not used on view
     *  but only in managed bean within the same package
     */
    Result getResult() {
      return result;
    }

    /**
     * To be called on page to instantiate ResultBeanView in Render view phase
     */
    public boolean isDummy() {
        return false;
    }

}