SpringBoot2.x参考指南(中文版)第三部分 使用SpringBoot

第三部分 使用SpringBoot


最近好忙,本部分翻译的不是很完整,随后会重新润色哒

版权声明:本文为博主原创文章,转载时请务必注明本文地址, 禁止用于任何商业用途, 否则会用法律维权。
转载请注明出处:http://blog.csdn.net/HITLiuXiaodong/article/details/53471184

本人水平有限,翻译中的错误还请多多指教

本部分会更加详细的讨论如何使用SpringBoot。主要包含的话题有构建系统,自动配置和运行程序。我们也会讨论一些SpringBoot的最佳实践。虽然SpringBoot没有什么特别之处(你可以把它看作一个第三方库),但是这里会有一些小建议,如果遵循的话会使开发稍微轻松一点。
如果你刚开始接触SpringBoot,在进入本部分之前,你最好先读一读 入门 部分。

13.构建系统

我们强烈推荐你使用一套构建工具来进行构建,最好是Maven或者Gradle。虽然你可以用其他构建工具比如ant,但是我们不会提供特定的支持。

13.1依赖管理

SpringBoot的每一个版本都会提供一份依赖清单。在实际应用中,你不需要手动去管理这些版本,因为SpringBoot会帮你管理。当你想升级Spring Boot的时候,这些依赖也会一同升级。

如果需要的话,你也可以自己指定版本进行覆盖

在清单里包含所有的Spring模块,也包含一份精简的第三方库。这份清单可以看作是一个标准的springboot依赖材料。

SpringBoot发布的每个版本都会和特定的Spring框架版本相联系。因此我们强烈建议你不要自己指定Spring版本。

13.2Maven

Maven使用者可以通过继承spring-boot-starter-parent来获取一些默认的配置。这个parent提供以下的配置:

  • java1.6或者更高的编译版本
  • 默认utf-8编码
  • 通过继承spring-boot-dependencies,你可以省略 标签
  • 聪明的 资源过滤器
  • 聪明的插件配置
  • 对 application.properties和application.yml很敏感
    (啊啊啊,这段翻译的很不好,原文如下)
  • Sensible resource filtering.
  • Sensible plugin configuration (exec plugin, surefire, Git commit ID, shade).
  • Sensible resource filtering for application.properties and application.yml including profile-specific files (e.g. application-foo.properties and application-foo.yml)

最后一点,因为默认配置文件中支持Spring风格的占位符 (${}),因此Maven过滤器中使用 @…@ 风格的占位符。(当然,你也可以通过重载resource.delimiter配置)

13.2.1继承starter

为了让你的工程继承自 spring-boot-starter-parent,你只需这样配置:



    org.springframework.boot
    spring-boot-starter-parent
    2.0.0.BUILD-SNAPSHOT

你只需要在依赖中指定SpringBoot的版本即可。如果你也使用了其他的 starters 你可以很放心的忽略指定他们的版本。

按照这样设置,你可以通过覆盖一个属性来覆盖相应的以来。例如我们想升级Spring Data的版本,就可以这样设置:

<properties>
    <spring-data-releasetrain.version>Fowler-SR2</spring-data-releasetrain.version>
</properties>

查看这里来获取一份支持覆盖的属性清单

13.2.2不继承我们的父节点来使用SpringBoot

并不是每一个人都想继承 spring-boot-starter-parent 。你可能需要继承公司的父节点,也可能单单想更确切的声明maven.
如果你不想继承 spring-boot-starter-parent,你也可以通过使用 scope=import 来享受依赖管理的便捷(并不是插件管理)

<dependencyManagement>
     <dependencies>
        <dependency>
            
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-dependenciesartifactId>
            <version>2.0.0.BUILD-SNAPSHOTversion>
            <type>pomtype>
            <scope>importscope>
        dependency>
    dependencies>
dependencyManagement>

上面的这种配置并不能让你用来覆盖单独的依赖。为了得到同样的结果,你需要在dependencyManagementspring-boot-dependencies前面添加一个入口,例如你想升级SpringData的版本,你需要在pom.xml中这样配置:

<dependencyManagement>
    <dependencies>
        
        <dependency>
            <groupId>org.springframework.datagroupId>
            <artifactId>spring-data-releasetrainartifactId>
            <version>Fowler-SR2version>
            <scope>importscope>
            <type>pomtype>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-dependenciesartifactId>
            <version>2.0.0.BUILD-SNAPSHOTversion>
            <type>pomtype>
            <scope>importscope>
        dependency>
    dependencies>
dependencyManagement>

在上面的例子中,我们指定了一个 BOM ,你也可以不指定

13.2.3 更改Java版本

spring-boot-starter-paren 会选择相对保守的java版本。但是如果你听从我们的建议,选择比较新的Java版本,你可以在配置文件中添加一个 java.version的属性。

<properties>
    <java.version>1.8java.version>
properties>

13.2.4 使用Maven插件

SpringBoot包含一个可以把工程打包成可执行jar包的maven插件。如果你想使用的话,只需要把她添加到 节点中

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-maven-pluginartifactId>
        plugin>
    plugins>
build>

如果你使用了SpringBoot的父节点,那么你只需要添加这个插件即可,不需要其他的配置,除非你想更改默认的配置。

13.3 Gradle

Gradle用户只需要在 dependencies中声明即可。不像maven,无需添加单独的父节点。

apply plugin: 'java'

repositories {
    maven { url "http://repo.spring.io/snapshot" }
    maven { url "http://repo.spring.io/milestone" }
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:2.0.0.BUILD-SNAPSHOT")
}

我们提供了 spring-boot-gradle-plugin插件以供你从源码生成jar包。也提供了 依赖管理,它可以帮你管理依赖的版本。

buildscript {
    repositories {
        maven { url "http://repo.spring.io/snapshot" }
        maven { url "http://repo.spring.io/milestone" }
    }

    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.0.BUILD-SNAPSHOT")
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'

repositories {
    maven { url "http://repo.spring.io/snapshot" }
    maven { url "http://repo.spring.io/milestone" }
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    testCompile("org.springframework.boot:spring-boot-starter-test")
}

13.4 Ant

你也可以通过 ant+Ivy 来构建一个SpringBoot。这个 spring-boot-antlib模块可以帮助 ant 创建一个可执行jar包。你只需像下面这样配置:

<ivy-module version="2.0">
    <info organisation="org.springframework.boot" module="spring-boot-sample-ant" />
    <configurations>
        <conf name="compile" description="everything needed to compile this module" />
        <conf name="runtime" extends="compile" description="everything needed to run this module" />
    configurations>
    <dependencies>
        <dependency org="org.springframework.boot" name="spring-boot-starter"
            rev="${spring-boot.version}" conf="compile" />
    dependencies>
ivy-module>

一个典型的 build.xml 就像下面这样:

<project
    xmlns:ivy="antlib:org.apache.ivy.ant"
    xmlns:spring-boot="antlib:org.springframework.boot.ant"
    name="myapp" default="build">

    <property name="spring-boot.version" value="1.3.0.BUILD-SNAPSHOT" />

    <target name="resolve" description="--> retrieve dependencies with ivy">
        <ivy:retrieve pattern="lib/[conf]/[artifact]-[type]-[revision].[ext]" />
    target>

    <target name="classpaths" depends="resolve">
        <path id="compile.classpath">
            <fileset dir="lib/compile" includes="*.jar" />
        path>
    target>

    <target name="init" depends="classpaths">
        <mkdir dir="build/classes" />
    target>

    <target name="compile" depends="init" description="compile">
        <javac srcdir="src/main/java" destdir="build/classes" classpathref="compile.classpath" />
    target>

    <target name="build" depends="compile">
        <spring-boot:exejar destfile="build/myapp.jar" classes="build/classes">
            <spring-boot:lib>
                <fileset dir="lib/runtime" />
            spring-boot:lib>
        spring-boot:exejar>
    target>
project>

如果你不想使用 spring-boot-antlib,你可以参看下面的章节 Section 80.10, “Build an executable archive from Ant without using spring-boot-antlib”

13.5 Starters

14. 组织代码

SpringBoot无需特定的代码结构,不过这里有一些最佳实践。

14.1 使用默认包名

当一个类没有包含包声明时,它就位于默认包下。我们不鼓励使用默认包名,也应该避免使用默认包名。因为这可能对SpringBoot的@ComponentScan, @EntityScan or @SpringBootApplication注释产生特定的问题。

我们建议你使用java推荐的包命名规范并且使用公司域名(比如:com.example.project)

14.2 确定main类的位置

我们建议你把 启动类放在根包名下面。因为@EnableAutoConfiguration注释会经常放在启动类里,它会以此为根扫描路径进行搜索。比如你正在写一个JPA程序,@EnableAutoConfiguration注释的类会用来搜索 @Entity注释的条目。
使用根包名时允许你在不指定 basePackage属性时使用@ComponentScan注释。也可以在这种情况下使用@SpringBootApplication
下面是一个典型的项目结构:

 +- example
     +- myproject
         +- Application.java
         |
         +- domain
         |   +- Customer.java
         |   +- CustomerRepository.java
         |
         +- service
         |   +- CustomerService.java
         |
         +- web
             +- CustomerController.java

Application.java文件中会包含 main 方法,也带有 @Configuration注释。

package com.example.myproject;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

15. 配置类

15.1 导入其它的配置类

15.2 导入XML配置

16. 自动配置

16.1 逐步替换自动配置

16.2 关闭特定的自动配置

17. SpringBeans和依赖注入

18. 使用 @SpringBootApplication注释

许多Spring Boot开发者会在他们的 main类中使用 @Configuration, @EnableAutoConfiguration 、 @ComponentScan注释。因为这些注释使用的太频繁了(特别是当你遵循了上面的最佳实践),SpringBoot提供了一个简单的 @SpringBootApplicatio 注释用来取代上面的三个注释。
@SpringBootApplication注释和@Configuration, @EnableAutoConfiguration and @ComponentScan具有相同的效果。

package com.example.myproject;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

@SpringBootApplication 也提供有别名以供你定制 @EnableAutoConfiguration 和 @ComponentScan

19. 运行你的程序

19.1 从IDE里运行程序

19.2 运行Jar包

如果你使用SpringMaven或者Gradle插件来创建的可执行jar包,你可以使用 java -jar来运行程序。例如:

$ java -jar target/myproject-0.0.1-SNAPSHOT.jar

你也可以通过绑定远程调试工具来运行程序。比如:

$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
       -jar target/myproject-0.0.1-SNAPSHOT.jar

19.3 使用Maven插件

19.4 使用Gradle插件

19.5 热替换

20. 开发工具

SpringBoot自带了一些工具集可以使编程体验变得愉悦。你可以把Spring-boot-devtools模块加入工程来体验额外的功能。为了添加这些开发工具的支持,你只需简单的添加依赖即可:
Maven

<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
        <optional>trueoptional>
    dependency>
dependencies>

Gradle

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

当你运行打包好的程序时,开发工具会自动关闭。如果你使用 java -jar 或者使用自定义的classloader启动时,它也会被当作 “发布的产品” 。把这个开发工具模块当作可选的部分是非常有用的,它可以避免你影响到工程的其他模块。不过Gradle不支持 可选依赖,所以你同时也需要看看 propdeps-plugin 这部分。
重新打包默认并不会把这个开发工具包打包进去。如果你想使用远程调试模块,你需要关闭 excludeDevtools属性来把它打包进去。Maven和Gradle都支持设置该属性。

20.1 默认的属性

SpringBoot支持的库可能使用缓存来提升性能。比如:Thymeleaf 会缓存模版来避免重复解析xml源文件。尽管缓存对发布产品有用,可是对开发确不利。比如你在IDE里修改了一些代码,你想立即看到结果。

Cache选项通常需要手动在 application.properties里进行设置。比如:Thymeleaf 提供spring.thymeleaf.cache属性来控制缓存。不过与这些手动设置不同,spring-boot-devtools模块会自动配置对于时间敏感的属性。

如果想得到完整的自动配置清单列表,请访问DevToolsPropertyDefaultsPostProcessor.

20.2 自动重启

应用程序如果使用了 spring-boot-devtools模块,那么当位于classpath路径下的文件发生改变后,服务就会重启。这会非常有用当你在IDE里修改了代码想尽快看到修改后的效果。默认情况下,classpath下的所有文件都会被监控。不过,一些特定的资源文件比如静态资源发生改变就无须重启服务器。

触发一个重启操作
因为这个DevTools会自动监测classpath下的资源文件,所以触发重启的唯一办法就是更新classpath下的文件。不过更新classpath下的文件取决于你使用的IDE。在Eclipse下,保存修改的文件会引发classpath的更新从而触发服务重启。在IDEA下,通过Build->Make Project会起到同样的效果。

你也可以通过构建工具的插件来启动项目,只要 forking 是启用的,因为DevTools需要一个独立的应用程序加载器才可以正常工作。当Maven和Gradle检测到classpath目录下有DevTools时就会自动做这些。

自动重启能够和LiveReload很好的配合工作。详情见下面。如果你使用了 JRebel,那么重启就会被关掉,因为JRebel会进行热部署。不过其他的一些特色(比如自动刷新和默认的一些配置)会被保留下来。

DevTools在重启时会依赖 application context的shutdown hook 来关闭它。所以当你关闭了shutdown hook (SpringApplication.setRegisterShutdownHook(false))) 它就没法正常工作了。

当classpath下的文件发生改变时,DevTools会根据改变的内容决定是否重启。DevTools会自动忽略名称为:spring-boot, spring-boot-devtools, spring-boot-autoconfigure, spring-boot-actuator, and spring-boot-starter.下的项目。

重启和重载
SpringBoot提供的重启技术是通过两个类加载器实现的。一些不变的类,(比如第三方的jar包)会被一个基础类加载器加载。一些需要频繁修改的类会被一个重启类加载器加载。当应用重启时,旧的重启类加载器会被丢弃,一个新的类加载器会被创建出来。这意味着应用重启速度会比冷启动快很多,因为基础类加载器已经存在了。
如果你觉得应用的重启速度不够快,或者你遇到类加载问题了,你可以考虑使用其它的重载技术比如JRebel。这些技术通过重写class文件来获得更快的加载速度。SpringLoaded提供了另外一种选择,不过它并不支持太多框架,也不提供商业支持。

20.2.1 排除一些资源

一些特定的资源发生改变是无需触发重启。比如:Thymeleaf 模版只需在原处发生改变。默认情况下
/META-INF/maven, /META-INF/resources ,/resources ,/static ,/public or /templates路径下的资源发生改变不会触发重启,不过会引发资源重新加载。如果你想定制需要排除的资源,你可以修改 spring.devtools.restart.exclude属性。比如,你只想排除 /static and /public 下的资源,你只需像下面这样设置:

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

如果你想保留默认的设置,想新增加一些排除想,请修改spring.devtools.restart.additional-exclude属性

20.2.2 监测特定路径

你可能需要SpringBoot在你修改非classpath路径下的文件时也触发重启。这时你需要修改spring.devtools.restart.additional-paths来添加额外的路径进行监测。你也可以通过设置上面提到的spring.devtools.restart.exclude来控制额外路径下的文件变动触发的行为。

20.2.3 关闭自动重启

如果你不想使用自动重启功能,你可以通过spring.devtools.restart.enabled来控制。大多数情况下,你只需在application.properties中进行设置(这仍然会初始化restart类加载器,不过不会监测文件的变化)
如果你想彻底的关闭重启支持,你需要在 调用SpringApplication.run(…​)之前进行设置:

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

20.2.4 使用触发器文件

20.2.5 自定义重启的classloader

20.2.6 一些限制

20.3 实时刷新

20.4 全局设置

20.5 远程开发

SpringBoot开发工具不仅局限于本地开发。你也可以在远程运行程序时使用一些功能。远程开发是可选的功能,为了启用它,你需要确保 devtools包含在 打包的压缩文件里:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-maven-pluginartifactId>
            <configuration>
                <excludeDevtools>falseexcludeDevtools>
            configuration>
        plugin>
    plugins>
build>

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

spring.devtools.remote.secret=mysecret

在远程开发中启用spring-boot-devtools会带来安全风向。因此你不应该在正式发布中启用此属性

20.5.1 远程运行程序

远程客户端程序设计的是从IDE内启动。你需要 和远程你需要连接的服务一样启动org.springframework.boot.devtools.RemoteSpringApplication,同时你必须传递需要连接的URL到应用程序中。
比如:你正在使用Eclipse或者 STS,你创建了了一个叫做 my-app的项目,你想把它部署到 云端服务中,那么你可以按照下面的步骤进行操作:

  • 在 Run 菜单中选择 Run configuration...
  • 创建一个新的 launch configuration
  • 浏览选中 my-app 项目
  • 使用 org.springframework.boot.devtools.RemoteSpringApplication作为入口类
  • 添加 https://myapp.cfapps.ioProgram arguments 或者你选择的其他url

一个运行的远程客户端像下面这样:

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

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)

20.5.2 远程更新

远程的客户端也会像在本地调试一样监控你应用程序的classpath中文件的改变。任何资源的改变都会被同步到远程客户端,并且在合适的时候触发重启。这在使用云服务并且需要频繁调试的时候非常有用。通常情况下,远程更新和重启会比一个完整的编译部署流程快上许多。

只有远程客户端在运行时才会监测本地文件的变动。如果你没有启动远程客户端,那么你对文件做出的更改不会被推送的远程服务中。

20.5.3 远程调试

当你想定位一个问题时,远程调试会变得非常有用。不过,如果你的应用没有部署在数据中心时,远程调试可能会不起作用。在容器技术比如docker中设置远程调试是非常困难的。
为了绕过这些限制,开发工具集采用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"

注意:你无须给-Xrunjdwp指定一个address=NNNN的选项。如果你忽略此选项,Java会选择一个随机的端口。
在网络上远程调试的话,网速可能会很慢,因此你需要在你的IDE中增加超时时间。比如,在Eclipse中,你可以选择java->Debug->Preferences… 修改Debugger timeout(ms) ,来选择一个合适的超时时间 (大多数情况下60000足够了)。

21. 打包发布

可执行的jar包可以用于发布。因为他们内部包含有服务器,因此也非常适合云端部署。

如果想了解更多关于发布的知识,比如运行状况、认证以及REST、JMX知识,可以考虑添加上
spring-boot-actuator 。请看第五部分 “Spring Boot Actuator: Production-ready features”

22. 接下来

现在你应该已经了解如何根据最佳实践来使用SpringBoot了。那么接下来,你可以深入学习SpringBoot的一些特色,或者你也可以跳过前面的部分,直接阅读 SpringBoot的发布部分。

你可能感兴趣的:(SpringBoot)