如何在servlet环境中初始化API

时间:2011-04-22 09:03:11

标签: servlets

显然我想编写分离的组件。一部分是表单引擎。我不希望它依赖于servlet API,但我必须按请求(或至少每个会话)对其进行初始化。

在应用程序中,我会使用类似

的内容
public static void setLocale(Locale l);

然后我的个人类可以使用静态getter获取它。这在servlet环境中是不可行的(servlet甚至缺少可以模拟静态行为的static getServletContext()方法。)

我绝对不想使用工厂(我将有10个以上的类,所有这些类都将使用一些配置,至少使用Locale)或者更糟糕的是:使用参数块(包含{{1})构造每个对象和其他设置)。

我想知道在这种情况下什么是最好的。是否可以以可用的方式模拟静态行为,或者servlet API是否可以解决此问题?

如果其他所有可能性都失败了,我会想到使用类似的东西:

Locale

...但这会产生一些安全问题(servlet可能无法初始化它并使用在同一线程提供的先前请求期间设置的值)。 - 尽管使用不同用户的Locale并不是一个威胁。

2 个答案:

答案 0 :(得分:3)

  

但我必须按请求(或至少每个会话)对其进行初始化。

使用FilterHttpServletServletRequestListener(或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中。除此之外,它们的设置和清理是在过滤器中完成的,就像上面的方法一样......