[英]How does the JSF EL Field Referencing From Getter Setter work?
我想將其復制到我自己的項目中,而不是xhtml或其他xml結構化文件。 我想在Java文件中復制這種功能。 可能嗎?
#{Object.field}
示例類
class Object
{
public String getField()
{
return "field";
}
public void setField()
{
}
}
它以某種方式將getter和setter的后綴轉換為像實際的字段引用一樣工作。 但是我希望開發人員只能將實際字段放進去。 因此,當他們不輸入實際字段的名稱(這是getter和setter函數的后綴)時,它將在編譯時顯示錯誤。
我從字面上不想使用EL表達式。 “#{Object.field}”。 我只想復制系統,以使開發人員不必使用循環,getter和setter來創建表。 如果可能的話,我希望他們能夠像這樣編碼
createTable(new Field[]{Object.field1, Object.field4, Object.field6}, new Object[]{object1, object2, object3});
//new Field[]{Object.field1, Object.field4} <-- selected fields
//new Object[]{object1, object2, object3} <-- objects that is going to be shown in the table
我發現可以通過使用Java反射來做到這一點。 但是要獲得一個特定的“字段”有很多麻煩。 如果我可以像“ Object.fieldName”一樣簡單地獲取“ Field”,那就太好了。
我認為您需要的是EL Resolver。 只要有任何EL字符串,就需要從javax&實現ELResolver,只需使用自己的EL Resolver即可解決它。
下面是示例代碼。 它將無法正常工作,因此請嘗試刪除不必要的內容,例如函數映射器,變量映射器等,然后運行它。
Maven依賴
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>jasper-el</artifactId>
<version>6.0.18</version>
</dependency>
定制EL旋轉變壓器
package ravi.tutorial.el;
import java.beans.FeatureDescriptor;
import java.util.Iterator;
import java.util.Map;
import javax.el.ELContext;
import javax.el.ELResolver;
import javax.el.MapELResolver;
public class DemoELResolver extends ELResolver {
private ELResolver delegate = new MapELResolver();
private Map<Object, Object> userMap;
public DemoELResolver(Map<Object, Object> userMap) {
this.userMap = userMap;
}
@Override
public Object getValue(ELContext context, Object base, Object property) {
if (base == null) {
base = userMap;
}
return delegate.getValue(context, base, property);
}
@Override
public Class<?> getCommonPropertyType(ELContext context, Object base) {
if (base == null) {
base = userMap;
}
return delegate.getCommonPropertyType(context, base);
}
@Override
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context,
Object base) {
if (base == null) {
base = userMap;
}
return delegate.getFeatureDescriptors(context, base);
}
@Override
public Class<?> getType(ELContext context, Object base, Object property) {
if (base == null) {
base = userMap;
}
return delegate.getType(context, base, property);
}
@Override
public boolean isReadOnly(ELContext context, Object base, Object property) {
if (base == null) {
base = userMap;
}
return delegate.isReadOnly(context, base, property);
}
@Override
public void setValue(ELContext context, Object base, Object property,
Object value) {
if (base == null) {
base = userMap;
}
delegate.setValue(context, base, property, value);
}
}
使用ELResolver
ExpressionFactory expressionFactory;
if (args == null || args.length == 0) {
System.out
.println("Enter command line argument 1=Apache Jasper 2=Sourceforge JUEL.");
return;
}
if (args[0].equals("1")) {
expressionFactory = new org.apache.el.ExpressionFactoryImpl();
System.out.println("Choosing org.apache.el.ExpressionFactoryImpl");
} else if (args[0].equals("2")) {
expressionFactory = new de.odysseus.el.ExpressionFactoryImpl();
System.out.println("Choosing de.odysseus.el.ExpressionFactoryImpl");
} else {
System.out.println("Wrong argument");
return;
}
// create a map with some variables in it
Map<Object, Object> userMap = new HashMap<Object, Object>();
userMap.put("x", new Integer(123));
userMap.put("y", new Integer(456));
// get the method for ${myprefix:hello(string)}
Method sayHello = DemoEL.class.getMethod("sayHello",
new Class[] { String.class });
// create the context
ELResolver demoELResolver = new DemoELResolver(userMap);
final VariableMapper variableMapper = new DemoVariableMapper();
final DemoFunctionMapper functionMapper = new DemoFunctionMapper();
functionMapper.addFunction("myprefix", "hello", sayHello);
final CompositeELResolver compositeELResolver = new CompositeELResolver();
compositeELResolver.add(demoELResolver);
compositeELResolver.add(new ArrayELResolver());
compositeELResolver.add(new ListELResolver());
compositeELResolver.add(new BeanELResolver());
compositeELResolver.add(new MapELResolver());
ELContext context = new ELContext() {
@Override
public ELResolver getELResolver() {
return compositeELResolver;
}
@Override
public FunctionMapper getFunctionMapper() {
return functionMapper;
}
@Override
public VariableMapper getVariableMapper() {
return variableMapper;
}
};
// create and resolve a value expression
String sumExpr = "${x+y}";
ValueExpression ve = expressionFactory.createValueExpression(context,
sumExpr, Object.class);
Object result = ve.getValue(context);
System.out.println("Result=" + result);
// call a function
String fnExpr = "#{myprefix:hello('Dave')}";
ValueExpression fn = expressionFactory.createValueExpression(context,
fnExpr, Object.class);
fn.getValue(context);
參考: http : //weblogs.java.net/blog/felipeal/archive/2008/10/adding_el_suppo.html
這些表達式是字符串,只能在運行時求值。 字段名稱以get / set為前綴,以形成方法名稱,然后使用Reflection API在對象上調用該方法名稱。
我認為,如果有可能在編譯時執行類似的操作,那么他們肯定會這樣做。
Object.field1
無效,除非您實際上在該類中有一個類似的公共字段。 它必須是字符串"Object.field1"
。 而且,您在編譯時實際上無法檢查該字符串的內容。
因此,不可能在編譯時強制執行該操作。 最好的辦法是拋出運行時異常。
我認為您不需要構建像EL-API一樣復雜的系統。 只需學習Reflection API 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.