Java servlet API 中是否有通用的 RequestContext?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10197046/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a generic RequestContext in Java servlet API?
提问by Two13
(I'm not sure exactly how to phrase the title here, and because of that I'm not really sure how to go about searching for the answer either.)
(我不确定如何准确地表达这里的标题,因此我也不确定如何去寻找答案。)
I have a Java servlet engine that handles requests. Say we have a doGet()
request:
我有一个处理请求的 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();
}
Now in doSomething()
, I want to be able to access which user made the request. Right now I'm doing it by creating a Java object within the method and passing it to wherever I need it:
现在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();
}
By doing this, I have access to the instance of MyUserObj
, and it can be further passed along in the application as needed.
通过这样做,我可以访问 的实例MyUserObj
,并且可以根据需要在应用程序中进一步传递它。
I know in ASP.NET MVC3 I can acheive this by storing items/attributes for the current thread like this: HttpContext.Current.Items.Add("myId", "123")
. HttpContext
is then available in other functions without explicitly having to pass around an object.
我知道在ASP.NET MVC3我可以通过将当前线程像这样的项目/属性达致这: HttpContext.Current.Items.Add("myId", "123")
。 HttpContext
然后可以在其他函数中使用而无需显式传递对象。
Is there a way in Java to set some variables per request (or even set the MyUserObject
to be accessed later) without passing the object through as a parameter?
Java 中有没有办法在MyUserObject
不将对象作为参数传递的情况下为每个请求设置一些变量(甚至设置稍后访问)?
回答by Bozho
There isn't in the servlet API, but you can make your own pretty easily. (Some frameworks like spring-mvc, struts provide such functionality)
servlet API 中没有,但您可以很容易地创建自己的 API。(一些框架如 spring-mvc、struts 提供了这样的功能)
Just use a public static ThreadLocal
to store and retrieve the object. You can even store the HttpServletRequest
itself in the threadlocal and use its setAttribute()
/getAttribute()
methods, or you can store a threadlocal Map
, to be agnostic of the servlet API. An important note is that you should clean the threadlocal after the request (with a Filter, for example).
只需使用 apublic static ThreadLocal
来存储和检索对象。您甚至可以将其HttpServletRequest
自身存储在 threadlocal 中并使用其setAttribute()
/getAttribute()
方法,或者您可以存储一个 threadlocal Map
,以与 servlet API 无关。一个重要的注意事项是您应该在请求之后清理 threadlocal(例如,使用过滤器)。
Also note that passing the object as parameter is considered a better practice, because you usually pass it from the web layer to a service layer, which should not be dependent on web-related object, like a HttpContext
.
另请注意,将对象作为参数传递被认为是一种更好的做法,因为您通常将其从 Web 层传递到服务层,该服务层不应依赖于与 Web 相关的对象,例如HttpContext
.
If you decide that it is fine to store them in a thread-local, rather than passing them around:
如果您决定将它们存储在线程本地中,而不是将它们四处传递:
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);
}
}
And a necessary filter:
还有一个必要的过滤器:
@WebFilter(urlPatterns="/")
public class RequestContextFilter implements Filter {
public void doFilter(..) {
RequestContext.initialize();
try {
chain.doFilter(request, response);
} finally {
RequestContext.cleanup();
}
}
}
回答by ataylor
You can attach an object to the current request with setAttribute
. This API is primarily used for internal routing, but it's safe to use for your own purposes too, as long as you use a proper namespace for your attribute names.
您可以使用 将对象附加到当前请求setAttribute
。此 API 主要用于内部路由,但也可以安全地用于您自己的目的,只要您为属性名称使用适当的命名空间。