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

ThreadLocal get() gives unexpected result when set() method is not invoked

我有包含 ThreadLocal 的基础 class :

@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() 方法应使用默认语言环境 - 英语。但是,如果我在浏览器中使用无效令牌刷新同一页面,我可能每次都会得到 different/non 相关语言。为什么会这样?

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

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