Servlets 如何在servlet环境中初始化API
显然,我想编写解耦组件。一部分是表单引擎。我不希望它依赖于ServletAPI,但我必须根据每个请求(或至少每个会话)将其初始化 在应用程序中,我会使用Servlets 如何在servlet环境中初始化API,servlets,Servlets,显然,我想编写解耦组件。一部分是表单引擎。我不希望它依赖于ServletAPI,但我必须根据每个请求(或至少每个会话)将其初始化 在应用程序中,我会使用 public static void setLocale(Locale l); 然后我的各个类可以通过静态getter获得它。这在servlet环境中是不可行的(servlet甚至缺少一个静态getServletContext()方法,通过该方法可以模拟静态行为) 我绝对不想使用factory(我将有10多个类,所有这些类都将使用一些配置,至
public static void setLocale(Locale l);
然后我的各个类可以通过静态getter获得它。这在servlet环境中是不可行的(servlet甚至缺少一个静态getServletContext()
方法,通过该方法可以模拟静态行为)
我绝对不想使用factory(我将有10多个类,所有这些类都将使用一些配置,至少是区域设置)或更糟糕的:使用参数块构造每个对象(其中包含Locale
和其他设置)
我想知道在这种情况下最好的做法是什么。静态行为可以用一种可用的方式进行模拟,还是ServletAPI可以解决这个问题
如果其他方法都失败了,我会考虑使用以下方法:
class MyParameters {
private Map<Thread, MyParameters> threadParameters = new Map<Thread, MyParameters>();
public static void setParameters(MyParameters parameters) {
threadParameters.put(Thread.getCurrentThread(), parameters);
}
public static MyParameters getParameters() {
return threadParameters.get(Thread.getCurrentThread());
}
}
类参数{
私有映射threadParameters=新映射();
公共静态void setParameters(MyParameters){
threadParameters.put(Thread.getCurrentThread(),parameters);
}
公共静态MyParameters getParameters(){
返回threadParameters.get(Thread.getCurrentThread());
}
}
。。。但这会产生一些安全问题(servlet可能无法初始化它,并且无法使用在同一线程服务的前一个请求期间设置的值)。-尽管使用不同用户的区域设置并不是一种威胁
但我必须根据每个请求(或至少每个会话)将其最小化
使用,或(或)
但这造成了一些安全问题
此外,线程由容器池化。对于不同的后续请求,同一个线程可以重复使用多次。当您在线程中放入某些内容,但在请求结束时没有将其删除时,您将得到线程不安全的代码
最好是创建一个ThreadLocal
类。假设您希望它基于请求/响应,下面是一个启动示例:
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();
}
// ...
}
(请注意,在获取上下文的try
块的finally
块中释放上下文非常重要,否则在请求-响应处理引发异常时不会释放上下文)
最后,您可以在代码中的任何地方获得它,如下所示:
Context context = Context.getInstance();
context.setLocale(locale);
Locale foo = context.getLocale();
// ...
其中,您将方法委托给本地请求
和/或响应
变量
注意,类似的构造已经存在于一些MVC框架中,比如JSF及其组件。你可以看看草坪是否比这里更绿,而你也可以考虑使用我在这里讨论的方法:
在我的方法中,请求和响应对象存储在JNI中,而不是存储在ThreadLocal中。除此之外,它们的设置和清理是在一个过滤器中完成的,就像上面的方法一样…谢谢!当然,我的
MyParameters
示例可以通过单个请求工作,我没有假设线程在整个会话中都是常量。我写的是:“我没有假设线程在整个会话中都是常量”还有一个问题:这是一种普遍使用的做法还是有一种特殊的设计来解决这个问题?在使用threadlocal上下文的MVC框架中,如JSF、Spring MVC、Wicket等,是的,这是实现它的一般方式。您必须非常小心,如代码示例中所示,最终应在中释放上下文,否则将导致严重的线程安全问题。这里应用的唯一设计模式是facade模式。如果不公开返回“原始”请求/响应的方法,则本例中的上下文基本上是一个facade。您应该只提供委托给它们的方法。
Context context = Context.getInstance();
context.setLocale(locale);
Locale foo = context.getLocale();
// ...