使用 Spring REST 控制器的 API 端点在调用后返回 404

发布于 2025-01-15 21:33:33 字数 2260 浏览 0 评论 0原文

我们有一个电子商务 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谁的新欢旧爱 2025-01-22 21:33:33

让我们概括一下我们所拥有的内容:

  • 您的服务代码被包装到一个 catch-all 块中,它将把任何内部异常转换为 http-400 响应。 Catch-alls 是一种代码味道,但在这种情况下,它有助于排除问题深植于您的服务中的可能性。
  • 执行服务代码(如您所说),因此方法查找通常有效。

恕我直言,问题一定出在响应处理中。我怀疑 HttpServletResponse 是这里的问题。只有极少数情况下才真正需要它(流、cookie 等),但通常它会导致比实际解决的问题更多的问题。因此,请从方法签名中删除任何不需要的参数,然后重试。

Let's recapitulate what we have:

  • Your service code is wrapped into a catch-all block, that will transform any inner exceptions into an http-400 response. Catch-alls are a code smell, but in this case it helps to exclude the possibility that the problem is deep in your service.
  • The service code is executed (as you say), so the method lookup generally works.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文