@Context 返回 Proxy 而不是 HttpServletRequest (代理范围内没有线程本地值)

2024-04-14

我不太明白为什么@Context依赖注入返回 $Proxy(random number) 实例的集合,而不是 HttpServletRequest 或 HttpServletResponse。

我正在使用 Glassfish 3.1.2.2 及其 Jersey 版本(Jersey:1.11.1),并且我的应用程序构建为 EAR 应用程序。

我有简单的 @Remote 接口,我可以在其中注释我的方法,并且 REST 服务可以正常工作,但当我尝试访问 HttpServletRequest 信息时,它只会导致问题。

我在会话 bean 中注释了私有字段:

@Context
private HttpServletRequest request;
@Context
private HttpServletResponse response;

还创建了方法签名以包含 @Context 作为参数集:

@POST
@Path("authenticate")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
public Response authenticate(@FormParam("username") String username, @FormParam("password") String password, @Context HttpServletRequest request, @Context HttpServletResponse response); 

当我尝试在条目之后调试该方法时,我可以看到全局请求和响应对象为 null,而本地方法实例为 $ProxyXXX 类型。

问题是我无法访问(或者我不确定如何访问)这些对象。根据网络上的教程,它们应该可供我使用,但当我尝试访问这些时,会抛出以下错误:

WARNING: StandardWrapperValve[RestDataService]: PWC1406: Servlet.service() for servlet RestDataService threw exception
java.lang.IllegalStateException: No thread local value in scope for proxy of class $Proxy245
    at com.sun.jersey.server.impl.ThreadLocalInvoker.invoke(ThreadLocalInvoker.java:93)
    at $Proxy245.getContextPath(Unknown Source)

这就是我尝试调用它们的方式(在本例中我简单地调用 getContextPath)

@Override
public Response authenticate(String username, String password, HttpServletRequest request, HttpServletResponse response) {

    System.out.println("just a test: " + request.getContextPath());

我在这里缺少什么?有没有人遇到过类似的问题?

Greg


要理解这个问题,您需要了解作用域的工作原理。为了描述发生的情况,这里有一个例子。假设你有这个

@Singleton
@Path("..")
public class SomeResource {

    @Context
    private HttpServletRequest request;
}

这种情况带来的问题是HttpServletRequest为每个请求生成,但资源类仅创建一次,因为它是单例,所以最初没有HttpServletRequest在创建单例时注入到单例中。

为了解决这个问题,Jersey 注入了一个代理。所以从概念上讲,结果更像是

@Singleton
@Path("..")
public class SomeResource {

    @Context
    private ProxyHttpServletRequest proxyRequest;
}

当请求进来时,实际的HttpServletRequest被放入一个ThreadLocal in a 范围上下文。这不是一个精确的实现,但您可以将范围上下文想象为类似的东西

public class RequestScopeContext {
    private static final ThreadLocal<HttpServletReqest> request
            = new ThreadLocal<>();

    public static HttpServletRequest get() { .. }
    public static void setRequest(HttpServletRequest request) { .. }
}

当请求到达时HttpServletRequest被设置到上下文中。当拨打电话时HttpServletRequest在 - 的里面SomeResource,它实际上是在代理对象上进行的,该对象从代理对象中获取请求ThreadLocal并转接电话。从概念上讲,你想象它看起来像

class ProxyHttpServletRequest {
    public String getContextPath() {
        HttpServletRequest request = RequestScopeContext.get();
        return request.getContextPath();
    }
}

现在假设我们有这个

@Singleton
@Path("..")
public class SomeResource {

    @GET
    public Response get(@Context HttpServletRequest request) {
        ...
    }
}

与此不同的是,请求不再注入到字段中,因此不需要代理。这HttpServletRequest仅当调用该方法时才需要。因此 Jersey 将注入实际请求而不是代理。

请注意,这种模式不仅仅适用于泽西岛。任何涉及 DI 和范围的框架,在尝试将较小范围的对象注入到更广泛范围的对象中时,都会使用类似的代理模式。


To OP:现在这不是你的确切问题。上述答案更有可能使大多数对代理有疑问的人受益。

就您而言,您说您正在尝试注入HttpServletRequest into a @RemoteEJB。一方面我什至不知道那是或is可能的。我的猜测是 EJB 引擎永远不会设置ThreadLocal。因此,当 Jersey 尝试调用它时,上下文中没有任何内容。

The @Context注释适用于 JAX-RS 组件,而不是 EJB。我个人不知道如何注入HttpServletRequest进入 EJB,因为我很少使用 EJB。因此,任何面临您确切问题的人都需要寻找如何做that。但就像我说的,我认为搜索这个问题的人并不是大多数。我想他们只是想知道为什么请求是代理而不是实际请求。所以这个答案更适合他们。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

@Context 返回 Proxy 而不是 HttpServletRequest (代理范围内没有线程本地值) 的相关文章

  • 服务定位器和依赖注入之间的实际区别是什么?

    我正在经历之前的讨论 其中详细讨论了服务定位器和依赖项注入器之间的区别 但我仍然无法理解 我可以在没有任何代码的情况下获得一般响应吗 此代码示例应用了依赖注入 http en wikipedia org wiki Dependency in
  • 我在socket上设置了超时,发现这个值不能大于21

    我在socket上设置了超时 该值小于21秒才有效 21秒后发现超时还是21秒 public static void main String args SimpleDateFormat sdf new SimpleDateFormat yy
  • 使用 HttpUrlConnection Android 将 base64 编码的图像发送到服务器

    我正在尝试使用 HttpUrlConnection 将 base64 编码的图像发送到服务器 我遇到的问题是大多数图像均已成功发送 但有些图像会生成 FileNotFound 异常 我的图像编码代码可以在下面找到 public static
  • 解决 Java Checkstyle 错误:名称 'logger' 必须匹配模式 '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'

    使用 Eclipse Checkstyle 插件我看到以下错误 名称 logger 必须匹配模式 A Z A Z0 9 A Z0 9 我通过更改解决了此错误 private static final Logger logger Logger
  • 无法使用 json 架构验证器根据预定义的 yaml 文件验证查询参数

    我需要根据预定义的 yaml 文件架构验证查询参数的架构 因此我使用 json 架构验证器 验证如何失败 我正在执行以下步骤 填充参数和相应的架构 final List
  • 如何比较 Struts 2 中 url 请求参数中的单个字符

    我正在读取具有单个字符的 url 参数 它将是Y or N 我必须写一个条件来检查它是否Y or N并做相应的事情 这是我写的 但似乎不起作用 总是转到其他地方 网址是
  • Java Microsoft Excel API [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 有多少种方法可以将位图转换为字符串,反之亦然?

    在我的应用程序中 我想以字符串的形式将位图图像发送到服务器 我想知道有多少种方法可以将位图转换为字符串 现在我使用 Base64 格式进行编码和解码 它需要更多的内存 是否有其他可能性以不同的方式做同样的事情 从而消耗更少的内存 现在我正在
  • 所有平台上的java

    如果您想用 java 为 Windows Mac 和 Linux 编写桌面应用程序 那么所有这些代码都相同吗 您只需更改 GUI 即可使 Windows 应用程序更像 Windows 等等 如果不深入细节 它是如何工作的 Java 的卖点之
  • 线程“main”中的异常 java.lang.StackOverflowError

    我有一段代码 但我无法弄清楚为什么它在线程 main java lang StackOverflowError 中给出异常 这是问题 Given a positive integer n prints out the sum of the
  • 发生错误。请参阅日志文件 - eclipse juno

    每当我启动 Eclipse Juno 时 都会出现错误 发生错误 请查看日志文件 C Program Files eclipse configuration 1362989254411 log 有的网站说卸载jdk重新安装 我这样做了 但没
  • 我想在java中使用XQuery进行Xml处理

    我想用XQuery用于从 java 中的 Xml 获取数据 但我没有得到需要为此添加哪个 Jar 我在谷歌上搜索了很多 但没有得到任何有用的例子 例如我得到以下链接 https docs oracle com database 121 AD
  • 如何找到被点击的JLabel并从中显示ImageIcon?

    这是我的代码 我想知道哪个l单击 然后在新框架中显示该 ImageIcon e getSource 不起作用 final JFrame shirts new JFrame T shirts JPanel panel new JPanel n
  • 改变for循环的顺序?

    我遇到一种情况 我需要根据用户输入以不同的顺序循环遍历 xyz 坐标 所以我是 3D 空间中的一个区域 然后是一组像这样的 for 循环 for int x 0 x lt build getWidth x for int y 0 y lt
  • Hibernate HQL:将对值作为 IN 子句中的参数传递

    我面临一个问题 如何使用 IN 子句将查询中的成对值的参数传递给 HQL 例如 select id name from ABC where id reg date in x y 并且参数是不同的数据类型string id 和reg date
  • 如何初始化静态地图?

    你会如何初始化静态Map在Java中 方法一 静态初始化方法二 实例初始化 匿名子类 或者 还有其他方法吗 各自的优点和缺点是什么 这是说明这两种方法的示例 import java util HashMap import java util
  • 实体框架 4 DB 优先依赖注入?

    我更喜欢创建自己的数据库 设置索引 唯一约束等 使用 edmx 实体框架设计器 从数据库生成域模型是轻而易举的事 现在我有兴趣使用依赖注入来设置一些存储库 我查看了 StackOverflow 上的一些文章和帖子 似乎重点关注代码优先方法
  • 春季 CORS。在允许的来源中添加模式

    查看CORS的弹簧指南 以下代码启用所有允许的来源 public class MyWebMVCConfigurer extends WebMvcConfigurerAdapter Override public void addCorsMa
  • 失败时石英重试

    假设我有一个这样配置的触发器
  • 防止Java实例化的正确方法[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi

随机推荐