Grizzly REST - POST 总是 404

Grizzly REST - POSTs are always 404

在我的端点中,我有一些方法 @GET 和一些方法 @POST@GETs 工作正常,但 @POSTs 总是 return 404.

这是端点接口的一部分:

public interface TestEndpoint {

    @GET
    @Path("/ping")
    Response ping();

    @POST
    @Path("/weather/{iata}/{pointType}")
    Response updateWeather(@PathParam("iata") String iataCode,
                           @PathParam("pointType") String pointType,
                           String datapointJson);

    @POST
    @Path("/airport/{iata}/{lat}/{long}")
    Response addAirport(@PathParam("iata") String iata,
                        @PathParam("lat") String latString,
                        @PathParam("long") String longString);

    @GET
    @Path("/exit")
    Response exit();
}

这里是服务器初始化部分:

public class TestServer {

    private static final String BASE_URL = "http://localhost:9090/";

    public static void main(String[] args) {
        try {
            final ResourceConfig resourceConfig = new ResourceConfig();
            resourceConfig.register(TestEndpointImpl.class);

            HttpServer server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URL), resourceConfig, false);
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                server.shutdownNow();
            }));

            HttpServerProbe probe = new HttpServerProbe.Adapter() {
                public void onRequestReceiveEvent(HttpServerFilter filter, Connection connection, Request request) {
                    System.out.println(request.getRequestURI());
                }
            };
            server.getServerConfiguration().getMonitoringConfig().getWebServerConfig().addProbes(probe);

            server.start();
            Thread.currentThread().join();
            server.shutdown();
        } catch (IOException | InterruptedException ex) {
            Logger.getLogger(TestServer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

其中,TestEndpointImplTestEndpoint 的实现(顾名思义),带有 class 级注释 @Path("/collect").

当我执行 GET 请求时,它工作正常。但是 POSTs 是有问题的。没有调用相应的方法。

作为旁注,probe 按预期打印 GET 和 POST 请求,因此我确信请求到达服务器并且路径正常。

有什么建议吗?

编辑: 实施中的一些片段:

@Path("/collect")
public class TestEndpointImpl implements TestEndpoint {

    ...

    @Override
    public Response updateWeather(@PathParam("iata") String iataCode, @PathParam("pointType") String pointType,
            String datapointJson) {
        System.out.println("TRACE: " + datapointJson);
        // do something and return a Response
    }

    ...

}

已注册的探测器打印 /collect/weather/BOS/wind,但未调用 updateWeather

如果 url 的格式不正确,也会发生这种情况;例如,您可以在没有正确路径参数的情况下发送请求。

简答

@POST and the @Path 注释复制到方法实现中。它会成功的。

长答案

JAX-RS 2.0规范(以Jersey为参考实现的规范)关于注解继承的部分说的很清楚。请参阅下面的引用:

3.6 Annotation Inheritance

JAX-RS annotations may be used on the methods and method parameters of a super-class or an implemented interface. Such annotations are inherited by a corresponding sub-class or implementation class method provided that the method and its parameters do not have any JAX-RS annotations of their own. Annotations on a super-class take precedence over those on an implemented interface. The precedence over conflicting annotations defined in multiple implemented interfaces is implementation specific. Note that inheritance of class or interface annotations is not supported.

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

public interface ReadOnlyAtomFeed {

    @GET 
    @Produces("application/atom+xml")
    Feed getFeed();
}
@Path("feed")
public class ActivityLog implements ReadOnlyAtomFeed {

    public Feed getFeed() {...}
}

In the above, ActivityLog.getFeed inherits the @GET and @Produces annotations from the interface. Conversely:

@Path("feed")
public class ActivityLog implements ReadOnlyAtomFeed {

    @Produces("application/atom+xml")
    public Feed getFeed() {...}
}

In the above, the @GET annotation on ReadOnlyAtomFeed.getFeed is not inherited by ActivityLog.getFeed and it would require its own request method designator since it redefines the @Produces annotation.

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