简体   繁体   English

从Getter Setter引用的JSF EL字段如何工作?

[英]How does the JSF EL Field Referencing From Getter Setter work?

I want to replicate this for my own project but not for xhtml or other xml structured files. 我想将其复制到我自己的项目中,而不是xhtml或其他xml结构化文件。 I want to replicate this kind of feature in java files. 我想在Java文件中复制这种功能。 Is it possible? 可能吗?

#{Object.field}

example class 示例类

class Object
{
   public String getField()
   {
      return "field";
   }

   public void setField()
   {
   }
}

It somehow converts the suffix of the getter and setter to work like an actual field reference. 它以某种方式将getter和setter的后缀转换为像实际的字段引用一样工作。 But I want the developers to ONLY be able to put the actual field. 但是我希望开发人员只能将实际字段放进去。 So it shows error on compile when they don't put an actual field's name (which is the suffix of the getter and setter function). 因此,当他们不输入实际字段的名称(这是getter和setter函数的后缀)时,它将在编译时显示错误。

I don't literally want to use EL expression. 我从字面上不想使用EL表达式。 "#{Object.field}". “#{Object.field}”。 I just want to replicate the system to ease the developers from having to use looping, getter and setter to make a table. 我只想复制系统,以使开发人员不必使用循环,getter和setter来创建表。 If it's possible, I want them to be able to code it like this 如果可能的话,我希望他们能够像这样编码

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

I found that it is possible to do that by using java reflection. 我发现可以通过使用Java反射来做到这一点。 But there is to much hassle to get a particular "Field". 但是要获得一个特定的“字段”有很多麻烦。 If I could make it as easy as "Object.fieldName" to get the "Field" it'd be great. 如果我可以像“ Object.fieldName”一样简单地获取“ Field”,那就太好了。

I think what you need is EL Resolver. 我认为您需要的是EL Resolver。 You need to implement ELResolver from javax & whenever you have any EL string , just resolve it using your own EL Resolver. 只要有任何EL字符串,就需要从javax&实现ELResolver,只需使用自己的EL Resolver即可解决它。

Below is sample code. 下面是示例代码。 It won't work as it is, so try deleting unnecessary stuff like function mapper, variable mapper etc & then run it. 它将无法正常工作,因此请尝试删除不必要的内容,例如函数映射器,变量映射器等,然后运行它。

Maven dependancies 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>

Custom EL Resolver 定制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);
    }

}

Using ELResolver 使用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);

Reference: http://weblogs.java.net/blog/felipeal/archive/2008/10/adding_el_suppo.html 参考: http : //weblogs.java.net/blog/felipeal/archive/2008/10/adding_el_suppo.html

Those expressions are strings, which can be evaluated at runtime only. 这些表达式是字符串,只能在运行时求值。 The field name is prefixed with get/set to form the method name which is then invoked on the object using the Reflection API. 字段名称以get / set为前缀,以形成方法名称,然后使用Reflection API在对象上调用该方法名称。

If it were possible to enforce something like that at compile then they would certainly have done that, I think. 我认为,如果有可能在编译时执行类似的操作,那么他们肯定会这样做。

Object.field1 that's not valid, unless you actually have a public field like that in that class. Object.field1无效,除非您实际上在该类中有一个类似的公共字段。 It has to be a string "Object.field1" . 它必须是字符串"Object.field1" And you can't really check the content of that string at compile time. 而且,您在编译时实际上无法检查该字符串的内容。

So, it's not possible to enforce that at compile-time. 因此,不可能在编译时强制执行该操作。 The best you can do is throw a runtime-exception. 最好的办法是抛出运行时异常。

I think you don't need to build a system as complicated as the EL-API. 我认为您不需要构建像EL-API一样复杂的系统。 Just learn the Reflection API . 只需学习Reflection API

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM