16.md 18.5 KB
Newer Older
W
mkdocs  
wizardforcel 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
# 20\. 开发工具

Spring Boot包括一组额外的工具,可以使应用程序开发体验更加愉快。 spring-boot-devtools模块可以包含在任何项目中,以提供额外的[开发时](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/development-time)功能。 要包含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")
}
```

> 当运行完全打包的应用程序时,开发人员工具将自动禁用。 如果您的应用程序是使用java -jar启动的,或者是使用特殊的类加载器启动,那么它将会被认为是“生产环境的应用程序”。 将开发工具依赖关系标记为可选(optional)是一种最佳做法,可以防止使用项目将devtools传递性地应用于其他模块。 Gradle不支持开箱即用的可选依赖项,因此您可能希望在此期间查看[propdeps-plugin](https://github.com/spring-projects/gradle-plugins/tree/master/propdeps-plugin)。

> 重新打包的jar包默认情况下不包含devtools。 如果要使用某些[远程devtools功能](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#using-boot-devtools-remote),您需要禁用excludeDevtools 构建下的属性以包含devtools。 该属性支持Maven和Gradle插件。

### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#201-属性默认值)20.1 属性默认值

Spring Boots支持的几个库使用缓存来提高性能。 例如,[模板引擎](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-template-engines)将缓存编译的模板,以避免重复解析模板文件。 此外,Spring MVC可以在返回静态资源时向响应中添加HTTP缓存头。

虽然缓存在生产中非常有益,但它在开发过程中可能会产生反效果,从而阻止您看到刚刚在应用程序中进行的更改。 因此,spring-boot-devtools将默认禁用这些缓存选项。

缓存选项通常由您的application.properties文件中的设置配置。 例如,Thymeleaf提供了spring.thymeleaf.cache属性。 spring-boot-devtools模块不需要手动设置这些属性,而是自动应用更加合理的开发时(development-time)配置。

> 有关应用的属性的完整列表,请参阅 [DevToolsPropertyDefaultsPostProcessor](https://github.com/spring-projects/spring-boot/tree/v1.5.2.RELEASE/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/env/DevToolsPropertyDefaultsPostProcessor.java)。

### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#202-自动重启)20.2 自动重启

使用spring-boot-devtools的应用程序将在类路径上的文件发生更改时自动重新启动。 这在IDE中开发时可能是一个有用的功能,因为它为代码更改提供了非常快的反馈循环。 默认情况下,将监视指向文件夹的类路径上的任何条目。 请注意,某些资源(如静态资源和视图模板)不需要重新启动应用程序。

触发重启

当DevTools监视类路径资源时,触发重新启动的唯一方法是更新类路径中的文件时。 导致类路径更新的方式取决于您正在使用的IDE。 在Eclipse中,保存修改的文件将导致类路径被更新并触发重新启动。 在IntelliJ IDEA中,构建项目(Build→Make Project)将具有相同的效果。

> 只要 forking 被启用,您也可以通过支持的构建插件(即Maven和Gradle)启动应用程序,因为DevTools需要一个单独的应用程序类加载器才能正常运行。Gradle和Maven默认情况下在类路径上检DevTools。

> 自动重启当与LiveReload一起使用时工作非常好。 详见[下文](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#using-boot-devtools-livereload)。 如果您使用JRebel,自动重启将被禁用,有利于动态类重新加载。 其他devtools功能仍然可以使用(如LiveReload和属性覆盖)。

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

> 当判断类路径中的项目是否会在更改时触发重新启动时,DevTools会自动忽略名为spring-boot,spring-boot-devtools,spring-boot-autoconfigure,spring-boot-actuator和spring-boot-start的项目。

重新启动(Restart) vs 重新加载(Reload)

Spring Boot提供的重新启动技术使用两个类加载器。 不会改的类(例如,来自第三方的jar)被加载到基类加载器中。 您正在开发的类被加载到重新启动(restart)类加载器中。 当应用程序重新启动时,重新启动类加载器将被丢弃,并创建一个新的类加载器。 这种方法意味着应用程序重新启动通常比“冷启动”快得多,因为基类加载器已经可以使用。

如果发现重新启动对应用程序不够快,或遇到类加载问题,您可以考虑来自ZeroTurnaround的JRebel等重新加载技术。 这些工作通过在加载类时重写(rewriting)类,使其更适合重新加载。 Spring Loaded提供了另一个选项,但是它在很多框架上不支持,并且不支持商用。

#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2021-排除资源)20.2.1 排除资源

在类路径下,某些资源在更改时不一定需要触发重新启动。 例如,Thymeleaf模板可以直接编辑不需重启。 默认情况下,有一些排除项,更改 /META-INF/maven,/META-INF/resources,/resources,/static,/public或/templates中的资源不会触发重新启动,但会触发[实时重新加载](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#using-boot-devtools-livereload)。 如果要自定义这些排除项,可以使用spring.devtools.restart.exclude属性。 例如,要仅排除 /static和 /public,您可以设置:

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

> 如果要保留这些默认值并添加其他排除项,请改用spring.devtools.restart.additional-exclude属性。

#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2022-监视额外的路径)20.2.2 监视额外的路径

有时当您对不在类路径中的文件进行更改时,需要重新启动或重新加载应用程序。为此,请使用spring.devtools.restart.additional-paths属性来配置其他路径以监视更改。 您可以使用[上述](described above)的spring.devtools.restart.exclude属性来控制附加路径下的更改是否会触发完全重新启动或只是[实时重新加载](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#using-boot-devtools-livereload)

#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2023-禁用重启)20.2.3 禁用重启

如果不想使用重新启动功能,可以使用spring.devtools.restart.enabled属性来禁用它。 在大多数情况下,您可以在application.properties中设置此项(这仍将初始化重新启动类加载器,但不会监视文件更改)。

例如,如果您需要完全禁用重新启动支持,因为它在一些特定库中不能正常运行,则需要在调用SpringApplication.run(...)之前设置System属性。 例如:

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

#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2024-使用触发文件)20.2.4 使用触发文件

如果您使用IDE工具编写代码,更改文件,则您可能希望仅在特定时间触发重新启动。 为此,您可以使用“触发文件”,这是一个特殊文件,当您要实际触发重新启动检查时,必须修改它。 更改文件只会触发检查,只有在Devtools检测到它必须执行某些操作时才会重新启动。 触发文件可以手动更新,也可以通过IDE插件更新。

要使用触发器文件,请使用spring.devtools.restart.trigger-file属性。

> 您可能希望将spring.devtools.restart.trigger-file设置为[全局设置](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#using-boot-devtools-globalsettings),以使所有项目的行为方式相同。

#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2025-自定义重新启动类加载器)20.2.5 自定义重新启动类加载器

如上面的 [Restart vs Reload](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#using-spring-boot-restart-vs-reload) 部分所述,重新启动功能是通过使用两个类加载器实现的。 对于大多数应用程序,此方法运行良好,但有时可能会导致类加载问题。

默认情况下,IDE中的任何打开的项目将使用“重新启动”类加载器加载,任何常规.jar文件将使用“base”类加载器加载。 如果您在多模块项目上工作,而不是每个模块都导入到IDE中,则可能需要自定义事件。 为此,您可以创建一个META-INF / spring-devtools.properties文件。

spring-devtools.properties文件可以包含restart.exclude 和 restart.include.prefixed属性。 include元素是应该被拉入“重新启动(restart)”类加载器的项目,排除元素是应该向下推入“基本(base)”类加载器的项目。 属性的值是将应用于类路径的正则表达式模式。

例如:

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

> 所有属性键必须是唯一的。 只要一个属性从restart.include. 或restart.exclude. 开始,将被考虑。

> 将加载类路径中的所有META-INF/spring-devtools.properties。 您可以在项目中打包文件,或者在项目所使用的库中打包文件。

#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2026-已知的限制)20.2.6 已知的限制

重新启动功能对于使用标准ObjectInputStream反序列化的对象无效。 如果需要反序列化数据,可能需要使用Spring的ConfigurableObjectInputStream与Thread.currentThread()。getContextClassLoader()组合使用。

不幸的是,几个第三方库在不考虑上下文类加载器的情况下反序列化。 如果您发现这样的问题,您需要向原始作者请求修复。

### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#203-livereload)20.3 LiveReload

spring-boot-devtools模块包括一个嵌入式LiveReload服务器,可以在资源更改时用于触发浏览器刷新。 LiveReload浏览器扩展程序可以从 [http://livereload.com](http://livereload.com/)免费获取Chrome,Firefox和Safari的插件。

如果您不想在应用程序运行时启动LiveReload服务器,则可以将spring.devtools.livereload.enabled属性设置为false。

> 一次只能运行一个LiveReload服务器。 开始应用程序之前,请确保没有其他LiveReload服务器正在运行。 如果从IDE启动多个应用程序,则只有第一个应用程序将支持LiveReload。

### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#204-全局设置)20.4 全局设置

您可以通过向 $HOME 文件夹添加名为.spring-boot-devtools.properties的文件来配置全局devtools设置(请注意文件名以“.”开头)。 添加到此文件的任何属性将适用于您的计算机上使用devtools的所有Spring Boot应用程序。 例如,要配置重新启动以始终使用触发器文件,您可以添加以下内容:

~/.spring-boot-devtools.properties.

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

### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#205远程应用)20.5远程应用

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
```

> 在远程应用程序上启用spring-boot-devtools是一种安全隐患。 您不应该在生产部署中启用该支持。

远程devtools支持分为两部分: 有一个接受连接的服务器端和您在IDE中运行的客户端应用程序。 当spring.devtools.remote.secret属性设置时,服务器组件将自动启用。 客户端组件必须手动启动。

#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2051-运行远程客户端应用程序)20.5.1 运行远程客户端应用程序

远程客户端应用程序旨在从IDE中运行。 您需要使用与要连接的远程项目相同的类路径运行org.springframework.boot.devtools.RemoteSpringApplication。 传递给应用程序的必选参数应该是您要连接到的远程URL。

例如,如果您使用Eclipse或STS,并且有一个名为my-app的项目已部署到Cloud Foundry,则可以执行以下操作:

*   从Run 菜单中选择Run Configurations…。
*   创建一个新的Java Application “launch configuration”。
*   浏览my-app项目。
*   使用org.springframework.boot.devtools.RemoteSpringApplication作为主类。
*

运行的远程客户端将如下所示:

```
.   ____          _                                              __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _          ___               _      \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` |        | _ \___ _ __  ___| |_ ___ \ \ \ \
 \\/  ___)| |_)| | | | | || (_| []::::::[]   / -_) '  \/ _ \  _/ -_) ) ) ) )
  '  |____| .__|_| |_|_| |_\__, |        |_|_\___|_|_|_\___/\__\___|/ / / /
 =========|_|==============|___/===================================/_/_/_/
 :: Spring Boot Remote :: 1.5.2.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)
```

> 由于远程客户端正在使用与实际应用程序相同的类路径,因此可以直接读取应用程序属性。 这是spring.devtools.remote.secret属性如何读取并传递到服务器进行身份验证。

> 建议使用https//作为连接协议,以便流量被加密,防止密码被拦截。

> 如果需要使用代理访问远程应用程序,请配置spring.devtools.remote.proxy.host和spring.devtools.remote.proxy.port属性。

#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2052-远程更新)20.5.2 远程更新

远程客户端将以与本地相同的方式监视应用程序类路径的更改。 任何更新的资源将被推送到远程应用程序,并且(如果需要的话)触发重新启动。 如果您正在迭代使用您当地没有的云服务的功能,这可能会非常有用。 通常,远程更新和重新启动比完全重建和部署周期要快得多。

> 仅在远程客户端运行时才监视文件。 如果在启动远程客户端之前更改文件,则不会将其推送到远程服务器。

#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2053-远程调试隧道)20.5.3 远程调试隧道

在远程应用程序诊断问题时,Java远程调试非常有用。 不幸的是,当您的应用程序部署在数据中心之外时,并不总是能够进行远程调试。 如果您正在使用基于容器的技术(如Docker),远程调试也可能难以设置。

为了帮助解决这些限制,devtools支持基于HTTP隧道的传输远程调试传输。 远程客户端在端口8000上提供本地服务器,您可以连接远程调试器。 建立连接后,通过HTTP将调试数据发送到远程应用程序。 如果要使用其他端口,可以使用spring.devtools.remote.debug.local-port属性更改。

您需要确保远程应用程序启用远程调试启用。 通常可以通过配置JAVA_OPTS来实现。 例如,使用Cloud Foundry,您可以将以下内容添加到manifest.yml中:

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

> 请注意,您不需要将 address=NNNN 选项传递给-Xrunjdwp。 如果省略Java将随机选择一个的空闲端口。

> 通过网络调试远程服务可能很慢,您可能需要在IDE中增加超时时间。 例如,在Eclipse中,您可以从Preferences...中选择Java→Debug ,并将Debugger timeout (ms)更改为更合适的值(大多数情况下,60000可以正常工作)。

> 当使用IntelliJ IDEA的远程调试隧道时,必须将所有调试断点配置为挂起线程而不是挂起VM。 默认情况下,IntelliJ IDEA中的断点会挂起整个VM,而不是仅挂起触发断点的线程。 这会导致挂起管理远程调试通道的线程等不必要的副作用,导致调试会话冻结。 当使用IntelliJ IDEA的远程调试隧道时,应将所有断点配置为挂起线程而不是VM。 有关详细信息,请参阅[IDEA-165769](https://youtrack.jetbrains.com/issue/IDEA-165769)。