当 @Context 用于 setter/field/constructor 注入时,HK2 Factory 在 Jersey 过滤器之前调用

2023-11-25

我已经能够根据过滤器注入我的球衣资源如何将对象注入球衣请求上下文中?。这使我能够成功注入方法参数:

@GET
public Response getTest(@Context MyObject myObject) { // this works

但是,对于 setter/field/constructor 注入,将调用 HK2 Factorybeforejersey 过滤器,这意味着 Provide() 方法返回 null:

@Override
public MyObject provide() {
    // returns null because the filter has not yet run,
    // and the property has not yet been set
    return (MyObject)context.getProperty("myObject");
}

有没有办法定义 HK2 Factory 何时运行以便调用它after过滤器运行?如果不是,那么解决方法是将 MyObject 定义为接口,并定义一个在其构造函数中采用 ContainerRequestContext 的附加实现;任何实际使用该实例的尝试都会延迟地委托给在 ContainerRequestContext 的属性上设置的实现(大概您在过滤器运行之前不会实际使用该实例 - 此时将设置该属性)。

但我想了解是否可以延迟 HK2 Factory 的运行点,以便它在过滤器之后运行(在方法参数注入的情况下,它已经在过滤器之后运行)。如果不可能,那么我想了解是否有根本原因。


奇怪的是它只对我有用@PreMatching在过滤器上(这限制了对您可能需要或不需要的某些内容的访问)。不太确定引擎盖下发生了什么,这会导致它在没有它的情况下无法工作:-(。下面是使用的完整测试泽西岛测试框架.

import java.io.IOException;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.internal.inject.AbstractContainerRequestValueFactory;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Assert;
import org.junit.Test;

public class FilterInjectionTest extends JerseyTest {

    private static final String MESSAGE = "Inject OK";
    private static final String OBJ_PROP = "myObject";

    public static class MyObject {

        private final String value;

        public MyObject(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }
    }

    @PreMatching
    @Provider
    public static class MyObjectFilter implements ContainerRequestFilter {

        @Override
        public void filter(ContainerRequestContext context) throws IOException {
            MyObject obj = new MyObject(MESSAGE);
            context.setProperty(OBJ_PROP, obj);
        }
    }

    public static class MyObjectFactory
            extends AbstractContainerRequestValueFactory<MyObject> {

        @Override
        @RequestScoped
        public MyObject provide() {
            return (MyObject) getContainerRequest().getProperty(OBJ_PROP);
        }

        @Override
        public void dispose(MyObject t) {
        }
    }

    @Path("method-param")
    public static class MethodParamResource {

        @GET
        public String getResponse(@Context MyObject myObject) {
            return myObject.getValue();
        }
    }

    @Path("constructor")
    public static class ConstructorResource {

        private final MyObject myObject;

        @Inject
        public ConstructorResource(@Context MyObject myObject) {
            this.myObject = myObject;
        }

        @GET
        public String getResponse() {
            return myObject.getValue();
        }
    }

    @Path("field")
    public static class FieldResource {

        @Inject
        private MyObject myObject;

        @GET
        public String getResponse() {
            return myObject.getValue();
        }
    }

    @Override
    public Application configure() {
        ResourceConfig config = new ResourceConfig();
        config.register(MethodParamResource.class);
        config.register(MyObjectFilter.class);
        config.register(ConstructorResource.class);
        config.register(FieldResource.class);
        config.register(new AbstractBinder() {
            @Override
            protected void configure() {
                bindFactory(MyObjectFactory.class)
                        .to(MyObject.class).in(Singleton.class);
            }
        });
        return config;
    }

    @Test
    public void methoParamInjectionOk() {
        String response = target("method-param").request().get(String.class);
        Assert.assertEquals(MESSAGE, response);
        System.out.println(response);
    }

    @Test
    public void costructorInjectionOk() {
        String response = target("constructor").request().get(String.class);
        Assert.assertEquals(MESSAGE, response);
        System.out.println(response);
    }

    @Test
    public void fieldInjectionOk() {
        String response = target("field").request().get(String.class);
        Assert.assertEquals(MESSAGE, response);
        System.out.println(response);
    }
}

UPDATE

解决方案,无需使其成为@PreMatching过滤器,是注入javax.inject.Provider。这将允许您延迟检索对象。我想构造函数和字段注入会发生什么,在匹配资源类之后,它立即创建并注入。因为过滤器还没有被调用,所以工厂没有对象。它适用于方法注入,因为它就像任何其他方法调用一样。当调用该方法时,该对象被传递给它。下面是示例javax.inject.Provider

@Path("constructor")
public static class ConstructorResource {

    private final javax.inject.Provider<MyObject> myObjectProvider;

    @Inject
    public ConstructorResource(javax.inject.Provider<MyObject> myObjectProvider) {
        this.myObjectProvider = myObjectProvider;
    }

    @GET
    public String getResponse() {
        return myObjectProvider.get().getValue();
    }
}

@Path("field")
public static class FieldResource {

    @Inject
    private javax.inject.Provider<MyObject> myObjectProvider;;

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

当 @Context 用于 setter/field/constructor 注入时,HK2 Factory 在 Jersey 过滤器之前调用 的相关文章

随机推荐

  • 可以通过 Apache 下载文件吗?

    Path var lib foo txt 是否可以配置 Apache 以便有一些 HTTP URL 可以启动该文件的下载以及如何配置 Without htaccess file 那么那个 URL 会是什么 localhost var lib
  • Google 云存储 CNAME URL 重定向

    我在 Google Cloud 存储上有一个公共存储桶 wordgamesswf 可以通过网址访问对象http commondatastorage googleapis com wordgamesswf linguistics 我需要托管我
  • 原型还是内联,有什么区别?

    我刚刚学习 Javascript 我想知道是否使用原型声明 如下所示 function TSomeObj this name my object TSomeObj prototype showname function alert this
  • Pickle 类实例加上定义?

    我怀疑这是一个常见问题 但我还没有找到解决方案 我想要的非常简单 而且在技术上似乎是可行的 我有一个简单的 python 类 我想将它存储在光盘上 实例和定义在一个文件中 Pickle 将存储数据 但不存储类定义 有人可能会说类定义已经存储
  • 如何使 jenkins 在 Windows 批处理命令失败时失败?

    我在 jenkins 中使用一些 Windows 批处理命令 其中每个命令都可能失败 为了使 jenkins 作业在每一步都失败 这些批处理命令如下所示 net use m IP ADDRESS Whatever PASSWORD user
  • 在 Android 中直接将捕获的图像上传到 Cloudinary

    我想捕捉一张图片并直接上传到Cloudinary 我如何知道图片的名称以在上传声明中设置它cloudinary uploader upload nameofthepic Cloudinary emptyMap 这是我的代码 public c
  • 正则表达式捕获两个分隔符内单词的每次出现

    假设我有一长串文本 我想捕获每个单词this是在圆括号内提到的 我怎么能这么做呢 以下模式仅匹配第一个this 忽略之后出现的每一个事件 this g 例如 在以下文本上使用上面的模式 Etiam scelerisque nunc ac e
  • 使用 iText5 for .NET 读取 PDF 文件

    我使用 C 作为编程平台iTextSharp阅读 PDF 内容 我使用下面的代码来读取内容 但似乎是每页读取的 public string ReadPdfFile object Filename string strText string
  • 如何在其他类中使用PDO连接?

    我认为我在理解 OOP 的工作原理方面存在问题 我已经更改了它可以工作的代码 但这不是我认为的正确方式 以下场景 不 我不是自己创建用户登录 它实际上只是为了本地开发人员更好地理解 OOP 我有一个database php 文件 class
  • iOS Safari 隐私浏览 localStorage 和 sessionStorage 支持吗?

    我在 StackOverflow 上发现了一些问题 解决了 iOS Safari Private Browsing 的特定功能和sessionStorage and localStorage 但我还没有找到明确的资源来表示 iOS Safa
  • WebRequest 不发送客户端证书

    我正在为 REST API 编写一个客户端 为了对 API 进行身份验证 我必须使用提供给我的证书 这段代码如下 public string GetCustomer int custId X509Certificate2 Cert new
  • fgetcsv 正在吃掉字符串的第一个字母(如果它是变音符号)

    我正在将 Excel 生成的 CSV 文件中的内容导入到 XML 文档中 例如 csv fopen csvfile r words array while pair fgetcsv csv FALSE array push words ar
  • TurboParser 的依赖解析输出是什么意思?

    我一直在尝试使用由生成的依赖解析树CMU 的 TurboParser 它工作完美 但问题是文档太少 我需要精确理解他们的解析器的输出 例如 这句话 我用统计方法解决了这个问题 生成以下输出 1 I PRP PRP 2 SUB 2 solve
  • 如何让 Protractor 不等待 $timeout?

    我正在使用 Protractor 测试我的角度应用程序 用户登录到我的应用程序后 我设置了 timeout 以在一小时内完成某些工作 因此 如果用户在 13 00 登录 timeout 将在 14 00 运行 我不断遇到这些失败 Timed
  • 如何在 C# 中封送集合以传递给本机 (C++) 代码

    我正在从事企业应用程序开发 整个应用程序都是用 C 开发的 除了 UI 是用 C 开发的 现在是时候将 UI 与 C 代码挂钩了 经过详细研究 我选择了 PInvoke 来实现这一点 一切都很成功 我唯一遇到的问题是如何将集合传递给 C 代
  • 以 ip 地址为目标的 Powershell 远程处理

    我在 Server 2008 R2 上成功启用了 PSRemoting 我可以使用主机名作为目标从同一网络内执行远程 pssession 当我尝试从任何计算机 在网络内或从另一个网络 例如通过 VPN 使用 IP 地址作为目标时 我失败了
  • AVPlayer 不会触发playbackBufferEmpty 但也不播放

    我使用 AVPlayer 通过互联网播放音频直播 如果暂停时间超过 1 分钟 我喜欢恢复播放 I call player rate 1 0恢复 但是 如果流暂停超过 1 分钟 则不会再播放 在这种情况下 我需要重新创建 AVPlayerIt
  • Rest API 中 Streamfield 的自定义表示

    我对这个话题有几个疑问 https groups google com forum topic wagtail developers Z4oaCIJXYuI 我正在构建一个无头 Wagtail 具有基于 React 的前端 它调用 Wagt
  • 确定浮点平方根

    如何确定浮点数的平方根 牛顿拉夫森法是个好方法吗 我也没有硬件平方根 我也没有硬件除法 但我已经实现了浮点除法 如果可能的话 我宁愿尽可能减少除法的数量 因为它们非常昂贵 另外 减少迭代总数的初始猜测应该是什么 太感谢了 当您使用 Newt
  • 当 @Context 用于 setter/field/constructor 注入时,HK2 Factory 在 Jersey 过滤器之前调用

    我已经能够根据过滤器注入我的球衣资源如何将对象注入球衣请求上下文中 这使我能够成功注入方法参数 GET public Response getTest Context MyObject myObject this works 但是 对于 s