You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Docker Compose运行的Maven多模块项目中使用Spring Dev Tools热重载

Spring Boot多模块Maven项目Docker化后无法实现DevTools热重载

项目背景

我有一个Spring Boot、Maven多模块项目,通过Docker Compose运行,项目能正常启动,但Spring Dev Tools热重载功能失效。

项目结构

my-service
- api (子模块)
- domain (子模块)
- entity (子模块)
- graphql (主模块)
- repository (子模块)

当前Dockerfile配置

FROM openjdk:21-jdk-slim as dependencies

WORKDIR /app
COPY . .

RUN ./mvnw dependency:go-offline

FROM dependencies as build

RUN ./mvnw package spring-boot:repackage

FROM openjdk:21-jdk-slim as runtime

COPY --from=build /app/graphql/target/graphql-0.0.1-SNAPSHOT.jar /app/graphql/target/
EXPOSE 8080
CMD ["java", "-jar", "/app/graphql/target/graphql-0.0.1-SNAPSHOT.jar"]

FROM openjdk:21-jdk-slim as debug

COPY --from=build /app/graphql/target/graphql-0.0.1-SNAPSHOT.jar /app/graphql/target/
EXPOSE 5006
CMD ["java", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5006", "-jar", "/app/graphql/target/graphql-0.0.1-SNAPSHOT.jar"]

docker-compose.yml配置

version: "3.8"

services:
  my-service:
    build:
      context: .
      target: debug
    environment:
      - SPRING_PROFILES_ACTIVE=local
    volumes:
      - "~/.m2:/root/.m2"
      - ".:/app"
    ports:
      - "8080:8080"
      - "5050:5006"

遇到的问题

尝试配置热重载后,启动服务发送GraphQL查询时,持续出现类加载器冲突错误:

my-service-1  | java.lang.ClassCastException: class com.example.myservice.repository.MyClass cannot be cast to class com.example.myservice.repository.MyClass (com.example.myservice.repository.MyClass is in unnamed module of loader 'app'; com.example.myservice.repository.MyClass is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @3bbdbc95)

解决方案

1. 调整Docker镜像,改用spring-boot:run启动而非打包Jar

当前Dockerfile先打包成Jar再运行,DevTools热重载需要实时编译的类文件,而非打包后的Jar。修改Dockerfile的debug阶段:

FROM openjdk:21-jdk-slim as dependencies

WORKDIR /app
COPY . .

RUN ./mvnw dependency:go-offline

FROM dependencies as debug
EXPOSE 8080
EXPOSE 5006
CMD ["./mvnw", "-pl", "graphql", "spring-boot:run", "-Dspring-boot.run.jvmArguments='-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5006'"]
  • -pl graphql指定只运行主模块,避免编译所有子模块浪费时间
  • 直接用spring-boot:run启动,DevTools可实时监测类文件变化

2. 配置Spring DevTools重启策略

在主模块graphql的src/main/resources/application-local.properties中添加:

# 开启自动重启
spring.devtools.restart.enabled=true
# 指定需要监测变化的子模块源码路径
spring.devtools.restart.additional-paths=../api/src/main/java,../domain/src/main/java,../entity/src/main/java,../repository/src/main/java
# 排除无需监测的静态资源目录
spring.devtools.restart.exclude=static/**,public/**
# 禁用模板缓存,确保资源实时生效
spring.thymeleaf.cache=false
spring.freemarker.cache=false

3. 解决类加载器冲突

类转换异常是因为同一个类被两个不同类加载器加载,需确保子模块类被RestartClassLoader统一加载:
在主模块graphql的src/main/resources/META-INF/spring-devtools.properties中添加:

# 指定需要被RestartClassLoader加载的子模块Jar包
restart.include.api=/api-.+\\.jar
restart.include.domain=/domain-.+\\.jar
restart.include.entity=/entity-.+\\.jar
restart.include.repository=/repository-.+\\.jar

4. 调整Docker Compose挂载配置

确保本地代码修改实时同步到容器,同时避免本地无target目录时覆盖容器内编译产物:

version: "3.8"

services:
  my-service:
    build:
      context: .
      target: debug
    environment:
      - SPRING_PROFILES_ACTIVE=local
      - MAVEN_OPTS=-Dspring.devtools.restart.enabled=true
    volumes:
      - "~/.m2:/root/.m2"
      - ".:/app"
      # 隔离容器内的target目录,避免本地覆盖
      - /app/graphql/target
      - /app/api/target
      - /app/domain/target
      - /app/entity/target
      - /app/repository/target
    ports:
      - "8080:8080"
      - "5050:5006"

5. 验证热重载

启动容器后,修改任意子模块的Java代码,等待容器内Maven自动编译,DevTools会触发应用重启,之后验证接口是否生效。

内容的提问来源于stack exchange,提问作者user3067870

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 09:06:01