(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 中,您的 Accept
和 Content-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
问题
问题是我的带有@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 中,您的 Accept
和 Content-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