我正在解决如何在不使用会话范围托管bean的情况下将值从一个页面传递到另一个页面的问题。对于大多数托管bean,我希望只有Request scope。
我创建了一个非常非常简单的计算器示例,它将来自第5阶段的请求bean(CalculatorRequestBean)上的操作产生的 Result 对象作为初始化值传递给下一阶段生命周期中初始化的请求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>
计算器2页面,操作乘法和除法:
<?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 2</title>
</h:head>
<h:body>
<h:form>
<h:panelGrid columns="2">
<h:outputText value="Value to use:"/>
<h:inputText value="#{calculatorBeanRequest2.valueToAdd}"/>
<h:outputText value="Navigate to new view:"/>
<h:selectBooleanCheckbox value="#{calculatorBeanRequest2.navigateToNewView}"/>
<h:commandButton value="Multiply" action="#{calculatorBeanRequest2.multiply}"/>
<h:commandButton value="Divide" action="#{calculatorBeanRequest2.divide}"/>
<h:outputText value="Result:"/>
<h:outputText value="#{calculatorBeanRequest2.result.value}"/>
<h:commandButton value="Calculator" action="calculator"/>
<h:outputText value="DUMMY" rendered="#{resultBeanView.dummy}"/>
</h:panelGrid>
</h:form>
</h:body>
</html>
要通过生命周期传递的对象:
package cz.test.calculator;
import java.io.Serializable;
/**
* Data object passed among pages.
* Lets imagine it holds something much more complicated than primitive int
*/
public class Result implements Serializable {
private int value;
public void setValue(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
请求在视图“calculator.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 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以将Result变量传递给新页面:
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;
}
}
答案 0 :(得分:6)
您的问题询问如何在不使用会话范围托管bean的情况下将值从一个页面传递到另一个页面,但在您的示例中,我实际上看不到不同的页面。
您始终保持同一页面(查看)。 JSF组件自动将其值保留在所谓的视图状态中,因此您无需在此处手动传递任何内容。
如果你真的想在完全不同的页面之间传递信息(例如从calculator.xthml到result_overview.xhtml),那么一种可能的解决方案是使用Java EE 6中的conversation scope
。如果你只是使用例如,JSF 2.0库Tomcat,您不能使用此范围,但如果您添加了CDI实现或部署到完整的Java EE AS(如Glassfish V3或Jboss AS 6),那么您可以使用它。
会话范围确实在页面之间起作用,但是有一个小问题,你必须将托管bean从@ManagedBean更改为@Named,并且必须意识到你将使用CDI bean而不是JSF托管bean。它们主要是互操作,但有一些警告。