servlets - 如何在servlet环境中初始化API

标签 servlets

显然我想编写解耦的组件。其中一部分是表单引擎。我不希望它依赖于 servlet API,但我必须按请求(或至少按 session )初始化它。

在应用程序中我会使用类似的东西

public static void setLocale(Locale l);

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

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

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

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

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());
    }    
}

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

最佳答案

but I have to inialize it per-request (or at least per-session).

使用 Filter , HttpServlet ServletRequestListener (或 HttpSessionListener )。

but this creates some security concerns

此外,线程由容器池化。对于不同的后续请求,可以多次重用同一个线程。当您在线程中放入某些内容并且在请求结束时未将其删除时,您最终会得到线程不安全的代码。

你最好的选择是创建一个 ThreadLocal<T>类(class)。假设您希望它基于请求/响应,下面是一个启动示例:

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 block 的 try block 中释放上下文非常非常重要,否则无论何时它都不会被释放请求-响应处理抛出异常)

最后,您可以在代码中的任何位置获取它,如下所示:

Context context = Context.getInstance();
context.setLocale(locale); 
Locale foo = context.getLocale();
// ...

其中您将方法委托(delegate)给本地 request和/或 response变量。

请注意,类似的构造已经存在于某些 MVC 框架中,例如 JSF 及其 FacesContext 。您不想自己种植,而是想看看那边的草是否更绿。

关于servlets - 如何在servlet环境中初始化API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5753913/

相关文章:

java - 在linux中执行命令

java - block /方法中控制并发的逻辑

java - 有什么方法可以从 Java 中的响应对象中读取 cookie?

linux - tomcat 7 在 hello world jsp 中显示编译错误

java - 将 HttpServletRequest 转发到不同的服务器

Autowiring 的 HTTPServletRequest bean 的 Spring AOP 和方面线程安全

java - 在 JSESSIONID cookie 中设置 httponly (Java EE 5)

java - 在 webapp 之间共享对象时出现 ClassCastError

java - 在 JSP 中显示包含 csv 数据的 java 对象的最佳方式?

java - servlet 能否确定发布的数据是否为多部分/表单数据?