JAX-RS/Jersey 资源路径会继承吗?

Will JAX-RS/Jersey resource paths honor inheritance?

假设我希望我的 JAX-RS/Jersey 应用公开以下 URLs:

http://myapp.example.com/app/fizz
http://myapp.example.com/app/buzz
http://myapp.example.com/app/foo
http://myapp.example.com/app/bar

假设我希望 /app 成为父基础资源,/app/* 成为 "child" 资源。以下是否会实现我正在寻找的 URL 策略 (?):

@Path('/app')
@Produces(MediaType.APPLICATION_JSON)
public abstract class AppResource {
    // Whatever...
}

@Path('/fizz') // <--- right here, will FizzResource live at /app/fizz?
@Produces(MediaType.APPLICATION_JSON)
public class FizzResource extends AppResource {
    // Whatever...
}

FizzResource 会暴露在 /app/fizz 还是只是 /fizz

你要的是

@Path("/app")
public class YourHandler {
   @Path('/')
   @Produces(MediaType.APPLICATION_JSON)
   public String yourHandlerForApp() {
      // Whatever...
   }

   @Path('/fizz') // <--- right here, will FizzResource live at /app/fizz?
   @Produces(MediaType.APPLICATION_JSON)
   public String yourHandlerForAppSlashFizz() {
       // Whatever...
   }
}

Will the FizzResource be exposed at /app/fizz or just /fizz?

简答

FizzResource 将在 /fizz 曝光。

长答案

引用JSR 339(第3.6节关于注释继承):

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

specification 还说:

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

正在创建子资源

JAX-RS/Jersey documentation解释了如何创建子资源:

@Path may be used on classes and such classes are referred to as root resource classes.

@Path may also be used on methods of root resource classes. This enables common functionality for a number of resources to be grouped together and potentially reused.

The first way @Path may be used is on resource methods and such methods are referred to as sub-resource methods.

因此,请执行以下操作来创建子资源:

@Path("/app")
public class YourHandler {

    @Produces(MediaType.APPLICATION_JSON)
    public String yourHandlerForApp() {
        // This method is be exposed at /app
    }

    @Path("/fizz") 
    @Produces(MediaType.APPLICATION_JSON)
    public String yourHandlerForAppSlashFizz() {
        // This method is be exposed at /app/fizz
    }
}

我认为给出的答案不是最适合原始问题陈述的答案。

他想将他的子资源放在单独的 classes 中。这是可以理解和令人钦佩的,因为不这样做将意味着将他的所有端点放在同一个 class 中,这将是巨大的。

如果此端口上的所有端点都以 /app 开头,那么我认为最好的方法是配置过滤器以将其放入 @ApplicationPath

如果不是所有端点都以相同的前缀开头,那么您将不得不使用这种样式的 JAX-RS 子资源,您在其中指定 @Path 而不是 HTTP 方法注释(@GET, 等) 和 return 您要委托给的资源实例:

@Path("/app")
public class AppResource {
    @Context UriInfo uriInfo;

    @Path("fizz")
    public FizzResource getItemContentResource() {
        return new FizzResource ();
    }
}

@Produces(MediaType.APPLICATION_JSON)
public class FizzResource extends AppResource {
    // Whatever...
}

JAX-RS documentation.

中提供了这种做资源的方法

您还可以让所有子资源将其路径声明为

    @Path(BASE_URL + "/fizz")

其中 BASE_URL 是静态字符串,但我会尽量避免这种情况,因为对 @Path 使用不完全恒定的参数似乎会导致每个 JAX-RS IDE 插件我见过问题。他们无法计算出实际路径,所以他们放弃了。因此,您可能会失去 "JAX-RS View" 允许您通过路径 visualize/navigate 您的 JAX-RS 资源的能力。