当前位置: 首页 > 知识库问答 >
问题:

Spring-boot-devols自动重启不工作

慕高格
2023-03-14

我有一个使用mvn构建的Spring Boot 2.25应用程序。根据本文件,我添加

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

从留档:

当DevTools监视类路径资源时,触发重启的唯一方法是更新类路径。导致类路径更新的方式取决于您正在使用的IDE。在Eclipse中,保存修改后的文件将导致类路径更新并触发重启。在IntelliJ IDEA中,构建项目(构建-

随着应用程序的运行,我尝试了一个简单的方法

touch /path/to/app.jar

希望应用程序重新启动,但什么也没发生。

好吧,也许它在做更聪明的事情。我修改了一些来源。java,重新编译。jar,并将其替换为运行。jar文件和。。。什么都没发生。

也来自文档

DevTools依赖于应用程序上下文的关闭钩子在重启期间关闭它。如果禁用了关闭挂钩(SpringApplication.SetRegisterShotDownhook(false)),它将无法正常工作。

我不会这么做的。

DevTools需要定制ApplicationContext使用的ResourceLoader。如果您的应用程序已经提供了一个,它将被包装。不支持对ApplicationContext直接重写getResource方法。

我不会这么做的。

我在Docker容器中运行这个,如果这很重要的话。从文件中:

当运行完全打包的应用程序时,开发人员工具会自动禁用。如果您的应用程序是从java-jar启动的,或者从特殊的类加载器启动的,那么它将被视为“生产应用程序”。如果这不适用于您(即,如果您从容器运行应用程序),请考虑排除devols或设置-Dspring.devtools.restart.enabled=false系统属性。

我不明白这意味着什么,也不知道这是否相关。

我想重新编译一个。jar并将其替换到正在运行的docker容器中,然后触发并重新启动应用程序,而无需重新启动容器。我该怎么做?

编辑:我正在使用mvn重建jar,然后docker cp在运行的容器中替换它。(IntelliJ IDEA声称要重建项目,但jar文件实际上没有被触及,但那是另一回事。)我正在寻找一个非特定于IDE的解决方案。

共有3个答案

杨凌
2023-03-14

我不是海岸,因为你没有明确地说如果你尝试了这些东西,但是:

>

  • 尝试将其设置为true:(SpringApplication.setRegisterShotDownhook(true))

    尝试在dockerfile中手动添加此属性-Dspring.devtools.restart.enabled=true

    我知道它说在默认情况下应该是真实的,但是试着手动做

    也许给我们看看文档。

    后期编辑:在文档中看到:

    默认情况下,重新打包的归档文件不包含devtools。如果要使用某些远程devtools功能,需要禁用excludeDevtools build属性以包含它。Maven和Gradle插件都支持该属性。

    Spring Boot开发者工具不仅限于本地开发。在远程运行应用程序时,还可以使用多种功能。远程支持是选择性加入,要启用它,您需要确保重新打包的存档中包含devtools:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludeDevtools>false</excludeDevtools>
                </configuration>
            </plugin>
        </plugins>
    </build>
    

    然后需要设置一个spring.devtools.remote.secret属性,例如:

    spring.devtools.remote.secret=mysecret
    

    远程devtools支持分两部分提供;有一个接受连接的服务器端endpoint和一个在IDE中运行的客户端应用程序。当spring启动时,服务器组件将自动启用。开发工具。遥远的设置了秘密属性。客户端组件必须手动启动。

    来自spring的文件

  • 虞华彩
    2023-03-14

    我有一个类似的问题,当使用intellij的想法,我看到的地方,你必须使用构建按钮的工作。

    在jsp中,应用程序重新加载文件并不是完全自动的,因为intellij会自动保存-

    仅适用于jsp应用程序,如果您尝试使用标准应用程序,它将创建双帧执行(摇摆)

    蔚和风
    2023-03-14

    Spring Boot开发工具为Spring Boot应用程序提供了通常在IntelliJ等IDE中可用的功能,例如,当某些类或资源更改时,您可以重新启动应用程序或强制实时浏览器重新加载。这在应用程序的开发阶段非常有用。

    它通常与IDE结合使用,这样当在类路径中检测到并且未禁用时,它将在Spring Boot之前与应用程序的其余部分一起启动。

    尽管您可以将其配置为监视更多资源,但它通常会查找应用程序代码、类和资源中的更改。

    很重要的一点是,开发工具将以分解的方式监控您自己的类和资源,我的意思是,如果覆盖整个应用程序jar,重启过程将不起作用,只有覆盖目录中的一些资源。

    这个功能可以用Maven测试。请考虑从Spring RealalIZR下载一个简单的蓝图,例如Spring Bug、Spring Boover DeVoices和Spring Web,以保持应用程序的运行。从终端,在包含pom的目录中。例如,在pom中包含的spring boot maven插件的帮助下运行应用程序。xml

    mvn spring-boot:run
    

    该命令将下载项目依赖项,编译并运行应用程序。

    现在,在您的源代码中执行任何修改,无论是在您的类中还是在您的资源中,然后从同一目录中的另一个终端重新编译您的资源:

    mvn compile
    

    如果查看第一个终端窗口,您将看到应用程序被重新启动以反映更改。

    如果您在应用程序部署中使用docker,尝试重现这种行为可能会很棘手。

    一方面,我不知道这是否合理,但您可以尝试创建一个基于maven的映像,并在其中运行代码,如上所述。您的Dockerfile可能与以下内容类似:

    FROM maven:3.5-jdk-8 as maven
    
    WORKDIR /app
    
    # Copy project pom
    COPY ./pom.xml ./pom.xml
    
    # Fetch (and cache) dependencies
    RUN mvn dependency:go-offline -B
    
    # Copy source files
    COPY ./src ./src
    
    # Run your application
    RUN mvn springboot:run
    

    使用此设置,您可以使用docker cp将资源复制到/app/目标目录,这将触发应用程序重新启动。作为替代方案,考虑在容器中安装一个卷,而不是使用docker cp

    更好的是,考虑到覆盖应用程序jar可能不起作用,您可以尝试复制类和库依赖项,并以分解的方式运行应用程序。考虑下面的<代码> DOCKFrase< /代码>:

    FROM maven:3.5-jdk-8 as maven
    
    WORKDIR /app
    
    # Copy your project pom
    COPY ./pom.xml ./pom.xml
    
    # Fetch (and cache) dependencies
    RUN mvn dependency:go-offline -B
    
    # Copy source files
    COPY ./src ./src
    
    # Compile application and library dependencies
    # The dependencies will, by default, be copied to target/dependency
    RUN mvn clean compile dependency:copy-dependencies -Dspring-boot.repackage.skip=true
    
    # Final run image (based on https://stackoverflow.com/questions/53691781/how-to-cache-maven-dependencies-in-docker)
    FROM openjdk:8u171-jre-alpine
    # OPTIONAL: copy dependencies so the thin jar won't need to re-download them
    # COPY --from=maven /root/.m2 /root/.m2
    
    # Change working directory
    WORKDIR /app
    
    # Copy classes from maven image
    COPY --from=maven /app/target/classes ./classes
    
    # Copy dependent libraries
    COPY --from=maven /app/target/dependency ./lib
    
    EXPOSE 8080
    
    # Please, modify your main class name as appropriate
    ENTRYPOINT ["java", "-cp", "/app/classes:/app/lib/*", "com.example.demo.DemoApplication"]
    

    Dockerfile中的重要一行是:

    mvn clean compile dependency:copy-dependencies -Dspring-boot.repackage.skip=true
    

    它将指导maven编译您的资源并复制所需的库。虽然在典型的Maven阶段,spring boot Maven插件重新打包目标运行时是多余的,但是标志spring boot。重新包装skip=true将指示此插件不要重新打包应用程序。

    使用此Dockerfile构建您的图像(例如,让我们将其标记为devtools demo):

    docker build -t devtools-demo .
    

    然后运行它:

    docker run devtools-demo:latest
    

    使用此设置,如果现在更改类和/或资源,并在本地运行mvn

    mvn compile
    

    您应该能够使用以下docker cp命令强制容器中的重启机制:

    docker cp classes <container name>:/app/classes
    

    请再次考虑在您的容器中安装一个卷,而不是使用<代码> DOCKPCP <代码>。

    我测试了设置,它工作正常。

    要记住的重要一点是替换爆炸式的资源,而不是整个应用程序jar。

    作为另一种选择,您可以采取类似于评论中指出的方法,并在远程模式下运行您的开发工具:

    FROM maven:3.5-jdk-8 as maven
    
    WORKDIR /app
    
    # Copy project pom
    COPY ./pom.xml ./pom.xml
    
    # Fetch (and cache) dependencies
    RUN mvn dependency:go-offline -B
    
    # Copy source files
    COPY ./src ./src
    
    # Build jar
    RUN mvn package && cp target/your-app-version.jar app.jar
    
    # Final run image (based on https://stackoverflow.com/questions/53691781/how-to-cache-maven-dependencies-in-docker)
    FROM openjdk:8u171-jre-alpine
    # OPTIONAL: copy dependencies so the thin jar won't need to re-download them
    # COPY --from=maven /root/.m2 /root/.m2
    
    # Change working directory
    WORKDIR /app
    
    # Copy artifact from the maven image
    COPY --from=maven /app/app.jar ./app.jar
    
    ENV JAVA_DOCKER_OPTS "-agentlib:jdwp=transport=dt_socket,server=y,address=*:8000,suspend=n"
    
    ENV JAVA_OPTS "-Dspring.devtools.restart.enabled=true"
    
    EXPOSE 8000
    
    EXPOSE 8080
    
    ENTRYPOINT ["/bin/bash", "-lc", "exec java $JAVA_DOCKER_OPTS $JAVA_OPTS -jar /app/app.jar"]
    

    为了让Spring Boot Devols远程模式正常工作,您需要几件事(Opri在他/她的回答中也指出了其中的一些)。

    首先,您需要配置spring boot maven插件,将devtools包含在您的应用程序jar中(默认情况下,它将被排除在外):

    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <configuration>
        <excludeDevtools>false</excludeDevtools>
      </configuration>
    </plugin>
    

    然后,需要为配置属性spring设置一个值。开发工具。遥远的秘密。此属性与Spring Boot Devtools中远程调试的工作方式有关。

    远程调试功能由两部分组成,一个客户端和一个服务器。基本上,客户机是服务器代码的副本,它使用spring的值。开发工具。遥远的secretconfiguration属性以针对服务器进行身份验证。

    该客户机代码应该从IDE运行,并将IDE调试过程附加到从该客户机公开的本地服务器。

    记住,在客户机监控的资源中执行的每一项更改都会被推送到远程服务器,并在必要时触发重新启动。

    如您所见,从开发的角度来看,此功能再次更合适。

    如果需要通过覆盖jar应用程序文件来重新启动应用程序,那么更好的方法可能是将docker容器配置为在ENTRYPOINTCMD中运行shell脚本。这个shell脚本将监视特定目录中的jar副本。如果由于您的docker cp,该资源发生了变化,那么这个shell脚本将停止当前正在运行的应用程序版本——该应用程序应该从不同的位置运行,以避免更新jar时出现问题——用新的jar替换当前jar,然后启动新的应用程序版本。不一样,但请考虑阅读相关的答案。

    在任何情况下,当您在容器中运行应用程序时,您都在尝试为其提供一致且独立于平台的部署方式。从这个角度来看,与监视docker容器中的更改不同,更方便的方法可能是生成并部署具有这些新更改的容器映像的新版本。使用Jenkins、Travis等工具,这个过程可以大大自动化。这些工具允许您定义CI/CD管道,例如,为了响应代码提交,这些管道可以使用您的代码动态生成docker映像,并相应地进行配置,稍后将该映像部署到docker flavor或Kubernetes等服务、内部部署或云中。其中一些,尤其是Kubernetes,但swarm甚至还有docker compose,将允许您在不中断应用程序服务的情况下执行滚动更新。

    总之,它可能不适合您的需要,但请注意,您可以直接使用spring boot starter actuator,或者与spring boot Admin一起重新启动应用程序。

    最后,正如Spring Boot Devtools文档中已经指出的,您可以在热交换中尝试不同的选项,不是基于重启,而是基于应用程序重新加载。这种功能由JRebel等商业产品提供,不过也有一些开源的替代品,主要是dcevm和HotswapAgent。这篇相关的文章提供了关于最后两个产品如何工作的一些见解。这个Github项目提供了关于如何在docker容器中运行它的补充信息。

     类似资料:
    • 我在网上看了很多关于< code > spring-boot-dev tools 的文章和问题,但是仍然不明白为什么它对我不起作用。每次运行我的应用程序,我都会得到以下信息: 每当我更改其中一个控制器文件时,什么也没发生。所以我遇到了一篇文章,提到我应该尝试将添加到我的应用程序属性文件中。使用 src 将不起作用,因为它会认为这是一个绝对路径,所以我将其更改为 。完成此操作后,将新endpoint

    • 我正在尝试重新开始使用Spring Boot开发工具。我一直遵循此处提供的说明:https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html 我正在使用gradle,并将其包含在我的build.gradle文件中: 我创建jar文件并运行jar文件: 我能够通过Intellij连接到正

    • 我正在使用最新的spring boot版本,我正在尝试设置一个应用程序,但我想禁用数据源配置。我的配置类如下所示: 但当我运行应用程序时,我会得到以下堆栈跟踪: 我的配置中是否缺少任何东西来完全禁用数据源配置?我将手动设置数据源,所以我不希望Spring为我处理这个问题。

    • 我遵循这篇指南https://medium.com/@lhartikk/development-environment-in-spring-boot-with-docker-734ad6c50b34,尝试在本地docker容器中使用我的简单Spring Boot应用程序实现自动重启、实时重新加载和远程调试。触发自动重新启动时出现错误: DockerFile:

    • 此链接中的信息也无济于事:https://dzone.com/articles/spring-boot-application-live-reload-hot-swap-with

    • 我最近开始使用,发现它非常有趣。由于我的大多数应用程序都在中,我决定使用团队提供的spring boot starter项目进行快速设置。它附带了autoconf-spring设置,这使得查询endpoint更加容易。 在IDEA中花了几个小时进行项目设置后,我能够运行graphql示例应用程序。但我认为我的servlet仍然没有启用,只有endpoint正在运行,因为默认查询返回。 这是: 这就