ThreadLocal get()在未调用set()方法时给出意外结果

时间:2016-03-21 09:40:21

标签: java locale guice thread-local

我有包含ThreadLocal的基类:

@Singleton
public class BaseView extends HttpServlet {

protected ThreadLocal<Locale> locale = new ThreadLocal<Locale>();

private Locale getLocale() {
    return (Locale) ObjectUtils.defaultIfNull(locale.get(), Locale.ENGLISH);
}

...

}

它在EmailValidatedView中扩展:

@Singleton
public class EmailValidatedView extends BaseView {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String token = req.getParameter("token");
    if (token != null) {
        try {
            User user = userService.validateEmail(token);
            locale.set(user.parseLocale());
        } catch (ServiceException e) {
            e.printStackTrace();
        }
    }
    sendResponse("validatedEmail.vm", resp.getWriter(), $());
}
}

当令牌无效时,我收到ServiceException并且未设置区域设置。在这种情况下,sendResponse()方法应该使用默认语言环境 - 英语。但是,如果我使用无效令牌在浏览器中刷新同一页面,我可能每次都会得到不同/不相关的语言。为什么会这样?

1 个答案:

答案 0 :(得分:1)

大多数HTTP服务器都会重用池中的线程。保持线程安全配置是一件好事,ThreadLocal可以提供帮助,但是您的逻辑结构使得您的语言环境不会在每次请求时重置。因此,毫不奇怪,来自过去请求的线程的旧语言环境将会流失。

您需要确保每个读取它的请求都设置了您的语言环境,并且为每个新请求设置了默认语言环境(或者等效地清除了ThreadLocal值)。