Jsf 有了EL,可以在bean上进行字段访问而不是在getter/setter上进行字段访问吗? 编辑

Jsf 有了EL,可以在bean上进行字段访问而不是在getter/setter上进行字段访问吗? 编辑,jsf,el,getter-setter,field-accessors,Jsf,El,Getter Setter,Field Accessors,对这个答案持保留态度。自从我多年前提出这个问题以来,情况发生了很大变化。我建议现在使用Lombok而不是我的EL解决方案。出于历史原因,保留原始问题 当我不需要控制对对象内部状态的访问时,我真的厌倦了getter/setter阻塞我的代码。我仍然必须生成getter/setter的唯一真正原因是EL通过定位方法而不是字段来工作:${myBean.fieldName}。其中fieldName指的是方法getFieldName()。除非找到getter,否则是否可以扩展EL解析器以仅返回公共字段值

对这个答案持保留态度。自从我多年前提出这个问题以来,情况发生了很大变化。我建议现在使用Lombok而不是我的EL解决方案。出于历史原因,保留原始问题


当我不需要控制对对象内部状态的访问时,我真的厌倦了getter/setter阻塞我的代码。我仍然必须生成getter/setter的唯一真正原因是EL通过定位方法而不是字段来工作:
${myBean.fieldName}
。其中
fieldName
指的是方法
getFieldName()
。除非找到getter,否则是否可以扩展EL解析器以仅返回公共字段值


根据Steve Atkinson的回答更新: 我希望这对其他人有帮助。请注意,我是如何明确检查我只在表单或Lead对象上使用这个elresolver的,它们是我的域对象

public class PublicFieldSupportingELResolver extends ELResolver {
    @Override
    public Class<?> getCommonPropertyType(ELContext context, Object base) {
        if (base instanceof Form || base instanceof Lead) {
            try {
                context.setPropertyResolved(true);
                return base.getClass();
            } catch (Exception e) {
                context.setPropertyResolved(false);
                return null;
            }
        } else {
            context.setPropertyResolved(false);
            return null;
        }
    }

    @Override
    public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
        return null;
    }

    @Override
    public Class<?> getType(ELContext context, Object base, Object property) {
        if (base instanceof Form || base instanceof Lead) {
            try {
                Field field = base.getClass().getField((String) property);
                context.setPropertyResolved(true);
                return field.getType();
            } catch (Exception e) {
                context.setPropertyResolved(false);
                return null;
            }
        } else {
            context.setPropertyResolved(false);
            return null;
        }
    }

    @Override
    public Object getValue(ELContext context, Object base, Object property) {
        if (base instanceof Form || base instanceof Lead) {
            try {
                Field field = base.getClass().getField((String) property);
                Object value = field.get(base);
                context.setPropertyResolved(true);
                return value;
            } catch (Exception e) {
                context.setPropertyResolved(false);
                return null;
            }
        } else {
            context.setPropertyResolved(false);
            return null;
        }
    }

    @Override
    public boolean isReadOnly(ELContext context, Object base, Object property) {
        if (base instanceof Form || base instanceof Lead) {
            try {
                base.getClass().getField((String) property);
                context.setPropertyResolved(true);
                return true;
            } catch (Exception e) {
                context.setPropertyResolved(false);
                return false;
            }
        } else {
            context.setPropertyResolved(false);
            return false;
        }
    }

    @Override
    public void setValue(ELContext context, Object base, Object property, Object value) {
        if (base instanceof Form || base instanceof Lead) {
            try {
                Field field = base.getClass().getField((String) property);
                field.set(base, value);
                context.setPropertyResolved(true);
            } catch (Exception e) {
                context.setPropertyResolved(false);
            }
        } else {
            context.setPropertyResolved(false);
        }
    }
}
公共类PublicFieldSupportingELResolver扩展了ELResolver{
@凌驾
公共类getCommonPropertyType(ELContext上下文,对象库){
if(表格的基本实例| |引线的基本实例){
试一试{
context.setPropertyResolved(true);
返回base.getClass();
}捕获(例外e){
context.setPropertyResolved(false);
返回null;
}
}否则{
context.setPropertyResolved(false);
返回null;
}
}
@凌驾
公共迭代器GetFeatureDescriptor(ELContext上下文,对象库){
返回null;
}
@凌驾
公共类getType(ELContext上下文、对象基、对象属性){
if(表格的基本实例| |引线的基本实例){
试一试{
Field=base.getClass().getField((字符串)属性);
context.setPropertyResolved(true);
返回字段。getType();
}捕获(例外e){
context.setPropertyResolved(false);
返回null;
}
}否则{
context.setPropertyResolved(false);
返回null;
}
}
@凌驾
公共对象getValue(ELContext上下文、对象基、对象属性){
if(表格的基本实例| |引线的基本实例){
试一试{
Field=base.getClass().getField((字符串)属性);
对象值=field.get(基本);
context.setPropertyResolved(true);
返回值;
}捕获(例外e){
context.setPropertyResolved(false);
返回null;
}
}否则{
context.setPropertyResolved(false);
返回null;
}
}
@凌驾
公共布尔值isReadOnly(ELContext上下文、对象基、对象属性){
if(表格的基本实例| |引线的基本实例){
试一试{
base.getClass().getField((字符串)属性);
context.setPropertyResolved(true);
返回true;
}捕获(例外e){
context.setPropertyResolved(false);
返回false;
}
}否则{
context.setPropertyResolved(false);
返回false;
}
}
@凌驾
public void setValue(ELContext上下文、对象基、对象属性、对象值){
if(表格的基本实例| |引线的基本实例){
试一试{
Field=base.getClass().getField((字符串)属性);
设置字段(基、值);
context.setPropertyResolved(true);
}捕获(例外e){
context.setPropertyResolved(false);
}
}否则{
context.setPropertyResolved(false);
}
}
}

如果不想在Java Bean上编写/生成getter和setter方法,可以使用中的注释。

是。Jsf是非常可扩展的,几乎所有东西都可以扩展或替换

自定义解析器的一个很好的例子是


这家伙用它来填充数据库查询的下拉列表。我确信您可以使用类似的技术来基于公共字段而不是公共get/set方法进行解析。

如果在我的faces配置中替换el-resolver元素,则无法使用默认元素。有没有办法在不替换默认解析程序的情况下添加一个额外的解析程序?@JonathanS.Fisher是的,对此的回答会很好,请参见第一篇文章的编辑:)警告:这不一定适用于代理bean(例如CDI)。是的,这真的不应该再做了