Spring Boot 1.5的主要改变

我想通过发布说明来介绍Spring Boot 1.5.RC1的主要变化(目前1.5版本的正式发布日期设定为2017年1月25日,但可能还会有更多变化…)。

注意事项:

2017/01/15 添加了「OAuth 2 资源过滤器」。(由于 RC1 发布后修正了发布说明)

升级至 Spring Boot 1.4

主要的变更点如下,在从Spring Boot 1.4迁移至Spring 1.5时可能会产生影响。

Spring Boot 1.4的不予支持

「Spring Boot 1.4中弃用的API和属性键」将在1.5中被删除。
顺便说一下,HornetQ和Velocity将完全不被支持,所以如果计划升级到Spring Boot 1.5,最好现在考虑措施。

更名的起始球员

如果您仍在使用「Spring Boot 1.4中更改名称并被视为过时的starter构件」,它将在1.5中被删除。如果您仍在使用这些构件…

spring-boot-starter-ws は spring-boot-starter-web-services

spring-boot-starter-redis は spring-boot-starter-data-redis

需要确保使用这个。

春季会议存储

在Spring Boot 1.4版本之前,如果在Spring Session中使用Redis作为会话存储,无需进行特殊配置,Redis的设置会自动应用。但是从1.5版本开始,需要明确指定会话存储类型(store-type),否则会报错(准确地说…在Spring Boot 1.4版本时,会输出警告日志)。

所以…如果没有明确定义 store-type 的情况下…

spring.session.store-type=redis

需要添加。

请注意:

如果您从未使用过Spring Session,请尝试使用「Spring Boot + Spring Session」创建可扩展的状态管理Web应用程序。

执行器安全

:hearts:

注意:

如果在启用了认可控制的状态下访问敏感的Actuator端点,从Spring Boot 1.4到1.5之前,默认情况下需要用具有ADMIN角色的用户进行访问,从1.5开始需要用具有ACTUATOR角色的用户进行访问。
请注意,可以通过属性文件更改能够访问Actuator敏感端点的角色,所以如果想要与1.4版本相同的行为,请添加以下属性。

src/main/resources/application.properties
management.security.roles=ADMIN

内存度量存储库

在Spring Boot 1.4版本之前,使用InMemoryMetricRepository类来实现MultiMetricRepository接口,但从1.5版本开始,新增了InMemoryMultiMetricRepository类来实现MultiMetricRepository接口,并且规定InMemoryMetricRepository只能在InMemoryMultiMetricRepository类内部使用。所以…由于是通过MetricRepository和MultiMetricRepository接口来使用的,所以用户不需要意识到这个变更…大概是这个意思吧。

spring.jpa.database 的中文翻译为:春季.jpa.数据库

从Spring Boot 1.4版本开始,需要指定一个属性(spring.jpa.database),用来指定JPA实现提供者(比如Hibernate ORM)内使用的数据库类型。但是从1.5版本开始,可以省略这个属性。省略时,会根据spring.datasource.url中指定的URL来确定数据库的类型。

spring.datasource.url=jdbc:postgresql://localhost:5432/spring
#spring.jpa.database=postgresql # ← Spring Boot 1.5からURLから自動検出されるため省略できる!!

@整合组件扫描

从Spring Boot 1.5开始,带有@IntegrationComponentScan注解的类将自动配置,因此如果符合”Spring Boot推荐的项目结构”,可以省略对@IntegrationComponentScan的指定。

应用程序启动事件

从Spring Boot 1.5开始,通知Spring Boot应用程序启动的事件类的名称将从ApplicationStartedEvent更改为ApplicationStartingEvent。由于ApplicationStartedEvent已经被弃用的API,因此建议进行重构,使用ApplicationStartingEvent。

春天整合入门

从Spring Boot 1.5开始,spring-boot-starter-integration将不再包含spring-integration-jmx。如果使用了spring-integration-jmx,需要单独添加依赖项。

默认情况下不包括开发工具。

从Spring Boot 1.5开始,spring-boot-devtools不再被打包到jar或war文件中。
如果想要使用spring-boot-devtools提供的远程功能,可以在Maven或Gradle的Spring Boot插件中将excludeDevtools选项设置为false,这样spring-boot-devtools就可以被打包到jar或war文件中。

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <excludeDevtools>false</excludeDevtools>
    </configuration>
</plugin>

Gradle 1.x can be paraphrased in Chinese as “Gradle 1.x 版本”.

从Spring Boot 1.5开始,由于Gradle的Spring Boot插件不再支持Gradle 1.x版本,因此需要使用Gradle 2.9+版本的Gradle。

远程CRaSH shell

从Spring Boot 1.5开始,”通过SSH访问Spring Boot应用程序以查看内部状态的功能”被标记为不推荐使用,并将在Spring Boot 2.0中被废弃。

OAuth 2 资源过滤器

在Spring Boot 1.4中,如果同时使用Actuator的自动配置功能和Spring Security OAuth2提供的资源服务器配置功能@EnableResourceServer,不管Actuator功能的每个端点的授权定义如何,都会要求进行OAuth 2的认证(即访问令牌的认证)(gh-5072)。

换言之,使用默认设置,敏感的执行器端点(默认为/health和/info)无法在没有身份验证的情况下访问。

$ curl -s -D - http://localhost:8080/health
HTTP/1.1 401
WWW-Authenticate: Bearer realm="null", error="unauthorized", error_description="Full authentication is required to access this resource"
...

{"error":"unauthorized","error_description":"Full authentication is required to access this resource"}

这个动作从Spring Boot 1.5开始得到改进。

sensitiveなエンドポイント(デフォルトだと/health と /info 以外)はBasic認証

$ curl -s -D – http://localhost:8080/env
HTTP/1.1 401
WWW-Authenticate: Basic realm=”Spring”
….

{“timestamp”:1484460898978,”status”:401,”error”:”Unauthorized”,”message”:”Full authentication is required to access this resource”,”path”:”/env”}

sensitiveでないエンドポイント(デフォルトだと/health と /info)は認証なし

$ curl -s -D – http://localhost:8080/health
HTTP/1.1 200

{“status”:”UP”}

ユーザ定義のリソースのエンドポイント(デフォルトだと上記以外)はOAuth2認証(アクセストークン認証)

$ curl -s -D – http://localhost:8080/hello
HTTP/1.1 401
WWW-Authenticate: Bearer realm=”null”, error=”unauthorized”, error_description=”Full authentication is required to access this resource”
….

{“error”:”unauthorized”,”error_description”:”Full authentication is required to access this resource”}

将变得可以通过网络访问。

这是由于Spring Security OAuth2和Spring Boot Actuator在应用认证和授权设置时的顺序问题。在Spring 1.4中,顺序是”Spring Security OAuth2 → Spring Boot Actuator”,但在Spring Boot 1.5中,已经改进为”Spring Boot Actuator → Spring Security OAuth2″的顺序。如果想要实现与Spring Boot 1.4相同的行为,可以通过修改属性文件来改变Spring Security OAuth2配置的应用顺序。

security.oauth2.resource.filter-order=3

新进展和值得关注的

以下是Spring Boot 1.5版本中的新功能和改进主要变更。

请参考「Spring Boot 1.5配置变更日志」,了解有关在Spring Boot 1.5中添加、废止和不推荐使用的属性键的情况。

第三方库升级

第三方制作的库或者Maven插件的版本已经更新。

详细来说,、、、

    • Spring Data Ingalls

 

    • Jetty 9.4

 

    • JooQ 3.9

 

    • AssertJ 2.6.0

 

    • Hikari 2.5

 

    • Neo4J 2.1

 

    etc ..

是的。

日志记录终端

Spring Actuator中增加了用于确认日志记录器和更改日志级别的端点(/loggers)。

在具体说一下……

    • ロガーの一覧確認用の「GET /loggers」

 

    • 特定のロガーの確認用の「GET /loggers/{ロガー名}」

 

    特定のロガーのログレベル変更用の「POST /loggers/{ロガー名}」

有一种选择可供使用。

那么,让我们实际上来确认和更改com.example的日志级别。原本应该进行授权控制,但在这里我们将禁用授权控制(management.security.enabled=false)以便进行操作确认。

$ curl -s http://localhost:8080/loggers/com.example
{"configuredLevel":null,"effectiveLevel":"INFO"}
$ curl -s http://localhost:8080/loggers/com.example -X POST -H "Content-Type: application/json" -d '{"configuredLevel": "DEBUG"}'
$ curl -s http://localhost:8080/loggers/com.example
{"configuredLevel":"DEBUG","effectiveLevel":"DEBUG"}

注意:
顺便一提,在更新时指定的日志级别必须使用大写字母,否则会发生IllegalArgumentException异常。我认为这是一个错误,所以我提交了一个Pull Request(spring-boot#gh-7914)。
2017/1/22 追加
Pull Request已经合并,所以上述问题将在1.5.0.RELEASE版本中得到解决。

:hearts:

Apache Kafka的支持

从Spring Boot 1.5版本开始,支持自动配置Spring for Apache Kafka。

注意:

Apache Kafka 是一个开源的分布式消息系统,2011年由LinkedIn发布,旨在收集和传递来自Web服务等的大容量数据(如日志和事件),以实现高吞吐量/低延迟。在这里,我们将省略关于Apache Kafka和Spring Kafka的说明和用法的解释。

将spring-kafka添加到依存项目中

<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
</dependency>

根据需要,通过设置spring.kafka.*属性,可以实现通过Apache Kafka进行消息通信。当然,还需要单独启动Kafka Cluster(Broker)。

# APACHE KAFKA (KafkaProperties)
spring.kafka.bootstrap-servers= # Comma-delimited list of host:port pairs to use for establishing the initial connection to the Kafka cluster.
spring.kafka.client-id= # Id to pass to the server when making requests; used for server-side logging.
spring.kafka.consumer.auto-commit-interval= # Frequency in milliseconds that the consumer offsets are auto-committed to Kafka if 'enable.auto.commit' true.
spring.kafka.consumer.auto-offset-reset= # What to do when there is no initial offset in Kafka or if the current offset does not exist any more on the server.
spring.kafka.consumer.bootstrap-servers= # Comma-delimited list of host:port pairs to use for establishing the initial connection to the Kafka cluster.
spring.kafka.consumer.client-id= # Id to pass to the server when making requests; used for server-side logging.
spring.kafka.consumer.enable-auto-commit= # If true the consumer's offset will be periodically committed in the background.
spring.kafka.consumer.fetch-max-wait= # Maximum amount of time in milliseconds the server will block before answering the fetch request if there isn't sufficient data to immediately satisfy the requirement given by "fetch.min.bytes".
spring.kafka.consumer.fetch-min-size= # Minimum amount of data the server should return for a fetch request in bytes.
spring.kafka.consumer.group-id= # Unique string that identifies the consumer group this consumer belongs to.
spring.kafka.consumer.heartbeat-interval= # Expected time in milliseconds between heartbeats to the consumer coordinator.
spring.kafka.consumer.key-deserializer= # Deserializer class for keys.
spring.kafka.consumer.max-poll-records= # Maximum number of records returned in a single call to poll().
spring.kafka.consumer.value-deserializer= # Deserializer class for values.
spring.kafka.listener.ack-count= # Number of records between offset commits when ackMode is "COUNT" or "COUNT_TIME".
spring.kafka.listener.ack-mode= # Listener AckMode; see the spring-kafka documentation.
spring.kafka.listener.ack-time= # Time in milliseconds between offset commits when ackMode is "TIME" or "COUNT_TIME".
spring.kafka.listener.concurrency= # Number of threads to run in the listener containers.
spring.kafka.listener.poll-timeout= # Timeout in milliseconds to use when polling the consumer.
spring.kafka.producer.acks= # Number of acknowledgments the producer requires the leader to have received before considering a request complete.
spring.kafka.producer.batch-size= # Number of records to batch before sending.
spring.kafka.producer.bootstrap-servers= # Comma-delimited list of host:port pairs to use for establishing the initial connection to the Kafka cluster.
spring.kafka.producer.buffer-memory= # Total bytes of memory the producer can use to buffer records waiting to be sent to the server.
spring.kafka.producer.client-id= # Id to pass to the server when making requests; used for server-side logging.
spring.kafka.producer.compression-type= # Compression type for all data generated by the producer.
spring.kafka.producer.key-serializer= # Serializer class for keys.
spring.kafka.producer.retries= # When greater than zero, enables retrying of failed sends.
spring.kafka.producer.value-serializer= # Serializer class for values.
spring.kafka.properties.*= # Additional properties used to configure the client.
spring.kafka.ssl.key-password= # Password of the private key in the key store file.
spring.kafka.ssl.keystore-location= # Location of the key store file.
spring.kafka.ssl.keystore-password= # Store password for the key store file.
spring.kafka.ssl.truststore-location= # Location of the trust store file.
spring.kafka.ssl.truststore-password= # Store password for the trust store file.
spring.kafka.template.default-topic= # Default topic to which messages will be sent.

Cloud Foundry扩展程序

:hearts:

只需要一种选择的本地化中文释义:
稍作说明,当在Cloud Foundry实例上部署Spring Boot应用时,会公开一个名为“/cloudfoundryapplication”的特殊端点(无法从外部访问的端点),通过该端点可以进行Spring Boot应用的状态确认和更改,这是通过Cloud Foundry的运维功能实现的。因此,即使对于Actuator端点应用了授权控制,从Cloud Foundry的运维功能仍然可以访问。

注意事项:

值得一提的是,在当前时点上,似乎只有Pivotal Cloud Foundry提供与Spring Boot的Actuator功能集成的UI支持。但是需要注意的是,Spring Boot本身并没有针对Pivotal Cloud Foundry进行特别的实现,因此在除了Pivotal Cloud Foundry以外的Cloud Foundry上也可以通过类似的方式实现相同的功能。

LDAP支援

从Spring Boot 1.5版本开始,支持”用于LDAP集成的Starter(spring-boot-starter-data-ldap)以及针对spring-data-ldap的自动配置机制”。此外,还支持作为嵌入式内存LDAP的”UnboundedID”的自动配置。

添加spring-boot-starter-data-ldap和com.unboundid:unboundid-ldapsdk作为依赖项

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>

<dependency> <!-- 組み込みLDAPを使う場合のみ -->
    <groupId>com.unboundid</groupId>
    <artifactId>unboundid-ldapsdk</artifactId>
</dependency>

根据需要,通过设置spring.ldap.*属性,可以实现与LDAP进行数据协作。

# SPRING LDAP (LdapProperties)
spring.ldap.urls= # LDAP url of the server.
spring.ldap.base= # Base suffix from which all operations should originate.
spring.ldap.username= # Login user of the server.
spring.ldap.password= # Login password of the server.
spring.ldap.base-environment.*= # Ldap specification settings.

# EMBEDDED LDAP (EmbeddedLdapProperties)
spring.ldap.embedded.port= # Embedded LDAP port.
spring.ldap.embedded.credential.username= # Embedded LDAP username.
spring.ldap.embedded.credential.password= # Embedded LDAP password.
spring.ldap.embedded.base-dn= # The base DN
spring.ldap.embedded.ldif= # Schema (LDIF) script resource reference.

请注意:如果使用内嵌的LDAP,请务必在spring.ldap.embedded.base-dn中指定一个值,否则将无法自动配置。

审计事件终端支持

从Spring Boot 1.5开始,成功和失败的认证和授权事件可以通过Spring MVC的端点(/auditevents)和JMX的MBean进行参考。
以下是通过Spring MVC端点获取的JSON示例。

{
  "events": [
    {
      "timestamp": "2017-01-09T04:57:41+0000",
      "principal": "anonymousUser",
      "type": "AUTHORIZATION_FAILURE",
      "details": {
        "remoteAddress": "0:0:0:0:0:0:0:1",
        "sessionId": null
      },
      "type": "org.springframework.security.access.AccessDeniedException",
      "message": "Access is denied"
    },
    {
      "timestamp": "2017-01-09T04:57:46+0000",
      "principal": "a",
      "type": "AUTHENTICATION_FAILURE",
      "details": {
        "remoteAddress": "0:0:0:0:0:0:0:1",
        "sessionId": null
      },
      "type": "org.springframework.security.authentication.BadCredentialsException",
      "message": "Bad credentials"
    },
    {
      "timestamp": "2017-01-09T04:57:54+0000",
      "principal": "user",
      "type": "AUTHENTICATION_SUCCESS",
      "details": {
        "remoteAddress": "0:0:0:0:0:0:0:1",
        "sessionId": null
      }
    }
  ]
}

注意:

Spring Boot 1.4中,认证和授权的成功和失败事件似乎已经被记录了,但似乎没有提供用于公开信息的端点。但是,我想知道为什么没有介绍MVC端点…于是我在RC1的发布公告的博客中留下了评论。

2017/01/11 补充:
MVC的端点现在也在发布说明中介绍了!(所以…我也稍作修改了内容)

事务管理器属性

从Spring Boot 1.5开始,您可以使用以下属性来自定义自动配置的PlatformTransactionManager。

    • デフォルトのトランザクションタイムアウト時間(秒)

 

    コミット時にエラーが発生した際にロールバック処理を行うか否かのフラグ(デフォルト値はfalse=ロールバックメソッドは呼び出さない)
# TRANSACTION (TransactionProperties)
spring.transaction.default-timeout= # Default transaction timeout in seconds.
spring.transaction.rollback-on-commit-failure= # Perform the rollback on commit

请注意:

在这种情况下,同时引入了自定义PlatformTransactionManager的机制,如果您感兴趣,请参阅“从Spring Boot 1.5开始,将添加PlatformTransactionManager自定义器”。

JmxEndpoint 接口

从Spring Boot 1.5开始,新增了org.springframework.boot.actuate.endpoint.jmx.JmxEndpoint接口以公开Actuator的JMX端点。开发人员只需实现此接口并将其注册到DI容器中即可将MBean注册到JMX服务器上。
这与用于公开Spring MVC端点的org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint接口具有相同的功能。

极端的说法是,只需进行以下类似的Bean定义,就能够在JMX上注册MBean。

@Bean
JmxEndpoint fooJmxEndpoint(){
    return new JmxEndpoint() {
        @Override
        public boolean isEnabled() {
            return true;
        }

        @Override
        public String getIdentity() {
            return null;
        }

        @Override
        public Class<? extends Endpoint> getEndpointType() {
            return null;
        }
    };
}

只需进行以下Bean定义,Spring MVC的端点就可以在Web上公开,例如,访问GET /foo时将返回字符串foo作为响应。

@Bean
MvcEndpoint fooMvcEndpoint() {
    return new MvcEndpoint() {
        @Override
        public String getPath() {
            return "/foo";
        }

        @Override
        public boolean isSensitive() {
            return false;
        }

        @Override
        public Class<? extends Endpoint> getEndpointType() {
            return null;
        }

        @GetMapping
        @ResponseBody
        public String get(){
            return "foo";
        }
    };
}

厂商特定的Flyway迁移

从Spring Boot 1.5版本开始,您可以使用Flyway来为每个数据库供应商准备数据库迁移脚本。
如果您使用该机制,请在读取脚本文件的位置中指定占位符{vendor}。

flyway.locations=db/migration/{vendor}
.
└── src
    └── main
        └── resources
            ├── application.properties
            └── db
                └── migration
                    ├── h2
                    │   └── V1_0_0_00__schema.sql
                    └── oracle
                        └── V1_0_0_00__schema.sql

创建这样一个机制很方便,可以选择使用的数据库来构建应用程序。

测试更新

从Spring Boot 1.5版本开始,在用于测试的注解(@JsonTest、@WebMvcTest、@DataJpaTest、@JdbcTest、@RestClientTest)中增加了一个属性(excludeAutoConfiguration),用于排除指定的自动配置类,以启用测试用的自动配置。

@RunWith(SpringRunner.class)
@SpringBootTest
@WebMvcTest(excludeAutoConfiguration = HttpMessageConvertersAutoConfiguration.class) // Spring 1.5+
//@ImportAutoConfiguration(exclude = HttpMessageConvertersAutoConfiguration.class) // Spring 1.4以前
public class FooTests {
    // ...
}

另外,@JdbcTest是从Spring Boot 1.5开始新增的注解。

自定义的fat jar布局

听说从Spring Boot 1.5开始,可以通过使用Spring Boot Maven和Gradle插件来引入自定义的jar布局。通过引入这种机制,可以开发出类似于spring-boot-thin-launcher(实验性的)的jar布局。

JmsTemplate 定制化操作

从Spring Boot 1.5版本开始,您可以使用以下属性来自定义自动配置的JmsTemplate。

# JMS (JmsProperties)
# ...
spring.jms.template.default-destination= # Default destination to use on send/receive operations that do not have a destination parameter.
spring.jms.template.delivery-delay= # Delivery delay to use for send calls in milliseconds.
spring.jms.template.delivery-mode= # Delivery mode. Enable QoS when set.
spring.jms.template.priority= # Priority of a message when sending. Enable QoS when set.
spring.jms.template.qos-enabled= # Enable explicit QoS when sending a message.
spring.jms.template.receive-timeout= # Timeout to use for receive calls in milliseconds.
spring.jms.template.time-to-live= # Time-to-live of a message when sending in milliseconds. Enable QoS when set.

杂项

其他方面的杂项修改如下:

    • Mockito 2.xで@MockBeanが使えるようになる。

 

    • Fully Executable Jar/Warの組み込みスクリプトにて、強制停止(force-stop)オプションがサポートされる。

 

    • Cassandraのヘルスチェックがサポートされる。

 

    • Cassandraのユーザ定義の型がSpring DataのSimpleUserTypeResolverを介して解決できるようになる。

 

    • Spring Boot Maven Pluginのskipプロパティが、run、stop、repackageで動作するようになる。

 

    複数のメインメソッドクラスが見つかった場合、MavenとGradleのSpring BootPluginは自動的に@SpringBootApplicationアノテーションが付与されているクラスを使用するようになる。

Spring Boot 1.5的废弃通知

由于存在某些被不推荐的API和属性,因此根据需要进行修改!

    • TomcatEmbeddedServletContainerFactoryのsetTldSkipメソッドが非推奨になるため、代わりにsetTldSkipPatternsを使うようにする。

 

    • ApplicationStartedEventは非推奨になるため、 代わりにApplicationStartingEventを使うようにする。

 

    • LoggingApplicationListenerに定義していた定数(PATH_PROPERTYとFILE_PROPERTY)が非推奨になるため、代わりにLogFileの定数を使うようにする。

 

    • Cacheの実装としてGuavaが非推奨になるため、代わりにCaffeineへの移行を検討する必要がある。なお、GuavaはSpring Frameowrk 5でサポート機能が完全に削除されます。

 

    • CRaSHを使用してSpring BootアプリケーションにSSHでアクセスする機能が非推奨になるため、運用ツールなどでこの機能を使っている場合は別の仕組みへの移行を検討する必要がある。

 

    • JmxEndpointの導入に伴い、EndpointMBeanExporterのいくつかのprotectedメソッドが非推奨になるため、JmxEndpoint又はadaptEndpointメソッドを使ってJMXサーバ上にMBeanを登録するようにする。

 

    • SearchStrategy#PARENTSが非推奨になるため、SearchStrategy#ANCESTORSを使うようにする。

 

    • Apache Commons DBCPが非推奨になるため、Apache Commons DBCP 2又は他のコネクションプーリングを使うようにする。

 

    • Undertow内部で使われていないため(UNDERTOW-587)、Undertow用のプロパティ(server.undertow.buffers-per-region)が非推奨になる。

 

    @AutoConfigureTestDatabaseのパッケージがorg.springframework.boot.test.autoconfigure.orm.jpaからorg.springframework.boot.test.autoconfigure.jdbcされるため、新しいパッケージに移動になったアノテーションを使うようにする。

产权更名

有些属性的名称将被更改或删除。

    • server.max-http-post-sizeプロパティは、サーバ固有のプロパティ(例: server.tomcat.max-http-post-size)に変更される。これはサーバによって扱う型(int vs long)が異なるからみたいです。

 

    Spring Data Neo4Jのバージョンアップに伴い、spring.data.neo4j.session.scopeプロパティが削除されます。

总结

由于这是基于发布说明的,我认为还有很多其他的变更点…但我认为重点的变更点已经得到控制。另外,由于我对英语不太自信…可能会有误解。如果有奇怪的地方,请留下评论,谢谢!

请查看下列网站

    • https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.5-Release-Notes

 

    • https://blog.ik.am/entries/401

 

    http://docs.spring.io/spring-boot/docs/1.5.x-SNAPSHOT/reference/htmlsingle/
广告
将在 10 秒后关闭
bannerAds