您的位置:首页 > 编程语言 > Java开发

Spring Boot参考文档(12)开发者工具

2017-05-12 16:18 190 查看
原文链接:http://www.dubby.cn/detail.html?id=8725

Spring Boot包含一些额外的工具,让我们在开发时可以更愉快一些。项目中可以加入
spring-boot-devtools
模块,为我们的应用带来一些额外的开发时功能。为了添加这个devtools功能,我们需要先添加依赖:

Maven

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


Gradle

dependencies {
compile("org.springframework.boot:spring-boot-devtools")
}


当你运行一个打包成jar的应用时,开发工具的功能会自动禁止。如果你的应用以
java -jar
命令启动,那么Spring Boot认为这是一个生产环境的应用。把devtools标志位optional(可选的)是一个最佳实践,这样可以防止其他项目依赖你的项目是也用到了devtools。Gradle不支持optional,所以你或许要参考propdeps-plugin

默认情况下打包时是不会包含devtools的。如果你希望使用某个特定的远程功能,你需要自己去关闭
excludeDevtools
属性,来包含devtools。这个属性对Maven和Gradle都是支持的。

默认属性

Spring Boot支持的很多库都使用cache来提高性能。例如,模板引擎会缓存编译过的模板,来避免重复的转换文件。同样的,对于静态文件,Spring MVC可以缓存HTTP返回给response的headers。

虽然在生产环境中缓存有很多好处,但是在开发时却有可能起反作用。例如,不能及时的看到你的一些代码变动。所以,spring-boot-devtools默认是关闭缓存功能的。

缓存配置通常是在
application.properties
配置的。例如,Thymeleaf 有
spring.thymeleaf.cache
属性。不需要手动的设置这些属性配置,
spring-boot-devtools
会自动给我做出合适的配置。

想要获得一个完整的属性列表,参考DevToolsPropertyDefaultsPostProcessor

自动化(无意识)重启

应用如果使用了
spring-boot-devtools
,那么当classpath中的class发生改变时,他会自动重启。这个功能是很有用的,因为我们在使用IDE编写代码时,可以很快的得到一个反馈。默认情况下,classpath中任何一个入口都意味着,对这个文件夹的改变有一个的监控。注意,静态文件和视图模板的改变不需要重启应用。

触发重启

当DevTools监控classpath的资源时,只有classpath发生改变时,才会触发重启。你的IDE会做到这一点。在Eclipse中,保存一个改变的文件会导致重新编译成一个class,这会触发重启。在IntelliJ IDEA中,构建(
Build -> Make Project
)也会起到同样的效果。

通过Maven和Gradle的插件启动时,只要你的classpath中包含DevTools,也会触发重启。

自动重启可以和LiveReload搭配使用。但是如果你使用的是JRebel ,那么自动重启就会失效。

在重启时,DevTools依赖于应用的shutdown hook(译者注:hook是钩子,变成常见的一种概念)。如果你禁用了shutdown hook(
SpringApplication.setRegisterShutdownHook(false)
),那么重启也会失效了。

在监控classpath改变时,DevTools会自动忽略这几个项目
spring-boot
,
spring-boot-devtools
,
spring-boot-autoconfigure
,
spring-boot-actuator
, 和
spring-boot-starter


Restart vs Reload

Spring Boot提供的重启技术,是使用两个classloader实现的。一些不变得class(例如第三方库)会被一个”基本classloader”加载。那些你直接开发的class会被”重启classloader”加载。当应用重启时,这个”重启classloader”会被销毁,然后重新创建一个”重启classloader”。这种方式可以让重启变得比”冷重启”快很多,因为第三方的”基本classloader”是已经存在的。

如果你发现重启不是快到让你满意,甚至起了反作用,那你可以考虑使用reload技术,例如JRebel。当reload时,会重写class保证可以reload。Spring Loader提供了另外一种选择,但是,很多框架并不支持,而且也没有商业支持。

除外的资源

某些特定的资源的改变不会触发重启。例如,Thymeleaf 模板可以实时编辑替换。默认情况下,
/META-INF/maven
,
/META-INF/resources
,
/resources ,/static
,
/public
/templates
都不会触发重启。如果你想自动以这些除外的资源,你可以设置
spring.devtools.restart.exclude
属性。例如,为了除外
/static
/public
,你可以这么设置:

spring.devtools.restart.exclude=static/**,public/**


如果你希望保留默认的除外列表,只是新家除外列表,你可以使用
spring.devtools.restart.additional-exclude
属性。

监控额外的文件

或许,你希望当你改变某个不在classpath的文件时,你的项目可以重启。你可以设置
spring.devtools.restart.additional-paths
来设置你希望监控的额外的路径。

禁止重启

如果你不想要重启这个功能,你可以设置
spring.devtools.restart.enabled
属性。大部分情况下,你可以在
application.properties
里设置这个属性(这个也会启动一个”重启classloader”,但是不会监控文件的改变了)。

如果你希望完全禁止重启,例如,他对某个特定的库不支持,你需要在调用
SpringApplication.run(…)
前设置一个
System
属性:

public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(MyApp.class, args);
}


使用一个触发文件

如果你使用的时IDE,那你有可能无时无刻不在重启。也许你只想要在某个特定的时间重启。这样你可以使用”触发文件”,当你改变这个文件时,就会触发重启。改变这个文件只会让触发器查看是不是真的有必要重启,如果不得不重启,那”重启classloader”就会真的重启。这个触发文件你可以手动修改,也可以通过IDE插件修改。

为了使用触发文件,你需要设置
spring.devtools.restart.trigger-file
属性。

你可以把
spring.devtools.restart.trigger-file
设置成全局属性,这样你所有的项目都会监控一个文件了。

自定义 “重启classloader”

上面介绍了重启的实现,我们知道重启依赖两个classloader。大部分情况下,这可以很好的工作,但是有的时候,这个歌会引发classloader的问题。

默认情况下,所有的你的项目打开的文件都会使用”重启classloader”来加载,任何
.jar
都会用”基本classloader”加载。如果你在多module项目下工作过,并不是每一个module都会被你的项目使用,这种情况下,你需要自己来自定义些东西,来使得重启更为高效。你可以创建
META-INF/spring-devtools.properties
文件。

META-INF/spring-devtools.properties
文件可以包含以
restart.exclude.
restart.include.
为前缀的属性。
include
是那些应该被拉进”重启classloader”的类,
exclude
指的是那些不会被拉进”重启classloader”的类。之是正则表达式。

例如:

restart.exclude.companycommonlibs=/mycorp-common-[\\w-]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w-]+\.jar


所有属性的key必须是唯一的。只要属性的前缀是
restart.include.
或者
restart.exclude.
就都会被处理。

classpath下所有的
META-INF/spring-devtools.properties
都会被加载。你可以在你的项目内部打包,或者其他项目依赖你的项目打包,都可以生效。

已知的局限性

重启机制对于那些被
ObjectInputStream
反序列化的对象是无能为力的。如果你需要反序列化对象,你或许可以尝试使用
ConfigurableObjectInputStream
Thread.currentThread().getContextClassLoader()
配合使用。

不幸的是,有的第三方库直接反序列化的,而不考虑classloader。如果你发现这个问题,你需要去通知作者来fix这个问题。

LiveReload

spring-boot-devtools
包含一个LiveReload服务器(修改源码后,帮你刷新浏览器),帮你触发重启后刷新浏览器,支持Chrome。Firefox和Safari。

如果你不想要这个LiveReload服务器,你可以设置
spring.devtools.livereload.enabled
为false。

一次只能运行一个LiveReload服务器。在启动应用时,确保没有其他的项目在使用LiveReload服务器。如果你用IDE启动多个项目,那么只有第一个的LiveReload服务器会生效。

全局设置

你可以在你的
$HOME
目录下添加
.spring-boot-devtools.properties
文件来实现全局设置。这个文件里的任何属性都会被应用到这个机器上的所有开启了devtools的Spring Boot应用。例如,设置一个触发重启的文件,你可以这样修改:

~/.spring-boot-devtools.properties

spring.devtools.reload.trigger-file=.reloadtrigger


远程应用

Spring Boot的开发者工具不仅仅局限于本地开发。你也可以应用在远程应用上。远程应用是可选的。如果你想开启,你需要把
devtools
的包加到你的打包的jar中:

<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


开启远程开发功能是有风险的。永远不要在一个真正的生产机器上这么用。

远程应用支持两个方面的功能;一个是服务端,一个是客户端。只要你设置了
spring.devtools.remote.secret
,服务端就会自动开启。客户端需要你手动来开启。

运行远程应用的客户端

远程应用的客户端被设计成在你的IDE中运行。你需要在拥有和你的远程应用相同的classpath的前提下,运行
org.springframework.boot.devtools.RemoteSpringApplication
。这个application的参数就是你要连接的远程应用的URL。

例如,如果你用的是Eclipse或者STS,你有一个项目叫
my-app
,你已经部署在云平台上了,你需要这么做:

Run
菜单选择
Run Configurations…


创建一个
Java Application
的启动配置

使用
org.springframework.boot.devtools.RemoteSpringApplication
作为启动类

https://myapp.cfapps.io
作为程序的参数(这个URL是你真正的URL)

一个启动的远程应用是这样的:

.   ____          _                                              __ _ _
/\\ / ___'_ __ _ _(_)_ __  __ _          ___               _      \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` |        | _ \___ _ __  ___| |_ ___ \ \ \ \
\\/  ___)| |_)| | | | | || (_| []::::::[]   / -_) '  \/ _ \  _/ -_) ) ) ) )
'  |____| .__|_| |_|_| |_\__, |        |_|_\___|_|_|_\___/\__\___|/ / / /
=========|_|==============|___/===================================/_/_/_/
:: Spring Boot Remote :: 1.5.3.RELEASE

2015-06-10 18:25:06.632  INFO 14938 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Starting RemoteSpringApplication on pwmbp with PID 14938 (/Users/pwebb/projects/spring-boot/code/spring-boot-devtools/target/classes started by pwebb in /Users/pwebb/projects/spring-boot/code/spring-boot-samples/spring-boot-sample-devtools)
2015-06-10 18:25:06.671  INFO 14938 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2a17b7b6: startup date [Wed Jun 10 18:25:06 PDT 2015]; root of context hierarchy
2015-06-10 18:25:07.043  WARN 14938 --- [           main] o.s.b.d.r.c.RemoteClientConfiguration    : The connection to http://localhost:8080 is insecure. You should use a URL starting with 'https://'.
2015-06-10 18:25:07.074  INFO 14938 --- [           main] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2015-06-10 18:25:07.130  INFO 14938 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Started RemoteSpringApplication in 0.74 seconds (JVM running for 1.105)


因为classpath是一样的,所以可以直接读取真实的配置属性。这就是
spring.devtools.remote.secret
发挥作用的时候了,Spring Boot会用这个来认证。

建议使用
https://
来连接,这样密码会被加密,不会被拦截。

如果你有一个代理服务器,你需要设置
spring.devtools.remote.proxy.host
spring.devtools.remote.proxy.port
这两个属性。

远程更新

客户端会监控你的classpath,和本地重启的监控一样。任何资源更新都会被推送到远程服务器上,远程应用再判断是否触发了重启。如果你在一个云服务器上做迭代,这样会很有用。一般来说,字节更新远程应用,会比你本地打包再发布要快狠多。

资源监控的前提是你启动了本地客户端,如果你在启动之前修改了文件,这个变化是不会推送到远程应用的。

远程debug通道

在定位和解决问题时,Java远程调试是很有用的。不幸的是,如果你的应用部署在异地,远程debug往往不是很容易实现。而且,如果你使用了类似Docker的容器,也会给远程debug增加难度。

为了解决这么多困难,Spring Boot支持在HTTP层面的debug通道。远程应用汇提供
8000
端口来作为debug端口。一旦连接建立,debug信号就会通过HTTP传输给远程服务器。你可以设置
spring.devtools.remote.debug.local-port
来改变默认端口。

你需要首先确保你的远程应用启动时已经开启了debug模式。一般来说,可以设置
JAVA_OPTS
。例如,如果你使用的是Cloud Foundry你可以在
manifest.yml
加入:

---
env:
JAVA_OPTS: "-Xdebug -Xrunjdwp:server=y,transport=dt_socket,suspend=n"


注意,没有必要给
-Xrunjdwp
加上
address=NNNN
的配置。如果不配置,Java会随机选择一个空闲的端口。

远程debug是很慢的,所以你最好设置好debug的超时时间(一般来说60000是足够了)。

如果你使用IntelliJ IDEA来调试远程应用,你一定要把所有断点设置成悬挂线程,而不是悬挂JVM。默认情况,IDEA是悬挂JVM的。这个会造成很大的影响,因为你的session会被冻结。参考IDEA-165769
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring-boot