Ale*_*psa 4 composite-component jsf-2
我把这个问题放在一个简单的例子中,一个复合组件,计算2个输入的总和,并在outputText中打印结果
主JSF页面:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ez="http://java.sun.com/jsf/composite/ezcomp/">
<h:head></h:head>
<h:body>
<ez:Calculator />
<br/>
<br/>
<ez:Calculator />
<br/>
<br/>
<ez:Calculator />
</h:body>
</html>
Run Code Online (Sandbox Code Playgroud)
复合组件XHTML:
<!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:composite="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>This content will not be displayed</title>
</h:head>
<h:body>
<composite:interface componentType="calculator">
</composite:interface>
<composite:implementation>
<h:form>
<h:inputText id="first" value="#{cc.firstNumber}" />
<h:commandButton value="+" action="#{cc.sum}"/>
<h:inputText id="second" value="#{cc.secondNumber}" />
</h:form>
<h:outputText id="result" value="#{cc.result}" />
</composite:implementation>
</h:body>
</html>
Run Code Online (Sandbox Code Playgroud)
复合组件支持bean:
package ez;
import javax.faces.component.FacesComponent;
import javax.faces.component.UINamingContainer;
@FacesComponent("calculator")
public class Calculator extends UINamingContainer {
private Long firstNumber;
private Long secondNumber;
private Long result;
public Calculator() {
}
@Override
public String getFamily() {
return "javax.faces.NamingContainer";
}
public void setFirstNumber(String firstNumber) {
this.firstNumber = Long.parseLong(firstNumber);
}
public String getFirstNumber() {
if(firstNumber == null) {
return null;
}
return firstNumber.toString();
}
public void setSecondNumber(String secondNumber) {
this.secondNumber = Long.parseLong(secondNumber);
}
public String getSecondNumber() {
if(secondNumber == null) {
return null;
}
return secondNumber.toString();
}
public String getResult() {
if(result == null) {
return null;
}
return result.toString();
}
public void setResult(String result) {
this.result = Long.parseLong(result);
}
public void sum() {
this.result = this.firstNumber + this.secondNumber;
}
}
Run Code Online (Sandbox Code Playgroud)
所以,我有3个复合组件都应该做同样的事情,但是当我按下SUM按钮时,在服务器处理请求之后,结果将打印在页面上,但其他2个组件将清除它们的值.
我怎么能阻止这个?如何强制它保留这些值?
UIComponent每次请求都会重新创建实例,因此每次都会丢失所有实例变量.它们基本上像请求范围的托管bean一样,而您打算在视图范围内使用它们.您需要在每个属性的基础上考虑视图状态保存.默认情况下,这通常已经为所有属性完成#{cc.attrs}.所以,如果可以,只需使用它:
<cc:interface componentType="calculator">
<cc:attribute name="firstNumber" type="java.lang.Long" />
<cc:attribute name="secondNumber" type="java.lang.Long" />
</cc:interface>
<cc:implementation>
<h:form>
<h:inputText id="first" value="#{cc.attrs.firstNumber}" />
<h:commandButton value="+" action="#{cc.sum}"/>
<h:inputText id="second" value="#{cc.attrs.secondNumber}" />
</h:form>
<h:outputText id="result" value="#{cc.attrs.result}" />
</cc:implementation>
Run Code Online (Sandbox Code Playgroud)
只是这个(省略了nullchecks;我建议required="true"在输入上使用)
@FacesComponent("calculator")
public class Calculator extends UINamingContainer {
public void sum() {
Long firstNumber = (Long) getAttributes().get("firstNumber");
Long secondNumber = (Long) getAttributes().get("secondNumber");
getAttributes().put("result", firstNumber + secondNumber);
}
}
Run Code Online (Sandbox Code Playgroud)
否则,你得把状态保存到自己通过委派所有属性getter/setter方法来UIComponent#getStateHelper().基于与您相同的Facelets代码,整个后备组件将如下所示:
@FacesComponent("calculator")
public class Calculator extends UINamingContainer {
public void sum() {
setResult(getFirstNumber() + getSecondNumber());
}
public void setFirstNumber(Long firstNumber) {
getStateHelper().put("firstNumber", firstNumber);
}
public Long getFirstNumber() {
return (Long) getStateHelper().eval("firstNumber");
}
public void setSecondNumber(Long secondNumber) {
getStateHelper().put("secondNumber", secondNumber);
}
public Long getSecondNumber() {
return (Long) getStateHelper().eval("secondNumber");
}
public void setResult(Long result) {
getStateHelper().put("result", result);
}
public Long getResult() {
return (Long) getStateHelper().eval("result");
}
}
Run Code Online (Sandbox Code Playgroud)
看,没有局部变量了.请注意,我还String-Long通过声明正确的getter返回类型和setter参数类型来删除了那些丑陋的手动转换的需要.JSF/EL将根据默认转换器或自定义Converters 自动执行转换.由于已经存在默认值Long,因此您无需提供自定义Converter.
与具体问题无关,您可以安全地删除该getFamily()方法.在UINamingContainer已经提供的正是这种.如果您正在实现NamingContainer接口,那么您确实需要自己提供它,但这不是这里的情况.上述背衬组件示例已将其删除.
| 归档时间: |
|
| 查看次数: |
2130 次 |
| 最近记录: |