Java中是否有请求上下文?

Two*_*o13 13 java servlets

我不确定如何在这里说出标题,因此我也不确定如何去寻找答案.

我有一个处理请求的java servlet引擎.假设我们有一个doGet请求:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //set up user data

    //do whatever the user requested
    SomeClass c = new SomeClass();
    c.doSomething();
}
Run Code Online (Sandbox Code Playgroud)

现在在doSomething中,我希望能够访问哪个用户发出了请求.现在我通过创建一个java对象并将其传递到我需要的任何地方来做到这一点:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //set up user data
    MyUserObj userObj = new MyUserObj();
    userObj.setId('123');

    //do whatever the user requested
    SomeClass c = new SomeClass(userObj);
    c.doSomething();
}
Run Code Online (Sandbox Code Playgroud)

通过这样做,我可以访问MyUserObj的实例,并且可以根据需要进一步传递.

这感觉很草率.在asp.net MVC3中(我目前正在学习它,在我开始学习java之后开始,但发现这非常方便,所以让我重新思考我是如何在java中做的)我可以,例如,存储当前的项目像这样的线程: doGet(). doSomething()然后可以在其他函数中使用,而不必传递一个对象.

有没有一种方法在java中为每个请求设置一些变量(甚至设置MyUserObj以后访问)而不将对象作为参数传递?

如果这是一个常见的已经回答的问题,请随意指出我正确的方向,因为我不知道该怎么说.

Boz*_*zho 20

servlet API中没有,但你可以很容易地创建自己的.(像spring-mvc这样的一些框架,struts提供了这样的功能)

只需使用a public static ThreadLocal来存储和检索对象.您甚至可以将HttpServletRequest自己存储在threadlocal中并使用其setAttribute()/ getAttribute()methods,或者您可以存储threadlocal Map,以便与servlet API无关.一个重要的注意事项是您应该在请求后清理threadlocal(例如,使用Filter).

另请注意,将对象作为参数传递被认为是一种更好的做法,因为您通常将它从Web层传递到服务层,而服务层不应该依赖于与Web相关的对象,例如a HttpContext.

如果您认为可以将它们存储在本地线程中,而不是传递它们:

public class RequestContext {
    private static ThreadLocal<Map<Object, Object>> attributes = new ThreadLocal<>();
    public static void initialize() {
        attributes.set(new HashMap<Map<Object, Object>>());
    }
    public static void cleanup() {
        attributes.set(null);
    }
    public static <T> T getAttribute(Object key) {
        return (T) attributes.get().get(key);
    }
    public static void setAttribute(Object key, Object value) {
        attributes.get().put(key, value);
    }
}
Run Code Online (Sandbox Code Playgroud)

并且必要的过滤器:

@WebFilter(urlPatterns="/")
public class RequestContextFilter implements Filter {
     public void doFilter(..) {
         RequestContext.initialize();
         try {
             chain.doFilter(request, response);
         } finally {
             RequestContext.cleanup();
         }
     }
}
Run Code Online (Sandbox Code Playgroud)

  • 面对Servlet API 3.0可挂起的请求,这不会破坏性吗? (3认同)
  • 那么`ServletRequest.setAttribute`呢? (2认同)
  • 你必须传递请求.我认为这不是OP想要的.我添加它作为选项,但仍然需要threadlocal (2认同)

ata*_*lor 5

您可以将对象附加到当前请求setAttribute.此API主要用于内部路由,但只要您为属性名称使用适当的命名空间,它也可以安全地用于您自己的目的.