【问题标题】:How to get the value in an EnumMap using a key in EL expression?如何使用 EL 表达式中的键获取 EnumMap 中的值?
【发布时间】:2011-10-18 21:58:09
【问题描述】:

我有一个 EnumMap:

EnumMap<Gender, Integer> genderMap = new EnumMap(Gender.class);

性别是public enum Gender {Male, Female};

我有req.setAttribute("genderMap", genderMap);

现在我想通过 JSP 文件中的键从 genderMap 获取值:

${genderMap['Male']}

但这并没有得到genderMap 中的值。为什么?

【问题讨论】:

    标签: java jsp el


    【解决方案1】:
    Map<Gender, Integer> genderMap = new HashMap<Gender, Integer>();
    

    ${genderMap['Male']}

    这肯定行得通。

    【讨论】:

    • 错误,没有。 HashMap 不是 EnumMap 的子类,'Male' 的计算结果是一个字符串,而不是一个性别。
    • Male 将评估为 ENUM ,请参阅:stackoverflow.com/questions/123598/…
    • 没有。在您链接到的问题的最佳答案中,解决方案包括将字符串比较在一起。 someModel.status 被转换为字符串并与字符串“OLD”进行比较。我关于 HashMap 和 EnumMap 的观点仍然成立。
    • 类型不匹配:无法从 HashMap 转换为 EnumMap
    【解决方案2】:

    因为'Male' 的计算结果为字符串“Male”,而不是Gender.Male。您需要有权访问 Gender.Male 常量才能访问其映射条目。但是在 JSP EL 中访问常量是不可能的,所以你可能想要这样做:

    req.setAttribute("male", Gender.Male);
    req.setAttribute("genderMap", genderMap);
    
    ...
    
    ${genderMap[male]}
    

    【讨论】:

    • 如果枚举'Gender'有一百个值怎么办,我必须“req.setAttribute(“some enum value”Gender.someValue)”一百次吗?
    • 您可以将所有这些值放在一个 bean 中,或者您可以退后一步,问自己在 JSP 中访问数百个特定值是否正常,不应该以某种方式封装在某些一段Java代码。
    • 设置百次,使用Map也有同样的问题。你也会打电话给put() 一百次。
    【解决方案3】:

    不要使用枚举映射。只需将枚举用作 Java 中的枚举和 JSP/EL 中的字符串。

    我假设您因为数据库映射而需要该整数。例如。 Male 在数据库中存储为1Female 在数据库中存储为0。在这种情况下,您需要重新设计您的枚举,如下所示:

    public enum Gender {
    
        Male(1), Female(0);
    
        private int id;
    
        private Gender(int id) { 
            this.id = id;
        }
    
        public int getId() {
            return id;
        }
    
        public static Gender valueOf(int id) {
            for (Gender gender : values()) {
                if (gender.id == id) {
                    return gender;
                }
            }
    
            return null;
        }
    
    }
    

    当通过 JDBC 从 DB 中填充 Person 时,只需这样做

    person.setGender(Gender.valueOf(resultSet.getInt("gender")));
    

    在 JSP 中向最终用户显示预选选项时,只需这样做

    request.setAttribute("genders", Gender.values());
    

    Gender:<br/>
    <c:forEach items="${genders}" var="gender">
        <input type="radio" id="gender_${gender.id}" name="gender" value="${gender.id}" 
            ${gender == person.gender ? 'checked="checked"' : ''} />
        <label for="gender_${gender.id}">${gender}</label>
        <br />
    </c:forEach>
    

    甚至没有id

    Gender:<br/>
    <c:forEach items="${genders}" var="gender">
        <input type="radio" id="gender_${gender}" name="gender" value="${gender}" 
            ${gender == person.gender ? 'checked="checked"' : ''} />
        <label for="gender_${gender}">${gender}</label>
        <br />
    </c:forEach>
    

    在 servlet 中收集提交的值时,只需这样做

    Gender gender = Gender.valueOf(Integer.valueOf(request.getParameter("gender")));
    

    或者在 HTML 中不使用 id

    Gender gender = Gender.valueOf(request.getParameter("gender"));
    

    【讨论】:

    • 好的,谢谢你的回答。我的解决方案是使用新地图:HashMap genderMap,其中 Key(String) 是 Gender.name()。所以我可以使用genderMap['Male']来获取jsp中的值。
    • 讨厌投反对票,但答案并没有真正解决问题。
    【解决方案4】:

    我的解决方案是为枚举映射创建一个包装器(适配器)。它需要 String 键并通过调用 Enum.valueOf() 方法将它们转换为相应的 Enum 值。

    示例 bean 中的相关部分:

    private Map <Action, Permission> permissions = new EnumMap<>(Action.class);
    
    /** For java access */
    public Map<Action, Permission> getPermissions() {
        return permissions;
    }
    
    /** For EL access */
    public Map<String, Permission> getPermissionsAsString() {
        return new EnumMapWrapper<>(Action.class, permissions);
    }
    

    现在我可以方便地访问 EL 中的地图元素了:

    #{rule.permissionsAsString['MODIFY']}
    

    这是包装类:

    public class EnumMapWrapper<K extends String, V> implements Map<K, V> {
    
        private Map<Enum, V> map;
        private Class<? extends Enum> enumType;
    
        public EnumMapWrapper(Class<? extends Enum> enumType, Map<? extends Enum, V> map) {
            this.enumType = enumType;
            this.map = (Map<Enum, V>)map;
        }
    
        private Enum valueOf(Object key) {
            if (!(key instanceof String)) {
                throw new IllegalArgumentException("Only string keys are permitted");
            }
    
            return Enum.valueOf(enumType, (String)key);
        }
    
        @Override
        public int size() {
            return map.size();
        }
    
        @Override
        public boolean isEmpty() {
            return map.isEmpty();
        }
    
        @Override
        public boolean containsKey(Object key) {
            return map.containsKey(valueOf(key));
        }
    
        @Override
        public boolean containsValue(Object value) {
            return map.containsValue(value);
        }
    
        @Override
        public V get(Object key) {
            return map.get(valueOf(key));
        }
    
        @Override
        public V put(K key, V value) {
            return map.put(valueOf(key), value);
        }
    
        @Override
        public V remove(Object key) {
            return map.remove(valueOf(key));
        }
    
        @Override
        public void putAll(Map<? extends K, ? extends V> m) {
            throw new UnsupportedOperationException();
        }
    
        @Override
        public void clear() {
            map.clear();
        }
    
        @Override
        public Set<K> keySet() {
            throw new UnsupportedOperationException();
        }
    
        @Override
        public Collection<V> values() {
            return map.values();
        }
    
        @Override
        public Set<Entry<K, V>> entrySet() {
            throw new UnsupportedOperationException();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-11-04
      • 2014-01-23
      • 2012-01-23
      • 2012-02-21
      • 1970-01-01
      • 2011-12-25
      • 1970-01-01
      • 2012-03-06
      相关资源
      最近更新 更多