使用 Spring Boot 从不同端口提供 REST API 和静态内容

Posted

技术标签:

【中文标题】使用 Spring Boot 从不同端口提供 REST API 和静态内容【英文标题】:Serving REST API and static content from different ports with Spring Boot 【发布时间】:2018-03-30 11:57:24 【问题描述】:

是否可以?这在使用 CORS 时变得有趣。意味着,插入的 nginx 会将发往 api.example.com 的请求路由到一个端口,并将发往 static.example.com 的请求路由到另一个端口。示例:

GET :8080/index.html 应该提供 src/main/resources/static/index.htmlGET :8090/customers/1 应该提供由(例如)CustomerController 提供的内容

具有交换端口号的请求(因此 REST API 为 8080,静态内容为 8090)不应工作。

1 级答案:如何使用嵌入式 Tomcat 完成此任务? 2 级答案:如何使用运行 Spring Boot 应用程序的托管 Tomcat 来完成此任务?

不是解决方案,因为这很明显:“将其拆分为两个应用程序”。

【问题讨论】:

也许这有帮助***.com/questions/36357135/… 如果内容是真正的静态内容,并且您的服务前端使用 Web 服务器 (nginx),那么为什么不将静态内容部署到 Web 服务器? @jmhostalet 不幸的是,没有,因为这个答案还远远不够。我知道如何启用第二个端口。然而,最初的问题是如何在两个端口上提供不同的内容。还是谢谢! @AndyBrown 感谢您的提示,但这不是一个选项,因为 nginx 充当多个应用程序的网关。 如果内部你的rest调用隐藏在一个子路径后面,比如/rest,那可能会更容易,那么你可以配置nginx将8080上的所有内容路由到/static/bla,并将8090上的所有内容路由到/休息/布拉。如果人们切换端口,它应该会自动不起作用,因为内容不会存在于重新路由的子路径下。 【参考方案1】:

“如何使用嵌入式 Tomcat 完成此任务?”

这可能是可能的,但不推荐。这会让你承受太多压力,不值得。

改为使用“/api/v1/”前缀,并将所有的 restful 端点放在该路径后面。

“/api”路径可以由 spring security 专门管理(允许 CORS 等)。

“v1”路径允许您为您的客户或您可能具有依赖日期的业务逻辑的情况对您的 api 进行版本控制。

“如何使用运行 Spring Boot 应用程序的托管 Tomcat 来完成此任务?”

我明白你为什么要这样做;我有“人”(?)要求我做一些奇怪的事情,比如太/

在这种情况下,我也建议对 RESTful 端点使用相同的“/api”方法,但会阻止对 Tomcat 的所有静态内容请求。 Spring Security 可以配置为只通过 tomcat 请求“api”下的 restful 端点,并阻止对 Tomcat 的任何静态内容请求。

将 Nginx 配置为与 tomcat 位于同一服务器上,并将 NgineX 文档库设置为战争扩展后静态内容所在的位置。

不要将该目录放在“META-INF”或“WEB-INF”内的任何位置;这些目录中的文件只能由 Tomcat 提供服务,并且做其他任何事情都不安全。

另外,不要使用 Nginx 重定向到 Tomcat,以便 Tomcat 将静态内容提供给 Nginx,Nginx 将其传递给客户端。如果 Tomcat 要做的不仅仅是从战争中提取内容,那么拥有 Nginx 是多余的。

最终结果是 Nginx 在不同的端口上运行,看起来好像您有两个应用程序,但实际上并非如此。

这还不如将 Angular 应用分开,但你知道......“人”。

如果您打算使用 tomcat 从 war 文件中提供静态内容,请不要将其放在“src/main/resources/static/”下。静态目录对于 jar 部署很有用,但是在从 war 部署内容时就麻烦了。相反,将它放在“src/main/webapp/”下。您需要确保 Spring Security 仍然允许它,但标准 tomcat 允许对不在“META-INF”或“WEB-INF”下的内容的所有请求。

如果所有这些仍然不是你必须做的事情,那么你可以在 tomcats "server.xml" 中定义一个单独的主机和连接器,并定义两个不同的上下文在 context.xml 中他们自己的“文档库”。

上下文文档:https://tomcat.apache.org/tomcat-8.5-doc/config/context.html

主持文档:https://tomcat.apache.org/tomcat-8.5-doc/config/host.html

【讨论】:

【参考方案2】:

不确定如何使用 Spring 执行此操作,但您可以使用 Spring 中集成的 Camel。我应该说,虽然这只是 感觉 这是一个坏主意。最好使用不同的服务器来提供静态内容并根据需要创建代理。但无论如何,您需要做的就是创建一个骆驼路线,然后将其重定向回 Spring 世界,或者简单地从骆驼中提供您的内容。您可以将骆驼路由绑定到不同的端口。几乎有人在这里问过同样的问题:How to run @RestController on a different port? 和其他人建议 Spring Actutator 也可以是一个选项。

【讨论】:

以上是关于使用 Spring Boot 从不同端口提供 REST API 和静态内容的主要内容,如果未能解决你的问题,请参考以下文章

如何让Javamelody使用不同的端口(Spring Boot+暴露的两个HTTP端口)

Spring Boot 中处理跨域

在两个不同端口上具有两个服务的 Spring Boot 应用程序

在不同端口上注册 Spring Boot Servlet

netty-websocket-spring-boot-starter不同url端口复用

Spring Boot Management 安全性与端口集的工作方式不同