显然我想编写分离的组件。一部分是表单引擎。我不希望它依赖于servlet API,但我必须按请求(或至少每个会话)对其进行初始化。
在应用程序中,我会使用类似
的内容public static void setLocale(Locale l);
然后我的个人类可以使用静态getter获取它。这在servlet环境中是不可行的(servlet甚至缺少可以模拟静态行为的static getServletContext()
方法。)
我绝对不想使用工厂(我将有10个以上的类,所有这些类都将使用一些配置,至少使用Locale)或者更糟糕的是:使用参数块(包含{{1})构造每个对象和其他设置)。
我想知道在这种情况下什么是最好的。是否可以以可用的方式模拟静态行为,或者servlet API是否可以解决此问题?
如果其他所有可能性都失败了,我会想到使用类似的东西:
Locale
...但这会产生一些安全问题(servlet可能无法初始化它并使用在同一线程提供的先前请求期间设置的值)。 - 尽管使用不同用户的Locale并不是一个威胁。
答案 0 :(得分:3)
但我必须按请求(或至少每个会话)对其进行初始化。
使用Filter
,HttpServlet
或ServletRequestListener
(或HttpSessionListener
)。
但这会产生一些安全问题
此外,线程由容器合并。对于不同的后续请求,可以多次重用相同的线程。当您在线程中放入某些东西并且在请求结束时不删除它时,您最终会得到线程安全代码。
最好的办法是创建ThreadLocal<T>
课程。假设您希望它是基于请求/响应的,这是一个启动示例:
public final class Context {
private static ThreadLocal<Context> instance = new ThreadLocal<Context>();
private HttpServletRequest request;
private HttpServletResponse response;
private Context(HttpServletRequest request, HttpServletResponse response) {
this.request = request;
this.response = response;
}
public static Context getInstance() {
return instance.get();
}
public static Context newInstance(HttpServletRequest request, HttpServletResponse response) {
Context context = new Context(request, response);
instance.set(context);
return context;
}
public void release() {
instance.remove();
}
// ...
}
获取并在Filter
中设置。
Context context = null;
try {
context = Context.newInstance(request, response);
chain.doFilter(request, response);
} finally {
if (context != null) context.release();
}
(请注意,非常重要的是要释放您正在获取它的finally
区块的try
区块中的上下文,否则它会获胜每当请求 - 响应处理抛出异常时都会被释放)
最后,您可以在代码中的任何位置获取它,如下所示:
Context context = Context.getInstance();
context.setLocale(locale);
Locale foo = context.getLocale();
// ...
其中您将方法委派给本地request
和/或response
变量。
请注意,类似的构造已存在于某些MVC框架中,例如JSF及其FacesContext
。你不想在家里养一个,而是想看看那里的草是不是更绿。
答案 1 :(得分:0)
您还可以考虑使用我在此处讨论的方法:JSP/Servlet design question - Make request/response globally available via JNDI
在我的方法中,请求和响应对象存储在JNI而不是ThreadLocal中。除此之外,它们的设置和清理是在过滤器中完成的,就像上面的方法一样......