【发布时间】:2013-05-26 04:56:35
【问题描述】:
我正在对存储在数据库中的相当大的客户端/服务器(HTTP (Hessian) 用于通信)应用程序中的用户输入数据进行国际化。用户可以选择他们想看的语言,当请求的语言翻译不存在时,会使用默认语言。
目前一个数据类可能是这样的:
class MyDataClass {
private Long id;
private String someText;
/* getters and setters */
}
国际化后可能如下所示:
class MyDataClass {
private Long id;
private Set<LocalizedStrings> localizedStrings;
/* getters and setters */
}
class LocalizedStrings {
private Locale locale;
private String someText;
/* getters and setters */
}
当然,在 MyDataClass 中创建一个委托 getter 可能会很有趣,它负责在正确的语言环境中获取文本:
public String getSomeText(Locale locale) {
for(LocalizedString localized : localizedStrings) {
if (localized.getLocale().equals(locale)) {
return localized.getSomeText();
}
}
}
在我的团队中,有一些担心需要一直传递语言环境,直到他们到达数据类。由于所有这些事情都发生在服务器上,并且对服务器的每个请求都在专用线程中处理,因此有人建议将请求的语言环境存储在 ThreadLocal 对象中并创建一个向后兼容的无参数 getter:
public String getSomeText() {
return getSomeText(myThreadLocalLocale.get());
}
然后,ThreadLocal 需要是一个全局变量(在某处是静态的),或者需要在每次创建单个实例时将其注入 MyDataClass(我们使用的是 spring,因此如果我们使我们的数据类受 spring 管理,我们可以注入它(其中我觉得不对))。
在语言环境中使用 ThreadLocal 对我来说是错误的。我可以含糊地说,我不喜欢 getter 中的隐形魔法和对全局变量的依赖(在数据类中!)。然而,对此有“不好的感觉”并不是与我的同事争论的好方法。为了帮助我,我需要以下其中一项的答案:
- 告诉我,我的感觉很糟糕,解决方案很好,原因是 X、Y 和 Z。
- 给我一些很好的可引用论据,我可以用来与同事争论,并告诉我如何做得更好(只是总是传递语言环境或任何其他想法?)
【问题讨论】:
-
为什么
localizedStrings使用 Set 而不是 Map? -
您是否考虑过使用 Spring LocaleContextHolder。它以自己的方式存储线程的当前语言环境(由 DispatcherServlet 存储)。
-
如果您的本地化变量的范围是单线程,那么这似乎是一个聪明(且简单)的解决方案。如果您要冒险进入多个线程,那么显然,这需要更多的东西。如果您的 API 在每个请求中都有本地化信息,那么它是一个完全有效的解决方案。 KISS,这是你能提出的最好的论点。
-
@JimmyT.:因为与休眠映射有关的原因。另一个有趣的问题,但不是这里问题的一部分。
-
但是hibernate很好的支持Maps。
标签: java thread-local