针对具有静态WeakHashMap的通用JSF对象转换器的参数

Jou*_*ner 5 jsf converter jsf-2

我想避免使用样板代码来创建一个SelectItems列表,以便在视图和模型之间映射我的实体/ dtos,所以我使用了这个通用对象转换器的片段:

@FacesConverter(value = "objectConverter")
public class ObjectConverter implements Converter {

private static Map<Object, String> entities = new WeakHashMap<Object, String>();

@Override
public String getAsString(FacesContext context, UIComponent component, Object entity) {
    synchronized (entities) {
        if (!entities.containsKey(entity)) {
            String uuid = UUID.randomUUID().toString();
            entities.put(entity, uuid);
            return uuid;
        } else {
            return entities.get(entity);
        }
    }
}

@Override
public Object getAsObject(FacesContext context, UIComponent component, String uuid) {
    for (Entry<Object, String> entry : entities.entrySet()) {
        if (entry.getValue().equals(uuid)) {
            return entry.getKey();
        }
    }
    return null;
}

}
Run Code Online (Sandbox Code Playgroud)

similliar问题已有很多答案,但我想要一个香草解决方案(没有*面孔).以下几点仍然让我对我的片段质量不确定:

  1. 如果这很容易,为什么没有在JSF中构建通用对象转换器?
  2. 为什么这么多人还在使用SelectItems?使用通用方法不是更灵活吗?例如,#{dto.label}可以快速更改为#{dto.otherLabel}.
  3. 鉴于范围只是在视图和模型之间进行映射,通用方法是否有任何重大缺点?

Bal*_*usC 6

这种方法很麻烦,内存效率低下.

它在一个小应用程序中是"好的",但绝对不是在一个大型应用程序中,其中有数十或数十万个潜在实体可以在一个中被引用f:selectItems.而且,这种大型应用程序通常具有第二级实体缓存.然后WeakHashMap变得无用,并且仅在从底层数据存储区物理移除实体(并且因此也从第二级实体高速缓存)移除实体时才有效.

它肯定是一个"有趣"的因素,但我真的不建议在"大量生产"中使用它.

如果您不想使用像OmniFacesSelectItemsConverter这样的实用程序库中的现有解决方案(基本上完全没有状态且不使用任何DAO/Service调用),那么最好的办法就是用所有实体抽象所有实体.公共基础接口/类,并将转换器挂钩.这只需要DAO/Service调用.在本问答中详细阐述了这一点:为Java Generics实体实现转换器.