Update application.yml to disable resource mapping for improved SPA handling

This commit is contained in:
liumangmang
2026-02-04 11:16:01 +08:00
parent 7e6ebd18a5
commit 4558ef20c0
9 changed files with 258 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
package com.sshmanager.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.resource.PathResourceResolver;
import java.io.IOException;
/**
* SPA 前端路由回退:未匹配到静态资源时返回 index.html供 Vue Router history 模式使用。
*/
@Configuration
public class SpaForwardConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/")
.resourceChain(true)
.addResolver(new PathResourceResolver() {
@Override
protected Resource getResource(String path, Resource location) throws IOException {
Resource resource = location.createRelative(path);
if (resource.exists() && resource.isReadable()) {
return resource;
}
return location.createRelative("index.html");
}
});
}
}

View File

@@ -2,6 +2,9 @@ server:
port: 48080
spring:
web:
resources:
add-mappings: false # 使用 SpaForwardConfig 统一处理静态与 SPA 回退
datasource:
url: jdbc:h2:file:./data/sshmanager;DB_CLOSE_DELAY=-1
driver-class-name: org.h2.Driver

6
docker/.npmrc Normal file
View File

@@ -0,0 +1,6 @@
# 使用国内 npm 镜像npmmirror 淘宝镜像)
registry=https://registry.npmmirror.com
sass_binary_site=https://npmmirror.com/mirrors/node-sass
phantomjs_cdnurl=https://npmmirror.com/mirrors/phantomjs
electron_mirror=https://npmmirror.com/mirrors/electron/
chromedriver_cdnurl=https://npmmirror.com/mirrors/chromedriver

48
docker/Dockerfile Normal file
View File

@@ -0,0 +1,48 @@
# ========== 阶段一:前端构建(国内 npm 源) ==========
FROM node:20-alpine AS frontend
# 使用国内 npm 镜像npmmirror
COPY docker/.npmrc /root/.npmrc
WORKDIR /app
COPY frontend/package.json frontend/package-lock.json ./
RUN npm ci --prefer-offline --no-audit
COPY frontend/ ./
RUN npm run build
# ========== 阶段二:后端构建(国内 Maven 源) ==========
FROM maven:3.9-eclipse-temurin-8-alpine AS backend
COPY docker/maven-settings.xml /root/.m2/settings.xml
WORKDIR /build
# 先复制 pom利用层缓存
COPY backend/pom.xml ./
RUN mvn dependency:go-offline -B -q
# 复制后端源码
COPY backend/src ./src
# 将前端打包结果放入 Spring Boot 静态资源目录
COPY --from=frontend /app/dist ./src/main/resources/static
RUN mvn package -DskipTests -B -q
# ========== 阶段三:运行(单容器,仅 Java ==========
FROM eclipse-temurin:8-jre-alpine
RUN apk add --no-cache tzdata \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone
WORKDIR /app
COPY --from=backend /build/target/*.jar app.jar
ENV DATA_DIR=/app/data
RUN mkdir -p ${DATA_DIR}
EXPOSE 48080
ENTRYPOINT ["java", "-jar", "app.jar"]

35
docker/README.md Normal file
View File

@@ -0,0 +1,35 @@
# Docker 单容器部署
前端打包后放入 Spring Boot `static`,与 Java 一起在同一个容器内启动,不使用 Nginx。
## 国内源
- **npm**`docker/.npmrc` 使用 npmmirror淘宝镜像
- **Maven**`docker/maven-settings.xml` 使用阿里云仓库
## 构建与运行
在**项目根目录**执行:
```bash
# 构建镜像
docker compose -f docker/docker-compose.yml build
# 前台运行
docker compose -f docker/docker-compose.yml up
# 后台运行
docker compose -f docker/docker-compose.yml up -d
```
访问http://localhost:48080
## 环境变量(可选)
- `SSHMANAGER_ENCRYPTION_KEY`:连接密码加密密钥(生产务必修改)
- `SSHMANAGER_JWT_SECRET`JWT 密钥(生产务必修改)
- `TZ`:时区,默认 `Asia/Shanghai`
## 数据持久化
H2 数据目录通过 volume `app-data` 挂载到 `/app/data`,重启容器数据保留。

33
docker/backend.Dockerfile Normal file
View File

@@ -0,0 +1,33 @@
# Backend: Maven 使用阿里云镜像,多阶段构建
FROM maven:3.9-eclipse-temurin-8-alpine AS builder
# 使用国内 Maven 配置(阿里云)
COPY docker/maven-settings.xml /root/.m2/settings.xml
WORKDIR /build
# 先复制 pom利用 Docker 层缓存
COPY backend/pom.xml .
RUN mvn dependency:go-offline -B -q
COPY backend/src ./src
RUN mvn package -DskipTests -B -q
# 运行阶段
FROM eclipse-temurin:8-jre-alpine
RUN apk add --no-cache tzdata \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone
WORKDIR /app
COPY --from=builder /build/target/*.jar app.jar
# 数据目录H2 数据库文件)
ENV DATA_DIR=/app/data
RUN mkdir -p ${DATA_DIR}
EXPOSE 48080
ENTRYPOINT ["java", "-jar", "app.jar"]

24
docker/docker-compose.yml Normal file
View File

@@ -0,0 +1,24 @@
# 单容器运行:前端已打包进 JAR由 Spring Boot 统一提供静态资源与 API
# 构建:在项目根目录执行 docker compose -f docker/docker-compose.yml build
# 运行docker compose -f docker/docker-compose.yml up -d
services:
app:
build:
context: ..
dockerfile: docker/Dockerfile
image: ssh-manager:latest
container_name: ssh-manager
ports:
- "48080:48080"
environment:
- TZ=Asia/Shanghai
# 生产环境建议设置并挂载密钥
# - SSHMANAGER_ENCRYPTION_KEY=...
# - SSHMANAGER_JWT_SECRET=...
volumes:
- app-data:/app/data
restart: unless-stopped
volumes:
app-data:

61
docker/maven-settings.xml Normal file
View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
<mirrors>
<mirror>
<id>aliyun-central</id>
<name>Aliyun Maven Central</name>
<url>https://maven.aliyun.com/repository/central</url>
<mirrorOf>central</mirrorOf>
</mirror>
<mirror>
<id>aliyun-public</id>
<name>Aliyun Public</name>
<url>https://maven.aliyun.com/repository/public</url>
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
<profiles>
<profile>
<id>aliyun</id>
<repositories>
<repository>
<id>central</id>
<url>https://maven.aliyun.com/repository/central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</repository>
<repository>
<id>spring</id>
<url>https://maven.aliyun.com/repository/spring</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</repository>
<repository>
<id>spring-plugin</id>
<url>https://maven.aliyun.com/repository/spring-plugin</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>https://maven.aliyun.com/repository/central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-plugin</id>
<url>https://maven.aliyun.com/repository/spring-plugin</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>aliyun</activeProfile>
</activeProfiles>
</settings>

15
docker/start.sh Normal file
View File

@@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -e
# 脚本所在目录为 docker/,项目根目录为其上级
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"
echo ">>> 项目根目录: $ROOT"
echo ">>> 构建并启动..."
docker compose -f docker/docker-compose.yml build
docker compose -f docker/docker-compose.yml up -d
echo ""
echo ">>> 已启动。访问: http://localhost:48080"
echo ">>> 查看日志: docker compose -f docker/docker-compose.yml logs -f"