从第 1 章的介绍中,了解到在向 pom.xml 文件中添加以来之前需要先添加 spring-boot-starter-parent . spring-boot-starter-parent 主要提供了如下默认配置:
spring-boot-starter-parent 虽然方便,但是在公司中,开发微服务项目或多模块项目时一般需要使用公司自己的 parent,这个时候,如果还想进行项目依赖版本的统一管理,就需要使用 dependency Management 来实现了。添加如下代码到 pom 文件中:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.8.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
此时,就可以不用继承 spring-boot-starter-parent 了,但是 Java 的版本、编码的格式等都需要开发者手动配置。Java 版本的配置很简单,添加一个 plugin 即可:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
至于编码问题,如果采用了 简便创建方式 创建SpringBoot 项目,那么编码格式默认会加上;如果是通过普通 Maven 项目配置成的 SpringBoot 项目,那么在 pom.xml 文件中,加入如下配置即可:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
在前面介绍中,我们已经了解到 @SpringBootApplication 注解是加在项目的启动类上的。@SpringBootApplication 实际上是一个组合注释,定义如下:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@ComponentScan.Filter(type = FilterType.CUSTOM,classes = TypeExcludeFilter.class),
@ComponentScan.Filter(type = FilterType.CUSTOM,classes = AutoConfigurationExcludeFilter.class)
})
public class Chapter02Application {
public static void main(String[] args) {
SpringApplication.run(Chapter02Application.class, args);
}
}
这个注解由三个注解组成。
①第一个 @SpringBootConfiguration 的定义如下:
@Configuration
public @interface SpringBootConfiguration {
}
原来就是一个 @Configuration,所以 @SpringBootConfiguration 的功能就是表明这是一个配置类,开发者可以在这个类中配置 Bean。从这个角度来讲,这个类所扮演的角色有点类似于 Spring 中 applicationContext.xml 文件的角色。
②第二个注解 @EnableAutoConfiguration 表示开启自动化配置。SpringBoot 中的自动化配置是非侵入式的,在任意时刻,开发者都可以使用自定义配置代替自动化配置中的某一个配置。
③第三个注解 @ComponentScan 完成包扫描,也是 Spring 中的功能。由于 @ComponentScan 注解默认扫描的类都位于当前类所在包下,因此建议在实际项目开发中把项目启动类放在根包中,如图所示:
虽然项目的启动类也包含 @Configuration 注解,但是开发者可以创建一个新的类专门用来配置 Bean,这样便于配置的管理。这个类只需要加上 @Configuration 注解即可,代码如下:
@Configuration
public class MyConfig {
}
项目启动类中的@ComponentScan注解,除了扫描@Service、@Respository、@Component、@Controller和@RestController等之外,也会扫描@Configuration注解的类。
SpringBoot 项目在启动时会打印一个banner,如图所示:
这个 banner 是可以定制的,在 resources 目录下创建一个 banner.txt 文件,在这个文件中,写入的文本将在项目启动时打印出来。如果将 TXT 文件设置为艺术字体,有以下几个在线网站可供参考
以第一个网站为例,打开后输入要设置的文本,点击 “do it” 按钮,将生成的文本复制到 banner.txt 文件中,如图所示:
复制完成后再启动项目,就可以看到 banner 发生了改变,如图:
想取消 banner 展示也是可以的,修改项目启动类的 main 方法,代码如下:
public static void main(String[] args) {
SpringApplicationBuilder builder = new SpringApplicationBuilder(Chapter02Application.class);
builder.bannerMode(Banner.Mode.CONSOLE).run(args);
}
通过 SpringApplicationBuilder 来这是 bannerMode 为 OFF,这样启动时,banner 就不显示了。
server.port=8081
server.error.path=/error
server.servlet.session.timeout=30m
server.servlet.context-path=/chapter02
server.tomcat.uri-encoding=UTF-8
server.tomcat.max-threads=500
server.tomcat.basedir=/home/sang/tmp
代码解释:
当然,Web 容器相关的配置不止这些,这里只例举出了一些常用的配置,完整的配置可以参考官方文档 Appendix A. Common application properties一节。
keytool -genkey -alias tomcathttps -keyalg RSA -keysize 2048 -keystore sang.p12 -validity 365
命令解释:
在 cmd 窗口中,执行如上命令,在执行的过程中需要输入密钥口令等信息,根据提示输入即可。命令执行完成后,会在当前用户目录生成一个名为 sang.p12 的文件,将这个文件复制到项目根目录下,然后在 application-properties 中做如下配置:
server.ssl.key-store=sang.p12
server.ssl.key-alias=tomcathttps
server.ssl.key-store-password=123456
代码解释如下:
配置成功后,启动项目,在浏览器地址栏中输入 ”https://localhost:8081/chapter02/hello“ 来查看结果。注意,证书是自己生成的,不被浏览器认可,此时添加信任或者继续前进即可。
除了 Tomcat 外,也可以在 SpringBoot 中嵌入 Jetty,配置方式如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
主要是从 spring-boot-starter-web 中除去默认的 Tomcat,然后加入 Jetty 的依赖即可。此时启动项目,查看项目启动日志,如图所示:
Undertow 是一个红帽公司开源的 Java 服务器,具有非常好的性能,在 SpringBoot 中得到了很好的支持,配置方式与 Jetty 类似,代码如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
SpringBoot 中采用了大量的自动化配置,但是对开发者而言,在实际项目中不可避免会有一些需要自己手动配置,承载这些自定义配置的文件就是 resources 目录下的 application.properties 文件(也可以使用 YAML 配置来替代 application.properties 配置,YAML 配置将在后面介绍)。上文的 Web 容器配置中,已经见识到 application.properties 配置的基本用法了,本节会对 application.properties 的使用做进一步的介绍。
SpringBoot 项目中的 application.properties 配置文件一共可以出现在四个地方:
如果这 4 个位置中都有 application.properties 文件,那么加载的优先级从 1 到 4。SpringBoot 将按照这个优先级查找配置信息,并加载到 Spring Environment 中。如图:
如果开发者在开发中未使用 application.properties,而是使用了 application.yml 作为配置文件,那么配置文件的优先级如上图一致
默认情况下,SpringBoot 按照上图的顺序一次查找 application.properties 并加载。如果开发者不想使用 application.properteis 作为配置文件名,也可以自己定义。例如,在 resources 目录下创建一个配置文件 app.properties,然后将项目打成 jar 包,打包成功后,使用如下命令运行
java -jar chapter02-2-0.0.1-SNAPSHOT.jar --spring.config.name=app
在运行时再指定配置文件的明智。使用 spring.config.location 可以指定配置文件所在目录(注意需要以 / 结束),代码如下:
java -jar chapter02-2-0.0.1-SNAPSHOT.jar --spring.config.name=app --spring.config.location=classpath:/
无论是 Properties 配置还是 YAML 配置,最终都会被加载到 Spring Environment 中。Spring 提供了 @Value 注解以及 EnvironmentAware 接口来将 Spring Environment 中的数据注入到属性上,SpringBoot 对此进一步提供了类型安全配置属性(Type-safe Configuration Properties),这些即使在数据量非常庞大的情况下,也可以更加方便的将配置文件中的数据注入 Bean 中,考虑在 application.properties 中添加如下一段配置:
book.name=三国演义
book.author=罗贯中
book.price=30
将这一段配置数据注入到Bean中
@Component
@ConfigurationProperties(prefix = "book")
public class Book {
private String name;
private String author;
private Float price;
// getter/setter 省略
}
代码解释:
最后创建 BookController 进行简单的测试
@RestController
public class BookController {
@Autowired
private Book book;
@GetMapping("/book")
public String book(){
return book.toString();
}
}
YAML 是 JSON 的超集,简洁而强大,是一种专门用来书写配置文件的语言,可以替代 application.properties。在创建一个 SpringBoot 项目时,引入的 spring-boot-starter-web 依赖间接的引入了 snakeyaml 依赖,snakeyaml 会实现对 YAML 配置的解析。YAML 的使用非常简单,利用缩进来表示层级关系,并且大小写敏感。在 SpringBoot 项目中使用 YAML 只需要在 resources 目录下创建一个 application.xml 文件即可,然后向 application.yml 中添加如下配置:
server:
port: 80
servlet:
context-path: /chapter02
tomcat:
uri-encoding: UTF-8
这一段配置等效于 application.properties 中的如下配置:
server.port=8081
server.servlet.context-path=/chapter02
server.tomcat.uri-encoding=UTF-8
此时可以将 resources 目录下的 application.properties 文件删除,完全使用 YAML 完成文件的配置。
YAML 不仅可以配置常规属性,也可以配置复杂属性,例如下面一组配置:
my:
name: Geoffrey
address: China
像 Properties 配置文件一样,这一段配置也可以注入一个 Bean 中,代码如下:
@Component
@ConfigurationProperties(prefix = "my")
public class User {
private String name;
private String address;
// getter/setter 省略
}
YMAL 还支持列表的配置,例如下面一组配置:
my:
name: Geoffrey
address: China
favorites:
- 足球
- 徒步
- Coding
这一组配置可以注入如下 Bean 中:
@Component
@ConfigurationProperties(prefix = "my")
public class User {
private String name;
private String address;
private List<String> favorites;
// getter/setter 省略
}
YAML 还支持更复杂的配置,即集合中也可以是一个对象,例如下面一组配置:
my:
users:
- name: Geoffrey
address: China
favorites:
- 足球
- 徒步
- Coding
- name: sang
address: LA
favorites:
- 阅读
- 吉他
这组配置在集合中存放的是一个对象,因此可以注入如下集合中:
@Component
@ConfigurationProperties(prefix = "my")
public class Users {
private List<User> users;
// getter/setter 省略
}
在 SpringBoot 中使用 YAML 更方便,但是 YAML 也有一些缺陷,例如无法使用 @PropertySource 注解在家 YAML 文件,如果项目中有这种需求,还是需要使用 Properties 格式的配置文件。
开发者在项目发布之前,一般需要频繁的在开发环境、测试环境以及生产环境之间进行切换,这个时候大量的配置需要频繁修改,例如数据库配置、redis 配置、jms 配置、MongoDB 配置等。频繁修改带来了巨大的工作量,Spring 对此提供了解决方案(@Profile 注解),SpringBoot 则更进一步提供了更加简洁的解决方案,SpringBoot 中约定的不同环境下配置文件名称规则为 application-{profile}.properties,profile 占位符表示当前环境名称,具体配置步骤如下:
server.port=8080
application-prod.properties 文件的内容如下:
server.port=80
这里为了简化问题并且容易看到效果,两个配置文件中主要修改了一下项目端口号。
2. 配置application.properties
然后在 application.properties 中进行配置:
server.profiles.active=dev
这个表示使用 application-dev.properties 配置文件启动项目,若将 dev 改为 prod,则表示使用 application-prod.properties 启动项目。项目启动成功后,就可以通过相应的端口进行访问了。
3. 在代码中设置
对于第二步在 application.properties 中添加配置,我们也可以在代码中添加配置来完成,在启动类的 main 方法中添加上如下代码,可以替换第二步的配置:
public static void main(String[] args) {
SpringApplicationBuilder builder = new SpringApplicationBuilder(Chapter02Application.class);
builder.application().setAdditionalProfiles("prod");
builder.run(args);
}
java -jar chapter02-2.0.0-SNAPSHOT.jar --spring.profiles.active=prod
主要介绍了 SpringBoot 常见的基础性配置,包括依赖管理的多种方式,如入口类注解、banner 定制、Web 容器配置以及 Properties 配置 和 YAML 配置等,这些配置将是后面章节的基础,第三章将介绍 SpringBoot 整合视图层技术。