除了方法之外还使用 header 将请求路由到带注释的方法

Use header in addition to method to route request to annotated method

我想知道是否可以使用 JAX-RS 除了 HTTP 方法之外还使用 header 路由请求。事实上,我找不到这样做的方法。

我想到了类似的东西,其中 x-header 是一个 header:

@Path("/contacts/")
public class MyResource {
    @POST
    @Header("x-header:content1")
    public void method1(MyContent1 content) {
        (...)
    }

    @POST
    @Header("x-header:content2")
    public void method2(MyContent2 content) {
        (...)
    }
}

这个问题遵循这个答案:

非常感谢您的帮助! 蒂埃里

如果你需要影响请求 matching/routing 进程,你必须使用 JAX-RS 过滤器 - 具体来说是 PreMatching 过滤器 (@PreMatching) [这将在 JAX-RS 2.0 中起作用onwards] 如果在资源方法中使用 header 信息,它将没有意义,因为 JAX-RS 已经匹配了方法

这是过滤器实现的总体流程

  1. 使用 ContainerRequestContext 获取 header 信息
  2. 根据 header 值应用您的业务标准
  3. 现在的诀窍是能够路由到所需的资源方法 - 您的一个选择是使用 ContainerRequestContext 的 setRequestUri 方法,并在不同的 URI 上设置不同的资源方法(使用@Path)

Jersey 文档可能会有所帮助 -- https://jersey.java.net/documentation/latest/filters-and-interceptors.html#d0e9538

只是抛出另一个选项。您还可以使用 Sub-resource locators,这使我们可以对所选资源进行一些控制(并且是 JAX-RS 规范的一部分)。例如

@Path("contacts")
public class ContactsResource {
    
    @Path("/")
    public AbstractHeaderResource doSomething(@HeaderParam("X-Header") String xHeader) {
        if ("RequiredValue".equals(xHeader)) {
            return new WithHeaderResource();
        }
        return new WithOutHeaderResource();
    }
    
    public static abstract class AbstractHeaderResource {
        @POST
        @Consumes(MediaType.APPLICATION_JSON)
        public abstract Response doSometing(Contact contact);
    }
    
    public static class WithHeaderResource extends AbstractHeaderResource {
        @Override
        public Response doSometing(Contact contact) {
            return Response.ok("*** With Header ***").build();
        }
    }
    
    public static class WithOutHeaderResource extends AbstractHeaderResource {
        @Override
        public Response doSometing(Contact contact) {
            return Response.ok("*** WithOut Header ***").build();
        }
    }
}

测试

C:\>curl -v -X POST  
         -d "{\"name\":\"Peeskillet\"}" 
         -H "X-Header:RequiredValue" 
         -H "Content-Type:application/json"
         http://localhost:8080/contacts 

*** With Header ****

C:\>curl -v -X POST  
         -d "{\"name\":\"Peeskillet\"}"  
         -H "Content-Type:application/json"
         http://localhost:8080/contacts 

*** WithOut Header ****

资源方法没有接受相同的参数类型。我这样做只是为了简洁。您可以让子资源 classes 扩展一个空的抽象 class 或接口(仅用于输入),然后根据需要创建方法

更新

如果您需要将一些对象注入到子资源中,您也可以通过定位器方法return子资源class,或者您可以将ResourceContext注入主资源class 并使用它从定位器方法创建子资源实例和 return 该实例。这两种方式都将支持容器注入,因为容器将创建实例而不是你只是实例化它。