ThreadLocal 在 servlet 中存储 ServletRequest 和 Response:有什么用?

发布于 2024-10-27 02:20:02 字数 212 浏览 5 评论 0原文

有一次我遇到了一种模式,其中 ServletRequest 和响应对象被放入 servlet 的本地 ThreadLocal 变量中。 Servlet 类还具有获取当前请求和响应对象的方法。因此,为了获取这些对象,您仍然需要使用 servlet 对象进行操作。

拥有这些 ThrealLocal 局部变量有什么意义?

Once I have came across a pattern, where ServletRequest and response objects are put to servlet's local ThreadLocal variables. The servlet class has also methods to get current request and response objects. So in order to get these objects you still need to operate with servlet object.

What is the point of having these ThrealLocal local variables?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

独留℉清风醉 2024-11-03 02:20:02

重点是在类中包含请求和响应对象,否则这些类不会包含它们(例如,它们不是 servlet)。一个例子是 JSF 托管 bean - 它们的方法不采用 HttpServletRequest 参数,因此您可以通过 FacesContext 获取请求,其中它们位于 ThreadLocal 中代码>变量。

这样做的原因是因为每个请求都由单独的线程(由 servlet 容器)处理。所以线程=请求。但有一个警告 - 容器倾向于使用线程池。因此,必须始终在线程本地设置一个新的请求,并且最好在之后清理它(例如在 Filter 中)。否则你可能会得到一些意想不到的行为。

但你确实应该在代码中避免这种情况。如果您需要请求或响应中的任何内容,请将其作为方法参数传递。否则,您将面临违反层边界的风险(例如,如果您想在服务层中使用请求)

The point is to have the request and response objects in classes that would otherwise would not have them (for example they are not servlets). One example are JSF managed beans - their methods do not take HttpServletRequest parameters, and so you can obtain the request via the FacesContext, which has them in ThreadLocal variables.

The reason this works is because each request is handled by a separate thread (by the servlet container). So thread = request. But there is a caveat - containers tend to use thread pools. So one must always set a fresh request in the threadlocal, and preferably clean it up afterwards (for example in a Filter). Otherwise you can get some unexpected behaviour.

But you should really avoid this in your code. If you need anything from the request or response, pass it as method argument around. Otherwise you risk to violate layer boundaries (if you are tempted to use the request in the service layer, for example)

半衾梦 2024-11-03 02:20:02

它们允许您从项目中的其他类获取对 HttpServletRequest 和 HttpServletResponse 的访问,而无需将对这些对象的引用传递给其他类。这不是我特别喜欢的模式,因为它往往会将 Web 层代码与业务逻辑混合在一起,并使单元测试变得更加困难。

They allow you to gain access to the HttpServletRequest and HttpServletResponse from other classes within your project without having to pass references to these objects to the other classes. It's not a pattern I particularly like as it tends to mix up your web tier code with your business logic and makes unit testing more difficult.

十六岁半 2024-11-03 02:20:02

由于请求和响应对象存储在线程局部变量中,因此您可以安全地访问这些对象,而不必将它们作为方法参数传递。

示例 1:不使用线程本地

public class MyServlet extends Servlet {
    private MyObject myObject = new MyObject();

    public void service(ServletRequest request, ServletResponse response) {
        myObject.doSomething(request, response);
    }
}

public class MyObject {
    private MyOtherObject myOtherObject = new MyOtherObject();
    public void doSomething(ServletRequest request, ServletResponse response) {
        // I do nothing with request/response, but need to accept them in order
        // to pass them to myOtherObject
        myOtherObject.doSomethingElse(request, response);
    }
}

public class MyOtherObject {
    public void doSomethingElse(ServletRequest request, ServletResponse response) {
        // Do something else with request / response
    }
}

示例 2:使用线程本地

public class MyServlet extends Servlet {
    private MyObject myObject = new MyObject();

    private static ThreadLocal<ServletRequest> currentRequest = new ThreadLocal<ServletRequest>();

    public static ServletRequest getCurrentRequest() {
        return currentRequest.get();
    }

    private static ThreadLocal<ServletResponse> currentResponse = new ThreadLocal<ServletResponse>();

    public static ServletResponse getCurrentResponse() {
        return currentResponse.get();
    }

    public void service(ServletRequest request, ServletResponse response) {
        ...
        currentRequest.set(request);
        currentResponse.set(response);
        ...
        myObject.doSomething();
    }
}

public class MyObject {
    private MyOtherObject myOtherObject = new MyOtherObject();
    public void doSomething() {
        // I do not need to know about request / response as I do nothing with them
        myOtherObject.doSomethingElse();
    }
}

public class MyOtherObject {
    public void doSomethingElse() {
        // Now I can get the current request / response in a thread safe
        // manner and without having to accept them as parameters
        ServletRequest request = MyServlet.getCurrentRequest();
        ServletResponse response = MyServlet.getCurrentResponse();

        // Do something with request / response
    }
}

显然,对于简单的 servlet,仅传递对象是最简单的事情,但在复杂的场景中,使用一个静态但线程安全的 getter 有时很有用。

Since the request and the response objects are stored in thread local variables, you get thread safe access to those objects without having to pass them around as method parameters.

Example 1: Without thread local

public class MyServlet extends Servlet {
    private MyObject myObject = new MyObject();

    public void service(ServletRequest request, ServletResponse response) {
        myObject.doSomething(request, response);
    }
}

public class MyObject {
    private MyOtherObject myOtherObject = new MyOtherObject();
    public void doSomething(ServletRequest request, ServletResponse response) {
        // I do nothing with request/response, but need to accept them in order
        // to pass them to myOtherObject
        myOtherObject.doSomethingElse(request, response);
    }
}

public class MyOtherObject {
    public void doSomethingElse(ServletRequest request, ServletResponse response) {
        // Do something else with request / response
    }
}

Example 2: with thread local

public class MyServlet extends Servlet {
    private MyObject myObject = new MyObject();

    private static ThreadLocal<ServletRequest> currentRequest = new ThreadLocal<ServletRequest>();

    public static ServletRequest getCurrentRequest() {
        return currentRequest.get();
    }

    private static ThreadLocal<ServletResponse> currentResponse = new ThreadLocal<ServletResponse>();

    public static ServletResponse getCurrentResponse() {
        return currentResponse.get();
    }

    public void service(ServletRequest request, ServletResponse response) {
        ...
        currentRequest.set(request);
        currentResponse.set(response);
        ...
        myObject.doSomething();
    }
}

public class MyObject {
    private MyOtherObject myOtherObject = new MyOtherObject();
    public void doSomething() {
        // I do not need to know about request / response as I do nothing with them
        myOtherObject.doSomethingElse();
    }
}

public class MyOtherObject {
    public void doSomethingElse() {
        // Now I can get the current request / response in a thread safe
        // manner and without having to accept them as parameters
        ServletRequest request = MyServlet.getCurrentRequest();
        ServletResponse response = MyServlet.getCurrentResponse();

        // Do something with request / response
    }
}

Obviously, for simple servlets just passing the objects around is the easiest thing, but in complex scenarios it is sometimes useful to have one static but thread safe getter.

卸妝后依然美 2024-11-03 02:20:02

其他人几乎已经说明了在您提出的场景中线程局部变量的用途。但请注意,线程本地依赖实现是“线程”特定的,并且当事情脱离每个请求单个线程模型时就会中断。示例是基于事件的服务器,其中少数线程同时用于大量用户请求。

Others have pretty much stated what is the use of Thread Locals in the scenario you presented. But be warned though, Thread Local relying implementations are "thread" specific and break when things move away from a single thread per request model. Example would be event based servers wherein a handful of threads are used for lots of user requests concurrently.

酒解孤独 2024-11-03 02:20:02

ThreadLocal 的用途?

当你有一些非线程安全的对象,但你想避免同步访问该对象(SimpleDateFormat)。相反,为每个线程提供其自己的对象实例。

使用 ThreadLocal 的 remove() 方法清理 get()set() 的任何 ThreadLocal 时需要非常小心。

Purpose of ThreadLocal ?

when you have some object that is not thread-safe, but you want to avoid synchronizing access to that object ( SimpleDateFormat). Instead, give each thread its own instance of the object.

You need to be very careful about cleaning up any ThreadLocals you get() or set() by using the ThreadLocal's remove() method.

你是年少的欢喜 2024-11-03 02:20:02

我不是 100% 确定您曾经遇到的代码的作者的意图是什么,但我猜想, ServletRequest 实例可以从代码中的任何方法获取,而无需将其作为参数传递或设置为实例变量。通常 ThreadLocal 变量是静态的,并且有一个公开的方法允许静态获取 ServletRequest 的实例。例如,您可以使用此技术轻松访问 Struts FromBeans 中的 ServletRequest

I'm not 100% sure what was the intention of the author of the code you'd once came across, but I guess the idea there is that ServletRequest instance is available from any method in the code without passing it as parameter or setting as instance variable. Usually ThreadLocal variable is static and there is a method exposed that allows to obtain the instance of ServletRequest in statically. For instance you could access ServletRequest in Struts FromBeans easily using this technique.

差↓一点笑了 2024-11-03 02:20:02

这实在是太可怕了。您应该尽快从 HTTP 请求/会话中获取所需的值。您可以在方法调用或传输对象中传递这些值。您应该努力编写不受技术影响的方法/类。如果您的方法/类从 ThreadLocal 获取 http 请求,那么它就是一个毫无价值的类 - 它在任何非 http 上下文中不再有用。

尤其令我震惊的是,看到人们从 BO(业务对象)或 DAO 中的 ThreadLocal 提取 http 请求。 HTTP 请求绝不能出现在应用程序表示层以外的任何层中。

This is really terrible. You should obtain the values you need from the HTTP request/session as soon as you possibly can. you can pass these values in method invocations or Transfer Objects. you should strive to write methods/classes technology-free. if your method/class obtains an http request from ThreadLocal it's a worthless class - it's no longer useful in any any non-http context.

It's especially shocking to me to see people pull http requests from ThreadLocal in BOs (Business Objects) or DAOs. HTTP requests should never appear in any layer other than the presentation layer of the application.

耀眼的星火 2024-11-03 02:20:02

我认为更好的情况可以是这样的:

在Service层中创建的连接对象放入ThreadLocal中,然后调用DAO层,从Threadlocal中获取连接对象。

I think the better case can be like..

Connection object once created in Service layer put in ThreadLocal then call a DAO layer, get connection object from Threadlocal.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文