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