使用 Spring REST 控制器的 API 端点在调用后返回 404
我们有一个电子商务 Web 应用程序,前端服务器和 API 服务器位于单独的 EC2 Ubuntu 中。 API 服务器使用 Spring MVC 公开 168 个 API RESTFul 端点。每个类都有@RestController注释。我们对其中之一有疑问。
当前端调用这个端点(它是一个 PUT)时,我们知道它是在 Spring 中调用的,我们在数据库和它生成的 PDF 文件中看到它的效果,但随后(每次)它返回 404我们在 tomcat 访问日志中看到的浏览器也是如此,即使它每次都会被调用。这个端点没有什么特别之处。所有 168 个端点看起来都一样。它们具有 HTTP 方法,生成 JSON 并返回 ResponseEntity。我将此端点移至另一个新类,更改了其端点 URI,更改了方法名称,删除了此方法中除“return ResponseEntity.ok().body(new SomeObject())”之外的所有内容, 但它总是返回404。这是Spring MVC还是tomcat自己做的?
我们使用 OpenJDK 11.0.11+9、tomcat 9.0.59、Spring Framework 5.3.16、Spring Security 5.6.2、javaee-api 8.0.1 和 servlet 4.0。这是端点方法:
@RestController
@RequestMapping(value = "/api/v1/drivers")
public class DriverAPIService
{
@PutMapping(value = "/delivered", produces = "application/json")
public ResponseEntity<OrderStatusResponseBean> markOrderAsDelivered(@RequestBody OrderStatusUpdateRequestBean requestBean, HttpServletRequest request, HttpServletResponse response, Model model)
{
try
{
return DriverService.markOrderAsDelivered(requestBean, request);
}
catch(Throwable e)
{
return ResponseEntity.badRequest().build();
}
}
}
连接器的 server.xml 中的 tomcat 配置是:
<Executor name="tomcatThreadPool" namePrefix="tomcat9-thread-" maxIdleTime="60000"
maxThreads="50" minSpareThreads="5"/>
<Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" redirectPort="8443" maxConnections="100" acceptCount="300"/>
<Connector executor="tomcatThreadPool" SSLEnabled="true" maxPostSize="5000000" port="8443" protocol="org.apache.coyote.http11.Http11Nio2Protocol" scheme="https"
secure="true" compression="on" maxKeepAliveRequests="10" connectionTimeout="60000"
maxConnections="100" acceptCount="300" enableLookups="false" connectionUploadTimeout="120000" disableUploadTimeout="false">
<SSLHostConfig>
<Certificate certificateFile="conf/cert.pem" certificateKeyFile="conf/privkey.pem" certificateChainFile="conf/chain.pem" />
</SSLHostConfig>
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" compression="on" keepAliveTimeout="360000"/>
</Connector>
We have an eCommerce webapp with the front-end server and the API server being in separate EC2 Ubuntus. The API server exposes 168 API RESTFul endpoints using Spring MVC. Each class has the @RestController annotation. We have a problem with one of them.
When this endpoint (which is a PUT) is called by the front-end, we know that it is invoked in Spring, we see its effects in the database and the PDF file it generates, but then (every single time) it returns 404 to the browser which we see in the tomcat access logs, as well, even though it is invoked every time.. There is nothing extraordinary about this endpoint. All 168 endpoints look the same. They have the HTTP method, produces JSON and return ResponseEntity. I moved this endpoint to another new class, I changed its endpoint URI, I changed the method name, I removed everything from this method except for "return ResponseEntity.ok().body(new SomeObject())",
but it always returns 404. Does Spring MVC do this or tomcat itself?
We use OpenJDK 11.0.11+9, tomcat 9.0.59, Spring Framework 5.3.16, Spring Security 5.6.2, javaee-api 8.0.1 and servlet 4.0. Here is the endpoint method:
@RestController
@RequestMapping(value = "/api/v1/drivers")
public class DriverAPIService
{
@PutMapping(value = "/delivered", produces = "application/json")
public ResponseEntity<OrderStatusResponseBean> markOrderAsDelivered(@RequestBody OrderStatusUpdateRequestBean requestBean, HttpServletRequest request, HttpServletResponse response, Model model)
{
try
{
return DriverService.markOrderAsDelivered(requestBean, request);
}
catch(Throwable e)
{
return ResponseEntity.badRequest().build();
}
}
}
Our tomcat config in the server.xml for the connectors is:
<Executor name="tomcatThreadPool" namePrefix="tomcat9-thread-" maxIdleTime="60000"
maxThreads="50" minSpareThreads="5"/>
<Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" redirectPort="8443" maxConnections="100" acceptCount="300"/>
<Connector executor="tomcatThreadPool" SSLEnabled="true" maxPostSize="5000000" port="8443" protocol="org.apache.coyote.http11.Http11Nio2Protocol" scheme="https"
secure="true" compression="on" maxKeepAliveRequests="10" connectionTimeout="60000"
maxConnections="100" acceptCount="300" enableLookups="false" connectionUploadTimeout="120000" disableUploadTimeout="false">
<SSLHostConfig>
<Certificate certificateFile="conf/cert.pem" certificateKeyFile="conf/privkey.pem" certificateChainFile="conf/chain.pem" />
</SSLHostConfig>
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" compression="on" keepAliveTimeout="360000"/>
</Connector>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
让我们概括一下我们所拥有的内容:
恕我直言,问题一定出在响应处理中。我怀疑
HttpServletResponse
是这里的问题。只有极少数情况下才真正需要它(流、cookie 等),但通常它会导致比实际解决的问题更多的问题。因此,请从方法签名中删除任何不需要的参数,然后重试。Let's recapitulate what we have:
IMHO the problem must be in the response processing. I suspect the
HttpServletResponse
to be the problem here. There are only rare cases when it's really needed (streaming, cookies, etc.), but generally it causes more problems than it actually solves. So please remove any unneeded parameters from the method signature and try again.