代码之家  ›  专栏  ›  技术社区  ›  Wheezil

JAX-RS/jersey:客户端代理:如何从上下文而不是方法参数注入路径参数?

  •  0
  • Wheezil  · 技术社区  · 5 年前

    我正在使用代理模式调用使用JAX-RS和Jersey的web服务。我想在概念上做一些像。。。向界面添加@上下文注释,如:

    @Path("foo/{instance}")
    public interface Foo 
    {
        @Context private UriInfo uriInfo;
    
        @POST
        @Path("doit")
        @Produces(MediaType.APPLICATION_JSON)
        @Consumes(MediaType.APPLICATION_JSON)
        public Thing1 doit(Thing2 arg);
    }
    

    但当然不能这样做,它是一个接口而不是一个类。但使用代理模式需要一个接口。我使用代理模式创建客户端:

    ClientBuilder builder = ClientBuilder.newBuilder().register(JacksonJsonProvider.class);
    MyRequestFilter filter = new MyRequestFilter();
    builder = builder.register(filter);
    WebTarget target = builder.build().target(url);
    Foo serviceClient = WebResourceFactory.newResource(Foo.class, target);
    

    但是,呼叫 serviceClient.doit(...) 结果在 IllegalStateException: The template variable 'instance' has no value 。 我尝试使用ClientRequestFilter注入实例变量,但在引发此异常之前,甚至没有调用我的filter方法。是否有任何方法可以从客户端注入路径参数,而不将其添加为 @PathParam 每个方法的参数?原因是,我已经定义了一个接口,我希望我的代理客户端实现该接口,添加一个参数会更改签名。

    0 回复  |  直到 5 年前
        1
  •  2
  •   andrewJames Ikram Bashir    5 年前

    在JAX-WS客户端中 Foo 接口,添加 @PathParam 对于缺少的模板值:

    @Path("foo/{instance}")
    public interface Foo 
    {
        @POST
        @Path("doit")
        @Produces(MediaType.APPLICATION_JSON)
        @Consumes(MediaType.APPLICATION_JSON)
        public Thing1 doit(@PathParam("instance") String instance, Thing2 arg);
    }
    

    显然,您还需要更改客户的呼叫方式 doit() ,以适应此情况。

    Thing1 thing1 = serviceClient.doit("anything", arg);
    

    您的服务器资源(客户端接口所基于的)无需更改。


    警告

    这感觉像是一种黑客/变通方法。这可能不是最好的解决方案,我有点惊讶它居然能奏效。但这是我所知道的诱骗代理获得非空模板值的唯一方法。

        2
  •  1
  •   Wheezil    5 年前

    最终,似乎没有办法直接做到这一点。我没有找到任何方法从Jersey客户端代理中的上下文注入“实例”。即使Foo是class,并且安装了ClientRequestFilter,在发出错误之前也不会调用过滤器。作为一个可行的解决方案,我基本上采纳了@andrewjames的建议,并使用额外的实例参数创建了一个接口。这满足了能够使用WebTarget创建代理的要求。然后,我创建了一个实现基接口的类(方法中没有实例参数的类),包装代理实例,并将所有方法调用委托给代理。这并不漂亮,但由于所有这些都来自代码生成工具,因此也不是特别乏味或容易出错。

    推荐文章