在基于Eclipse(MyEclipse)+Tomcat6的开发环境中,经常会碰到EL表达式被当作字符串来处理,而没有正确解析出EL表示式的值的情况。
这个问题有两点需要注意,一是tag.tld文件中的version要设置为2.1,同时把value属性设置为Object。
<taglib
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee web-jsptaglibrary_2_1.xsd"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1">
...
<tag>
<name>textCommand</name>
<tag-class>org.freesky.tag.TextCommandTag</tag-class>
<attribute>
<name>label</name>
<required>true</required>
</attribute>
<attribute>
<name>value</name>
<deferred-value>
<type>java.lang.Object</type>
</deferred-value>
</attribute>
</tag>
..
-----------------------------------------------------------------------
而是在Tag Class中要用如下方法获取
1. FacesContext facesContext = getFacesContext();
2. Application app = facesContext.getApplication();
3. ExpressionFactory elFactory = app.getExpressionFactory();
4. ELContext elContext = facesContext.getELContext();
5. ValueExpression valueExp =
6. elFactory.createValueExpression(elContext, expression,
7. Object.class);
--------------TextCommandTag.java-----------------------
import javax.el.ValueExpression;
import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.webapp.UIComponentELTag;
public class TextCommandTag extends UIComponentELTag {
private String label;
private ValueExpression value;
public void setLabel(String label) {
this.label = label;
}
public void setValue(ValueExpression value) {
this.value = value;
}
@Override
public String getComponentType() {
return "txtCmd.component";
}
@Override
public String getRendererType() {
return "txtCmd.renderer";
}
@Override
public void setProperties(UIComponent component) {
super.setProperties(component);
TextCommandComponent txtCmd = (TextCommandComponent) component;
txtCmd.setLabel(label);
FacesContext context = FacesContext.getCurrentInstance();
Application application = context.getApplication();
ValueExpression expression = application.getExpressionFactory()
.createValueExpression(context.getELContext(),
value.getExpressionString(), String.class);
txtCmd.setValue( expression.getValue(context.getELContext()) );
txtCmd.setValueExpression(value.getExpressionString());
}
@Override
public void release() {
this.label = null;
this.value = null;
}
}
-------------------------------------
在JSP页面中
<tc:textCommand label="OTP" value="#{user.otp}" />
---------------------------------------------------------------------------------
这里value是字符串,所以在上述createValueExpression()方法中用了String.class 表示类型。
这样可以获取EL表达式所表示的值。
反过来,在Form提交的时候,如何把修改后的value值设置到EL表达式所代表的对象中呢?
这需要在Component中定义一个字符串来保存EL表达式,
private String valueExpression;
public String getValueExpression() {
return valueExpression;
}
public void setValueExpression(String valueExpression) {
this.valueExpression = valueExpression;
}
在Tag class的setProperties()方法中设置该值,如上
txtCmd.setValueExpression(value.getExpressionString());
这样在Renderer class的decode方法中可以通过如下方式把value值设置回去。
@Override
public void decode(FacesContext context, UIComponent component) {
TextCommandComponent txtCmd = (TextCommandComponent) component;
Map<String, String> parameters = context.getExternalContext()
.getRequestParameterMap();
String id = txtCmd.getClientId(context);
String value = parameters.get(id);
Application application = context.getApplication();
ValueExpression expression = application.getExpressionFactory()
.createValueExpression(context.getELContext(),
txtCmd.getValueExpression(), String.class);
expression.setValue(context.getELContext(), value);
txtCmd.setSubmittedValue(value);
}
---------------------------------------------------------------------------
这个问题有两点需要注意,一是tag.tld文件中的version要设置为2.1,同时把value属性设置为Object。
<taglib
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee web-jsptaglibrary_2_1.xsd"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1">
...
<tag>
<name>textCommand</name>
<tag-class>org.freesky.tag.TextCommandTag</tag-class>
<attribute>
<name>label</name>
<required>true</required>
</attribute>
<attribute>
<name>value</name>
<deferred-value>
<type>java.lang.Object</type>
</deferred-value>
</attribute>
</tag>
..
-----------------------------------------------------------------------
而是在Tag Class中要用如下方法获取
1. FacesContext facesContext = getFacesContext();
2. Application app = facesContext.getApplication();
3. ExpressionFactory elFactory = app.getExpressionFactory();
4. ELContext elContext = facesContext.getELContext();
5. ValueExpression valueExp =
6. elFactory.createValueExpression(elContext, expression,
7. Object.class);
--------------TextCommandTag.java-----------------------
import javax.el.ValueExpression;
import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.webapp.UIComponentELTag;
public class TextCommandTag extends UIComponentELTag {
private String label;
private ValueExpression value;
public void setLabel(String label) {
this.label = label;
}
public void setValue(ValueExpression value) {
this.value = value;
}
@Override
public String getComponentType() {
return "txtCmd.component";
}
@Override
public String getRendererType() {
return "txtCmd.renderer";
}
@Override
public void setProperties(UIComponent component) {
super.setProperties(component);
TextCommandComponent txtCmd = (TextCommandComponent) component;
txtCmd.setLabel(label);
FacesContext context = FacesContext.getCurrentInstance();
Application application = context.getApplication();
ValueExpression expression = application.getExpressionFactory()
.createValueExpression(context.getELContext(),
value.getExpressionString(), String.class);
txtCmd.setValue( expression.getValue(context.getELContext()) );
txtCmd.setValueExpression(value.getExpressionString());
}
@Override
public void release() {
this.label = null;
this.value = null;
}
}
-------------------------------------
在JSP页面中
<tc:textCommand label="OTP" value="#{user.otp}" />
---------------------------------------------------------------------------------
这里value是字符串,所以在上述createValueExpression()方法中用了String.class 表示类型。
这样可以获取EL表达式所表示的值。
反过来,在Form提交的时候,如何把修改后的value值设置到EL表达式所代表的对象中呢?
这需要在Component中定义一个字符串来保存EL表达式,
private String valueExpression;
public String getValueExpression() {
return valueExpression;
}
public void setValueExpression(String valueExpression) {
this.valueExpression = valueExpression;
}
在Tag class的setProperties()方法中设置该值,如上
txtCmd.setValueExpression(value.getExpressionString());
这样在Renderer class的decode方法中可以通过如下方式把value值设置回去。
@Override
public void decode(FacesContext context, UIComponent component) {
TextCommandComponent txtCmd = (TextCommandComponent) component;
Map<String, String> parameters = context.getExternalContext()
.getRequestParameterMap();
String id = txtCmd.getClientId(context);
String value = parameters.get(id);
Application application = context.getApplication();
ValueExpression expression = application.getExpressionFactory()
.createValueExpression(context.getELContext(),
txtCmd.getValueExpression(), String.class);
expression.setValue(context.getELContext(), value);
txtCmd.setSubmittedValue(value);
}
---------------------------------------------------------------------------