Springboot - DevTools - 在重建项目时并不总是映射RestController

时间:2016-08-18 13:48:26

标签: spring maven intellij-idea spring-boot

我正在使用带有maven的SpringBoot 1.3.5。

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

和devtools

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

我正在使用2014年之前的Intellij IDEA 2016.2同样的问题。

我正在从Intellij Idea运行我的springboot应用程序,首先启动一切都很好并且可以工作,我可以访问我的静态页面和我的2个Rest Controller工作。

2016-08-18 15:27:58.771  INFO 26626 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@469d0c02: startup date [Thu Aug 18 15:27:57 CEST 2016]; root of context hierarchy
2016-08-18 15:27:58.789  INFO 26626 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/authentication/introspect],methods=[GET]}" onto public com.myapp.models.TokenIntrospection com.myapp.resources.AuthenticationResources.introspectToken(java.lang.String)
2016-08-18 15:27:58.790  INFO 26626 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/configuration],methods=[GET]}" onto public com.myapp.models.AppConfiguration com.myapp.resources.ConfigurationResources.getConfiguration()
2016-08-18 15:27:58.792  INFO 26626 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" 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)
2016-08-18 15:27:58.793  INFO 26626 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)

因为简单的“Make Project”不能很好地用于静态重载,我使用“Rebuild Project”,有时候,当app重启时,我没有映射我的控制器,有时会丢失一个,有时两个都丢失了。

我对此没有任何线索:(

修改

@Morfic解决方案不起作用,因此我使用Intellij本地服务器来提供静态内容和gulp-livereload而不是spring-dev-tools。

IJ local server

当我处于开发模式时,我只需要在JS中管理REST调用,因为REST资源在localhost:8080上,但是我在localhost上的静态:63342,并在我的springboot中启用CORS(在属性文件中使用标志启用CORS与否)。

@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {

    @Value("${cors.enabled}")
    private boolean corsEnabled;

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        super.addCorsMappings(registry);
        if(corsEnabled) {
            registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowedMethods("GET", "PUT", "POST", "DELETE", "OPTIONS")
                    .allowedHeaders("Origin", "X-Requested-With", "Content-Type", "Accept", "Authorization")
                    .allowCredentials(true)
                    .maxAge(3600L);
        }
    }
}

所以问题仍然悬而未决。

2 个答案:

答案 0 :(得分:7)

我只是设法用一个简单的hello-world服务重复这个并使用Rebuild project几次,因为它只会偶尔复制一次。我的预感是开发工具找出了在IJ有机会完全清理之前发生的变化。重建。可能一旦资源被发布,并且在从我看到的输出目录编译类之前,dev-tools开始重新加载尚未出现的类 ...

在这个假设之后,我查看了日志和类时间戳,并且dev-tools开始重新加载上下文的时间与我的类写入磁盘的时间之间存在大约1s的差距。显然我的@PostConstruct日志都没有出现,而且spring的autoconfig找不到我的课程......

作为解决方法,您可以使用trigger-file。根据链接或application.properties文件中的建议,将其添加为home-dir中的全局配置。此外,由于对此文件的任何更改(创建,删除,修改)都会触发重新启动,并且Rebuild project清除输出目录,因此您必须定义一个额外的路径来查找此文件。因此,假设我们有一个常规的IJ spring boot运行配置,application.properties中有以下2个:

# name of the file to trigger a restart
spring.devtools.restart.trigger-file=restarttrigger

# where else to look for it. Also . evaluates to the app's base dir
spring.devtools.restart.additional-paths=.

...一旦你看到IJ完成构建过程,转到app root dir并添加或删除你的触发器文件,具体取决于它是否已经存在,这将导致重启。我已经测试了几次,没有尝试到目前为止失败。下面是手动重启过程的简短视频演示:

IJ - boot dev tools manual restart

有几种方法可以自动执行此过程。除了在IJ中定义一个人工制品并使用后期处理ant任务来生成文件之外,你可以使用maven(你已经在使用它)来生成这样一个文件,但缺点是你必须使用{{1}而不是maven compile,因为IJ在进行重建时不会调用maven(或者我还没有发现如何做到这一点)。请在下面找到一个简单的配置based on the fact that

  

(注意:在Maven 2.0.5及更高版本中,绑定到阶段的多个目标的执行顺序与它们在POM中声明的顺序相同,但不支持同一插件的多个实例。插件被分组以一起执行并在Maven 2.0.11及更高版本中进行排序。

因此,the compiler plugin is by default bound to the compile phase,我们添加了一个小任务,使用Rebuild project文件(或其他任何内容)生成trigger-file

application.properties

进一步更新:

查看FileSystemWatcher.scan()的来源,有一个<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <!-- first, compile all we need --> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> </plugin> <plugin> <!-- then, generate the trigger-file so dev-tools will restart --> <artifactId>maven-antrun-plugin</artifactId> <version>1.8</version> <executions> <execution> <phase>compile</phase> <configuration> <tasks> <copy file="${project.basedir}/src/main/resources/application.properties" toFile="${project.basedir}/restarttrigger" overwrite="true" /> </tasks> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> </plugin> </plugins> </build> 循环,可以解释为:,而自上次检查后文件系统上仍有变化,等待(可配置的时间并再次验证

do-while

根据documentationprivate void scan() throws InterruptedException { Thread.sleep(this.pollInterval - this.quietPeriod); Map<File, FolderSnapshot> previous; Map<File, FolderSnapshot> current = this.folders; do { previous = current; current = getCurrentSnapshots(); Thread.sleep(this.quietPeriod); } while (isDifferent(previous, current)); if (isDifferent(this.folders, current)) { updateSnapshots(current.values()); } } 可以通过quietPeriod属性配置,但根据上面提到的来源,它必须是小于spring.devtools.restart.quiet-period的值可通过pollInterval配置。因此,玩弄设置,我得到了一个不错的结果:

spring.devtools.restart.poll-interval

最后,您应该能够将这些值调整到最适合您的值。

尽管如此,如果您要修改的源是静态资源(如FE GUI页面)并且根据您的要求,可能最好使用从其位置为其提供服务的工具,例如节点或类似的简单http服务器。 ..

答案 1 :(得分:0)

@ Morfic的这部分答案对我很有帮助:

# Amount of time (in milliseconds) to wait between polling for classpath changes.
spring.devtools.restart.poll-interval=3000

# Amount of quiet time (in milliseconds) required without any classpath changes before a restart is triggered.
spring.devtools.restart.quiet-period=2999