【SpringBoot】不用第三方Web服务器部署静态资源

相信很多人都遇到过在使用 Springboot 构建前后端分离的 Web 应用时,往往需要使用静态网页服务器(例如:Nginx)部署前端,使用 java 环境来启动后端。对于单点部署来说,需要增加一个额外的Web服务器就显得有点麻烦,特别是在容器化环境下,如果既要静态网页服务器、又要Java环境,要么你iju使用两个容器来分别运行前后端,要么你就只能自己重新构建一个包含两个环境的新容器镜像来实现,对于小应用来说这都是不经济的。

我正好也遇到了这样的一个需求:

研发给我提供了后端应用的 jar 文件和前端静态页面文件包,要求部署在一个容器中

最终想到的方案是研究 SpringBoot 本身是否具备再不需要对后端文件进行重新打包的情况下,通过部署来解决了这个问题。最终在下面的文档中找到了解决方案:

web.servlet.spring-mvc.static-content

下面是我在实施这个方案中的一些具体细节,供读者大大们参考。

环境

  • JDK 1.8
  • Spring Boot 2.7.18
  • Docker (Docker Compose)

目录结构

<ROOT>
  |-- docker-compose.yml # 容器配置文件
  |-- web.jar # 后端 jar
  |-- public   # 前端文件包
        |-- index.html
        |-- js
        |-- css

容器运行配置

这里需要将后端文件(web.jar)和前端目录(public)都挂载到容器内部。

# docker-compose.yml
version: "3.7"

services:
    web:
      image: openjdk:8
      container_name: web
      volumes:
        - ./web.jar:/opt/web/web.jar
        - ./public:/opt/web/public
      ports:
        - "8080:8080"
      command: "java -jar /opt/web/web.jar --server.port=8080 --spring.mvc.async.request-timeout=30000 --server.servlet.register-default-servlet=true --spring.web.resources.static-locations=file:///opt/web/public/"
      restart: unless-stopped

启动命令

后端 jar 文件的启动命令如下:

java -jar web.jar --server.port=8080  --spring.mvc.async.request-timeout=10000 --server.servlet.register-default-servlet=true --spring.web.resources.static-locations=file:///opt/web/public/

其中最关键的有两个参数:

  1. --server.servlet.register-default-servlet=true 用于开启默认 servlet。SpringBoot 运行在 jar (standlone)模式时,默认是不开启这个的,所以需要添加这个参数。
  2. --spring.web.resources.static-locations=file:///opt/web/public/ 用于指定静态资源文件所在的路径。从上面的目录结构可以看到我们的静态资源就是存在在 public 目录下。