使用 JAX-RS 保持干燥

发布于 2024-11-04 21:07:51 字数 5188 浏览 0 评论 0原文

我试图最大限度地减少许多 JAX-RS 资源处理程序的重复代码,所有这些资源处理程序都需要一些相同的路径和查询参数。每个资源的基本 url 模板如下所示:

/{id}/resourceName

每个资源都有多个子资源:

/{id}/resourceName/subresourceName

因此,资源/子资源路径(包括查询参数)可能如下所示

/12345/foo/bar?xyz=0
/12345/foo/baz?xyz=0
/12345/quux/abc?xyz=0
/12345/quux/def?xyz=0

资源 foo之间的公共部分quux@PathParam("id")@QueryParam("xyz")。我可以像这样实现资源类:

// FooService.java
@Path("/{id}/foo")
public class FooService
{
    @PathParam("id") String id;
    @QueryParam("xyz") String xyz;
    
    @GET @Path("bar")
    public Response getBar() { /* snip */ }
    
    @GET @Path("baz")
    public Response getBaz() { /* snip */ }
}
// QuuxService.java
@Path("/{id}/quux")
public class QuxxService
{
    @PathParam("id") String id;
    @QueryParam("xyz") String xyz;
    
    @GET @Path("abc")
    public Response getAbc() { /* snip */ }
    
    @GET @Path("def")
    public Response getDef() { /* snip */ }
}

我已经设法避免重复将参数注入到每个 get* 方法中。1 这是这是一个好的开始,但我也希望能够避免资源类之间的重复。与 CDI 一起使用的一种方法(我也需要)是使用一个 abstract 基类,FooServiceQuuxService 可以扩展< /code>:

// BaseService.java
public abstract class BaseService
{
    // JAX-RS injected fields
    @PathParam("id") protected String id;
    @QueryParam("xyz") protected String xyz;
    
    // CDI injected fields
    @Inject protected SomeUtility util;
}
// FooService.java
@Path("/{id}/foo")
public class FooService extends BaseService
{
    @GET @Path("bar")
    public Response getBar() { /* snip */ }
    
    @GET @Path("baz")
    public Response getBaz() { /* snip */ }
}
// QuuxService.java
@Path("/{id}/quux")
public class QuxxService extends BaseService
{   
    @GET @Path("abc")
    public Response getAbc() { /* snip */ }
    
    @GET @Path("def")
    public Response getDef() { /* snip */ }
}

get* 方法内部,CDI 注入(奇迹般地)正常工作:util 字段不为空。不幸的是,JAX-RS 注入不起作用FooServiceget* 方法中的 idxyznull >QuuxService

这个问题有解决办法或解决方法吗?

鉴于 CDI 按我希望的方式工作,我想知道未能将 @PathParam(等)注入子类是一个错误还是只是 JAX-RS 规范的一部分。


我已经尝试过的另一种方法是使用 BaseService 作为单个入口点,根据需要委托给 FooService 和 QuuxService 。这基本上如 RESTful Java with JAX-RS 使用子资源定位器。

// BaseService.java
@Path("{id}")
public class BaseService
{
    @PathParam("id") protected String id;
    @QueryParam("xyz") protected String xyz;
    @Inject protected SomeUtility util;
    
    public BaseService () {} // default ctor for JAX-RS
    
    // ctor for manual "injection"
    public BaseService(String id, String xyz, SomeUtility util)
    {
        this.id = id;
        this.xyz = xyz;
        this.util = util;
    }
    
    @Path("foo")
    public FooService foo()
    {
        return new FooService(id, xyz, util); // manual DI is ugly
    }
    
    @Path("quux")
    public QuuxService quux()
    {
        return new QuuxService(id, xyz, util); // yep, still ugly
    }
}
// FooService.java
public class FooService extends BaseService
{
    public FooService(String id, String xyz, SomeUtility util)
    {
        super(id, xyz, util); // the manual DI ugliness continues
    }
    
    @GET @Path("bar")
    public Response getBar() { /* snip */ }
    
    @GET @Path("baz")
    public Response getBaz() { /* snip */ }
}
// QuuxService.java
public class QuuzService extends BaseService
{
    public FooService(String id, String xyz, SomeUtility util)
    {
        super(id, xyz, util); // the manual DI ugliness continues
    }
    
    @GET @Path("abc")
    public Response getAbc() { /* snip */ }
    
    @GET @Path("def")
    public Response getDef() { /* snip */ }
}

这种方法的缺点是 CDI 注入和 JAX-RS 注入都不能在子资源类中工作。这样做的原因相当明显2,但这意味着是我必须手动将字段重新注入到子类的构造函数中,这很混乱、丑陋,并且不容易让我自定义进一步的注入。示例:假设我想将一个实例 @Inject 到 FooService 中,而不是 QuuxService 中。因为我显式实例化了 BaseService 的子类,所以 CDI 注入不起作用,所以丑陋的情况仍然存在。


tl;dr 避免跨 JAX-RS 资源处理程序类重复注入字段的正确方法是什么?

为什么 JAX-RS 不注入继承字段,而 CDI 对此没有问题?


编辑1

@Tarlog的指导下,我想我已经找到了我的一个问题的答案,

为什么 JAX-RS 不注入继承字段?

JSR-311 §3.6 中:

如果子类或实现方法具有任何 JAX-RS 注释,则超类或接口方法上的所有注释都将被忽略。

我确信这个决定是有真正原因的,但不幸的是,在这个特定的用例中,这一事实对我不利。我仍然对任何可能的解决方法感兴趣。


1 使用字段级注入的警告是,我现在与每个请求资源类实例化相关联,但我可以接受这一点。
2 因为我是调用 new FooService() 而不是容器/JAX-RS 实现的人。

I'm trying to minimize repeated code for a number of JAX-RS resource handlers, all of which require a few of the same path and query parameters. The basic url template for each resource looks like this:

/{id}/resourceName

and each resource has multiple subresources:

/{id}/resourceName/subresourceName

So, resource/subresource paths (incl. query parameters) might look like

/12345/foo/bar?xyz=0
/12345/foo/baz?xyz=0
/12345/quux/abc?xyz=0
/12345/quux/def?xyz=0

The common parts across resources foo and quux are @PathParam("id") and @QueryParam("xyz"). I could implement the resource classes like this:

// FooService.java
@Path("/{id}/foo")
public class FooService
{
    @PathParam("id") String id;
    @QueryParam("xyz") String xyz;
    
    @GET @Path("bar")
    public Response getBar() { /* snip */ }
    
    @GET @Path("baz")
    public Response getBaz() { /* snip */ }
}
// QuuxService.java
@Path("/{id}/quux")
public class QuxxService
{
    @PathParam("id") String id;
    @QueryParam("xyz") String xyz;
    
    @GET @Path("abc")
    public Response getAbc() { /* snip */ }
    
    @GET @Path("def")
    public Response getDef() { /* snip */ }
}

I've managed to avoid repeating the parameter injection into every single get* method.1 This is a good start, but I'd like to be able to avoid the repetition across resource classes as well. An approach that works with CDI (which I also need) is to use an abstract base class which FooService and QuuxService could extend:

// BaseService.java
public abstract class BaseService
{
    // JAX-RS injected fields
    @PathParam("id") protected String id;
    @QueryParam("xyz") protected String xyz;
    
    // CDI injected fields
    @Inject protected SomeUtility util;
}
// FooService.java
@Path("/{id}/foo")
public class FooService extends BaseService
{
    @GET @Path("bar")
    public Response getBar() { /* snip */ }
    
    @GET @Path("baz")
    public Response getBaz() { /* snip */ }
}
// QuuxService.java
@Path("/{id}/quux")
public class QuxxService extends BaseService
{   
    @GET @Path("abc")
    public Response getAbc() { /* snip */ }
    
    @GET @Path("def")
    public Response getDef() { /* snip */ }
}

Inside of the get* methods, the CDI injection (miraculously) works correctly: the util field is not null. Unfortunately, the JAX-RS injection does not work; id and xyz are null in the get* methods of FooService and QuuxService.

Is there a fix or workaround for this problem?

Given that the CDI works as I'd like it to, I'm wondering if the failure to inject @PathParams (etc.) into subclasses is a bug or just part of the JAX-RS spec.


Another approach I have already tried is using BaseService as a single point of entry that delegates to FooService and QuuxService as needed. This is basically as described in RESTful Java with JAX-RS using subresource locators.

// BaseService.java
@Path("{id}")
public class BaseService
{
    @PathParam("id") protected String id;
    @QueryParam("xyz") protected String xyz;
    @Inject protected SomeUtility util;
    
    public BaseService () {} // default ctor for JAX-RS
    
    // ctor for manual "injection"
    public BaseService(String id, String xyz, SomeUtility util)
    {
        this.id = id;
        this.xyz = xyz;
        this.util = util;
    }
    
    @Path("foo")
    public FooService foo()
    {
        return new FooService(id, xyz, util); // manual DI is ugly
    }
    
    @Path("quux")
    public QuuxService quux()
    {
        return new QuuxService(id, xyz, util); // yep, still ugly
    }
}
// FooService.java
public class FooService extends BaseService
{
    public FooService(String id, String xyz, SomeUtility util)
    {
        super(id, xyz, util); // the manual DI ugliness continues
    }
    
    @GET @Path("bar")
    public Response getBar() { /* snip */ }
    
    @GET @Path("baz")
    public Response getBaz() { /* snip */ }
}
// QuuxService.java
public class QuuzService extends BaseService
{
    public FooService(String id, String xyz, SomeUtility util)
    {
        super(id, xyz, util); // the manual DI ugliness continues
    }
    
    @GET @Path("abc")
    public Response getAbc() { /* snip */ }
    
    @GET @Path("def")
    public Response getDef() { /* snip */ }
}

The downside to this approach is that neither CDI injection nor JAX-RS injection works in the subresource classes. The reason for this is fairly obvious2, but what that means is that I have to manually re-inject the fields into the subclasses' constructor, which is messy, ugly, and doesn't easily let me customize further injection. Example: say I wanted to @Inject an instance into FooService but not QuuxService. Because I'm explicitly instantiating the subclasses of BaseService, CDI injection won't work, so the ugliness is continued.


tl;dr What's the right way to avoid repeatedly injecting fields across JAX-RS resource handler classes?

And why aren't inherited fields injected by JAX-RS, while CDI has no issues with this?


Edit 1

With a bit of direction from @Tarlog, I think I've found the answer to one of my questions,

Why aren't inherited fields injected by JAX-RS?

In JSR-311 §3.6:

If a subclass or implementation method has any JAX-RS annotations then all of the annotations on the super class or interface method are ignored.

I'm sure that there's a real reason for this decision, but unfortunately that fact is working against me in this particular use case. I'm still interested in any possible workarounds.


1 The caveat with using field-level injection is that I'm now tied to per-request resource class instantiation, but I can live with that.
2 Because I'm the one calling new FooService() rather than the container/the JAX-RS implementation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

云淡月浅 2024-11-11 21:07:51

这是我正在使用的解决方法:

使用“id”和“xyz”作为参数定义 BaseService 的构造函数:

// BaseService.java
public abstract class BaseService
{
    // JAX-RS injected fields
    protected final String id;
    protected final String xyz;

    public BaseService (String id, String xyz) {
        this.id = id;
        this.xyz = xyz;
    }
}

使用注入在所有子类上重复构造函数:

// FooService.java
@Path("/{id}/foo")
public class FooService extends BaseService
{
    public FooService (@PathParam("id") String id, @QueryParam("xyz") String xyz) {
        super(id, xyz);
    }

    @GET @Path("bar")
    public Response getBar() { /* snip */ }

    @GET @Path("baz")
    public Response getBaz() { /* snip */ }
}

Here is a workaround I'm using:

Define a constructor for the BaseService with 'id' and 'xyz' as params:

// BaseService.java
public abstract class BaseService
{
    // JAX-RS injected fields
    protected final String id;
    protected final String xyz;

    public BaseService (String id, String xyz) {
        this.id = id;
        this.xyz = xyz;
    }
}

Repeat the constructor on all subclasses with the injects:

// FooService.java
@Path("/{id}/foo")
public class FooService extends BaseService
{
    public FooService (@PathParam("id") String id, @QueryParam("xyz") String xyz) {
        super(id, xyz);
    }

    @GET @Path("bar")
    public Response getBar() { /* snip */ }

    @GET @Path("baz")
    public Response getBaz() { /* snip */ }
}
︶葆Ⅱㄣ 2024-11-11 21:07:51

查看 Jax 的 JIRA 似乎有人要求将注释继承作为 JAX-RS 的里程碑。

您正在寻找的功能在 JAX-RS 中尚不存在,但是,这行得通吗?
它很丑,但可以防止重复注射。

public abstract class BaseService
{
    // JAX-RS injected fields
    @PathParam("id") protected String id;
    @QueryParam("xyz") protected String xyz;

    // CDI injected fields
    @Inject protected SomeUtility util;

    @GET @Path("bar")
    public abstract Response getBar();

    @GET @Path("baz")
    public abstract Response getBaz();

    @GET @Path("abc")
    public abstract Response getAbc();

    @GET @Path("def")
    public abstract Response getDef();
}

// FooService.java
@Path("/{id}/foo")
public class FooService extends BaseService
{
    public Response getBar() { /* snip */ }

    public Response getBaz() { /* snip */ }
}

// QuuxService.java
@Path("/{id}/quux")
public class QuxxService extends BaseService
{   
    public Response getAbc() { /* snip */ }

    public Response getDef() { /* snip */ }
}

或者在另一个解决方法中:

public abstract class BaseService
{
    @PathParam("id") protected String id;
    @QueryParam("xyz") protected String xyz;

    // CDI injected fields
    @Inject protected SomeUtility util;

    @GET @Path("{stg}")
    public abstract Response getStg(@Pathparam("{stg}") String stg);

}

// FooService.java
@Path("/{id}/foo")
public class FooService extends BaseService
{
    public Response getStg(String stg) {
        if(stg.equals("bar")) {
              return getBar();
        } else {
            return getBaz();
        }
    }
    public Response getBar() { /* snip */ }

    public Response getBaz() { /* snip */ }
}

但坦率地说,看到你有多敏感,我怀疑你的挫败感会因为这段丑陋的代码而消失:)

Looking at Jax's JIRA it seems someone asked for annotation inheritance as milestone for JAX-RS.

The feature you're looking for just doesn't exist in JAX-RS yet, however, would this work?
It's ugly, but prevents recurrent injection.

public abstract class BaseService
{
    // JAX-RS injected fields
    @PathParam("id") protected String id;
    @QueryParam("xyz") protected String xyz;

    // CDI injected fields
    @Inject protected SomeUtility util;

    @GET @Path("bar")
    public abstract Response getBar();

    @GET @Path("baz")
    public abstract Response getBaz();

    @GET @Path("abc")
    public abstract Response getAbc();

    @GET @Path("def")
    public abstract Response getDef();
}

// FooService.java
@Path("/{id}/foo")
public class FooService extends BaseService
{
    public Response getBar() { /* snip */ }

    public Response getBaz() { /* snip */ }
}

// QuuxService.java
@Path("/{id}/quux")
public class QuxxService extends BaseService
{   
    public Response getAbc() { /* snip */ }

    public Response getDef() { /* snip */ }
}

Or in another workaround :

public abstract class BaseService
{
    @PathParam("id") protected String id;
    @QueryParam("xyz") protected String xyz;

    // CDI injected fields
    @Inject protected SomeUtility util;

    @GET @Path("{stg}")
    public abstract Response getStg(@Pathparam("{stg}") String stg);

}

// FooService.java
@Path("/{id}/foo")
public class FooService extends BaseService
{
    public Response getStg(String stg) {
        if(stg.equals("bar")) {
              return getBar();
        } else {
            return getBaz();
        }
    }
    public Response getBar() { /* snip */ }

    public Response getBaz() { /* snip */ }
}

But seeing how touchy you are, frankly, I doubt your frustration will go away with this ugly code :)

世界等同你 2024-11-11 21:07:51

在 RESTEasy 中,我们可以构造一个类,像往常一样用 @*Param 进行注释,最后通过对类 @Form 进行注释来完成。然后,这个 @Form 类可以作为参数注入到任何其他服务的方法调用中。
http://docs.jboss.org/resteasy /docs/2.3.5.Final/userguide/html/_Form.html

In RESTEasy one can construct a class, annotate with @*Param as usual, and finish by annotating the class @Form. This @Form class may then be a parameter injection into any other service's method call.
http://docs.jboss.org/resteasy/docs/2.3.5.Final/userguide/html/_Form.html

浪菊怪哟 2024-11-11 21:07:51

我总是有一种感觉,注释继承使我的代码不可读,因为从哪里/如何注入它并不明显(例如,它将被注入到继承树的哪个级别以及它被覆盖在哪里(或者是在全部))。此外,您必须使变量受保护(并且可能不是最终的),这使得超类泄漏其内部状态,并且还可能引入一些错误(至少在调用扩展方法时我总是会问自己:受保护的变量是否已更改) ?)。恕我直言,它与 DRY 没有任何关系,因为这不是逻辑的封装,而是注入的封装,这对我来说似乎有点夸张。

最后我将引用 JAX-RS 规范中的3.6 Annotation Inheritance

为了与其他 Java EE 规范保持一致,建议
总是重复注释而不是依赖注释
继承。

PS:我承认我有时只使用注释继承,但在方法级别:)

I always had a feeling, that annotation inheritance makes my code unreadable, as it is not obvious from where/how it is injected (e.g on which level of the inheritance tree would it be injected and where was it overriden (or was it overriden at all)). Moreover, you have to make the variable protected (and probably NOT final), which makes the superclass leak its internal state and also may introduce some bugs ( at least I would always ask myself when calling an extended method: is the protected variable changed there?). IMHO it has nothing with DRY, as this is not encapsulation of logic, but encapsulation of injection, which seems exaggerated to me.

At the end I will cite from the JAX-RS spec, 3.6 Annotation Inheritance

For consistency with other Java EE specifications, it is recommended
to always repeat annotations instead of relying on annotation
inheritance.

PS: I admit that I use only sometimes annotation inheritance, but on the method level :)

梦行七里 2024-11-11 21:07:51

避免参数注入的动机是什么?
如果动机是避免重复硬编码字符串,因此您可以轻松地重命名它们,则可以重用“常量”:(

// FooService.java
@Path("/" +  FooService.ID +"/foo")
public class FooService
{
    public static final String ID = "id";
    public static final String XYZ= "xyz";
    public static final String BAR= "bar";

    @PathParam(ID) String id;
    @QueryParam(XYZ) String xyz;

    @GET @Path(BAR)
    public Response getBar() { /* snip */ }

    @GET @Path(BAR)
    public Response getBaz() { /* snip */ }
}

// QuuxService.java
@Path("/" +  FooService.ID +"/quux")
public class QuxxService
{
    @PathParam(FooService.ID) String id;
    @QueryParam(FooService.XYZ) String xyz;

    @GET @Path("abc")
    public Response getAbc() { /* snip */ }

    @GET @Path("def")
    public Response getDef() { /* snip */ }
}

很抱歉发布第二个答案,但太长了,无法将其放在上一个答案的评论中)

What is the motivation of avoiding parameters injections?
If the motivation is avoiding of repeating hard-coded strings, so you can easily rename them, you can reuse "constants":

// FooService.java
@Path("/" +  FooService.ID +"/foo")
public class FooService
{
    public static final String ID = "id";
    public static final String XYZ= "xyz";
    public static final String BAR= "bar";

    @PathParam(ID) String id;
    @QueryParam(XYZ) String xyz;

    @GET @Path(BAR)
    public Response getBar() { /* snip */ }

    @GET @Path(BAR)
    public Response getBaz() { /* snip */ }
}

// QuuxService.java
@Path("/" +  FooService.ID +"/quux")
public class QuxxService
{
    @PathParam(FooService.ID) String id;
    @QueryParam(FooService.XYZ) String xyz;

    @GET @Path("abc")
    public Response getAbc() { /* snip */ }

    @GET @Path("def")
    public Response getDef() { /* snip */ }
}

(Sorry for posting the second answer, but it was too long to put it in a comment of the previous answer)

面如桃花 2024-11-11 21:07:51

您可以添加自定义提供程序,特别是通过 AbstractHttpContextInjectable:

// FooService.java
@Path("/{id}/foo")
public class FooService
{
    @Context CommonStuff common;

    @GET @Path("bar")
    public Response getBar() { /* snip */ }

    @GET @Path("baz")
    public Response getBaz() { /* snip */ }
}


@Provider
public class CommonStuffProvider
    extends AbstractHttpContextInjectable<CommonStuff>
    implements InjectableProvider<Context, Type>
{

    ...

    @Override
    public CommonStuff getValue(HttpContext context)
    {
        CommonStuff c = new CommonStuff();
        c.id = ...initialize from context;
        c.xyz = ...initialize from context;

        return c;
    }
}

当然,您必须以困难的方式从 HttpContext 中提取路径参数和/或查询参数,但您将在一个地方完成一次。

You can add a custom provider, particularly via AbstractHttpContextInjectable:

// FooService.java
@Path("/{id}/foo")
public class FooService
{
    @Context CommonStuff common;

    @GET @Path("bar")
    public Response getBar() { /* snip */ }

    @GET @Path("baz")
    public Response getBaz() { /* snip */ }
}


@Provider
public class CommonStuffProvider
    extends AbstractHttpContextInjectable<CommonStuff>
    implements InjectableProvider<Context, Type>
{

    ...

    @Override
    public CommonStuff getValue(HttpContext context)
    {
        CommonStuff c = new CommonStuff();
        c.id = ...initialize from context;
        c.xyz = ...initialize from context;

        return c;
    }
}

Granted, you'll have to extract the path parameters and/or the query parameters the hard way from HttpContext, but you'll do it once in one place.

℡寂寞咖啡 2024-11-11 21:07:51

您可以使用 @Context UriInfo 来访问任何类型的参数,而不是使用 @PathParam@QueryParam 或任何其他参数。因此您的代码可以是:

// FooService.java
@Path("/{id}/foo")
public class FooService
{
    @Context UriInfo uriInfo;

    public static String getIdParameter(UriInfo uriInfo) {
        return uriInfo.getPathParameters().getFirst("id");
    }

    @GET @Path("bar")
    public Response getBar() { /* snip */ }

    @GET @Path("baz")
    public Response getBaz() { /* snip */ }
}

// QuuxService.java
@Path("/{id}/quux")
public class QuxxService
{
    @Context UriInfo uriInfo;

    @GET @Path("abc")
    public Response getAbc() { /* snip */ }

    @GET @Path("def")
    public Response getDef() { /* snip */ }
}

请注意 getIdParameter 是静态的,因此您可以将其放入某个实用程序类中并在多个类中重用。
UriInfo 保证是线程安全的,因此您可以将资源类保持为单例。

Instead of using @PathParam, @QueryParam or any other param, you can use @Context UriInfo to access any types of parameters. So your code could be:

// FooService.java
@Path("/{id}/foo")
public class FooService
{
    @Context UriInfo uriInfo;

    public static String getIdParameter(UriInfo uriInfo) {
        return uriInfo.getPathParameters().getFirst("id");
    }

    @GET @Path("bar")
    public Response getBar() { /* snip */ }

    @GET @Path("baz")
    public Response getBaz() { /* snip */ }
}

// QuuxService.java
@Path("/{id}/quux")
public class QuxxService
{
    @Context UriInfo uriInfo;

    @GET @Path("abc")
    public Response getAbc() { /* snip */ }

    @GET @Path("def")
    public Response getDef() { /* snip */ }
}

Pay attention that getIdParameter is static, so you can put it in some utility class and reuse accorss multiple classes.
UriInfo is guaranteed to be threadsafe, so you can keep resource class as singleton.

江南烟雨〆相思醉 2024-11-11 21:07:51

您可以尝试 @BeanParam 所有重复参数。因此,您不必每次都注入它们,只需注入 customBean 就可以了。

另一种更简洁的方法是您可以将

@Context UriInfo 

@Context ExtendedUriInfo

注入到您的资源类中,并且通过这种方法您可以简单地访问它们。
UriInfo 更加灵活,因为您的 jvm 将少一个要管理的 java 源文件,而且最重要的是,UriInfo 或 ExtendedUriInfo 的单个实例可以让您处理很多事情。

@Path("test")
public class DummyClass{

@Context UriInfo info;

@GET
@Path("/{id}")
public Response getSomeResponse(){
     //custom code
     //use info to fetch any query, header, matrix, path params
     //return response object
}

You can try @BeanParam for all the repeating params. so rather than injecting them every time you can simply inject you customBean which will do the trick.

Another approach which is more cleaner is that you can inject

@Context UriInfo 

or

@Context ExtendedUriInfo

to your Resource Class and in very method you can simply access them.
UriInfo is more flexible because your jvm will have one less java source file to manage and above all single instance of UriInfo or ExtendedUriInfo gives you a handle of a lot of things.

@Path("test")
public class DummyClass{

@Context UriInfo info;

@GET
@Path("/{id}")
public Response getSomeResponse(){
     //custom code
     //use info to fetch any query, header, matrix, path params
     //return response object
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文