【问题标题】:(Spring-Boot/CXF/JAXRS) @GET responds correctly with 200, @POST responds with 404 despite identical configuration(Spring-Boot/CXF/JAXRS)@GET 以 200 正确响应,@POST 以 404 响应,尽管配置相同
【发布时间】:2020-12-30 00:07:10
【问题描述】:

问题

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

背景

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

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

据我了解,spring boot starter 处理 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 Security 相同。

我已经使用 Postman 和 CURL 对此进行了测试。

获取有效的 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
}'

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

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

service.properties:

server.address=localhost

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

【问题讨论】:

  • 我知道你说它是空的,但是 BaseController 是用 @RestController 注解的吗?
  • 您好,感谢您的回复。不,它没有任何注释。它只是一些常量,用于自动接线目的。
  • 另外,我认为这也会破坏 @GET 注释,但在测试时有效。
  • 能否分享一下Get an Post的服务网址。
  • @P.Sanjay 我更新了问题以在底部包含此信息。

标签: java spring-boot jax-rs cxf


【解决方案1】:

您可以尝试将 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

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

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

【讨论】:

  • 嗨!感谢您的答复。由于设计要求,我确实需要 cxf.path=/ 我不得不承认,我不知道 2 路径设置之间的区别。我最初并没有设置“server.servlet-path”,但为了测试,我确实按照上述方式配置了它。它导致@POST 返回 403
  • [已解决] 我正在为未来遇到此问题的个人添加注释。分开两条路径确实解决了这个问题。如果您最终得到 403,您可能需要更改您的 spring 安全设置。也许禁用 csrf。
【解决方案2】:

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

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

【讨论】:

  • 感谢您的提示。我一直在使用邮递员,它已经正确设置为这样配置。邮递员的代码被添加到问题的底部。
  • @DanielMcBride - 添加 Accept 标头。
  • 我很确定它默认为接受 / 但我继续尝试了它。没有区别。我更新了帖子。
  • 你是对的@DanielMcBride - 我在考虑标准的 JAX-RS 环境,但事实并非如此。我会继续挖掘。作为参考,这在 JEE 环境中运行良好。
  • 谢谢。我包括了我使用的具体指南。我有一些偏差,但我想不出这可能会导致 GET 工作但不能 POST。我假设有一些特定于 spring-starter 实现的东西导致了这个问题。
猜你喜欢
  • 1970-01-01
  • 2018-09-04
  • 1970-01-01
  • 2018-05-03
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-29
相关资源
最近更新 更多