cor*_*iKa 5 java session tomcat thread-local-storage
我遇到的问题是,我的生产系统中突然出现异常,但我确实没有关于是谁导致异常的详细信息。doPost该人的用户名作为变量存储在他们的 tomcat 会话中,显然我可以在我的或方法中访问它doGet,但除非我将该信息作为参数传递给我的每个业务对象,否则我无权访问该会话。出于显而易见的原因,我想将用户名添加到日志消息中,以便我了解发生了什么。
所以我的解决方案是做这样的事情
public class ExceptionUtil {
private ExceptionUtil() { } // no instantiation
private static final ThreadLocal<String> local = new ThreadLocal<String>();
public static void set(String user) { local.set(user); }
public static String get() { return local.get(); }
}
Run Code Online (Sandbox Code Playgroud)
然后在我的帖子/获取中,我可以这样做
String username = request.getSession().getAttribute("username");
ExceptionUtil.set(username);
Run Code Online (Sandbox Code Playgroud)
然后在我的例外情况下,我可能会这样做(人为的、不好的实践示例)
catch(SQLException e) {
logger.error(ExceptionUtil.get() + " did something dumb in sql", e);
throw e;
}
Run Code Online (Sandbox Code Playgroud)
我唯一关心的问题是 Tomcat 如何管理我的线程。如果他们保留线程怎么办?他们会坚持吗?ThreadLocal 值也会持续存在吗?如果我将整个会话存储在 ThreadLocal 中而不只是一个字符串中,那么这将是一个严重的内存泄漏潜在问题。这还意味着,如果有人忘记重新设置(或完成后忘记清除)持续多个请求的线程上的用户名/会话,则其中可能存在过时的数据。
可以说我很愤世嫉俗,但我不想依赖程序员(甚至,尤其是我自己!)不忘记为程序的正确性做一些事情。如果我可以让我的代码防白痴,我愿意。这意味着更好地了解 Tomcat 将如何使用线程。
因此,问题以单句形式:
如果我在 Tomcat (7.0.27) 上运行的 Web 应用程序中使用 ThreadLocal,我是否会面临线程被用于多个请求以及保留先前请求中的数据的风险?
我应该注意到,即使他们没有回答“Tomcat/ThreadLocal 恶作剧”的确切问题,我也愿意接受替代解决方案,这些解决方案允许我优雅地访问会话变量以进行日志记录。我也愿意接受有关我的解决方案的潜在缺陷的评论。我有一个业务问题需要解决,但我不接受任何一种解决方案。我只是想知道是谁一直在我的产品系统上造成异常:)
是的,tomcat使用ThreadPool概念,这意味着线程被重用,因此正如您所建议的“您的线程本地保留值”,
我建议的替代方案可能是
完成后清理线程,在视图控制器中的某处
编写请求过滤器,并在过滤器启动时清理所有内容并推送新值,并将其分配给服务器上的每个 url 模式。
对于您所遵循的方法,而不是将某些值保存在类中,将请求存储在线程本地中,然后使用该请求使用自制的 util 类从会话中提取值,该类接受请求然后返回您想要的值,这样您就可以避免在线程中保存会话并获取值,但请确保每次添加新鲜内容并在完成后清理请求(使用第二个选项)。
| 归档时间: |
|
| 查看次数: |
7432 次 |
| 最近记录: |