我正在尝试构建一个简单的组件来理解JSF 2.X如何以及为什么以它的方式工作。我一直在使用较新的注释,并一直试图拼凑一个明确的例子。
所以我构建了我的组件并将其部署在xhtml文件中,如下所示:
<kal:day value="K.Day" title="Kalendar" model="#{kalendarDay}"/>
在UIComponent中,我执行以下操作:
ValueExpression ve = getValueExpression("model");
if (ve != null)
{
System.out.println("model expression "+ve.getExpressionString());
model = (KalendarDay) ve.getValue(getFacesContext().getELContext());
System.out.println("model "+model);
}
正确显示表达式“#{kalendarDay}”,表示该值已在页面和组件之间成功传输。然而,表达式的评估结果为“无效”。
这似乎表明此时支持bean不可用,尽管页面正确验证并部署。所以我95%肯定豆子在运行时就在那里。
那么也许这是一个阶段性的事情?我应该在解码渲染器并在属性映射中设置值时对此进行评估吗?我对实际值和值表达式的组合仍然有点困惑。
所以我的问题是我应该在哪里获取和评估模型的valueExpression,我应该将评估结果存储在UIComponent中,还是应该每次只评估它?
下面的SSCCE文件我认为这些是展示问题的唯一必需文件
Bean接口-----
/**
*
*/
package com.istana.kalendar.fixture;
import java.util.Date;
/**
* @author User
*
*/
public interface KalendarDay
{
public Date getDate();
}
Bean实现---
/**
*
*/
package com.istana.kalendar.session.wui;
import java.util.Calendar;
import java.util.Date;
import javax.ejb.Stateful;
import javax.inject.Named;
import com.istana.kalendar.fixture.KalendarDay;
/**
* @author User
*
*/
@Named ("kalendarDay")
@Stateful
public class KalKalendarDay
implements KalendarDay
{
private Calendar m_date = Calendar.getInstance();
/* (non-Javadoc)
* @see com.istana.kalendar.fixture.KalendarDay#getDate()
*/
@Override
public Date getDate()
{
return m_date.getTime();
}
}
UIComponent ---
/**
*
*/
package com.istana.kalendar.fixture.jsf;
import javax.el.ValueExpression;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIOutput;
import com.istana.kalendar.fixture.KalendarDay;
/**
* @author User
*
*/
@FacesComponent (value=UIDay.COMPONENT_TYPE)
public class UIDay extends UIOutput
{
static final
public String COMPONENT_TYPE = "com.istana.kalendar.fixture.jsf.Day";
static final
public String COMPONENT_FAMILY = "com.istana.kalendar.fixture.jsf.Day";
private KalendarDay m_model;
private String m_title;
@Override
public String getRendererType()
{
return UIDayRenderer.RENDERER_TYPE;
}
@Override
public String getFamily()
{
return COMPONENT_FAMILY;
}
public KalendarDay getModel()
{
KalendarDay model = (KalendarDay) getStateHelper().eval("model");
System.out.println("model "+model);
return model;
}
public void setModel(KalendarDay model)
{
getStateHelper().put("model",model);
}
public String getTitle()
{
return (String) getStateHelper().eval("title");
}
public void setTitle(String title)
{
getStateHelper().put("title",title);
}
}
UIComponentRenderer ---
/**
*
*/
package com.istana.kalendar.fixture.jsf;
import java.io.IOException;
import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.FacesRenderer;
import javax.faces.render.Renderer;
import com.istana.kalendar.fixture.KalendarDay;
/**
* @author User
*
*/
@FacesRenderer (componentFamily = UIDay.COMPONENT_FAMILY
,rendererType = UIDayRenderer.RENDERER_TYPE
)
public class UIDayRenderer extends Renderer
{
static final
public String RENDERER_TYPE = "com.istana.kalendar.fixture.jsf.DayRenderer";
@Override
public void encodeBegin (FacesContext context,UIComponent component)
throws IOException
{
UIDay uic = (UIDay) component;
ResponseWriter writer = context.getResponseWriter();
writer.startElement("p", uic);
/*
* This is the call that triggers the println
*/
writer.write("Day - "+uic.getModel().getDate());
}
@Override
public void encodeEnd (FacesContext context,UIComponent component)
throws IOException
{
ResponseWriter writer = context.getResponseWriter();
writer.endElement("p");
writer.flush();
}
}
kalendar.taglib.xml ---
<facelet-taglib
id="kalendar"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
version="2.0"
>
<namespace>http://istana.com/kalendar</namespace>
<tag>
<tag-name>day</tag-name>
<component>
<component-type>com.istana.kalendar.fixture.jsf.Day</component-type>
</component>
</tag>
</facelet-taglib>
答案 0 :(得分:0)
我不确定为什么它是null
,但症状表明在视图渲染时间期间指定了#{kalendarDay}
,而您在视图构建期间尝试对其进行评估。
所以也许这是一个阶段性的事情?我应该在解码渲染器并在属性映射中设置值时对此进行评估吗?我对实际值和值表达式的组合仍然有点困惑。
您应该使用组件的encodeXxx()
方法或关联的渲染器(如果有)根据组件的属性/属性生成HTML。
您应该使用组件的decode()
方法或关联的渲染器(如果有)根据HTTP请求参数设置组件的属性/属性,这些参数与HTML表单提交一起发送。
所以我的问题是我应该在哪里获取和评估模型的valueExpression,我应该将评估结果存储在UIComponent中,还是应该每次只评估它?
从JSF 2.x开始,建议为组件属性明确指定getter和setter,然后将其委托给UIComponent#getStateHelper()
。
public String getValue() {
return (String) getStateHelper().eval("value");
}
public void setValue(String value) {
getStateHelper().put("value", value);
}
public String getTitle() {
return (String) getStateHelper().eval("title");
}
public void setTitle(String title) {
getStateHelper().put("title", title);
}
public Object getModel() {
return getStateHelper().eval("model");
}
public void setModel(Object model) {
getStateHelper().put("model", model);
}
这就是你基本上所需要的(请注意,getter和setter必须与Javabeans规范完全匹配属性名称)。然后在encodeXxx()
方法中,只需调用getModel()
即可获取(并评估)model
属性的值。