Spring Boot 2.1.0版本增加和修改了哪些功能
简要概括
正在开发Spring Boot 2.1版本。GitHub上创建了M1、M2、M3、M4和RC1等里程碑,其中M1在2018年7月30日发布。
本文总结了每个里程碑中涉及的问题,以及添加或更改的功能。以下是我个人关注的一些内容。
环境
-
- Windows 10 Professional
-
- OpenJDK 11 (build 11+28)
-
- Spring Boot 2.1.0 RELEASE
-
- MySQL CE 8.0.12
-
- JUnit 5.2.0
- Maven 3.5.4
> java -version
openjdk version "11" 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)
Spring Boot 2.1.0 正式发布
-
- Spring Boot 2.1 Release Notes
- Spring Boot 2.1.0
2018年10月30日,Spring Boot 2.1.0版本发布了。
Spring Boot 2.1.0 RC1 这个版本
-
- Spring Boot 2.1.0 RC1 Release Notes
-
- 2.1.0.RC1 Milestone
- Spring Boot 2.1.0 RC1 available now
Thymeleaf 3.0.10 配置
Thymeleaf的设置参数增加了两个。
spring.thymeleaf.render-hidden-markers-before-checkboxes=false
应该在复选框元素之前渲染作为复选框标记的隐藏表单输入。
spring.thymeleaf.servlet.produce-partial-output-while-processing=true
Thymeleaf应该尽快开始编写部分输出,还是等到模板处理完才缓冲。
转变从thymeleaf-extras-springsecurity4到thymeleaf-extras-springsecurity5。
Thymeleaf和Spring Security 5的整合工具thymeleaf-extras-springsecurity5已经新增了。
Thymeleaf 扩展版 Springsecurity5
增加对自定义Flyway配置的支持。
新增了可以自定义Flyway配置的FlywayConfigurationCustomizer。
@Bean
public FlywayConfigurationCustomizer customizer() {
return (configuration) -> configuration.connectRetries(5).ignorePendingMigrations(true);
}
GitProperties和BuildProperties支持编码。
现在可以在build-info.properties和git.properties的输出中指定文件编码。
# PROJECT INFORMATION ({sc-spring-boot-autoconfigure}/info/ProjectInfoProperties.{sc-ext}[ProjectInfoProperties])
spring.info.build.encoding=UTF-8 # File encoding.
spring.info.git.encoding=UTF-8 # File encoding.
Spring Boot 2.1.0 M4:春季引进2.1.0 M4版本。
-
- Spring Boot 2.1.0 M4 Release Notes
-
- 2.1.0.M4 Milestone
- Spring Boot 2.1 M4 available now
为Spring Data JDBC添加支持
新的启动器spring-boot-starter-data-jdbc已经支持Spring Data JDBC。
春季引导JDBC启动器
支持SAP Hana数据库
SAP Hana数据库(HDB)现已支持内存数据库。
SAP("HDB", "com.sap.db.jdbc.Driver", "com.sap.db.jdbcext.XADataSourceSAP", "SELECT 1 FROM DUMMY"),
SAP HANA是一种内存数据库。
SAP HANA的核心是关系数据库管理系统(RDBMS)。它将OLAP和OLTP处理结合到一个单一的内存数据库中,消除了磁盘瓶颈,提供了突破性能。这个ACID兼容的内存列式数据库存储压缩数据,并提供多处理器核之间的并行处理,支持单指令多数据(SIMD)指令。
@SpringBootTest注解设置randomPort为true时,不会为actuator生成随机端口。
现在在Spring Boot测试中,除了可以生成server.port之外,还可以生成用于management.server.port的随机端口。
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
Spring Boot 2.1.0 M3 可以改写成 “春季引导 2.1.0 M3” 。
-
- Spring Boot 2.1.0 M3 Release Notes
-
- 2.1.0.M3 Milestone
- Spring Boot 2.1 M3 available now
增加对日志组的支持
- 26.5 Log Groups
现在可以将相关的记录器整理到日志组中进行设置。
在日志组中定义一个希望总结如下的记录器。{日志组名称}可以是任意字符串。
logging.group.{ロググループ名} = {ロガー1}, {ロガー2}, {ロガーn}
将调试级别设置为{日志组名称}。
logging.level.{ロググループ名} = debug
Spring Boot的预定义日志组
有两个预定义的日志组,一个是web日志组,一个是sql日志组。
设置实例
logging.level.sql = debug
如果应用程序将以root身份运行,从启动脚本中输出一个警告。
当以root用户身份运行Spring Boot应用时,启动脚本(launch.script)会开始输出警告。
# Issue a warning if the application will run as root
[[ $(id -u ${run_user}) == "0" ]] && { echoYellow "Application is running as root (UID 0). This is considered insecure."; }
在使用@MockBean时,考虑使用@Primary注解,使@MockBean/@SpyBean的行为保持一致。
现在,拥有@MockBean / @SpyBean注解的字段将优先注入带有@Primary注解的对象。
@SpringBootTest
public class ExampleServiceTests {
@SpyBean(classes = {ExampleService.class})
ExampleService service;
@Test
public void test() {
System.out.println(service.getName());
// example2
}
interface ExampleService {
String getName();
}
static class ExampleServiceImpl implements ExampleService {
private String name;
public ExampleServiceImpl(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
}
@Configuration
static class ExampleConfigure {
@Bean
public ExampleService example1() {
return new ExampleServiceImpl("example1");
}
@Bean
@Primary
public ExampleService example2() {
return new ExampleServiceImpl("example2");
}
}
}
在JPA启动器中提供所需的依赖项,以使其适用于Java 9及更高版本。
如果在Java 9及以后的版本中使用JPA(Hibernate ORM),以前需要将jaxb-api作为项目的依赖项包括其中,但现在spring-boot-starter-data-jpa已经添加了对jaxb-api的依赖关系,所以无需明确指定该依赖项。
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
在SPRING_APPLICATION_JSON中,当语法无效时抛出一个异常。
如果指定的JSON字符串无法解析为SPRING_APPLICATION_JSON,以前只会输出警告级别的日志,但现在将抛出JsonParseException。
SPRING_APPLICATION_JSON 的中文释义。
24. 外部化配置
SPRING_APPLICATION_JSON属性可以通过环境变量在命令行上提供。例如,您可以在一个UNIX shell中使用以下命令行:
$ SPRING_APPLICATION_JSON='{“acme”:{“name”:”test”}}’ java -jar myapp.jar
当@WebMvcTest.secure为true时,请包含Web安全配置类。
现在,实现了WebSecurityConfigurer接口的安全设置类将在@WebMvcTest中得到应用。
过去,在@WebMvcTest中进行测试,并对安全设置(包括认证、授权和访问控制等)进行测试时,需要额外导入安全设置。
网站安全配置器
public interface WebSecurityConfigurer<T extends SecurityBuilder<javax.servlet.Filter>> extends SecurityConfigurer<javax.servlet.Filter,T>
WebSecurityConfigurerAdapter: 网络安全配置适配器
@Order(value=100)
public abstract class WebSecurityConfigurerAdapter extends java.lang.Object implements WebSecurityConfigurer<WebSecurity>
弃用WebMvcTest和AutoConfigureMockMvc上的’secure’。
@WebMvcTest的secure方法已经标记为废弃。
在以前的@WebMvcTest测试中,如果想忽略安全设置,可以将其设置为false。
@WebMvcTest(secure = false)
在@WebFluxTest中支持WebExceptionHandler
实现了WebExceptionHandler接口的异常处理器类现在可以支持@WebFluxTest。
网络异常处理程序
public interface WebExceptionHandler
春季启动2.1.0 M2
-
- Spring Boot 2.1.0 M2 Release Notes
-
- 2.1.0.M2 Milestone
- Spring Boot 2.1 M2 available now
支持FormContentFilter,因为HttpPutFormContentFilter现已过时。
HttpPutFormContentFilter的使用已被弃用,改为支持FormContentFilter。
属性名称也发生了变化。
spring.mvc.formcontent.putfilter.enabled=true # Whether to enable Spring's HttpPutFormContentFilter.
现在开始使用以下属性进行设置。
spring.mvc.formcontent.filter.enabled=true # Whether to enable Spring's FormContentFilter.
在代码中增加一个属性来禁用HiddenHttpMethodFilter。
添加了一个禁用HiddenHttpMethodFilter的属性。
spring.mvc.hiddenmethod.filter.enabled=true # Whether to enable Spring's HiddenHttpMethodFilter.
调整和审查记录输出
新增了用于调整WebMvc和WebFlux日志输出的属性。
# INSIGHTS
spring.insights.web.log-request-details=false # Whether logging of (potentially sensitive) request details at DEBUG and TRACE level is allowed.
在M3中,属性名称已更改。
spring.http.log-request-details=false
当处于spring-boot-devtools启用状态时,将此参数设置为true,将使post参数被输出到日志中。
例如,发送以下类似的POST请求
curl -v -d "message=test" -d "param1=123" -d "param2=abc" -X POST "http://localhost:9000/app/echo3"
以下内容将被输出到日志中。
POST "/app/echo3", parameters={message:[test], param1:[123], param2:[abc]}
如果为 FALSE(默认),则会以以下方式屏蔽并输出。
POST "/app/echo3", parameters={masked}
在M4中删除了属性。
- Reconsider DEBUG web logs enabled by default when devtools is present
允许通过环境配置Spring Data JPA的引导模式。
新增了控制JPA存储库初始化时机的属性。可选择的时机有以下3种,其中默认为传统设置。
-
- default
-
- deferred
- lazy
spring.data.jpa.repositories.boostrap-mode=default # Bootstrap mode for JPA repositories.
默认
Bootstrapping Spring Data repositories in DEFAULT mode.
Finished Spring Data repository scanning in 87ms. Found 2 repository interfaces.
// ...省略...
延期
延迟JPA仓库的初始化时间。
Bootstrapping Spring Data repositories in DEFERRED mode.
Finished Spring Data repository scanning in 73ms. Found 2 repository interfaces.
// ...省略...
Triggering deferred initialization of Spring Data repositories…
// ...省略...
Spring Data repositories initialized!
// ...省略...
懒惰 duò)
当 JPA 仓库被使用时,它会被初始化。
Bootstrapping Spring Data repositories in LAZY mode.
Finished Spring Data repository scanning in 98ms. Found 2 repository interfaces.
提供属性来设置 Spring TaskScheduler 的线程数。
现在可以通过属性设置TaskScheduler的线程数。
spring.task.scheduling.pool.size=1 # Maximum allowed number of threads.
spring.task.scheduling.thread-name-prefix=scheduling- # Prefix to use for the names of newly created threads.
允许使用切片测试注释来配置属性。
在@SpringBootTest中,我们可以指定配置文件,其他的测试注解(如JdbcTests和DataJpaTest)也可以同样指定配置文件。
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
, properties = "spring.active.profiles=test")
以前需要像下面这样写:
@ActiveProfiles("test")
@DataJpaTest
从现在开始,可以按照以下方式书写。
@DataJpaTest("spring.profiles.active=test")
以下是已完成的标注对应内容:
-
- @JdbcTests
-
- @DataJpaTest
-
- @RestClientTest
-
- @WebMvcTest
-
- @WebFluxTest
-
- @DataLdapTest
-
- @DataMongoTest
-
- @DataNeo4jTest
-
- @DataRedisTest
-
- @JooqTest
- @JsonTest
提供一个丰富的类型和转换器,用于配置字节数的属性。
现在可以在指定字节数的属性中使用10MB或1GB等指定单位。
可用的单位如下所示。
B for bytes
KB for kilobytes
MB for megabytes
GB for gigabytes
TB for terabytes
顺便提一下,在使用IntelliJ IDEA补全属性名时,如果显示的类型是DataSize,可以使用这些表示法来描述值。

自动配置一个合理的任务执行器
TaskExecutor 现在支持自动配置。您可以使用以下属性进行调整。
# TASK EXECUTION
spring.task.pool.allow-core-thread-timeout=true # Whether core threads are allowed to time out. This enables dynamic growing and shrinking of the pool.
spring.task.pool.core-size=8 # Core number of threads.
spring.task.pool.keep-alive=60s # Time limit for which threads may remain idle before being terminated.
spring.task.pool.max-size= # Maximum allowed number of threads. If tasks are filling up the queue, the pool can expand up to that size to accommodate the load. Ignored if the queue is unbounded.
spring.task.pool.queue-capacity= # Queue capacity. A unbounded capacity does not increase the pool and therefore ignores the "max-size" parameter.
spring.task.thread-name-prefix=executor- # Prefix to use for the names of newly created threads.
使最大吞咽大小易于配置
现在可以通过server.tomcat.max-swallow-size属性来设置Tomcat的maxSwallowSize属性。
server.tomcat.max-swallow-size=2MB # Maximum amount of request body bytes to swallow.
Tomcat 9的默认大小如下所引用,为2,097,152字节(2MB)。
https://tomcat.apache.org/tomcat-9.0-doc/config/http.html
这是指Tomcat在处理异常上传时,允许吞噬的最大请求主体字节数(不包括传输编码开销)。异常上传是指当Tomcat知道请求主体将被忽略,但客户端仍然发送请求主体的情况。如果Tomcat不吞噬请求主体,客户端可能无法看到响应。如果不指定,将使用默认值2097152字节(2兆字节)。小于零的值表示不应强制执行任何限制。
升级到Lombok 1.18.2
我已将Lombok 1.16.x升级到Lombok 1.18.2。
Lombok 1.18.x的破坏性变更是不再默认生成私有无参数构造函数。
变更日志:
重大变更:1.16.22 版本引入的配置项 lombok.noArgsConstructor.extraPrivate 现在默认为 false。问题编号:#1708。
Spring Boot 2.1.0 M1的版本
-
- Spring Boot 2.1.0 M1 Release Notes
-
- 2.1.0.M1 Milestone
- Spring Boot 2.1 M1
PR #9714:JVM参数和选项
在使用Spring Boot Maven Plugin来运行应用程序时,您可以使用systemPropertyVariables设置系统属性。
(另外,jvmArguments在以前就可使用。)
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<jvmArguments>-Dprop1="value1" -Dprop2="value2"</jvmArguments>
<systemPropertyVariables>
<prop3>value3</prop3>
<prop4>value4</prop4>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
System.out.println("prop1:[" + System.getProperty("prop1") + "] prop2:[" + System.getProperty("prop2") + "]");
// → prop1:[value1] prop2:[value2]
System.out.println("prop3:[" + System.getProperty("prop3") + "] prop4:[" + System.getProperty("prop4") + "]");
// → prop3:[value3] prop4:[value4]
支持Hibernate 5.3.0 / JPA 2.2(使用JDK8的流进行分页)
由于支持JPA 2.2,您可以将查询结果作为流进行接收。
此外,正如评论-359568785中所提到的,非事务中也支持Spring Framework 5.0。
关于JPA 2.2 API,在Spring Framework 5.0中已经明确支持,包括在非事务场景下对结果流的正确处理。
查询.getResultStream
default Stream getResultStream()
TypedQuery.getResultStream 可以用以下方式翻译成中文:resultStream = TypedQuery.getResultStream
default Stream<X> getResultStream()
另外,按照JavaDoc的规定, 默认实现是将其委托给getResultList,因此不会有任何改变,与JPA 2.1 相同。
default Stream getResultStream() {
return getResultList().stream();
}
在 Hibernate ORM 5.3.3 版本中,此方法被重写如下。
(stream() 方法实现于 AbstractProducedQuery)
Stream<R> stream();
default Stream<R> getResultStream() {
return stream();
}
在yml配置文件的匹配中支持AND运算符。
在应用程序设置文件(yml)中,已经支持使用AND操作符(&)进行配置文件匹配。
spring:
profiles:
active: dev
# ...省略...
---
spring:
profiles: dev & app1
server:
port: 9001
---
spring:
profiles: dev & app2
server:
port: 9002
当以以下方式指定两个配置文件并运行时,将应用与满足该条件的配置文件相匹配的设置。在此示例中,应用程序将使用端口9001。
> mvnw spring-boot:run -Dspring-boot.run.profiles=dev,app1
顺便提一下,可用于配置匹配的运算符不是YAML的功能,而是Spring Framework和Spring Boot自有的。以下是可用的运算符有:
& AND
| OR
! NOT
在@Profile注解中支持AND运算符。
即使在@Profile中也支持AND运算符,但这个问题已经在Spring Framework的5.1 RC1版本中解决了。
public interface AppCondition {
String name();
}
当指定 “dev,app1” 作为运行时的配置文件时,会注册该配置.
@Component
@Profile("dev & app1")
public class DevApp1 implements AppCondition {
@Override
public String name() {
return "app1";
}
}
当在运行时的配置文件中指定了”profile”为”dev,app2″时,将进行注册。
@Component
@Profile("dev & app2")
public class DevApp2 implements AppCondition {
@Override
public String name() {
return "app2";
}
}
使用Maven插件设置环境变量。
在使用Spring Boot Maven插件运行应用程序时,可以使用environmentVariables设置环境变量。
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<environmentVariables>
<ENV1>value1</ENV1>
<ENV2>value2</ENV2>
</environmentVariables>
</configuration>
</plugin>
</plugins>
</build>
System.out.println("ENV1: [" + environment.getProperty("ENV1") + "] ENV2: [" + environment.getProperty("ENV2") + "]");
// → ENV1: [value1] ENV2: [value2]
在WebMvcTest中添加对PageableHandlerMethodArgumentResolver的支持。
由于@WebMvcTest支持PageableHandlerMethodArgumentResolver,在控制器的单元测试中,我们可以像下面这样编写测试代码来接收一个Pageable参数的处理方法。
示例代码
考试对象
@RestController
public class EchoController {
@GetMapping(path = "page")
public ResponseEntity<Pageable> page(Pageable page) {
return ResponseEntity.ok(page);
}
}
localhost:9000/page?page=0&size=20&sort=id,desc
↓ response
Page request [number: 0, size 20, sort: id: DESC]
测试代码
@WebMvcTest(EchoController.class)
public class EchoControllerTests {
@Autowired
private MockMvc mvc;
@Test
public void page() throws Exception {
mvc.perform(get("/page")
.param("page", "0")
.param("size", "20")
.param("sort", "id,desc"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.pageNumber", is(0)))
.andExpect(jsonPath("$.pageSize", is(20)))
.andExpect(jsonPath("$.offset", is(0)))
.andExpect(jsonPath("$.paged", is(true)))
.andExpect(jsonPath("$.unpaged", is(false)))
.andExpect(jsonPath("$.sort.sorted", is(true)))
.andExpect(jsonPath("$.sort.unsorted", is(false)))
.andDo(print());
}
}
为setConnectTimeout和setReadTimeout添加持续时间支持。
RestTemplateBuilder(Spring Boot Docs 2.1.0.M1 API)的解释如下:
RestTemplateBuilder现在可以使用Duration类型指定连接和读取超时时间。同时,使用现有的以毫秒为单位的int类型指定超时时间的方法已被弃用。
已存在的方法已被废弃
所有这些方法都以毫秒为单位指定数值。
@Deprecated
public RestTemplateBuilder setConnectTimeout(int connectTimeout)
设置底层ClientHttpRequestFactory的连接超时时间(以毫秒为单位)。
@Deprecated
public RestTemplateBuilder setReadTimeout(int readTimeout)
在底层的ClientHttpRequestFactory上设置读取超时时间,以毫秒为单位。
从2.1.0 M1版本开始添加的方法。
接收 Duration 类型。
public RestTemplateBuilder setConnectTimeout(Duration connectTimeout)
public RestTemplateBuilder setReadTimeout(Duration readTimeout)
Sample code (Chinese: 示例代码)
RestTemplate restTemplate = new RestTemplateBuilder()
.setConnectTimeout(Duration.ofSeconds(3))
.setReadTimeout(Duration.ofSeconds(3))
.build();
支持Logback中的配置文件表达式。
在logback-spring.xml文件的标签中,现在支持使用AND运算符(&)进行profile匹配。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<springProfile name="dev & app1">
<property name="logFilePath" value="./log/app1/" />
</springProfile>
<springProfile name="dev & app2">
<property name="logFilePath" value="./log/app2/" />
</springProfile>
</configuration>
使用@ExtendWith(SpringExtension.class)来给@…Test进行注解
如果同时使用JUnit5和Spring Boot的测试注解(如@SpringBootTest和@WebMvcTest等),可以省略@ExtendWith。
@ExtendWith(SpringExtension.class)
@SpringBootTest
public class ApplicationTests {
@Test
public void contextLoads() {
}
}
可以用以下方式来写上述的代码。
@SpringBootTest
public class ApplicationTests {
@Test
public void contextLoads() {
}
}
当使用同时时,可省略注解。
-
- SpringBootTest
-
- WebMvcTest
-
- WebFluxTest
-
- RestClientTest
-
- DataJpaTest
-
- DataRedisTest
-
- DataNeo4jTest
-
- DataMongoTest
-
- DataLdapTest
-
- JdbcTest
- JooqTest
不可省略的注释
- JsonTest