我有一个单实例类,实现了ExceptionMapper。它不是一个静态类,但它是一个我知道只创建单个实例的类(我检查过 - 构造函数只调用一次)。
我的类使用 @Context HttpServletRequest ,我可以清楚地看到,当我的 ExceptionMapper.toResponse()方法被调用时, @Context&#39 ; request' 参数的值与抛出异常的请求相关。
The doc says 这确实是设计支持的功能,并且通过使用"代理"来完成。
我想知道这是如何实现的 - 单个实例如何同时具有不同的成员变量值?
谢谢你,
AG
P.S。:这是测试代码:
@Provider
public class MyExceptionMapper implements ExceptionMapper<Exception> {
public MyExceptionMapper() {
System.out.println("CTOR!!");
}
@Context HttpServletRequest req;
public static boolean done = false;
public Response toResponse(Exception ex) {
if (!done) {
done = true;
Thread.sleep(10000);
}
System.out.println(req.getRequestURI());
return null;
}
}
我的REST处理程序方法抛出异常,所以当我执行以下2个请求&#34;并行&#34; (上面的睡眠确保当第二个到达时第一个没有完成,恕我直言应该修改唯一的“req&#39;字段”:
- http://localhost/app/one
- http://localhost/app/two
我的节目打印:
CTOR!
http://localhost/app/one
http://localhost/app/two
答案 0 :(得分:6)
实现所观察到的效果的最简单方法是将注入的HttpServletRequest
对象实际上作为代理对象, real HttpServletRequest
的线程感知委托。当您在委托上调用方法时,他们所做的只是查找正确的真实对象(例如,通过线程局部变量)并将调用传递给它。这个策略相对来说比较简单,因为它是一个接口,我们绝对不必担心字段访问(这对代理来说相当棘手)。
构建这样的代理对象有几种不同的方法。特别是,它可以通过直接实现HttpServletRequest
接口来完成,或者可以通过Java general dynamic proxy mechanism(可以为任何接口构建代理)更一般地完成。还有其他更复杂的可能性,例如运行时代码生成,但这里不需要它们。 OTOH,如果HttpServletRequest
被直接实施,我不会感到惊讶;对于JAX-RS实现来说,它是一个有点重要的类......