(Spring-Boot/CXF/JAXRS) @GET 正确响应 200,@POST 尽管配置相同,但响应 404

(Spring-Boot/CXF/JAXRS) @GET responds correctly with 200, @POST responds with 404 despite identical configuration

问题

问题是我的带有@GET 注释的端点工作正常,结果为 200。@POST 导致 404。它们的配置几乎相同。控制台不报告任何错误。

背景

我正在设置一个包含一系列 GET 和 POST 的控制器。 我正在使用 SpringBoot/Tomcat。 具体库为cxf-spring-boot-starter-jaxrs (version: 3.3.3)

我按照本指南进行设置: https://cxf.apache.org/docs/springboot.html

据我所知,spring 引导启动器处理 servlet 设置,所以我没有那个可以分享。

服务器和服务 bean 初始化如下所示:

    @Autowired
    private List<? extends BaseController> controllers;

    @Bean
    public Server rsServer()
    {
        JAXRSServerFactoryBean endpoint = new JAXRSServerFactoryBean();

        endpoint.setBus(bus);
        endpoint.setAddress("/");
        endpoint.setServiceBeans(new ArrayList<Object>(controllers));
        endpoint.setExtensionMappings(getExtensionMapping());

        // jsonProvider() is an instance of org.apache.cxf.jaxrs.provider.json.JSONProvider
        endpoint.setProviders(Arrays.asList(jsonProvider()));

        return endpoint.create();
    }

我的控制器看起来像这样:

@Path("/v1/test")
@Service
public class SimpleTestController extends BaseController
{

    @GET
    @Path("/gettest")
    @Produces(value = { "application/json" })
    @Consumes(value = { "application/json" })
    public Response getTest()
    {
        BlankResource blankResource = new BlankResource();
        blankResource.setTest("WORKING");

        return Response.ok(gson.toJson(blankResource), MediaType.APPLICATION_JSON)
                .build();
    }

    @POST
    @Path("/posttest")
    @Produces(value = { "application/json" })
    @Consumes(value = { "application/json" })
    public Response postTest(BlankResource blankResource)
    {
        blankResource.setTest("WORKING");
        return Response.ok(gson.toJson(blankResource), MediaType.APPLICATION_JSON)
                .build();
    }
}

注意:BaseController 实际上是空的,所以我们可以忽略它。

我还禁用了所有@Providers 以确保没有任何干扰。与 spring 安全性相同。

我已经用 Postman 和 CURL 来测试了。

GET URL 有效: http://localhost:8080/selector-service/v1/test/gettest

POST URL 不起作用: http://localhost:8080/selector-service/v1/test/posttest

curl --location --request POST 'http://localhost:8080/selector-service/v1/test/posttest' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Cookie: JSESSIONID=262BEEF808419C6CEC61E064AEA3EEAA' \
--data-raw '{
    "test": true
}'

Update(12/31/2020) 另一个有趣的注意事项:当我在方法上 运行 a POST 时,它 returns a 404 但是当我尝试获取 POST 端点它 returns 一个 405。这对我来说很突出,因为看起来服务器确实已经注册了 post 端点。

更新(1/4/2020)我从使用“cxf.jaxrs.component-scan”配置类似设置的人那里找到了 blog post。我遵循了本指南,该指南使我的 rsServer() @Bean 变得多余。我试过删除它。这没有效果,我仍然遇到同样的问题。

service.properties:

server.address=localhost

cxf.path=/
cxf.jaxrs.component-scan=true

在 JAX-RS 中,您的 AcceptContent-Type headers 必须与您在 @Consumes@Produces 中声明的方法以及URL。因此,对于 Curl,您必须这样做:

curl -i -H "Accept: application/json" -H "Content-Type: application/json" http://localhost:8080/selector-service/v1/test/posttest

您可以尝试将 Spring 的 DispatcherServlet 和 CXF Servlet 映射到不同的路径吗?

类似于:

# Spring MVC dispatcher servlet path. Needs to be different than CXF's to enable/disable Actuator endpoints access (/info, /health, ...)
server.servlet-path: /

# http://cxf.apache.org/docs/springboot.html#SpringBoot-SpringBootCXFJAX-RSStarter
cxf:
  path: /api # CXFServlet URL pattern
  jaxrs:
    component-scan: true

顺便说一句,我是博客 post 的作者,您用作参考:

https://tech.asimio.net/2017/06/12/Implementing-APIs-using-Spring-Boot-CXF-and-Swagger.html