在别人写的jsf应用程序上工作,我一定错过了一些非常基本的东西。我将其剥离为以下内容,这不起作用:
page.jsp
:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<!doctype html>
<html>
<body>
<f:view>
<h:messages id="error" globalOnly="true"/>
<h:outputText value="#{testBean.msg}"/>
</f:view>
</body>
</html>
testBean.java
:
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
public class testBean {
public String getMsg() {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "getMsg"), null));
return "getMsg";
}
}
该代码不显示testBean#getMsg
中生成的错误信息。如果我将<h:messages>
移动到<h:outputText>
行之后,则显示消息。为什么呢?这应该管用吗?
您在getter方法中执行业务工作,该方法在本例中仅在呈现响应阶段生成HTML输出时调用。如果消息组件的HTML表示已经事先生成,那么在这个特定的构造中添加faces消息就太晚了。您不能从响应中收回已经写入的字节。
事实上,你永远不应该在getter中做业务逻辑。您没有在任何地方清楚地说明具体的功能需求,因此很难提出正确的解决方案,但在这个特定的示例中,解决方案之一将是在预呈现视图侦听器方法中执行该工作。
<f:view>
<f:event type="preRenderView" listener="#{testBean.init}" />
<h:messages id="error" globalOnly="true"/>
<h:outputText value="#{testBean.msg}"/>
</f:view>
private String msg;
public void init() {
msg = "getMsg";
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "getMsg"), null));
}
public String getMsg() { // Keep getter untouched! Don't do business logic in there!
return msg;
}
Update上述内容仅适用于JSF2 Facelets。对于遗留的和弃用的JSP,没有类似的方法。最好的方法是使用getter返回一个空字符串,并在JSP顶部引用它。
<f:view>
<h:outputText value="#{testBean.initHack}" />
<h:messages id="error" globalOnly="true"/>
<h:outputText value="#{testBean.msg}"/>
</f:view>
private String msg;
public String getInitHack() {
msg = "getMsg";
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "getMsg"), null));
return "";
}
public String getMsg() { // Keep getter untouched! Don't do business logic in there!
return msg;
}