通过实现java.util.Map#get实现EL的动态bean属性



我有一个@SessionScoped bean,我想把它用作映射,这样我就可以在视图中使用EL动态获取它的属性。

myBean['someDynamicProperty']

我通过实现java.util.Map、用我的应用程序逻辑实现get(Object o)以及在所有其他overriden Map方法中抛出UnsupportedOperationException来实现这一点。

@SessionScoped
@Named
public class MyBean implements Map<String, String> {
    @Override
    public String get(Object key) {
        // Application logic here
    }
    @Override
    public boolean containsKey(Object key) {
        throw new UnsupportedOperationException();
    }
    // All other map methods overriden like containsKey
}

属性是只读的,我只需要使用代码中的get方法,但不实现其他Map方法安全吗?

有没有更好的方法来定义bean中EL的动态属性?

最好将映射存储为会话属性,这样就不需要创建@SessionScoped bean,并且可以通过表达式语言访问它,而不会出现问题。

public void methodThatShouldCreateTheMap() {
    //declaring the variable as myBean for compatibility with your current code
    Map<String, Object> myBean = new HashMap<String, Object>();
    //fill myBean here...
    //...
    //store myBean in session
    FacesContext.getCurrentInstance()
        .getExternalContext()
        .getSession(false)
        .setAttribute("myBean", myBean);
}

您可以直接在EL:中访问地图

${myBean['key']}

来自评论:

问题是我的bean并不是真正的Map。在get方法中,我根据收到的密钥来实现所需的逻辑。(…)在我的情况下,getter中的业务逻辑并不昂贵。

在某种程度上,您似乎需要您的bean来实现Map接口。相反,重新发明轮子或标记方法以抛出UnsupportedOperationException,从一个已经实现所有方法的类(如HashMapLinkedHashMap)扩展,或者从一个实现Map但根本不实现的类(例如AbstractMap)扩展,并保留其他方法为空:

@Named
@SessionScoped
public class MyBean extends AbstractMap<String, Object> {
    @Override
    public Object get(String key) {
        //add your logic here...
    }
    @Override
    public void set(String key, Object value) {
        //do nothing...
    }
    //similar for other unnecessary methods...
}

最新更新