反对具有静态 WeakHashMap 的通用 JSF 对象转换器的参数
Arguments against a generic JSF object converter with a static WeakHashMap
我想避免使用样板代码创建 SelectItems 列表以在视图和模型之间映射我的 entities/dtos,因此我使用了这个 snippet 通用对象转换器:
@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;
}
}
已经有很多 answers 类似的问题,但我想要一个普通的解决方案(没有 *faces)。以下几点仍然让我不确定我的代码片段的质量:
- 如果有那么简单,为什么不在 JSF 中内置通用对象转换器?
- 为什么还有这么多人在使用 SelectItems?使用通用方法不是有更大的灵活性吗?例如。 #{dto.label}可以快速变成#{dto.otherLabel}.
- 鉴于范围只是在视图和模型之间进行映射,通用方法是否有任何主要缺点?
这种方法是 hacky 和内存效率低下。
在小型应用程序中是 "okay",但在具有数万或数十万个潜在实体的大型应用程序中绝对不是 f:selectItems
。而且,这么大的应用一般都有二级实体缓存。 WeakHashMap
变得无用,只有当实体从底层数据存储中物理移除(因此也从二级实体缓存中移除)时才有效。
它肯定有一个 "fun" 因素,但我真的不建议在 "heavy production" 中使用它。
如果您不想使用 OmniFaces SelectItemsConverter
as you already found, which is basically completely stateless and doesn't use any DAO/Service call, then your best bet is to abstract all your entities with a common base interface/class and hook the converter on that instead. This only still requires a DAO/Service call. This has been fleshed out in detail in this Q&A: Implement converters for entities with Java Generics 等实用程序库中的现有解决方案。
我想避免使用样板代码创建 SelectItems 列表以在视图和模型之间映射我的 entities/dtos,因此我使用了这个 snippet 通用对象转换器:
@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;
}
}
已经有很多 answers 类似的问题,但我想要一个普通的解决方案(没有 *faces)。以下几点仍然让我不确定我的代码片段的质量:
- 如果有那么简单,为什么不在 JSF 中内置通用对象转换器?
- 为什么还有这么多人在使用 SelectItems?使用通用方法不是有更大的灵活性吗?例如。 #{dto.label}可以快速变成#{dto.otherLabel}.
- 鉴于范围只是在视图和模型之间进行映射,通用方法是否有任何主要缺点?
这种方法是 hacky 和内存效率低下。
在小型应用程序中是 "okay",但在具有数万或数十万个潜在实体的大型应用程序中绝对不是 f:selectItems
。而且,这么大的应用一般都有二级实体缓存。 WeakHashMap
变得无用,只有当实体从底层数据存储中物理移除(因此也从二级实体缓存中移除)时才有效。
它肯定有一个 "fun" 因素,但我真的不建议在 "heavy production" 中使用它。
如果您不想使用 OmniFaces SelectItemsConverter
as you already found, which is basically completely stateless and doesn't use any DAO/Service call, then your best bet is to abstract all your entities with a common base interface/class and hook the converter on that instead. This only still requires a DAO/Service call. This has been fleshed out in detail in this Q&A: Implement converters for entities with Java Generics 等实用程序库中的现有解决方案。