11.3.1 @RestController and @RequestMapping 注解
@RestController 是一个stereotyp(原型)注解, 用于提供给用户和Spring阅读 .
@RequestMapping 注解 ,提供URL访问的路由信息.
这两个注解都是Spring MVC提供的 .
11.3.2 @EnableAutoConfiguration 注解
这个注解告诉Spring boot 推测spring的配置方式 .
11.5 创建一个能够运行的jar包
为了让应用成为一个自包含的包. 需要pom.xml中包含以下插件:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
构建系统
选maven或者gradle
依赖管理
每一个版本的Spring boot 版本都定义了所引用的Spring Framework的版本 , 所以 , 最好不要自己再去定义Spring Framework的版本号了.
13.2 Maven
spring-boot-starter-parent包含以下特性:
- java 1.8 作为默认的编译版本
- UTF-8 编码
- 依赖管理单元可以让我们忽略一些通用依赖的版本号 .
- 自动检测的resource过滤
- 自动检测的插件配置
- 自动检测application.properties, application.yml(包括profile , 例如 application-foo.properties , application-foo.yml)
13.2.1 继承starter parent
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>
这个部分 , 只需要修改version. 如果引用了其它的starter , 不需要单独声明version.
13.2.2 没有parent pom的情况下使用spring boot
?没懂
如果不想使用parent , 我们任然可以使用依赖管理的功能(不包含插件管理). 这个功能通过添加scope=import实现:
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
13.2.3 使用spring boot maven plugin
提供打包功能
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
13.5 starters
starters是一组方便使用的依赖描述符. 可以一站式的获取所有spring和相关的功能. 有一些基础的starter是此处不列出 . http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/ 自行到这个地方查看.
除了应用的starters , 以下的starters 可以添加用以增加生产环境的监控特性:
spring-boot-starter-actuator 用来管理和监控应用的特性.其它starters是一些替代技术
https://github.com/spring-projects/spring-boot/tree/master/spring-boot-starters/README.adoc
14组织代码
14.1 不推荐使用默认包
推荐使用反向域名命名包
14.2 定位main application class
推荐的文件结构
com
+- example
+- myproject
+- Application.java
|
+- domain
| +- Customer.java
| +- CustomerRepository.java
|
+- service
| +- CustomerService.java
|
+- web
+- CustomerController.java
标准配置java类:
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 配置类
一般推荐使用@Configuration 类. main函数定义的地方就是配置@configuration的地方. 很多地方可能使用XML文件进行配置 ,但是最好使用java类来配置 . 查找Enable* .
15.1 导入额外的配置类 ?
不需要将所所有的配置都放在一个@Configuration类中 . @Import注解可以用来注入更多的配置 . 另一种方法是使用@ComponentScan来自动扫描所有的组件 . 包括@Configuration
15.2 导入XML配置文件 ?
如果实在要使用XML文件, 依然推荐使用@Configuration 类 ,然后通过@ImportResource 注解来加载XML配置文件.
16 自动配置
spring boot 会根据导入的jar依赖来自动配置 . 比如HSQLDB没有在类上, 而且没有显式的配置其它的数据源 . 那么就会默认使用内存数据库. 这个功能需要使用@EnableAutoConfiguration 或者 @SpringBootApplication注解在一个@Configuration类上面来启用.
只能添加一个@EnableAutoConfiguration.
16.1 逐步替换 auto-configuration
自动配置是非侵入式的(noninvasive), 所以可以在任何时候替换成自己定义的内容 . 如果需要看到详情, 在运行的时候打开–debug选项 .
16.2 禁用特定的auto-configuration
import org.springframework.boot.autoconfigure.*;
import org.springframework.boot.autoconfigure.jdbc.*;
import org.springframework.context.annotation.*;
@Configuration
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}
如果类不在classpath上的话 , 可以使用excludeName属性来排除.
17 spring beans 以及依赖注入(DI)
我们常使用@ComponentScan来查找beans , 加上@Autowired 的构造器注入, 配合的很好 . 如果将@ComponentScan注解的类放在包结构的root上. 应用中的所有组件 @Component @Service @Repository @Controller等都会自动注册成Spring的bean. 如下:
package com.example.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class DatabaseAccountService implements AccountService {
private final RiskAssessor riskAssessor;
@Autowired
public DatabaseAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
}
// ...
}
如果bean只有一个构造方法 , 可以忽略@Autowried
@Service
public class DatabaseAccountService implements AccountService {
private final RiskAssessor riskAssessor;
public DatabaseAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
}
// ...
}
18 使用 @SpringBootApplication 注解
@SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan
19 运行程序
- 从IDE运行
- 通过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
- 使用mvn plugin
mvn spring-boot:run
- 使用gradle plugin
gradle bootRun
- 热切换
看第二十章
20 开发工具(restart liveReload) ?
spring-boot-devtools可以被引用到任何开发阶段的工程引入开发时特性.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
这个功能在以java -jar方式运行时 , 自动被禁用.
20.1 属性默认值
有一些库使用缓存来改善性能 . 在生产环境中 , 缓存是十分有用的 .但是在开发的时候 , 这些性能是不需要的. spring-boot-devtools 会禁止掉这些特性. 缓存选项一班可以通过application.properties文件来设置 .
详细缓存列表见链接 : https://github.com/spring-projects/spring-boot/tree/master/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/env/DevToolsPropertyDefaultsPostProcessor.java
20.2 自动重启
使用spring-boot-devtools的工程 , 在文件发生改变的时候会自动重启. 注意一些静态文件, 不需要重启应用.
20.2.1 excluding resources
/META-INF/maven, /META-INF/resources ,/resources ,/static ,/public or /templates,目录下的文件不会触发重启, 而是reload.
21 打包生产环境应用
查看第五章的spring-boot-actuator
PART IV. Spring boot features
23 SpringApplication
SpringApplication类提供快捷方便的方式启动main().
public static void main(String[] args){
SpringApplication.run(MySpringConfiguration.class,args);
}
23.1 启动失败
spring boot 提供了大量的FailureAnalyzer的实现 ,我们可以自行添加(后文介绍)
java -jar myproject-0.0.1-SNAPSHOT.jar --debug
23.2 自定义启动的Banner
spring:
main:
banner-mode: "off"
23.3 自定义SpringApplication
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
也可以使用application.properties文件配置SpringApplication , 详见C24.
23.4 Fluent builder API ?
23.5 Application 事件和监听器
除了Spring Framework的事件 , 例如 ContextRefreshedEvent , SpringApplication也可以发送一些其它类型的事件 .
一些事件在ApplicationContext创建之前就被触发了,因此并不能使用@Bean. 这些事件可以使用SpringApplication.addListeners()或者 SpringApplicationBuilder.listeners()方法.
如果需要这些监听器不管以何种方式启动application都注册 , 那么可以添加一个META-INF/spring.factories文件. 引用需要的监听器 :
org.springframework.context.ApplicationListener=com.example.project.MyListener
应用的事件传播顺序如下:
1. ApplicationStartingEvent 在run开始的时候 , 在监听器和初始化器注册之后.
2. ApplicationEnvironmentPreparedEvent 在context中Environment已经知道的时候 , 但是在context创建之前
3. ApplicationPreparedEvent 在refresh之前, 在所有bean定义加载之后
4. ApplicationReadyEvent 在refresh和任何相关的表示应用已经可以接受请求的回调执行完之后
5. ApplicationFailedEvent 在应用启动的时候发生异常的时候
23.6 Web environment
SpringApplication 会尝试使用正确的ApplicationContext . 默认的AnnotationConfigApplicationContext或者 AnnotationConfigServletWerServerApplicationContext会被使用. 这取决于我们是否是在开发一个web应用.
23.7 使用应用的参数
如果想使用传递给SpringApplication.run()的参数 . 可以注入一个ApplicationArguments bean . 这个类的接口提供了args 还有 转化过得options和非options .
import org.springframework.boot.*
import org.springframework.beans.factory.annotation.*
import org.springframework.stereotype.*
@Component
public class MyBean {
@Autowired
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
// if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
}
}
23.8 使用ApplicationRunner 或者 CommandLineRunner
如果现在SpringApplication启动时候做一些操作的话, 可以实现ApplicationRunner或者CommandLineRunner接口. 如果有多个要按顺序执行的话, 再实现org.springframework.core.Ordered就可以了
import org.springframework.boot.*
import org.springframework.stereotype.*
@Component
public class MyBean implements CommandLineRunner {
public void run(String... args) {
// Do something...
}
}
23.9 应用退出
可以实现org.springframework.boot.ExitCodeGenerator 在应用退出的时候实现逻辑
23.10 admin功能
通过设置spring.application.admin.enabled 属性 ,会暴露出一些对应用进行管理的接口
24 外部化的配置
外部化配置用以实现部署同样的代码到不同环境. 可以使用的外部配置文件包括: properties文件 , YAML文件 , 环境变量 , 命令行参数 . 属性可以通过@Value注解直接注入到bean中(通过Spring 的Environment抽象或者@ConfigurationProperties注解的结构化对象). Spring boot使用了一个特定的顺序加载配置 , 这样后面的配置就会自动发现并且覆盖之前的配置 . 顺序如下:
1. devtools 在根目录上全局设定的properties(~/.spring-boot-devtools.properties 如果devtools被激活)
2. @TestPropertySource test中注解
3. @SpringBootTest#properties test中注解的属性
4. 命令行的属性
5. SPRING_APPLICATION_JSON(内嵌在环境变量中或者系统属性中)
6. ServletConfig 初始化参数
7. ServletContext 初始化参数
8. JNDI 用java:comp/env中的属性
9. Java 系统属性(System.getProperties())
10. 操作系统环境变量
11. RandomValuePropertySource 只有random.*
12. jar 包外面的 application-{profile}.properties 和YAML
13. jar 包里面的 application-{profile}.properties 和YAML
14. @PropertySource 注解的@Configuration 类
15. 默认属性(用SpringApplication.setDefaultProperties声明的属性)
24.1 配置随机值
RandomValuePropertySource 可以用于注入随机值.
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}
24.2 使用command line 属性值
SpringApplication会将 “–server.port=9000” 这样的命令行的值转换成属性并且加入到Spring的Environment中 . 如果不想它们被加入到Envrionment中 ,如下
SpringApplication.setAddCommandLineProperties(false)
24.3 应用的属性文件 TBC
以下几个位置的application.properties文件会被加入到Environment中
1. 当前文件夹的/config子文件夹
2. 当前文件夹
3. classpath的/config文件夹
4. classpath本身
更高级的目录覆盖低级目录
java -jar myproject.jar --spring.config.name=myproject
java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
24.4 特定profile的属性
application-{profile}.properties 用以声明特定profile的属性. 如果没有特定的激活的profile , 自动加载application-default.properties .
24.5 属性中的占位符
后面的属性定义可使用前面声明的值
app.name=MyApp
app.description=${app.name} is a Spring Boot application
24.6 使用YAML代替属性值
如果使用了starters , SnakeYAML功能自动引入 . 不需要添加maven
24.6.1 加载YAML
有两个类可以用来加载YAML文件. YamlPropertiesFactoryBean 将YAML加载成Properties . YamlMapFactoryBean 将YAML加载成Map.
environments:
dev:
url: http://dev.bar.com
name: Developer Setup
prod:
url: http://foo.bar.com
name: My Cool App
my:
servers:
- dev.bar.com
- foo.bar.com
被转化成:
environments.dev.url=http://dev.bar.com
environments.dev.name=Developer Setup
environments.prod.url=http://foo.bar.com
environments.prod.name=My Cool App
my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com
24.6.2 把YAML属性当做Spring Environment使用
YamlPropertySourceLoader 可以将YAML转变成PropertySource 并且放在Spring Environment中. 这样我们就可以使用@Value注解和占位符来获取YAML的属性.
24.6.3 多profile YAML文件
server:
address: 192.168.1.100
---
spring:
profiles: development
server:
address: 127.0.0.1
---
spring:
profiles: production
server:
address: 192.168.1.120
24.6.4 YAML缺点
不能通过@PropertySource注解加载上去 . 所以需要加载的话一定要使用properties文件.
24.6.5 合并YAML 列表 TBC
24.7 类型安全的属性配置 TBC
25 profiles TBC
@Configuration
@Profile("production")
public class ProductionConfiguration {
// ...
}
一般的方法是在环境属性中声明 spring.profiles.active=dev,hsqldb
也可以在命令行中使用参数:
--spring.profiles.active=dev,hsqldb
25.1 添加active profiles
26 日志 TBC
26.1 日志格式
略
26.2 控制台输出
java -jar myapp.jar --debug
或者直接在application.properties中指定debug=true
26.3 输出日志到文件
设置logging.file属性或者logging.path属性 . 否则日志只会在控制台输出.
26.4 日志级别
logging.level.*=LEVEL (TRACE/DEBUG/INFO/WARN/ERROR/FATAL/OFF)
logging.level.root=WARN
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR
26.5 自定义日志配置
可以使用logging.config指定日志配置文件的位置