Spring Boot、Spring Loaded、Eclipse、Maven 基本示例

Posted

技术标签:

【中文标题】Spring Boot、Spring Loaded、Eclipse、Maven 基本示例【英文标题】:Spring Boot, Spring Loaded, Eclipse, Maven basic example 【发布时间】:2015-02-27 09:56:37 【问题描述】:

根据文档,我发现带有 Spring Loaded 的 Spring Boot 的基本示例设置不起作用。我按照http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#getting-started-first-application 的说明创建了一个基本应用程序,唯一的区别是我将我的类放入了一个包中,并使用了父 pom 的发布版本。应用程序工作正常。然后我按照文档中的描述将弹簧加载到 pom 文件中。

我使用 mvn spring-boot:run 运行应用程序。

更改我的控制器输出,例如“Hello World”到“Hello me”不会热重载。

我尝试使用其他地方描述的 javaagent 命令行参数作为 java 应用程序运行,但这也不起作用。

pom 看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>myproject</artifactId>
<version>0.0.1-SNAPSHOT</version>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.2.0.RELEASE</version>
</parent>

<!-- Additional lines to be added here... -->
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <dependencies>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>springloaded</artifactId>
                    <version>1.2.1.RELEASE</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

在这里可以找到编译的类:project_dir\target\classes(我使用的是 Eclipse 和 m2e 插件)。

启动日志:

[INFO] Scanning for projects...
[INFO] 
[INFO] Using the builder org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder with a thread count of 1
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building myproject 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] >>> spring-boot-maven-plugin:1.2.0.RELEASE:run (default-cli) @ myproject >>>
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ myproject ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ myproject ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\dev\src\scrapi\target\classes
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ myproject ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\dev\src\scrapi\src\test\resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ myproject ---
[INFO] No sources to compile
[INFO] 
[INFO] <<< spring-boot-maven-plugin:1.2.0.RELEASE:run (default-cli) @ myproject <<<
[INFO] 
[INFO] --- spring-boot-maven-plugin:1.2.0.RELEASE:run (default-cli) @ myproject ---

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.2.0.RELEASE)

2015-01-02 13:23:25.311  INFO 2180 --- [.Example.main()] first.Example                            : Starting Example on DEFRAVD804016 with PID 2180 (C:\dev\src\scrapi\target\classes started by john in C:\dev\src\scrapi)
2015-01-02 13:23:25.359  INFO 2180 --- [.Example.main()] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@44354005: startup date [Fri Jan 02 13:23:25 CET 2015]; root of context hierarchy
2015-01-02 13:23:26.193  INFO 2180 --- [.Example.main()] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'beanNameViewResolver': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]]
2015-01-02 13:23:27.121  INFO 2180 --- [.Example.main()] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8182/http
2015-01-02 13:23:27.689  INFO 2180 --- [.Example.main()] o.apache.catalina.core.StandardService   : Starting service Tomcat
2015-01-02 13:23:27.691  INFO 2180 --- [.Example.main()] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.0.15
2015-01-02 13:23:27.814  INFO 2180 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2015-01-02 13:23:27.814  INFO 2180 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 2457 ms
2015-01-02 13:23:28.653  INFO 2180 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2015-01-02 13:23:28.657  INFO 2180 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2015-01-02 13:23:28.657  INFO 2180 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'characterEncodingFilter' to: [/*]
2015-01-02 13:23:28.883  INFO 2180 --- [.Example.main()] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@44354005: startup date [Fri Jan 02 13:23:25 CET 2015]; root of context hierarchy
2015-01-02 13:23:28.995  INFO 2180 --- [.Example.main()] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "[/],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]" onto java.lang.String first.Example.home()
2015-01-02 13:23:28.997  INFO 2180 --- [.Example.main()] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "[/error],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2015-01-02 13:23:28.998  INFO 2180 --- [.Example.main()] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "[/error],methods=[],params=[],headers=[],consumes=[],produces=[text/html],custom=[]" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest)
2015-01-02 13:23:29.112  INFO 2180 --- [.Example.main()] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-01-02 13:23:29.112  INFO 2180 --- [.Example.main()] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-01-02 13:23:29.160  INFO 2180 --- [.Example.main()] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-01-02 13:23:29.268  INFO 2180 --- [.Example.main()] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2015-01-02 13:23:29.394  INFO 2180 --- [.Example.main()] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8182/http
2015-01-02 13:23:29.399  INFO 2180 --- [.Example.main()] first.Example                            : Started Example in 4.417 seconds (JVM running for 11.803)

在这种情况下,我需要做什么才能使 Spring Loaded 工作?

【问题讨论】:

确保更改类时已编译该类并将其复制到目标目录(通常是 Eclipse 的默认目录,但请检查您的项目设置是否为“自动构建”)。 @DaveSyer 是的,“自动构建”已打开,当我保存时,目标/类下的类的时间戳会更新。但没有热重载。 您是否看到在应用程序启动时将代理添加到日志中?我假设控制器在更改之前正在工作? 感谢@DaveSyer 的帮助。是的,控制器工作正常。不,我没有在日志中看到代理。我已编辑问题以包含启动日志。 我可以看到日志丢失了。就像您没有使用您发布的 pom 一样(Eclipse 玩花样?)。在命令行上为我工作。你试过了吗? 【参考方案1】:

我从来没有以这种方式加载弹簧。就个人而言,我使用每次都对我有用的“旧方式”。请尝试遵循:

在 Eclipse 中打开运行/调试配置。

在左侧展开 Java 应用程序选项并选择您的运行配置。 App 就我而言。设置错误是常见的错误配置,请确保projectmain class正确。

编辑VM arguments 并将其设置为-javaagent:&lt;spring_loaded_jar_file_path&gt; -noverify。如果您没有本地弹簧加载,最简单的获取方法是checkout their official repo 并运行./gradlew

包含一个 gradle 构建脚本,运行“./gradlew build”来重建代理 - 它将被创建为类似:springloaded/build/libs/springloaded-1.1.5.BUILD-SNAPSHOT.jar

现在您可以启动您的新配置。在浏览器中检查之前,请检查您在 eclipse 中的配置。右键单击您的 java 应用程序并选择属性。

然后您应该看到您的应用程序正在使用 javaagent 运行。

如果这对您有用,请告诉我们。

【讨论】:

【参考方案2】:

好的,我至少有一个偶然发现的解决方法。希望这将帮助某人弄清楚到底发生了什么。总结:在 pom 中配置调试器时,它可以工作。

我想启用调试,所以我按照in the plugin doco 的描述在 pom 中添加了以下内容:

<configuration>
  <jvmArguments>
    -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005
  </jvmArguments>
</configuration>

然后我重新启动了应用程序,你瞧,我在 spring 徽标之前的日志中得到了这个:

[INFO] Attaching agents: [C:\dev\maven_local\org\springframework\springloade
d\1.2.1.RELEASE\springloaded-1.2.1.RELEASE.jar]
Listening for transport dt_socket at address: 5005

启动然后停止,应用程序在附加调试器之前不会开始为请求提供服务(这是正常的吗?编辑:重新阅读我链接到的页面,我发现这是预期的。如果有是一种启动方式,无需附加调试器,但保持调试端口打开)。一旦附加了调试器,就会出现 Spring 徽标和其余的启动日志。然后我分离调试器(只是为了证明重新加载不是通过调试器),应用程序继续服务请求,果然,热重新加载工作!

非常感谢@DaveSyer 帮助放弃了其他各种可能性。暂时可以这样做,但由于没有记录,我猜这个要求不是设计使然,如果它在所有情况下都能正常工作,那就太棒了。

【讨论】:

我只能认为windows平台有点奇怪。顺便说一句,是 suspend=y 使 JVM 在启动时暂停。 嗯,我想是的。但是你会认为会有更多的人抱怨。哦,好吧,让我们看看它是否更频繁地出现。感谢您的暂停提示 - 是的,它适用于 suspend=n。【参考方案3】:

尝试将Spring Loaded 添加为Spring Boot Maven 插件的依赖项:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <dependencies>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>springloaded</artifactId>
                    <version>$spring-loaded.version</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

我用一个简单的Spring Cloud 应用程序运行Spring Loaded

【讨论】:

我不明白 - 我认为我在问题中包含的代码表明我已经这样做了。 这可行,但在 Mac OS X 上,当我停止控制台时服务器不会停止。我必须手动杀死它。

以上是关于Spring Boot、Spring Loaded、Eclipse、Maven 基本示例的主要内容,如果未能解决你的问题,请参考以下文章

Spring Loaded is a JVM agent for reloading class file changes

spring-boot 热加载实现替换Jrebel

spring-boot与springloaded进行热部署

spring boot 使用 springloaded 在 gradle 中没有工作

未加载 Spring Boot 测试 H2 sql 脚本

如何使用 Kotlin、Gradle 和 Web 框架设置 Spring Loaded?