Spring Boot与多个数据技术集成,包括SQL和NoSQL。
Spring Framework提供扩展支持用于与SQL数据工作,从使用JdbcTemplate
直接JDBC访问到完全的“对象关系映射”技术比如Hibernate。Spring Data提供一个额外的功能级别:直接从接口创建Repository
实现并使用约定从方法名称生成查询。
Java的javax.sql.DataSource
接口提供标准的与数据库链接工作的方法。传统上,'DataSource’使用URL
连同证书一起建立数据库链接。
查看"How-to"部分了解更多高级示例,通常是为了完全控制数据源的配置。
通常非常方便使用一个基于内存的内嵌数据库开发应用程序。显然,内存数据库不提供持久化存储。你需要在应用程序启动时填充数据,在应用程序结束时丢弃数据。
"How-to"章节包括一部分关于如何初始化数据库。
Spring Boot可以自动配置内嵌的H2,HSQL和Derby数据库。你不需要提供任何连接URL。你只需要包含你想要使用的内嵌数据库的构建依赖。如果在类路径有多个内嵌数据库,设置spring.datasource.embedded-database-connection
配置属性控制你使用的那一个。设置属性值为none
则禁用内嵌数据的自动配置。
如果在你的测试中,你正在使用这个特性,你可能注意到无论你使用的多少应用程序上线文,你的全部测试套件重用了相同的数据库。如果你想确保每一个上下文有单独的内嵌数据库,你应该设置
spring;datasource.generate-unique-name
为true
。
例如,典型的POM依赖如下:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-jpaartifactId>
dependency>
<dependency>
<groupId>org.hsqldbgroupId>
<artifactId>hsqldbartifactId>
<scope>runtimescope>
dependency>
你需要在
spring-jdbc
上的一个依赖项用于自动配置内嵌数据库。在这个示例中,它通过spring-boot-starter-data-jpa
传递拉入的。
如果,无论什么原因,你所做的配置链接URL用于内嵌数据库,注意确保数据库的自动停机是禁用的。如果你使用H2,为此你应该使用
DB_CLOSE_ON_EXIST=FALSE
。如果你使用HSQLDB,你应该确保不使用shutdown=true
。当关闭数据库时,禁用数据库自动停机可以让Spring Boot控制,从而确保不在需要访问数据库进行自动关闭。
生产数据库链接也可以使用DataSource
连接池自动配置。
在spring.datasource.*
中的外部配置属性控制DataSource配置。例如,你可以在application.properties
中声明以下部分:
spring:
datasource:
url: "jdbc:mysql://localhost/test"
username: "dbuser"
password: "dbpass"
你应该至少通过设置
spring.datasource.url
属性指定URL。否则,Spring Boot尝试自动配置一个内嵌数据库。
Spring Boot可以从URL中推断大多数数据库的JDBC驱动。如果你需要指定一个特定的类,你可以使用
spring.datasource.driver-class-name
属性。
为创建
DataSource
池,我们需要可以校验一个有效的Driver
类是可用的,所以在做任何事情之前我们会对其进行检查。换句话说,如果你设置spring.datasource.driver-class-name=com.mysql.jdbc.Driver
,然后该类必须是可加载的。
请查看DataSourceProperties
了解更多的支持的选项。不管真正的实现这些都是标准的选项。也可以通过使用他们的各自的前缀微调特定的实现设置(spring.datasource.hikari.*
,spring.datasource.tomcat.*
,spring.datasource.dbcp2.*
和spring.datasource.oracleucp.*
)。请查看你正使用的连接池实现文档了解更多详情。
例如,如果你使用Tomcat 连接池,你可以定制许多额外的设置,如下示例所示:
spring:
datasource:
tomcat:
max-wait: 10000
max-active: 50
test-on-borrow: true
如果没有链接可用,这个将设置抛出异常之前链接池等待10000ms,限制最大的链接数是50并且在池中借出它之前校验链接。
Spring Boot使用以下算法用于选择特定实现:
DataSource
池可用,我们使用它。如果你使用
spring-boot-starter-jdbc
或者spring-boot-starter-data-jap
启动器,你自动得到HikariCP
依赖项。
你可以完全绕过该算法并通过设置spring.datasource.type
属性指定链接池来使用。如果在tomcat容器运行应用程序这点非常重要,因为默认提供tomcat-jdbc
。
使用DataSourceBuilder
可以手工配置额外的链接池。如果你定义你自己的DataSource
bean,自动配置不会发生。下面的链接池通过DataSourceBuilder
支持。
DataSource
池OracelDataSource
SimpleDriverDataSource
JdbcDataSource
PGSimpleDataSource
如果你部署你的Spring Boot应用程序到Application Server,你可能想要通过使用你的Application Server内建特性配置和管理你的DataSource并通过使用JNDI访问它。
spring.datasource.jndi-name
属性可以用来当做spring.datasource.url
的替代方案,spring.datasource.username
和spring.datasource.password
属性可以从特定的JNDI位置访问DataSource
。例如,下面的application.properties
中部分展示根据定义的DataSource
如何访问JBoss:
spring:
datasource:
jndi-name: "java:jboss/datasources/customers"
Spring的JdbcTempalte
和NamedParameterJdbcTemplate
类是自动配置的,你可以直接@Autowire
他们到自己的bean,如下示例所示:
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final JdbcTemplate jdbcTemplate;
public MyBean(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void doSomething() {
this.jdbcTemplate ...
}
}
你可以通过使用spring.jdbc.template.*
属性定制一些模板的属性,如下示例所示:
spring:
jdbc:
template:
max-rows: 500
NamedParameterJdbcTemplate
在底层重用相同的JdbcTemplate
实例。如果超过一个JdbcTemplate
被定义并没有主要的候选者存在,NamedParameterJdbcTempalte
不会自动配置。
Java Persistence API(Java持久化API)是标准的技术,让你“映射”对象到相关的数据库。spring-boot-starter-data-jpa
POM提供一个快速的方式开始。它提供以下关键依赖:
这里我们不深入了解JPA和Spring Data的更多细节。你可以遵循来自spring.io的“使用JPA访问数据”指南并阅读Spring Data JPA和Hibernate参考文档。
传统上,在persistence.xml
文件中指定JPA“实体”类。使用Spring Boot,这个文件不必须的并使用“Entity Scanning”代替。默认情况下,在你的主配置类(使用@EnableAutoConfiguration
或者@SpringBootApplication
注解的一个)下的所有包都会被搜索。
使用@Entity
、@Embeddable
或者@MappedSuperclass
注解的所有类都会考虑。一个典型的实体类类似于下面的示例:
import java.io.Serializable;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@Entity
public class City implements Serializable {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String state;
// ... additional members, often include @OneToMany mappings
protected City() {
// no-args constructor required by JPA spec
// this one is protected since it should not be used directly
}
public City(String name, String state) {
this.name = name;
this.state = state;
}
public String getName() {
return this.name;
}
public String getState() {
return this.state;
}
// ... etc
}
通过使用
@EntityScan
注解你可以定制实体扫描位置。请查看“将@Entity 定义与Spring Configuration分隔”如果做。
Spring Data JPA仓库是接口,你可以定义以访问数据。JPA查询根据你的方法名称自动创建。例如,CityRepository
接口可能声明findAllByState(String state)
方法来查找给定状态的所有城市。
对于更复杂的查询,你可以使用Spring Data的Query
注解来注解你的方法。
Spring Data仓库通常集成自Repository
或者CrudRepository
接口。如果你使用自动配置,将从你的主配置类(使用@EnableAutoConfiguration
或者@SpringBootApplication
注解的一个)搜索仓库。
下面的示例展示了一个典型的Spring Data仓库接口定义:
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.City;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
public interface CityRepository extends Repository<City, Long> {
Page<City> findAll(Pageable pageable);
City findByNameAndStateAllIgnoringCase(String name, String state);
}
Spring Data JPA仓库支持不同的引导指令模式:defalut,defered和lazy。为启用延迟的或者懒惰的引导指令,分别设置spring.data.jpa.repositories.bootstrap-mode
属性为deferred
或者lazy
。当使用defered或者lazy引导指令,自动配置EntityManagerFactoryBuilder
将使用上下文的AsyncTaskExecutor
,若有的话,作为引导执行器。如果存在多余一个,名称为applicationTaskExecutor
的那个将被使用。
当使用deferred或者lazy引导指令,确保在应用程序上下文引导阶段之后延迟对JPA基础设施的任何访问。你可以使用
SmartInitializingSingleton
以调用任何需要JPA基础设施的初始化。对于JPA组件(例如converters)被创建为Spring bean,如果有依赖项,请使用ObjectProvider
来延迟解析。
我们只触碰到Spring Data JPA的皮毛。要了解完整的详情,请查阅Spring Data JPA参考文档。
如果Sprig Data Enver可用,JPA仓库自动配置以支持典型的Enver需求。
为使用Spring Data Enver,确保你的仓库继承于RevisionRepository
如下示例所示:
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.Country;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.history.RevisionRepository;
public interface CountryRepository extends RevisionRepository<Country, Long, Integer>, Repository<Country, Long> {
Page<Country> findAll(Pageable pageable);
}
为了解更多详情,请查看Spring Data Enver参考文档。
默认情况下,只有使用内嵌数据库(H2,HSQL或者Derby)时JPA数据库是自动创建。你可以通过使用spring.jpa.*
属性明确的配置JPA设置。例如,为创建和移除表,你可以添加以下行到你的application.properties
:
spring:
jpa:
hibernate.ddl-auto: "create-drop"
Hibernate自己对此的内部属性名称是
hibernate.hbm2ddl.auto
。你可以通过使用spring.jpa.properties.*
(将他们添加到实体管理之前剔除前缀)设置它和其他Hibernate本身属性一起。以下行展示对Hibernate设置JPA属性的示例:
spring:
jpa:
properties:
hibernate:
"globally_quoted_identifiers": "true"
在前面的示例中的行传入hibernate.globally_quoted_identifiers
属性true
值到Hibernate实体管理。
默认情况下,DDL执行器(或者校验器)是延迟的直到ApplicationContext
已经开始。也存在spring.jpa.generate-ddl
标志,但是如果Hibernate自动配置是活跃的,它不会被使用,因为ddl-auto
设置是更细粒度的。
如果你正在运行一个web应用程序,默认情况下,Spring Boot注册OpenEntityManagerInViewInterceptor
以应用“Open EntityManager In View”格式,允许在web视图中用于懒加载。如果你不希望这样的行为,你应该在application.properties
中的spring.jpa.open-in-view
设置为false
。
Spring Boot包含对JDBC支持的仓库并将对在CrudRepository
上的方法自动生成SQL。对于更高级的查询,提供@Query
注解。
当必须的依赖在类路径中时,Spring Boot将自动配置Spring Data的JDBC仓库。使用在spring-boot-starter-data-jdbc
上的单个依赖将他们加入的项目。如果必须,你可以通过添加@EnableJdbcRepositories
注解或者JdbcConfiguration
子类到你的应用程序以控制Spring Data JDBC的配置。
为了解Spring Data JDBC完整详情,请查看参考文档。
H2数据库提供基于浏览器的控制台,Spring Boot可以自动配置给你。当以下条件满足时自动配置控制台:
com.h2database:h2
在类路径中。如果你没有使用开发者工具但是仍想使用H2控制台, 你可以使用
true
值配置spring.h2.console.enabled
属性。
H2控制台只打算用于开发期间使用,所以你应该小心,以确保生产环境
spring.h2.console.enabled
没有设置为true
。
默认情况下,控制台是使用在/h2-console
。你可以通过使用spring.h2.console.path
属性定制控制台路径。
H2控制台使用框架并只打算用于开发环境,不支持CSRF保护措施。如果你的应用程序使用Spring Security,你需要配置它为:
X-Frame-Options
为SAMEORIGIN
。X-Frame-Options
更多信息可以在Spring Security参考指南中发现。在简单的设置中,像以下的SecurityFilterChain
可以使用:
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Profile("dev")
@Configuration(proxyBeanMethods = false)
public class DevProfileSecurityConfiguration {
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
SecurityFilterChain h2ConsoleSecurityFilterChain(HttpSecurity http) throws Exception {
http.requestMatcher(PathRequest.toH2Console());
http.authorizeRequests(yourCustomAuthorization());
http.csrf((csrf) -> csrf.disable());
http.headers((headers) -> headers.frameOptions().sameOrigin());
return http.build();
}
}
H2控制台只打算在开发期间使用。在生产环境,对站点禁用CSRF保护或者允许框架可能创建严重安全风险。
当控制台路径已经被定制,
PathRequest.toH2Console()
也可以返回正确的请求匹配器。
jOOQ Object Oriented Querying(jOOQ)是来自Data Geekery非常受欢迎的产品,它根据你的数据库生成Java代码并允许你通过它的流式API构建类型安全的SQL查询。商业和开源版本都可以被Spring Boot使用。
为了使用jOOQ类型安全查询,你需要从你的数据库模式生成Java类。你可以遵循jOOQ用户手册说明。如果你使用jooq-codegen-maven
插件并且你也可以spring-boot-start-parent
父POM,你可以安全地省去插件的
标签。你也可以使用预定义的Spring Boot版本变量(比如h2.version
)以声明插件的数据库依赖。以下列表展示了一个示例:
<plugin>
<groupId>org.jooqgroupId>
<artifactId>jooq-codegen-mavenartifactId>
<executions>
...
executions>
<dependencies>
<dependency>
<groupId>com.h2databasegroupId>
<artifactId>h2artifactId>
<version>${h2.version}version>
dependency>
dependencies>
<configuration>
<jdbc>
<driver>org.h2.Driverdriver>
<url>jdbc:h2:~/yourdatabaseurl>
jdbc>
<generator>
...
generator>
configuration>
plugin>
jOOQ提供的流式API通过org.jooq.DSLContext
接口发起的。Spring Boot自动配置DSLContext
作为Spring bean并将它与应用程序DataSource
连接。为使用DSLContext
,你可以注入它,如下示例所示:
import java.util.GregorianCalendar;
import java.util.List;
import org.jooq.DSLContext;
import org.springframework.stereotype.Component;
import static org.springframework.boot.docs.data.sql.jooq.dslcontext.Tables.AUTHOR;
@Component
public class MyBean {
private final DSLContext create;
public MyBean(DSLContext dslContext) {
this.create = dslContext;
}
}
jOOQ手册倾向于使用名为
create
变量名称来保存DSLContext
。
你仍可以使用DSLContext
来构造你的查询,如下示例所示:
public List<GregorianCalendar> authorsBornAfter1980() {
return this.create.selectFrom(AUTHOR)
.where(AUTHOR.DATE_OF_BIRTH.greaterThan(new GregorianCalendar(1980, 0, 1)))
.fetch(AUTHOR.DATE_OF_BIRTH);
除了spring.jooq.sql-dialect
属性已经配置,Spring Boot决定SQL方言来用于数据源的使用。如果Spring Boot无法检测方言,他使用DEFAULT
。
Spring Boot只能通过开源的jOOQ版本自动配置支持的方言。
通过定义自己的DefaultConfigurationCustomizer
bean可以实现更高级的定制,该bean将在创建org.jooq.Configuration``@Bean
之前被调用。
Reactive Relational Database Connectivity(R2DBC)项目采用响应式程序API关系型数据库。R2DBC的io.r2dbc.spi.Connection
提供标准的工作于非阻塞数据库链接的方法。通过使用ConnectionFactory
提供链接,类似于使用jdbc的DataSource
。
通过在spring.r2dbc.*
外部配置属性控制ConnectionFactory
配置。例如,你可以在application.properties
中声明以下部分:
spring:
r2dbc:
url: "r2dbc:postgresql://localhost/test"
username: "dbuser"
password: "dbpass"
你不需要指定驱动类名称,因为Spring Boot从R2DBC的链接工厂发现获得。
至少应该提供url,URL中特定的信息优先级高于个别属性,那是
name
,username
,password
和池化选项。
“如何做”章节包含在如何初始化数据库部分。
为了通过ConnectionFactory
定制创建的链接,就是说,在主要的数据库配置中设置你不想(或者不能)配置特定的参数,你可以使用ConnectionFactoryOptionsBuilderCustomizer``@Bean
。下面的示例展示了如何手工重写数据库端口,而其余的选项从应用程序配置中获取:
import io.r2dbc.spi.ConnectionFactoryOptions;
import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyR2dbcConfiguration {
@Bean
public ConnectionFactoryOptionsBuilderCustomizer connectionFactoryPortCustomizer() {
return (builder) -> builder.option(ConnectionFactoryOptions.PORT, 5432);
}
}
下面的示例展示如何设置一些PostgreSQL连接选项:
import java.util.HashMap;
import java.util.Map;
import io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider;
import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyPostgresR2dbcConfiguration {
@Bean
public ConnectionFactoryOptionsBuilderCustomizer postgresCustomizer() {
Map<String, String> options = new HashMap<>();
options.put("lock_timeout", "30s");
options.put("statement_timeout", "60s");
return (builder) -> builder.option(PostgresqlConnectionFactoryProvider.OPTIONS, options);
}
}
当ConnectionFactory
bean可用时,常规的JDBCDataSource
自动配置就会消失。如果你想保留JDBCDataSource
自动配置并能够承担在响应式应用程序中使用阻塞JDBC API的风险,在@Configuration
类上添加@Import
(@DataSourceAutoConfiguration.class
)以重新启用它。
类似于JDBC的支持,Spring Boot可以自动配置一个内嵌的数据库用于响应式用法。你无需提供任何连接URL.你只需要包括构建你想使用的内嵌数据库的依赖,如下示例所示:
<dependency>
<groupId>io.r2dbcgroupId>
<artifactId>r2dbc-h2artifactId>
<scope>runtimescope>
dependency>
如果你正在你的测试中使用这个特定,你可能要注意无论你所使用的应用程序上下文的数据,你的所有测试用例都会重用相同的数据库。如果你想确保每一个上下文有隔离的内嵌数据库,你应该设置
spring.r2dbc.generate-unique-name
为true
。
DatabaseClient
bean是自动配置,你可以直接@Autowire
它到你自己的bean,如下示例所示:
import java.util.Map;
import reactor.core.publisher.Flux;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final DatabaseClient databaseClient;
public MyBean(DatabaseClient databaseClient) {
this.databaseClient = databaseClient;
}
public Flux<Map<String, Object>> someMethod() {
return this.databaseClient.sql("select * from user").fetch().all();
}
}
Spring Data R2DBC仓库是接口,你可以定义以访问数据。根据你的方法名自动创建查询。例如,CityRepository
接口可能声明findAllByState(String state)
方法来根据给定的状态查找所有的城市。
对于更复杂的查询,你可以使用Spring Data的Query
注解来注解你的方法。
Spring Data通常实现Repository
或者CrudRepository
接口。如果你使用自动配置,从包含你的主配置类(使用@EnableAutoConfiguration
或者@SpringBootApplication
)的包搜索仓库。
下面的示例展示了典型的Spring Data 仓库接口定义:
import reactor.core.publisher.Mono;
import org.springframework.data.repository.Repository;
public interface CityRepository extends Repository<City, Long> {
Mono<City> findByNameAndStateAllIgnoringCase(String name, String state);
}
我们只是触及了Spring Data R2DBC皮毛。为了解完整细节,请查阅Spring Data R2DBC参考文档。
Spring Data提供额外的项目帮助你访问访问多个NoSQL技术,包括:
Redis是缓存,消息broker和特性丰富 key-value存储。Spring Boot为Lettuce和Jedis客户端类库以及Spring Data Redis提供的基于他们的抽象提供了基础的自动配置。
有spring-boot-starter-data-redis
启动器用于以方便的方式汇总依赖。默认情况下,它使用Letture。此启动器处理传统的和响应式的应用程序。
我们也提供
spring-boot-starter-data-redis-reactive
启动器为了与支持响应式的其他存储保持一致。
你可以注入自动配置的RedisConnectionFactory
,StringRedisTemplate
或原版的RedisTemplate
实例作为你任何其他的Spring Bean。默认情况下,此实例尝试在localhost:6379
连接Redis。下方的列表展示这样bean的一个示例:
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final StringRedisTemplate template;
public MyBean(StringRedisTemplate template) {
this.template = template;
}
public Boolean someMethod() {
return this.template.hasKey("spring");
}
}
你也可以注册一个随意数量实现
LettuceClientConfigurationBuildrCustomizer
的bean用于更高级的定制。也可以使用ClientResourcesBuilderCustomizer
定制ClientResources
。如果你使用Jedis,JedisClientConfigurationBuilderCustomizer
是可用的。或者,你可以注册RedisStandaloneConfiguration
,RedisSentineConfiguration
或者RedisClusterConfiguration
型的bean以完全控制配置。
如果你添加自己的任何自动配置类型的@Bean
,他会替换默认值(除了RedisTempplate
情况,当排除基于bean名称redisTemplate
而不是类型时)。
默认情况下,如果commons-pooks
在类路径中,连接池工厂自动配置。
MongoDB是开源的NoSQL文档数据库,它使用类似于JSON模式替代传统的基于表的相关的数据。Spring Boot为与MongoDB工作提供许多方便,包括spring-boot-starter-data-mongdb
和spring-boot-starter-data-mongodb-reactive
启动器。
为访问MongoDB数据库,你可以注入自动配置的org.springframework.data.mongodb.MongoDatabaseFactory
。默认情况下,该实例尝试连接到在mongodb://localhost/test
的MongoDB服务器。以下示例展示了如何连接到MongoDB数据库:
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final MongoDatabaseFactory mongo;
public MyBean(MongoDatabaseFactory mongo) {
this.mongo = mongo;
}
public MongoCollection<Document> someMethod() {
MongoDatabase db = this.mongo.getMongoDatabase();
return db.getCollection("users");
}
}
如果你已经定义了自己的MongoClinet
,它将被用来自动配置适宜的MongoDatabaseFactory
。
使用MongoClientSettings
bean创建自动配置的MongoClient
。如果你已经定义了自己的MongoClientSetting
,无需修改使用它并且spring.data.mongodb
属性将被忽略。否则MongoClientSetting
将自动配置并应该spring.data.mongodb
属性。不论发生何种情况,你可以声明一个或者更多MongoClientSettingsBuilderCustomizer
bean来微调MongoClientSettings
配置。MongClientSettings.Builder
顺序地调用每一个,用来构建MongoClientSettings
。
你可以设置spring.data.mongodb.uri
属性来改变URL并配置额外的设置例如replica set,如下示例所示:
spring:
data:
mongodb:
uri: "mongodb://user:[email protected]:12345,mongo2.example.com:23456/test"
或者,你可以使用离散的属性指定链接明细。例如,你可以在application.properties
中声明以下设置:
spring:
data:
mongodb:
host: "mongoserver.example.com"
port: 27017
database: "test"
username: "user"
password: "secret"
如果
spring.data.mongodb.port
没有指定,将使用默认的27017
。你可以从前面展示的示例中删除这行。
如果你不使用Spring Data MongoDB,你可以注入
MongoClient
bean代替使用MongoDatabaseFactory
。如果你想完成控制建立MongoDB连接,你还可以声明自己的MongoDatabaseFactory
或者MongoClient
bean。
如果你正在使用响应式驱动,Netty需要用于SSL。自动配置自动配置该工厂如果Netty可用并且要使用工厂还没有定制好。
Spring Data MongoDB提供MongoTemplate
类,它的设计非常类似于Spring的JdbcTemplate
。正如JdbcTemplate
一样,Spring Boot为你自动配置一个bean来注入这个模板,如下:
import com.mongodb.client.MongoCollection;
import org.bson.Document;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final MongoTemplate mongoTemplate;
public MyBean(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
public MongoCollection<Document> someMethod() {
return this.mongoTemplate.getCollection("users");
}
}
请查阅MongoOperations
Javadoc了解全部细节。
Spring Data 包含支持MongoDB的仓库。正如前面讨论的JPA仓库,基本的原理是基于方法名称自动构造查询。
事实上,Spring Data JPA和Spring Data MongoDB共享相同的通用基础设施。你可以从前面了解JPA示例并且假定现在City
是MongoDB的数据类而不是JPA@Entity
,他以相同的方式工作,如下示例所示:
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
public interface CityRepository extends Repository<City, Long> {
Page<City> findAll(Pageable pageable);
City findByNameAndStateAllIgnoringCase(String name, String state);
}
你可以通过使用
@EntityScan
注解定制文档的扫描位置。
为了解Spring Data MongoDB的全部细节,包括他的丰富的对象映射技术,请查阅他的参考文档。
Neo4j是开源的NoSQL图数据库,其使用丰富的连接节点的数据模型,通过一级关系连接,它比传统的RDBMS方法更适合用于连接大数据。Spring Boot为Neo4j的使用提供了一些方便,包括spring-boot-starter-data-neo4j
启动器。
为访问Neo4j服务器,你可以注入一个自动配置的org.neo4j.driver.Driver
。默认情况下,这个实例在localhost:7687
使用Bolt协议尝试连接Neo4j服务器。下方的示例展示了如何注入Neo4jDriver
用于给你访问一个Session
:
import org.neo4j.driver.Driver;
import org.neo4j.driver.Session;
import org.neo4j.driver.Values;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final Driver driver;
public MyBean(Driver driver) {
this.driver = driver;
}
public String someMethod(String message) {
try (Session session = this.driver.session()) {
return session.writeTransaction((transaction) -> transaction
.run("CREATE (a:Greeting) SET a.message = $message RETURN a.message + ', from node ' + id(a)",
Values.parameters("message", message))
.single().get(0).asString());
}
}
}
你可以使用spring.neo4j.*
属性配置驱动程序的各个方面。下面的示例展示了如何配置uri和凭证的使用:
spring:
neo4j:
uri: "bolt://my-server:7687"
authentication:
username: "neo4j"
password: "secret"
使用ConfigBuilder
创建自动配置的Driver
。为微调他的配置,声明一个或者多个ConfigBuilderCustomizer
bean。使用ConfigBuilder
按顺序调用每一个用来构建Driver
。
Spring Data包含支持Neo4j的仓库。为了解Spring Data Neo4j的全部细节,请查阅参考文档。
Spring Data Neo4j和Spring Data JPA共享常用的基础设施正如许多其他Spring Data模块所做的。你可以使用前面的JPA示例并定义City
为Spring Data Neo4j @Node
而不是JPA@Entity
,仓库的方式以相同的方式工作,如下示例所示:
import java.util.Optional;
import org.springframework.data.neo4j.repository.Neo4jRepository;
public interface CityRepository extends Neo4jRepository<City, Long> {
Optional<City> findOneByNameAndState(String name, String state);
}
spring-boot-starter-data-neo4j
启动器启用仓库支持以及事务管理。Spring Boot使用Neo4jTemplate
或者ReactiveNeo4jTemplate
bean支持经典和响应式Neo4j仓库。当Project Reactor在类路径上可用,响应式风格也自动配置。
你可以通过在@Configuraiton
bean上分别使用@EnableNeo4jRepositories
和@EntityScan
定制位置来查找仓库和实体。
在应用程序中使用响应式风格,
ReactiveTransactionManager
不会自动配置。为启用事务管理,以下bean必须在你的配置中定义:import org.neo4j.driver.Driver; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.neo4j.core.ReactiveDatabaseSelectionProvider; import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager; @Configuration(proxyBeanMethods = false) public class MyNeo4jConfiguration { @Bean public ReactiveNeo4jTransactionManager reactiveTransactionManager(Driver driver, ReactiveDatabaseSelectionProvider databaseNameProvider) { return new ReactiveNeo4jTransactionManager(driver, databaseNameProvider); } }
Elasticsearch
是开源的,分布式的,RESTful查询和解析引擎。Spring Boot为Elasticsearch客户端提供基本的自动配置。
Spring Boot支持几个客户端:
ReactiveElasticsearchClient
。Spring Boot提供一个相关的“启动器”,spring-boot-starter-data-elasticsearch
。
Elasticsearch提供了两个不同的REST客户端可以用来查询集群:来自org.elasticsearch.client:elasticsearch-rest-client
模块的低级别客户端和来自org.elasticsearch.client:elasticsearch-high-level-client
模块高级别客户端。此外,Spring Boot对响应式客户端提供支持,基于来自org.springframework.data:spring-data-elasticsearch
模块的Spring Framework的WebClient
。默认情况下,客户端将指向localhost:9200
。你可以使用spring.elasticsearch.*
属性更进一步调整如何配置客户端,如下示例所示:
spring:
elasticsearch:
uris: "https://search.example.com:9200"
socket-timeout: "10s"
username: "user"
password: "secret"
如果在类路径中有elasticsearch-rest-client
,Spring Boot将自动配置并注册RestClient
bean。如果在类路径存在elasticsearch-rest-high-level-client
,RestHighLevelClient
bean也将自动配置。在Elasticsearch弃用RestHighLevelClient
之后,它的自动配置是弃用的并将在未来发布移除。除了前面所描述的属性,为微调RestClient
和RetHighLevelClient
,你可以注册一个随意数量为更高级定制而实现RestClientBuilderCustomizer
的bean。为完全控制客户端的配置,定义RestClientBuilder
bean。
此外,如果elasticsearch-rest-client-sniffer
在类路径中,Sniffer
自动配置以发现来自正在运行的Elasticsearch集群的节点并在RestClient
bean设置他们。你可以进一步微调Sniffer
如何配置,如下示例所示:
spring:
elasticsearch:
restclient:
sniffer:
interval: "10m"
delay-after-failure: "30s"
Spring Data Elasticsearch提供ReactiveElasticsearch
,以响应式的方式查询Elasticsearch实例。它建立在WebFlux的WebClient
之上,所以spring-boot-starter-elasticsearch
和spring-boot-starter-webflux
依赖项启用这个支持是非常有用的。
默认情况下,Spring Boot将自动配置并注册ReactiveElasticsearchClient
。除了前面所描述的属性,spring.elasticsearch.webclient.*
属性可以用来配置特性的响应式设置,如下示例所示:
spring:
elasticsearch:
webclient:
max-in-memory-size: "1MB"
如果spring.elasticsearch.
和spring.elasticsearch.webclient.
配置属性是不满足的,你想完全控制客户端配置,你可以注册一个自定义的ClientConfiguration
bean。
为连接Elasticsearch,必须定义RestHighLevelClient
bean,通过Spring Boot自动配置或者通过应用程序(请查看前面的部分)手工提供。有了这个配置,可以像其他Springbean一样注入ElasticsearchRestTempalte
,如下示例所示:
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final ElasticsearchRestTemplate template;
public MyBean(ElasticsearchRestTemplate template) {
this.template = template;
}
public boolean someMethod(String id) {
return this.template.exists(id, User.class);
}
}
在存在spring-data-elasticsearch
和所需依赖用于使用WebClient
(典型的spring-boot-starter-webflux
),Spring Boot也可以自动配置ReactiveElasticsearchClient
和ReactiveElasticsearchTemplate
作为bean。他们等价于其他REST客户端。
Spring Data包括对Elasticsearch仓库的支持。正如前面讨论的JPA仓库,基本原理是根据方法名自动构造查询。
事实上,Spring Data JPA和Spring Data Elasticsearch共享相同的通用基础设施。你可以使用前面的JPA示例,假设现在City
是Elasticsearch
的@Document
而不是JPA@Entity
,它以相同的方式工作。
为了解Spring Data Elasticsearch的全部细节,请查看参考文档。
Spring Boot支持典型的和响应式的Elasticsearch仓库,使用ElasticsearchRestTemplate
或者ReactiveElasticsearch
bean。给定所需要的依赖是存在的,很可能大部分这些bean通过Spring Boot自动配置。
如果你希望使用你自己的模板来支持Elasticsearch仓库,你可以添加自己的ElasticsearchRestTemplate
或者ElasticesearchOperations
的bean,只要它命名为elasticsearchTemplate
。使用bean名称reactiveElasticsearchTemplate
,同样会应用到ReactiveElasticsearchTemplate
和ReactiveElasticsearchOperations
。
你可以使用以下属性选择禁用仓库支持:
spring:
data:
elasticsearch:
repositories:
enabled: false
Cassandra是开源的,分布式数据管理系统被设计为处理跨许多商品服务器的大量数据。Spring Boot为Cassandra提供自动配置和Spring Data Cassandra基于Cassandra提供的实现。spring-boot-starter-data-cassandra
启动器用于以非常方便的方式收集依赖项。
你可以注入一个自动配置的CassandraTempalte
或者Cassandra的CqlSession
实例正如你将使用的任何其他Spring bean。spring.data.cassandra.*
属性可以用来定制这个链接。通常,你提供keyspace-name
和contact-points
以及数据中心的名称,如下示例所示:
spring:
data:
cassandra:
keyspace-name: "mykeyspace"
contact-points: "cassandrahost1:9042,cassandrahost2:9042"
local-datacenter: "datacenter1"
如果对于所有的链接端的端口是相同的,你可以使用快捷方式并只指定主机名称,如下示例所示:
spring:
data:
cassandra:
keyspace-name: "mykeyspace"
contact-points: "cassandrahost1,cassandrahost2"
local-datacenter: "datacenter1"
这两个示例是完全相同的,因为端口默认为
9042
。如果你需要配置这个端口,使用spring.data.cassandra.port
。
Cassandra驱动有它自己的配置基础设施,其在根类路径加载
application.conf
。默认情况下,Spring Boot不会查找这样的文件但是会使用
spring.data.cassandra.config
加载一个。如果一个属性同时在spring.data.cassandra.*
和配置文件同时存在,在spring.data.cassandra.*
的值优先。对于更高级的驱动自定义,你可以注册随意数量实现
DriverConfigLoaderBuilderCustomizer
的bean。CqlSession
可以使用类型为CqlSessionBuilderCustomizer
类型的bean定义。
如果你使用
CqlSessionBuilder
来创建多个CqlSession
bean,记住构造器是可变的,所以请确保为每一个session注入一个新的副本。
下面的代码列表展示如何注入一个Cassandra bean:
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final CassandraTemplate template;
public MyBean(CassandraTemplate template) {
this.template = template;
}
public long someMethod() {
return this.template.count(User.class);
}
}
如果你添加你自己CassandraTemplate
类型的bean,他将替换默认的。
Spring Data包含对Cassandra基础仓库支持。目前,比前面所讨论的JPA仓库有更多的限制,需要使用@Query
注解发现者方法。
为了解Spring Data Cassandra的全部细节,请查阅参考文档。
Couchbase是开源的,分布式的,多模型NoSQL面向文档数据库,它针对交互式应用程序进行了优化。Spring Boot为Couchbase提供了自动配置和通过Spring Data Couchbase提供基于他的实现。有spring-boot-starter-data-couchbase
和spring-boot-starter-data-couchbase-reactive
启动器用于以方便的方式收集依赖项。
通过添加Couchbase SDK和一些配置,你可以得到Cluster
。spring.couchbase.*
属性可以用来定制连接。通常,你提供链接字符串,用户名和密码,如下示例所示:
spring:
couchbase:
connection-string: "couchbase://192.168.1.123"
username: "user"
password: "secret"
它也可以定制一些ClusterEnvironment
设置。例如,以下配置改变超时来使用打开一个新的Bucket
并启用SSL支持:
spring:
couchbase:
env:
timeouts:
connect: "3s"
ssl:
key-store: "/location/of/keystore.jks"
key-store-password: "secret"
检查
spring.couchbase.env.*
属性了解更多细节。为获取更多控制,可以使用一个或者更多ClusterEnvironmentBuilderCustomizer
bean。
Spring Data包含为Couchbas提供仓库支持。为了解Spring Data Couchbase的全部细节,请查阅参考文档。
你可以像使用任何其他Spring Bean一样注入一个自动配置CouchbaseTemplate
实例,提供的CouchbaseClientFactory
bean是可用的。当Cluster
是可用的时,如上所述,并bucket名称已经被指定:
spring:
data:
couchbase:
bucket-name: "my-bucket"
以下示例展示了如何注意CouchbaseTemplate
bean:
import org.springframework.data.couchbase.core.CouchbaseTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final CouchbaseTemplate template;
public MyBean(CouchbaseTemplate template) {
this.template = template;
}
public String someMethod() {
return this.template.getBucketName();
}
}
你可以在你的自己的配置定义一些bean来重写自动配置提供的那些bean:
couchbaseMappingContext
名称的CouchbaseMappingCoutext
的@Bean
couchbaseCustomConversions
名称的CustomConversions
的@Bean
couchbaseTemplate
名称的CouchbaseTemplate
的@Bean
为避免在你自己的配置中硬编码这些名字,你可以重用Spring Data Couchbase提供的BeanName
。例如,你可以定制转换器来使用,如下:
import org.assertj.core.util.Arrays;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.config.BeanNames;
import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions;
@Configuration(proxyBeanMethods = false)
public class MyCouchbaseConfiguration {
@Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)
public CouchbaseCustomConversions myCustomConversions() {
return new CouchbaseCustomConversions(Arrays.asList(new MyConverter()));
}
}
LDAP(Lightweight Directory Access Protocol)是开源的,厂商中立,工业标准的应用程序协议用于通过IP访问和维护分布式目录信息服务。Spring Boot为任意兼容的LDAP服务器提供自动配置以及对来自UnboundID内嵌内存的LDAP服务器提供支持。
通过Spring Data LDAP提供LDAP抽象。spring-boot-starter-data-ldap
启动器用于方便的方式收集依赖项。
为连接LDAP服务器,确保你在spring-boot-starter-data-ldpa
启动器上声明依赖项或者spring-ldap-core
并且在你的application.properties
中声明你服务器的URL,如下示例所示:
spring:
ldap:
urls: "ldap://myserver:1235"
username: "admin"
password: "secret"
如果你需要定制连接设置,你可以使用spring.ladp.base
和spring.ldap.base-environment
属性。
LdapContextSource
是基于这些设置自动配置的,如果DirContextAuthenticationStrategy
bean可用,它会自动配置的LdapContextSource
相关联。如果你需要定制它,例如使用PooledContextSource
,你可以注入自动配置LadpContextSource
。确保将定制的ContextSource
标记为@Primary
以便自动配置的LdapTemplate
使用它。
Spring Data包括对LDAP仓库支持。要了解Spring Data LDAP完整详情,请查阅参考文档。
你也可以注入一个自动配置的LdapTemplate
实例,就像使用其他Spring Bean一样,如下示例所示:
import java.util.List;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final LdapTemplate template;
public MyBean(LdapTemplate template) {
this.template = template;
}
public List<User> someMethod() {
return this.template.findAll(User.class);
}
}
出于测试目的,Spring Boot支持来自UnboundID的内存服务器的自动配置。为配置服务器,添加一个依赖到com.unboudid:unboundid-ldapsdk
和声明spring.ldap.embedded.base-dn
属性,如下:
spring:
ldap:
embedded:
base-dn: "dc=spring,dc=io"
它可以定义多个基于db的值,然而,因为标志名称通常包含逗号,他们必须使用正确的表示法来定义。
在yaml文件,你可以使用yaml列表符号。在properties文件,你必须包含索引作为属性名的一部分
Propertiesspring.ldap.embedded.base-dn[0]=dc=spring,dc=io spring.ldap.embedded.base-dn[1]=dc=pivotal,dc=io
Yaml
spring.ldap.embedded.base-dn: - "dc=spring,dc=io" - "dc=pivotal,dc=io"
默认情况下,使用随机端口服务器启动并触发常规的LDAP支持。不需要指定spring.ldap.urls
属性。
如果在类路径中存在schemo.ldif
文件,它用来初始化服务器。如果你想从不同的资源加载初始化脚本,你也可以使用spring.ldap.embedded.ldif
属性。
默认情况下,标准的模式用来校验LDIF
文件。你可以设置spring.ldap.embedded.validataion.enabled
属性来完全关闭验证。如果你有自定义属性,你可以使用spring.ldap.embedded.validation.schema
来定义你自定义的属性类型或者类对象。
InfluxDB是开源的,时间序列的数据库,针对操作监控,应用程序指标,物联网传感器数据和实时分析等领域的时间序列数据进行了快速、高可用存储的优化。
Spring Boot自动配置一个InfluxDB
实例,提供influxdb-java
客户端在类路径并且设置数据库URL,如下示例所示:
spring:
influx:
url: "https://172.0.0.1:8086"
如果连接到InfluxDB需要用户和密码,你可以直接设置spring.influx.user
和spring.influx.password
属性。
InfluxDB依赖OkHttp。如果你需要底层调整http客户端InfluxDB
使用,你可以注册InfluxDbOkHttpClientBuilderProvider
bean。
如果你需要控制配置,考虑注册InfluxDbCustomizer
bean。
现在你应该熟悉如何使用Spring Boot与多种data技术。至此,你可以阅读关于Spring Boot对多种消息技术的支持并如何在你的应用程序中启用他们。
Spring Framework与消息系统集成提供了广泛的支持,从使用JmsTempalte
简化JMS API到完整基础设施来异步接收消息。Spring AMQP提供一个用于高级消息队列协议(Advanced Message Queuing Protocol)类似的特性集合。Spring Boot为RabbitTemplate
和RabbitMQ也提供自动配置选项。Spring WebSocket本身就包含对STOMP消息的支持,并且Spring Boot通过启动器和小数量的自动配置提供对STOMP的支持。Spring Boot也对Apache Kafka提供支持。
javax.jms.ConnnectionFactory
接口提供了一个创建与JMS borker交互的javax.jms.Connnection
的标准方法。尽管Spring需要ConnectionFactory
以便与JMS工作,你通常不需要你自己直接使用它并且可以改为依赖更高级别的消息抽象。(请查阅Spring Framework参考文档相关的章节了解细节)。Spring Boot也自动配置必须的基础设施以发送和接收消息。
当ActiveMQ Artemis在类路径中可用时,Spring Boot可以自动配置ConnectionFactory
。如果broker存在,内嵌的broker自动启动并配置(除非这模式属性已经明确设置)。支持的模式是embedded
(为明确内嵌的broker是必须的,如果在类路径中broker不可用将发生一个错误。)和native
(使用netty
传输协议连接broker)。当配置后者时,Spring Boot配置一个ConnectionFactory
用于使用默认的设置链接运行在本地机器的broker。
如果你使用
spring-boot-starter-artemis
,提供连接到现有的ActiveMQ Artemis实例的必须的依赖项 ,以及与JMS集成的Spring基础设施。添加org.apache.activemq:artemis-jms-server
到你的应用程序允许你使用内嵌的模式。
通过在spring.artemis.*
外部配置属性控制ActiveMQ Artemis配置。例如,你可以在application.properties
声明以下部分:
spring:
artemis:
mode: native
broker-url: "tcp://192.168.1.210:9876"
user: "admin"
password: "secret"
当内嵌broker时,你可以选择是否启用持久化,并列出应该可用的目的地。这些可以被指定为一个逗号分隔的列表来使用默认的选项创建他们,或者你可以为高级的队列和主题配置依次定义org.apache.activemq.artemis.jms.server.config.JMSQueueConfiguration
或者org.apache.activemq.artemis.jms.server.config.TopicConfiguration
类型的bean(s)。
默认情况下,CachingConnectionFactory
使用合理的设置封装本地ConnectionFactory
,你可以通过外部配置属性spring.jms.*
合理的配置:
spring:
jms:
cache:
session-cache-size: 5
如果你更愿意使用本地池,你可以直接通过添加org.messaginghub:pooled-jms
依赖和配置JmsPoolConnectionFactory
,如下示例所示:
spring:
artemis:
pool:
enabled: true
max-connections: 50
请查阅ArtemisProperties
了解更多支持的选项。
不涉及JNDI查找,通过他们的名称解析目的地,使用Artemis配置中的name
属性或者通过配置提供的名称。
如果你正在应用程序服务器内运行你的应用程序,Spring Boot尝试通过使用JNDI定义一个JMSConnectionFactory
。默认情况下,检查java:/JmsXA
和java:/XAConnectionFactory
位置。如果你需要指定一个可代替的位置,你可以使用spring.jms.jndi-name
属性,如下示例所示:
spring:
jms:
jndi-name: "java:/MyConnectionFactory"
Spring的JmsTemplate
是自动配置的,你可以直接自动装配它到你自己的bean,如下示例所示:
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final JmsTemplate jmsTemplate;
public MyBean(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
public void someMethod() {
this.jmsTemplate.convertAndSend("hello");
}
}
JmsMessagingTemplate
可以以类似的方式注入。如果DestinationResolver
或者MessageConverter
bean已经定义,它自动与自动配置的JmsTempalte
相关联。
当JMS基础设施存在时,任何使用JmsListener
注解的bean来创建监听器端。如果没有JmsListenerContainerFactory
定义,默认的一个自动配置。如果DestinationResolver
,MessageConverter
或者javax.jms.ExceptionListener
bean被定义,他们自动与默认的工厂关联。
默认情况下,默认的工厂是事务的。如果在JtaTransactionManager
存在的基础设施中运行,默认情况下,他关联到监听者容器。如果不存在,启用sessionTransacted
标志。在后者的场景,你可以通过添加@Transactional
在你的监听器方法(或其委托)上将本地数据存储事务与传入消息的处理关联起来。一旦本地事务已经完成,这样确保传入的消息是证实的。这也包含在相同的JMS会话中已经执行发送响应消息。
下方的组件在someQueue
目的地创建一个监听器端点:
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@JmsListener(destination = "someQueue")
public void processMessage(String content) {
// ...
}
}
请查阅
@Enable的Javadoc
了解更多详情。
如果你需要创建更多的JmsListenerContainerFactory
实例或者你想重写默认的,Spring Boot提供DefaultJmsListenerContainerFactoryConfigurer
,你可以使用和自动配置相同的设置来初始化DefaultJmsListenerContainerFactory
。
例如,下面的示例公开使用特定的MessageConverter
的另外一个工厂:
import jakarta.jms.ConnectionFactory;
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
@Configuration(proxyBeanMethods = false)
public class MyJmsConfiguration {
@Bean
public DefaultJmsListenerContainerFactory myFactory(DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
ConnectionFactory connectionFactory = getCustomConnectionFactory();
configurer.configure(factory, connectionFactory);
factory.setMessageConverter(new MyMessageConverter());
return factory;
}
private ConnectionFactory getCustomConnectionFactory() {
return ...
}
}
然后你可以在任何带有@JmsListener
方法中使用工厂,如下:
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@JmsListener(destination = "someQueue", containerFactory = "myFactory")
public void processMessage(String content) {
// ...
}
}
高级消息队列协议(Advanced Message Queuing Protocol:AMQP)是跨平台,底层协议的面向消息的中间件。Spring AMQP项目应用核心的Spring概念来进行基于AMQP消息开发的解决方案。Spring Boot 通过RabbitMQ使用AMQP提供了一些便利,包括spring-boot-starter-amqp
启动器。
RabbitMQ
是轻量级,可靠的,基于AMQP协议可移植消息的broker。Spring使用RabbitMQ
通过AMQP协议来传递信息。
通过使用spring.rabbitmq.*
外部配置属性提供RabbitMQ配置。例如,你可以在application.properties
中声明以下部分:
spring:
rabbitmq:
host: "localhost"
port: 5672
username: "admin"
password: "secret"
或者,你可以使用addresses
属性配置相同的链接:
spring:
rabbitmq:
addresses: "amqp://admin:secret@localhost"
当指定这个方式的地址,
host
和port
属性是忽略的。如果这个地址使用amqps
协议,SSL支持自动启用。
请查阅RabbitProperties
了解更多的支持的基于属性的配置选项。为配置SpringAMAP使用的RabbitMQConnectionFactory
的低级别明细,定义一个ConnnectionFactoryCustomizer
bean。
如果在上下文中ConnectionNameStrategy
bean存在,它将自动用于命名由自动配置CachingConnnectionFactory
创建的链接。
请查阅理解AMQP,RabbitMQ使用的协议了解更多详情。
Spring的AmqpTemplate
和AmqpAdmin
是自动配置的,并且你可以直接自动装配他们到你自己的bean,如下示例所示:
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final AmqpAdmin amqpAdmin;
private final AmqpTemplate amqpTemplate;
public MyBean(AmqpAdmin amqpAdmin, AmqpTemplate amqpTemplate) {
this.amqpAdmin = amqpAdmin;
this.amqpTemplate = amqpTemplate;
}
public void someMethod() {
this.amqpAdmin.getQueueInfo("someQueue");
}
public void someOtherMethod() {
this.amqpTemplate.convertAndSend("hello");
}
}
RabbitMessagingTemplate
可以以类似的方式注入。如果MessageConverter
bean已经定义,它将自动与自动配置的AmqpTemplate
关联。
如果必须,任何已经定义为一个bean的org.springframework.amqp.core.Queue
自动用来在RabbitMQ实例声明一个相对应的队列。
为重试操作,你可以在AmqpTempalte
上启用重试(例如,在borker连接丢失的时间中):
spring:
rabbitmq:
template:
retry:
enabled: true
initial-interval: "2s"
默认情况下,重试是禁用的。你也可以通过声明RabbitRetryTemplateCustomizer
bean程序化定制RetryTemplate
。
如果你需要创建更多的RabbitTemplate
实例或者如果你想重写默认的,Spring Boot提供RabbitTemplateConfigurer
bean,你可以用来初始化RabbitTemplate
,其使用了和使用自动配置的工厂相同的设置。
为发送消息到一个特定的流,指定流的名称,如下示例所示:
spring:
rabbitmq:
stream:
name: "my-stream"
如果MessageConverter
,StreamMessageConverter
或者ProducerCustomizer
bean已经定义,他将自动与自动配置的RabbitStreamTemplate
关联。
如果你需要创建更多的RabbitStreamTemplate
示例或者如果你想重写默认值,Spring Boot提供RabbitStreamTemplateConfigurer
bean,你可以使用和与自动配置的工厂相同的配置初始化RabbitStreamTemplate
。
当Rabbit基础设施存在时,任何bean可以使用@RabbitListener
注解创建监听器端。如果没有RabbitListenerContainerFactory
已经定义,默认的SimpleRabbitListenerContainerFactroy
自动配置并且你可以使用spring.rabbit.listener.type
属性转换到一个直接的容器。如果MessageConverter
或者MessageRecoverer
bean已经定义,它将自动与默认的工厂关联。
下方的示例组件在someQueue
队列创建了一个监听器端:
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@RabbitListener(queues = "someQueue")
public void processMessage(String content) {
// ...
}
}
请查看
@EnableRabbit
的Javadoc了解更多详情。
如果你需要创建更多的RabbitListenerContainerFactory
示例或者如果你想重写默认值,Spring Boot提供SimpleRabbitListenerContainerFactoryConfigurer
和DirectRabbitListenerContainerFactoryConfigurer
,你可以使用与自动配置的工厂相同设置初始化SimpleRabbitListenerContainerFactory
和DirectRabbitListenerContainerFactory
。
他不关注你选择的容器类型。通过自动配置公开这两个bean.
例如,下方的配置类公开另外使用特定的MessageConverter
一个工厂:
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyRabbitConfiguration {
@Bean
public SimpleRabbitListenerContainerFactory myFactory(SimpleRabbitListenerContainerFactoryConfigurer configurer) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
ConnectionFactory connectionFactory = getCustomConnectionFactory();
configurer.configure(factory, connectionFactory);
factory.setMessageConverter(new MyMessageConverter());
return factory;
}
private ConnectionFactory getCustomConnectionFactory() {
return ...
}
}
然后你可以在任何带有注解@RabbitListener
的方法上使用这个工厂,如下:
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@RabbitListener(queues = "someQueue", containerFactory = "myFactory")
public void processMessage(String content) {
// ...
}
}
你可以启动重试来处理你的监听器抛出一个异常的解决方案。默认情况下,使用RejectAndDontRequestRecoverer
,但是你可以定义你自己的MessageRevoverer
。如果broker被配置这样做,当重试耗尽时,拒绝消息并且丢弃或者路由到死信交换器。默认情况下,重试是禁用的。你也可以通过声明RabbitRetryTemplateCustomizer
bean程序化定制RetryTemplate
。
默认情况下,如果重试是禁用的并且监听器抛出一个异常,交付则无限期重试。你可以以两种方式修改这种行为:设置
defaultRequeueRejected
属性为false
以便尝试零重新提交或者抛出AmqpRejectAndDontRequeueException
来标志消息应该被拒绝。后者是在启用重试并达到最大传递尝试次数时使用的机制。
Apache Kafka通过提供spring-kafka
项目的自动配置提供支持。
通过使用spring.kafka.*
外部化配置属性控制Kafka配置。例如,你可以在application.properties
声明以下章节:
spring:
kafka:
bootstrap-servers: "localhost:9092"
consumer:
group-id: "myGroup"
为在启动时创建主体,添加了类型为
NewTopic
的bean。如果这个主题已经存在,忽略这个bean。
请查看KafkaProperties
了解更多支持的选项。
Spring的KafkaTemplate
是自动配置的,并且你可以直接自动装载它到你自己的bean,如下示例所示:
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final KafkaTemplate<String, String> kafkaTemplate;
public MyBean(KafkaTemplate<String, String> kafkaTemplate) {
this.kafkaTemplate = kafkaTemplate;
}
public void someMethod() {
this.kafkaTemplate.send("someTopic", "Hello");
}
}
如果属性
spring.kafka.producer.transaction-id-prefix
被定义,KafkaTransactionManager
是自动配置。同时,如果RecordMessageConverter
bean已经定义,它会自动与自动配置的KafkaTemplate
关联。
当Apache Kafka基础设施存在,任何使用@KafkaListener
注解的bean创建了一个监听器端。如果没有KafkaListenerContainerFactory
已经定义,将使用在spring.kafka.listener.*
中定义的key自动配置默认的一个。
以下组件在someTopic
主题,创建一个监听器端:
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@KafkaListener(topics = "someTopic")
public void processMessage(String content) {
// ...
}
}
如果定义一个KafkaTransactionManager
bean,它将自动与容器工厂关联。类似地,如果定义了RecordFilterStrategy
,CommonErrorHandler
,AfterRollbackProcessor
或者ConsumerAwareRebalanceListener
bean,它将自动与默认的工厂关联。
依据监听器类型,RecordMessageConverter
或者BatchMessageConverter
bean与默认的工厂关联。如果只有一个用于批量监听器RecordMessageConverter
bean存在,将使用BatchMessageConveter
封装它。
自定义的
ChaindKafkaTransactionManager
必须被标记为@Primary
,因为它通常引用自动配置的KafkaTransactionManager
bean。
用于Apache Kafka的Spring提供工厂bean创建StreamBuilder
对象并管理它的流的生命周期。只要kafka-streams
在类路径中,Spring Boot自动配置所需要的KafkaStreamsConfiguration
bean并且Kafka Stream通过@EnableKafkaStreams
注解启用。
启用Kafka流意味着必须设置应用程序id和引导服务器。前者使用spring.kafka.streams.application-id
配置,如果没有设置默认使用spring.application.name
。后者可以全局设置或者专门为流覆盖。
使用专用的属性可以获得几个额外的属性;其他任意Kafka属性可以使用spring.kafka.streams.properties
命名空间设置。请查阅额外的Kafka属性了解更多信息。
为使用工厂bean,将StreamsBuilder
连接到@Bean
,如下示例所示:
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KeyValue;
import org.apache.kafka.streams.StreamsBuilder;
import org.apache.kafka.streams.kstream.KStream;
import org.apache.kafka.streams.kstream.Produced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafkaStreams;
import org.springframework.kafka.support.serializer.JsonSerde;
@Configuration(proxyBeanMethods = false)
@EnableKafkaStreams
public class MyKafkaStreamsConfiguration {
@Bean
public KStream<Integer, String> kStream(StreamsBuilder streamsBuilder) {
KStream<Integer, String> stream = streamsBuilder.stream("ks1In");
stream.map(this::uppercaseValue).to("ks1Out", Produced.with(Serdes.Integer(), new JsonSerde<>()));
return stream;
}
private KeyValue<Integer, String> uppercaseValue(Integer key, String value) {
return new KeyValue<>(key, value.toUpperCase());
}
}
默认情况下,由它创建的StreamBuilder
对象管理的流是自动启动的。你可以使用spring.kafka.streams.auto-startup
属性定制这种行为。
自动配置支持的属性是展示在附录中的“集成属性”章节中的。注意,对于大多数部分,这些属性(带有连字符或者驼峰)直接映射到Apache Kafka带有逗号的属性。请查阅Apache Kafka文档了解详情。
最开始这些属性的几个适用所有组件(生产者,消费者,管理员和流)但是如果希望使用不同的值,可以在组件级别指定。Apache Kafka使用非常重要的HIGH,MEDIUM或者LOW指定属性。Spring Boot自动配置支持所有的HIGH重要属性,一些选中的MEDIUM和LOW属性,以及任何没有默认值属性。
只有Kafka支持的这些属性的子集可以通过KafkaProperties
类直接获取。如果你希望使用不直接支持的额外的属性配置生产者或者消费者,使用以下属性:
spring:
kafka:
properties:
"[prop.one]": "first"
admin:
properties:
"[prop.two]": "second"
consumer:
properties:
"[prop.three]": "third"
producer:
properties:
"[prop.four]": "fourth"
streams:
properties:
"[prop.five]": "fifth"
这个设置普通的prop.one
Kafka属性为first
(应用到生产者,消费者和管理者),prop.two
admin属性为second
,prop.three
consumer属性为third
,prop.four
生产者属性为fourth
,prop.five
stream 属性为fifth
。
你也可以如下配置Spring KafkaJsonDeserializer
:
spring:
kafka:
consumer:
value-deserializer: "org.springframework.kafka.support.serializer.JsonDeserializer"
properties:
"[spring.json.value.default.type]": "com.example.Invoice"
"[spring.json.trusted.packages]": "com.example.main,com.example.another"
类似地,你可以禁用JsonSerializer
在数据头发送类型信息的默认行为:
spring:
kafka:
producer:
value-serializer: "org.springframework.kafka.support.serializer.JsonSerializer"
properties:
"[spring.json.add.type.headers]": false
这种方式的属性设置覆盖Spring Boot明确支持的任何配置项。
用于Apache Kafka的Spring 提供了方便的方式测试使用内嵌的Apache Kafka broker的项目。为使用这个特性,使用来自spring-kafka-test
模块@EnbeddedKafka
注解一个测试类。对于更多信息,请查阅用于Apache Kafka参考手册。
为使Spring Boot自动配置与上述的内嵌Apache Kafka broker一起工作,你需要将内嵌broker地址的系统属性(由EmbeddedKafkaBorker
填充)重新映射到Apache Kafka的Spring Boot配置属性。几种方式可以做到这些:
spring.kafka.bootstrap-servers
:static {
System.setProperty(EmbeddedKafkaBroker.BROKER_LIST_PROPERTY, "spring.kafka.bootstrap-servers");
}
@EmbeddedKafka
注解上配置属性名称:import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.kafka.test.context.EmbeddedKafka;
@SpringBootTest
@EmbeddedKafka(topics = "someTopic", bootstrapServersProperty = "spring.kafka.bootstrap-servers")
class MyTest {
// ...
}
spring:
kafka:
bootstrap-servers: "${spring.embedded.kafka.brokers}"
RSocket是二进制协议用在字节流传输。它通过在单个连接上传递异步消息来支持对称交互模型。
Spring Framework的spring-messaging
模型在客户端和消费端对RSocket请求者和响应者提供支持。请查看Spring Framework仓考的RSocket部分了解更多详情,包括RSocket协议概览。
Spring Boot自动配置一个RSocketStrategies
bean,为编码和解码RSocket负载提供了所有的基础设施。默认情况下,自动配置将尝试配置以下内容(按照顺序):
spring-boot-starter-rsocket
启动器提供两者依赖。请查看Jackson支持部分了解更多关于定制可能性。
开发者通过创建实现了RSocketStrategiesCustomizer
接口的bean可以定制RSocketStrategies
组件。注意他们的@Order
是重要的,因为它决定编码的顺序。
Spring Boot提供RSocket服务器自动配置。通过spring-boot-starter-rsocket
提供需要的依赖项。
Spring Boot允许从WebFlux服务器通过WebSocket暴露RSocket,或者建立一个独立的RSocket服务器。这个依据应用程序的类型和它的配置。
对于WebFlux应用程序(这个是WebApplicationType.REACTIVE
类型),只有以下属性匹配时,RSocket服务器将才会被插入到Web服务器:
spring:
rsocket:
server:
mapping-path: "/rsocket"
transport: "websocket"
只有使用Reactor Netty支持将RSocket插入到web服务器,因为RSocket它自己使用这个类库构建的。
或者,RSocket TCP或者websocket服务器作为独立内嵌服务器启动的。除了依赖项的需求外,仅需要的配置是定义服务器的端口:
spring:
rsocket:
server:
port: 9898
Spring Boot将为RSocket自动配置Spring Messaging基础设施。
这表示Spring Boot将创建RSocketMessageHandler
bean,将处理对应用程序的RSocket请求。
一旦RSocket
频道已经在服务器和客户端确定,任意一方可以发送或者接受到另一方的请求。
作为服务器,你可以在任意RSocket的@Controller
的处理方法上注入RScoketRequester
实例。作为客户端,首先你需要配置和简历RSocket连接。Spring Boot使用期望的编解码器为这种情况自动配置一个RSocketRequest.Builder
并应用任何RSocketConnectorConfigurer
bean。
RSocketRequester.Builder
实例是原型bean,表示每个注入点都将提供一个新的实例。这样做是有目的的,是因为这个构造器是有状态的,你不应该使用相同的实例创建具有不同的设置的requester。
下方的代码展示了典型的示例:
import reactor.core.publisher.Mono;
import org.springframework.messaging.rsocket.RSocketRequester;
import org.springframework.stereotype.Service;
@Service
public class MyService {
private final RSocketRequester rsocketRequester;
public MyService(RSocketRequester.Builder rsocketRequesterBuilder) {
this.rsocketRequester = rsocketRequesterBuilder.tcp("example.org", 9898);
}
public Mono<User> someRSocketCall(String name) {
return this.rsocketRequester.route("user").data(name).retrieveMono(User.class);
}
}
Spring Boot为与Spring Integration一起工作提供了多种方便,包括spring-boot-starter-integration
启动器。Spring Integration提供消息和其他传输协议,比如HTTP,TCP等抽象。如果Spring Integration在类路径中可用,通过@EnableIntegration
注解初始化。
Spring Integration轮询逻辑依据自动配置的TaskScheduler
。默认的PollerMetadata
(每秒钟轮询无数次消息)可以使用spring.integration.poller.*
配置属性定制。
Spring Boot也配置一些特性,这些特性通过额外的Spring Integration模块触发。如果spring-integration-jmx
也在类路径中,消息处理统计信息通过JXM发布。如果spring-integration-jdbc
可用,默认的数据库模式在启动时创建,如下行所示:
spring:
integration:
jdbc:
initialize-schema: "always"
如果spring-integration-rsocket
是可用的,开发者可以使用spring.rsocket.server.*
属性配置一个RSocket服务器并允许它使用IntegrationRSocketEndpoint
或者RSocketOutboundGateway
组件处理传入RSocket消息。
这个基础设施可以处理Spring Integration RSocket通道适配器和@MessageMapping
处理器(给定的"spring.integration.rsocket.server.message-mapping-enable"
已经配置)。
Spring Boot也可以使用配置属性自动配置ClientRSocketConnector
:
# Connecting to a RSocket server over TCP
spring:
integration:
rsocket:
client:
host: "example.org"
port: 9898
# Connecting to a RSocket Server over WebSocket
spring:
integration:
rsocket:
client:
uri: "ws://example.org"
请查看IntegrationAutoConfiguration
和IntegrationProperties
类了解更多详情。
Spring Boot对内嵌的tomcat,Jetty和Undertow提供WebSocket自动配置。如果你发布一个war文件到独立运行的容器,Spring Boot假设容器负责配置其WebSocket支持。
Spring Framework对MVCweb应用程序提供丰富的WebSocket支持,可以通过spring-boot-starter-websocket
模块非常容易进行访问。
WebSocket支持对于响应式web应用程序也是可用的,需要包括WebSocket API与spring-boot-starter-webflux
一起:
<dependency>
<groupId>javax.websocketgroupId>
<artifactId>javax.websocket-apiartifactId>
dependency>
下一章节描述在应用程序中如何启用IO功能。你可以在这个章节中读关于caching,mail,validation,rest clients或者更多的内容。
大多数应用程序在某些时候都需要处理输入和输出。当你需要IO功能的时候,Spring Boot提供工具和集成一系列技术来提供帮助。这个章节包含标准的IO特性比如缓存和校验以及更高级主题比如定时和分布式事务。我们也将包含调用远程REST或者SOAP服务和发送email。
Spring Framework对显示的添加缓存到应用程序提供支持。其核心是,抽象将缓存应用到方法,从而根据缓存中可用的信息减少执行次数。缓存逻辑的应用是透明的,不会对调用者造成任何干扰。只要通过使用@EnableCaching
注解启用缓存支持,Spring Boot自动配置缓存的基础设施。
查看Spring Framework的相关章节了解更多详情。
简言之,为添加缓存到服务的操作中, 请将相关的注解一个到它的方法中,如下示例所示:
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
@Component
public class MyMathService {
@Cacheable("piDecimals")
public int computePiDecimal(int precision) {
...
}
}
这个示例演示了在可能开销较大的操作上使用缓存。在调用computePiDecimal
之前,这个抽象查找匹配i参数piDecimals
缓存入口。如果找到入口,在缓存中的内容立即返回给调用者,并且这个方法不会被调用。否则,调用这个方法,并且在返回值之前更新缓存。
你也可以显示地使用标准的JSR-107(JCache)注解(比如
@CacheResult
)。然而,我们强烈建议你不要混合使用Spring Cache和JCache注解。
如果你不添加任何特定的缓存类库,Spring Boot自动配置一个简单的提供者,在存储上使用并行map。当需要一个缓存时(例如前面例子中的piDecimals
),这个提供者为你创建它。这个简单的提供者不建议在生产中使用,但是他是比较好的入门并确保你理解这个特性。当你已经想好使用缓存提供者,请务必阅读它的文档,弄清楚如何配置应用程序使用的缓存。几乎所有的提供者需要你明确配置每一个在应用程序中使用的缓存。有些提供了一种方式通过spring.cache.cache-names
属性来定制已定义的默认缓存。
他也可以显性地更新或者从缓存中移除数据。
缓存抽象不是提供一个真实的存储并依赖于org.springframework.cache.Cache
和org.springframework.cache.CacheManager
接口的实现抽象。
如果你没有定义CacheManager
或者命名为cacheResolver
的CacheResolver
(请看CachingConfigurer
),Spring Boot尝试检测以下提供者(按照表明的顺序):
它也可能通过设置
spring.cache.type
属性强制提供一个特别的缓存。如果你需要在某一环境(比如测试)完全禁用缓存请使用这个属性。
使用
spring-boot-starter-cache
启动器快速添加基本的缓存依赖项。启动器引入spring-context-support
。如果你手工添加依赖,你必须包含spring-context-support
为了使用JCache或者Caffeine支持。
如果CacheManager
通过Spring Boot自动配置,在完全初始化之前,你可以通过公开一个实现CacheManagerCustomizer
接口的bean在进一步调整他的配置。下方的示例设置了一个标志,表示null
值不应该传入到底层映射:
import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizer;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyCacheManagerConfiguration {
@Bean
public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {
return (cacheManager) -> cacheManager.setAllowNullValues(false);
}
}
在前面的示例中,需要一个自动配置的ConcurrentMapCacheManager
。如果不是这样的话(或者你提供你自己的配置或者自动配置了不同的缓存提供者),则定制器根本不会被调用。你可以拥有任意数量的定制器,你也可以使用@Order
或者Ordered
对他们进行排序。
如果上下文定义了至少一个org.springframework.cache.Cache
bean则会使用Generic缓存。CacheManager
包装所有创建该类型的bean。
通过类路径中的javax.cache.spi.CachingProvider
(也就是说,类路径上存在符合JSR-107缓存库)启动JCache ,并且通过spring-boot-starter-cache
启动器提供JCacheCacheManager
。多种符合的类库是可用的,Spring Boot为Ehcache 3和Hazelcast提供依赖管理。也可以添加任何其他的符合类库。
可能发生存在超过一个提供者的情况,这种情况提供者必须明确指定。即使JSR-107标准没有实施标准化的方式来定义配置文件的位置,Spring Boot尽最大努力通过实现细节设置一个缓存,如下示例所示:
# Only necessary if more than one provider is present
spring:
cache:
jcache:
provider: "com.example.MyCachingProvider"
config: "classpath:example.xml"
当一个缓存类库提供本身实现和JSR-107支持,Spring Boot更倾向于JSR-107支持,以便如果你改变到一个不同的JSR-107实现,相同的特性是可用的。
Spring Boot对Hazelcast提供常规支持。如果单独的
HazelcastInstance
是可用的,它也会被CacheManager
自动重用,除非指定了spring.cache.jcache.config
属性。
有两种方式定制底层的javax.cache.cacheManager
:
spring.cache.cache-names
属性,在启动时可以创建Cache。如果一个自定义的javax.cache.configuration.Configuration
bean已经定义,使用它定制他们。org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer
bean通过引用CacheManager
来进行完全定制的。如果一个标准的
javax.cache.CacheManager
bean被定义,它自动包装在抽象所期望的org.springframework.cache.CacheManager
实现中。没有对其应用任何进一步的定制。
Spring Boot存在对Hazelcast的常规支持。如果一个HazelcastInstance
已经自动配置,它自动封装在CacheManager
。
如果Spring Data Couchbase是可用的并且Couchbase已经配置,CouchbaseCacheManager
则自动配置。可以通过设置spring.cache.cache-name
属性启动时创建额外的缓存并且使用spring.cache.couchbase.*
属性配置默认缓存。例如,下面的配置创建了条目过期时间为10分钟的cache1
和cache2
缓存:
spring:
cache:
cache-names: "cache1,cache2"
couchbase:
expiration: "10m"
如果你需要更多控制配置,考虑注册CouchbaseCacheManagerBuilderCustomizer
bean。以下示例展示了配置了特定的条目过期时间的cache1
和cache2
的定制:
import java.time.Duration;
import org.springframework.boot.autoconfigure.cache.CouchbaseCacheManagerBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.cache.CouchbaseCacheConfiguration;
@Configuration(proxyBeanMethods = false)
public class MyCouchbaseCacheManagerConfiguration {
@Bean
public CouchbaseCacheManagerBuilderCustomizer myCouchbaseCacheManagerBuilderCustomizer() {
return (builder) -> builder
.withCacheConfiguration("cache1", CouchbaseCacheConfiguration
.defaultCacheConfig().entryExpiry(Duration.ofSeconds(10)))
.withCacheConfiguration("cache2", CouchbaseCacheConfiguration
.defaultCacheConfig().entryExpiry(Duration.ofMinutes(1)));
}
}
如果Redis是可用的并且已经配置,RedisCacheManager
是自动配置的。可以通过设置spring.cache.cache-name
属性启动时创建额外的缓存,通过使用spring.cache.redis.*
属性配置默认缓存。例如,下面的配置创建了存活时间为10分钟的cache1
和cache2
缓存:
spring:
cache:
cache-names: "cache1,cache2"
redis:
time-to-live: "10m"
通过添加你自己的RedisCacheConfiguration
bean,你可以完全控制默认的配置。如果你需要定制默认的序列化策略的话这个是非常有用的。
如果你需要更多的控制,考虑注册RedisCacheManagerBuilderCustomizer
bean。下面的示例展示了配置指定存活时间的cache1
和cache2
的定制:
import java.time.Duration;
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
@Configuration(proxyBeanMethods = false)
public class MyRedisCacheManagerConfiguration {
@Bean
public RedisCacheManagerBuilderCustomizer myRedisCacheManagerBuilderCustomizer() {
return (builder) -> builder
.withCacheConfiguration("cache1", RedisCacheConfiguration
.defaultCacheConfig().entryTtl(Duration.ofSeconds(10)))
.withCacheConfiguration("cache2", RedisCacheConfiguration
.defaultCacheConfig().entryTtl(Duration.ofMinutes(1)));
}
}
Caffeine是Java 8 Guava的缓存重写的,取代了Guava支持。如果Caffeine存在,CaffeineCacheManager
(spring-boot-starter-cache
启动器提供)自动配置。通过设置spring.cache.chache-names
属性Cache在启动时创建并通过以下其中一种方式定制(按照指定的顺序):
spring.cache.caffeine.spec
定义的spec缓存。com.github.benmanes.caffeine.cache.CaffeineSpec
bean。com.github.benmanes.caffeine.cache.Caffeine
。cache1
和cache2
缓存:spring:
cache:
cache-names: "cache1,cache2"
caffeine:
spec: "maximumSize=500,expireAfterAccess=600s"
如果com.github.benmanes.caffeine.cache.CacheLoader
bean被定义,将自动与CaffeineCacheManager
关联。因为CacheLoader
将通过缓存管理器与所有的管理的缓存关联,它必须被定义为CacheLoader
。自动配置任何忽略泛型。
Cache2k是一个内存缓存。如果Cache2k spring 集成存在,SpringCache2kCacheManager
是自动配置的。
通过设置spring.cache.cache-name
属性在启动时创建缓存。通过使用Cache2kBuilderCustomizer
bean可以定制默认的缓存。以下示例展示配置了容量为200条目的缓存并且过期时间5分钟的定制:
import java.util.concurrent.TimeUnit;
import org.springframework.boot.autoconfigure.cache.Cache2kBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyCache2kDefaultsConfiguration {
@Bean
public Cache2kBuilderCustomizer myCache2kDefaultsCustomizer() {
return (builder) -> builder.entryCapacity(200)
.expireAfterWrite(5, TimeUnit.MINUTES);
}
}
如果没有发现其他提供者,一个简单的实现使用ConcurrentHashMap
作为缓存存储被配置。如果应用程序中没有缓存类库存在则使用这个默认的。默认情况下,缓存根据所需创建的,但是如果你可以通过设置cache-names
属性限制可用缓存的列表。例如,如果你只想cache1
和cache2
缓存,设置如下cache-names
属性:
spring:
cache:
cache-names: "cache1,cache2"
如果你这样做,并且你的应用程序使用了未列出的缓存,然后当需要缓存时,运行时失败,并不是在启动的时候。如果使用未声明的缓存,这就类似于“真正”的缓存提供者的行为。
当你的配置中@EnableCaching
存在时,也需要一个合适的缓存配置。如果你需要在某一环境中完全禁用缓存,强制缓存类型为none
以使用无操作的实现,如下示例所示:
spring:
cache:
type: "none"
如果Hazelcast在类路径中并且发现可用的配置,Spring Boot自动配置HazelcastInstance
,你可以将其注入到应用程序。
Spring Boot首先通过检查以下配置选项,尝试创建一个客户端:
com.hazelcast.client.config.ClientConfig
bean的存在。spring.hazelcast.config
属性定义的配置文件。hazelcast.client.config
系统属性的存在。hazelcast-client.xml
。hazelcast-client.yaml
。如果客户端不能被创建,Spring Boot尝试配置一个内嵌的服务器。如果你定义了com.hazelcast.config.Config
bean,Spring Boot使用这个。如果配置定义了一个实例的名称,Spring Boot尝试定位现有的实例而不是创建一个新的。
你也可以通过配置指定Hazelcast配置文件以使用,如下示例所示:
spring:
hazelcast:
config: "classpath:config/my-hazelcast.xml"
否则,Spring Boot尝试在默认的位置查找Hazelcast配置:在工作目录或者根类路径中的hazelcast.xml
,或者相同位置对应的.yml
。我们也检查hazelcast.config
系统属性是否设置。请查阅Hazelcast文档了解更多详情。
默认情况下,在Hazelcast 组件上的
@SpringAware
是支持的。ManagementContext
可以通过声明一个使用大于零的Order
的HazelcastConfigCustomizer
bean重写。
Spring Boot也对Hazelcast也明确的缓存支持。如果禁用缓存,
HazelcastInstance
自动封装在CacheManager
实现中。
Spring Boot为与Quartz Scheduler工作提供多种方便,包括spring-boot-starter-quartz
启动器。如果Quartz是可用的,Scheduler
是自动配置(通过SchedulerFactoryBean
抽象)。
以下类型的bean自动选取并关联Scheduler
:
JobDetail
:定义特定的Job。JobDetail
实例可以使用JobBuilder
API构造。Calendar
。Trigger
:当特定的job触发时定义。默认情况下,使用一个内存的JobStore
。然而,如果应用程序中DataSource
bean 可用并且如果相应的配置spring.quartz.job-store-type
属性,可以配置基于JDBC存储,如下示例所示:
spring:
quartz:
job-store-type: "jdbc"
当使用JDBC存储时,在启动时初始化此模式,如下示例所示:
spring:
quartz:
jdbc:
initialize-schema: "always"
默认情况下,通过使用Quartz类库提供的标准的脚本,检测和初始化数据库。在每次重启,这些脚本删除存在的表,删除所有的触发器。通过设置
spring.quartz.jdbc.schema
属性可以提供自定义的脚本。
要让Quartz使用应用程序的主DataSource
以外的DataSource
,声明一个DataSource
bean,使用@QuartzDataSource
注解它的@Bean
方法。这样做确保SchedulerFactoryBean
和用于模式初始化使用特定的QuartzDataSource
。类似地,要让Quartz使用应用程序的主要的TransactionManager
,声明一个TransactionManager
bean,使用@QuartzTranscationManager
注解它的@Bean
方法。
默认情况下,通过配置创建的job将不会重写已经注册并且已经从持久化job存储读取的job。为启用重写现在有job定义,请设置spring.quartz.overwrite-existing-jobs
属性。
Quartz Scheduler配置可以使用spring.quartz
属性和SchedulerFactoryBeanCustomizer
bean定制,它们允许对SchedulerFactoryBean
程序化定制。高级的Quartz配置属性可以使用spring.quartz.properties.*
定制。
特别是,
Executor
bean不会与scheduler结合因为Quartz通过spring.quartz.properties
配置方式配置scheduler。如果你需要定制任务执行器,考虑实现SchedulerFactoryBeanCustomizer
。
Job可以定义setter注入数据映射属性。常规的bean也可以以类似的方式注入,如下示例所示:
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class MySampleJob extends QuartzJobBean {
private MyService myService;
private String name;
// Inject "MyService" bean
public void setMyService(MyService myService) {
this.myService = myService;
}
// Inject the "name" job data property
public void setName(String name) {
this.name = name;
}
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
this.myService.someMethod(context.getFireTime(), this.name);
}
}
Spring Framework通过使用JavaMailSender
接口提供发送邮件的抽象,并且Spring Boot为它提供自动配置以及启动器模块。
请查看参考文档了解解释了如何使用
JavaMailSender
情况。
如果spring.mail.host
和相关的类库(spring-boot-starter-mail
定义的)是可用的,如果默认的JavaMailSender
不存在则创建。发送器(sender)可以通过配置来自spring.mail
命名空间的项进一步定制。请查看MailProperties了解更多详情。
特别是,某个默认的超时的值是无限的,你可能想改变这一点,来避免被无响应的邮件服务器线程阻塞,如下示例所示:
spring:
mail:
properties:
"[mail.smtp.connectiontimeout]": 5000
"[mail.smtp.timeout]": 3000
"[mail.smtp.writetimeout]": 5000
也可以使用JNDI中现有的Session
配置JavaMailSender
:
spring:
mail:
jndi-name: "mail/Session"
当jndi-name
已经设置,它的优先级在所有其他相关的Session设置之上。
支持方法验证特性通过Bean Validation 1.1自动启用只要在类路径中存在JSR-303实现(例如Hibernate验证)。这个使得bean方法可以在其参数或者他们的返回值上javax.validation
约束进行注解。使用这样的带有注解方法的目标类需要在类型级别上使用@Validated
注解进行注解,以便搜索他们的方法以内联约束注解。
例如,以下服务触发第一个参数的校验,确保他的长度在8和10之间:
import jakarta.validation.constraints.Size;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@Service
@Validated
public class MyBean {
public Archive findByCodeAndAuthor(@Size(min = 8, max = 10) String code, Author author) {
return ...
}
}
当解析在约束信息中的{参数}
时使用应用程序的MessageSource
。这个允许你使用你的应用程序的messages.properties
文件用于Bean Validation信息。一旦参数已经被解析,使用Bean Validation的默认内插器完成信息内插。
为定制用于构建ValidatorFactory
的Configuration
,定义ValidationConfigurationCustomizer
bean。当定义了多个定制器bean,他们按照基于@Order
注解或者Ordered
实现的顺序调用。
如果你的应用程序调用远程的REST服务,Spring Boot使用RestTemplate
或者WebClient
使其非常方便。
如果你需要在你的应用程序调用远程的REST服务,你可以使用Spring Framework的RestTemplate
类。因为在使用RestTemplate
实例之间通常需要被定制,Spring Boot不会提供任何单个自动配置的RestTemplate
bean。但是,他会自动配置RestTemplateBuilder
,当需要时它可以用来创建RestTemplate
实例。自动配置的RestTemplateBuilder
确保合适的HttpMessageConverters
应用到RestTemplate
实例中。
以下代码展示了典型的示例:
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class MyService {
private final RestTemplate restTemplate;
public MyService(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}
public Details someRestCall(String name) {
return this.restTemplate.getForObject("/{name}/details", Details.class, name);
}
}
RestTemplateBuilder
包含多个有用处的方法,可以用来快速配置RestTemplate
。例如,为添加基本的授权支持,你可以使用builder.basicAuthentication("user","password").build()
。
有三种主要的方法实现RestTemplate
定制,这取决于你希望自定义的应用范围。
为了使定制的范围尽可能的小,注入自动配置的RestTemplateBuilder
,然后根据所需调用他的方法。每次方法调用返回一个新的RestTemplateBuilder
实例,所以这个定制只影响builder的使用。
为使应用程序范围内的,递增地定制,使用RestTemplateCustomizer
bean。所有这样的bean是自动注册到RestTemplateBuilder
并且被应用于使用它构建的任何模板。
下方的示例展示了一个定制器,其配置了用于除了192.168.0.6
以外的所有主机的代理的使用:
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.routing.HttpRoutePlanner;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
import org.apache.http.protocol.HttpContext;
import org.springframework.boot.web.client.RestTemplateCustomizer;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
public class MyRestTemplateCustomizer implements RestTemplateCustomizer {
@Override
public void customize(RestTemplate restTemplate) {
HttpRoutePlanner routePlanner = new CustomRoutePlanner(new HttpHost("proxy.example.com"));
HttpClient httpClient = HttpClientBuilder.create().setRoutePlanner(routePlanner).build();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
}
static class CustomRoutePlanner extends DefaultProxyRoutePlanner {
CustomRoutePlanner(HttpHost proxy) {
super(proxy);
}
@Override
public HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context) throws HttpException {
if (target.getHostName().equals("192.168.0.5")) {
return null;
}
return super.determineProxy(target, request, context);
}
}
}
最后,你可以定义你自己的RestTemplateBuilder
bean。这样做将替换自动配置的builder。如果你希望任何RestTemplateCustomizer
bean被应用到自定义builder,就像自动配置那样,使用RestTemplateBuilderConfigurer
配置它。下面的示例暴露匹配Spring Boot的自动配置所做的RestTemplateBuilder
,除了自定义连接以外,读超时也被指定:
import java.time.Duration;
import org.springframework.boot.autoconfigure.web.client.RestTemplateBuilderConfigurer;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyRestTemplateBuilderConfiguration {
@Bean
public RestTemplateBuilder restTemplateBuilder(RestTemplateBuilderConfigurer configurer) {
return configurer.configure(new RestTemplateBuilder()).setConnectTimeout(Duration.ofSeconds(5))
.setReadTimeout(Duration.ofSeconds(2));
}
}
最极端的情况(很少使用)是不使用configurer创建自己的RestTemplateBuilder
。除了替换自动配置的builder,也可以防止使用任何RestTemplateCustomizer
。
如果你有Spring WebFlux在类路径中,你也可以选择使用WebClient
来调用远程的REST服务。相比于RestTemplate
,这个客户端有更强的功能性,而且完全是响应式的。你可以在Spring Framework文档中相关的章节学习更多关于WebClient
。
Spring Boot为你创建和预配置一个WebClient.Builder
。强烈建议将它注入你的组件和使用它创建WebClient
实例。Spring Boot正在配置该构建器以共享HTTP资源,以与服务器相同的方式反射编解码器的设置(请查看WebFlux HTTP编解码自动配置),等等。
下面的代码展示了一个典型的示例:
import org.neo4j.cypherdsl.core.Relationship.Details;
import reactor.core.publisher.Mono;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
@Service
public class MyService {
private final WebClient webClient;
public MyService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://example.org").build();
}
public Mono<Details> someRestCall(String name) {
return this.webClient.get().uri("/{name}/details", name).retrieve().bodyToMono(Details.class);
}
}
Spring Boot将自动检测使用哪个ClientHttpConnector
来驱动WebClient
,取决于在应用程序类路径可用的类库。现在,Reactor Netty,Jetty RS客户端和Apache HttpClient是支持的。
spring-boot-starter-webflux
启动器默认情况下依赖io.projectreactor.netty:reactor-netty
,其带有服务器和客户端实现。如果你选择使用Jetty作为响应式服务器代替,你应该在Jetty Reactive HTTP客户端类库上添加一个依赖项,org.eclipse.jetty:jetty-reactive-httpclient
。服务器和客户端使用相同的技术有它的优势,因为它将在客户端和服务器自动共享HTTP资源。
开发者可以通过提供自定义的ReactorResourceFactory
或者JettyResourceFactory
bean对Jetty和Reactor Netty重写资源配置,ReactorResourceFactory
或者JettyResourceFactory
bean将应用到客户端和服务器。
如果你希望为客户端重写该选择,你可以定义你自己的ClientHttpConnector
bean并且完全控制客户端配置。
你也可以学习更多关于在Spring Framework参考文档的WebClient
配置选项。
WebClient
定制有三种主要的方法,取决于你想要应用的定制范围。
为是任何定制的范围尽可能的小,注入自动配置的WebClient.Builder
,然后调用他的所需要的方法。WebClient.Builder
实例是有状态的:任何在builder的改变都会反应到随后使用它创建的所有客户端上。如果你想使用相同的builder创建多个客户端,你也可以考虑使用WebClient.Builder other = builder.clone()
克隆builder。
要对所有的WebClient.Builder
实例进行应用程序范围的递增地定制,你可以声明WebClientCustomizer
bean并且在注入点局部改变WebClient.Builder
。
最终,你可以回退到原始的API并使用WebClient.create()
。在这种情况,没有自动配置或者应用WebClientCustomizer
。
Spring Boot提供Web服务自动配置,因此你必须做的是定义你的Endpoints
。
Spring Web Service特性使用spring-boot-starter-webservices
模块可以非常容易访问。
可以为WSDL和XSD分别自动创建SimpleWsdl11Definition
和SimpleXsdSchema
bean。为此,配置他们的位置,如下示例所示:
spring:
webservices:
wsdl-locations: "classpath:/wsdl"
如果你需要在应用程序中调用远程的web服务,你可以使用WebServiceTemplate
类。因为WebServiceTemplate
实例通常在使用之前需要定制它,Spring Boot不提供任何单独自动配置的WebServiceTemplate
bean。但是他会自动配置WebServiceTemplateBuilder
,当需要的它可以用来创建WebServiceTemplate
实例。
下面的代码展示了典型的示例:
import org.springframework.boot.webservices.client.WebServiceTemplateBuilder;
import org.springframework.stereotype.Service;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.client.core.SoapActionCallback;
@Service
public class MyService {
private final WebServiceTemplate webServiceTemplate;
public MyService(WebServiceTemplateBuilder webServiceTemplateBuilder) {
this.webServiceTemplate = webServiceTemplateBuilder.build();
}
public SomeResponse someWsCall(SomeRequest detailsReq) {
return (SomeResponse) this.webServiceTemplate.marshalSendAndReceive(detailsReq,
new SoapActionCallback("https://ws.example.com/action"));
}
}
默认情况下,WebServiceTemplateBuilder
使用类路径中可用的HTTP客户端类库检测合适的基于HTTP的WebServiceMessageSender
,你也可以定制读和连接超时,如下:
import java.time.Duration;
import org.springframework.boot.webservices.client.HttpWebServiceMessageSenderBuilder;
import org.springframework.boot.webservices.client.WebServiceTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.transport.WebServiceMessageSender;
@Configuration(proxyBeanMethods = false)
public class MyWebServiceTemplateConfiguration {
@Bean
public WebServiceTemplate webServiceTemplate(WebServiceTemplateBuilder builder) {
WebServiceMessageSender sender = new HttpWebServiceMessageSenderBuilder()
.setConnectTimeout(Duration.ofSeconds(5))
.setReadTimeout(Duration.ofSeconds(2))
.build();
return builder.messageSenders(sender).build();
}
}
Spring Boot通过使用从JNDI检索的事务管理支持跨多个XA资源的分布式JTA事务。
当检测JTA环境时,Spring的JtaTransactionManager
用来管理事务。自动配置的JMS,DataSource和JPAbean升级为支持XA事务。你可以使用标准的Spring风格,比如@Transactional
,来参与分布式事务。如果你在一个JTA环境内并想使用本地事务,你可以设置spring.jta.enabled
属性为false
来禁用JTA自动配置。
如果你打包Spring Boot应用程序为war
或者ear
文件并部署它到Jakarta EE应用程序服务器,你可以使用应用程序服务器的内建的事务管理器。Spring Boot尝试通过查找常用的JNDI位置(java:comp/UserTransaction
,java:comp/TransactionManager
等等)自动配置一个事务管理器。当使用应用程序服务器提供的事务服务时,你通常也希望确保所有的资源通过服务器管理并且通过JNDI暴露。Spring Boot尝试通过在JNDI路径(java:/JmsXA
或者java:/XAConnectionFactory
)查找ConnectionFactory
自动配置JMS,你可以使用spring.datasource.jndi-name
属性配置你的DataSource
。
当我们使用JTA,主要的JMSConnectionFactory
bean是支持XA并在分布式事务中参与。你无需使用任何@Qualifier
可以注入到你自己的bean。
public MyBean(ConnectionFactory connectionFactory) {
// ...
}
在一些情况中,你可能想使用非XA的ConnectionFactory
处理某一个JMS消息。例如,你的JMS处理逻辑所花费的时间可能比XA超时长。
如果你想使用一个非XAConnectionFactory
,你可以使用nonXaJmsConnectionFactory
bean:
public MyBean(@Qualifier("nonXaJmsConnectionFactory") ConnectionFactory connectionFactory) {
// ...
}
为保持一致性,通过使用别名为xaJmsConnectionFactory
也可以提供jmsConnectionFactory
bean:
public MyBean(@Qualifier("xaJmsConnectionFactory") ConnectionFactory connectionFactory) {
// ...
}
XAConnectionFactoryWrapper
和XADataSourceWrapper
接口可以用来支持内嵌的事务管理器。接口是负责包装XAConnectionFactory
和XADataSource
bean并且暴露他们作为常规的ConnectionFactory
和DataSource
bean,他们透明地注册到分布式事务中。DataSource和JMS自动配置使用JTA变体,前提是你有一个JtaTransactionManager
bean并且合适的XA封装bean注册到ApplicationContext
中。
现在你应该对Spring Boot的核心特性有一个很好的理解,并且Spring Boot通过自动配置提供支持各种技术。
下几个章节带你了解关于发布应用程序到云平台的细节。你可以读关于下一个章节构建容器镜像或者跳到生产就绪特性章节。
Spring Boot应用程序可以使用Docketfile容器化,或者使用云生打包创建优化的docker,兼容的容器镜像,可以在任何地方运行
可以容易地将Spring Boot fat jar打包为docker镜像。然而,在docker镜像中复制和运行fat jar也有多种缺点。当运行fat jar而不解压它时,总是有大量开销。并且在容器化环境中这个是很明显的。另一个问题是将你应用程序的代码和所有他的依赖放在Docker镜像中一个层是次优的。因为你可能重新编译你的代码通常多余升级你使用Spring Boot版本,最好是将代码的内容分开一些。如果你将jar文件放在应用程序类之前的那一层,Docker通常只需要改变最底层,就可以从缓存中获取其他文件。
如果你正在容器中运行你的应用程序,你可以使用可执行jar,但是它也通常具有优势来引爆它并且以不同的方式运行它。某些PaaS实现可能也选择在他们运行之前解压文档。例如,Cloud Foundry这种方式操作。一种方式运行一个未解压的档案是通过启动适合的启动器,如下:
$ jar -xf myapp.jar
$ java org.springframework.boot.loader.JarLauncher
这实际上在启动时确实比运行在未爆炸的存档要快一些(依据jar的大小)。在运行时你不应该期望有任何差异。
一旦你解压了jar文件,你也可以通过使用它的“自然的”主方法代替JarLauncher
来运行应用程序来获得额外的启动时间的提升。例如:
$ jar -xf myapp.jar
$ java -cp BOOT-INF/classes:BOOT-INF/lib/* com.example.MyApplication
在应用程序的主方法上使用
JarLauncher
还有额外的好处,那就时可预测的类路径顺序。jar包含classpath.idx
文件,在构造类路径时被JarLauncher
使用。
为使它容易创建最优的Docker映像,Spring Boot支持添加一个分层索引文件到jar。它提供分层列表和应该包含在其中的jar部分。在索引中的分层列表是基于分层应该被添加到Docker/OCI镜像顺序排序的。以下分层是支持开箱即用的:
dependencies
(用于常规的发布依赖)spring-boot-loader
(在org/springframework/boot/loader
下的任何东西)snapshot-dependencies
(用于快照依赖)application
(用于应用程序和资源)layers.idx
文件的示例:- "dependencies":
- BOOT-INF/lib/library1.jar
- BOOT-INF/lib/library2.jar
- "spring-boot-loader":
- org/springframework/boot/loader/JarLauncher.class
- org/springframework/boot/loader/jar/JarEntry.class
- "snapshot-dependencies":
- BOOT-INF/lib/library3-SNAPSHOT.jar
- "application":
- META-INF/MANIFEST.MF
- BOOT-INF/classes/a/b/C.class
这个分层被设计用于基于不同应用程序构建之间更改的可能性来分隔代码。类库代码在不同的构建可能很少改变,所以它放在他自己的分层以允许工具从缓存中重用这个分层。应用程序代码在构建之间更可能改变所以它被隔离放一个单独的分层。
Spring Boot在layers.idx
的帮助下也支持对war文件分层。
对于Maven,关于添加分层索引到存档,请查看打包分层jar或者war章节了解更多详情。对于Gradle,请查看Gradel插件文档的打包分层jar或者war章节
虽然在Dockerfile仅仅几行就可以转换Spring Boot fat jar到docker镜像,我们将使用分层特性来创建一个更优的docker镜像。当你创建包含分层索引文件的jar时,spring-boot-jarmode-layertools
jar将作为一个依赖项添加到你的jar中。有了类路径中的这个jar,你可以以一个特殊的模式启动你的应用程序,此模式允许引导代码运行与应用程序完全不同的东西,例如,提取层的东西。
layertools
模式不能与包含运行脚本完全的可执行的Spring Boot存档使用。当构建一个打算使用layertools
的jar文件时,禁用启动脚本配置。
这是你如何启动使用layertools
jar模式运行你的jar:
$ java -Djarmode=layertools -jar my-app.jar
这个将提供以下输出:
Usage:
java -Djarmode=layertools -jar my-app.jar
Available commands:
list List layers from the jar that can be extracted
extract Extracts layers from the jar for image creation
help Help about any command
extract
命令可以用来容易的将应用程序分隔成添加到dockerfile的分层。这是一个Dockerfile使用jarmode
的示例:
FROM eclipse-temurin:11-jre as builder
WORKDIR application
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract
FROM eclipse-temurin:11-jre
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
假设上面的Dockerfile
在当前目录,你的docker镜像可以使用docker build .
构建,或者随意地指定你的应用程序 jar的路径,如下示例所示:
$ docker build --build-arg JAR_FILE=path/to/myapp.jar .
这个是一个多级dockerfile。构造器阶段提取以后需要的目录。每个COPY
命令都与jarmode提取的层相关。
当然,Dockerfile可以在不使用jarmode的情况下重写。你可以使用一些unzip
和mv
的组合来移动东西到正确的分层但是jarmode简化了这一点。
Dockerfile只是一种方式构建docker镜像。另外一种方式构建docker镜像是直接使用Maven或者Gradle插件,使用构建包。如果你曾经使用过应用程序平台,比如Cloud Foundry或者Heroku,那么你可能使用过构建包。构建包是平台的一部分,他把你的应用程序转换成平台可以实际运行的东西。例如,Cloud Foundry的Java构建包会注意到你正在推送.jar
文件并自动添加一个相关的JRE。
使用云原生构建包,你可以创建可以在任何地方运行的Docker兼容镜像。Spring Boot包含构建包直接支持Maven和Gradle。这意味着你只需输入单个命令,就可以快速得到将一个合理的镜像导入到本地运行的Docker守护进程。
查看各自的插件文档关于如何在Maven和Gradle中使用构建包。
Paketo Spring Boot构建包也已经更新支持
layers.idx
文件,所以任何应用到它的定制,都会反应到构建包创建的镜像。
为了实现可复制的构建和容器镜像缓存,构建包可以操作应用程序资源元数据(例如文件“最后修改”信息)。你应该确保你的应用程序运行时不依赖该元数据。当提供静态资源时,Spring Boot可以使用该信息,但是可以使用
spring.web.resources.cache.use-last-modified
禁用这个功能。
一旦你已经学会如何构建高效的容器镜像,你可以读关于发布应用程序到云平台,例如Kubernetes。
当你将应用程序推送生产时,Spring Boot包含多种额外特性帮助你监控和管理你的应用程序。你可以通过使用HTTP端或者使用JMX选择管理和监控你的应用程序。监察,健康度和指标收集也可以自动应用到应用程序。
spring-boot-actuator
模块提供所有的Spring Boot的生产就绪状态特性。启用特性推荐的方式是添加spring-boot-starter-actuator
启动器依赖项。
Actuator定义
Actuator是一个制造术语,指的是移动和控制某物的一种机械装置。Actuator可以由一个微小的变化生成大量的运动。
为将Actuatro添加到基于Maven的项目,添加以下“启动器”依赖项:
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
dependencies>
对于Gradle,使用以下声明:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
}
Actuator端点允许你监控应用程序并与之交互。Spring Boot包含多个内建的端点并允许你添加自己的。例如,health
端点提供基本的应用程序监控信息。
你可以启用或者禁用每一个个别的端点或者在HTTP或者JMX暴露他们(使他们远程访问)。当一个端点启用并且暴露则认为是可用的。只有当他们是可用的,内建的端点是自动配置的。大多数应用程序选择在HTTP端暴露,其中端点的ID和/actuator
的前缀被映射到URL。例如,默认情况下,health
端点被映射到/actuator/health
。
为了解更多关于Actuator的端点和他们的请求响应格式,查看单独的API文档(HTML或者PDF)。
以下是可用的与技术无关的端点:
ID | 描述 |
---|---|
auditevents |
暴露当前应用程序审核事件信息。需要AuditEventRepository bean |
beans |
显示在你的应用程序中所有的bean的完整列表 |
caches |
暴露可用缓存 |
conditions |
展示在配置文件和自动配置类评估的条件和为什么他们没有或者匹配的原因 |
configprops |
展示所有的ConfigurationProperties 整理列表 |
env |
展示来自Spring的ConfigurableEnvironment 的属性 |
flyway |
展示任何已经应用的Flyway数据迁移。需要一个或者更多Flyway bean |
health |
展示应用程序健康信息 |
httptrace |
展示HTTP追踪信息(默认情况下,最后100个HTTP请求响应交换).需要HttpTraceRepository bean |
info |
展示任意的应用程序信息 |
integrationgraph |
展示Spring集成图像。需要spring-integration-core 依赖项 |
loggers |
展示和修改应用程序中日志的配置 |
liquibase |
展示任何已经应用的Liquibase数据库迁移.需要一个或者多个Liquibase bean |
metrics |
展示当前应用程序的指标 |
mappings |
展示所有的@RequestMapping 路径的整理列表 |
quartz |
展示关于Quartz Scheduler工作的信息 |
scheduledtasks |
展示你应用程序中的计划任务 |
sessions |
允许从Spring Session-backed会话库中用户会话的找回和删除。需要使用Spring Session基于servlet的web应用程序 |
shutdown |
使应用程序优雅停机。默认情况下展示 |
shutdown |
使应用程序优雅停机。默认情况下禁用 |
startup |
展示通过ApplicationStartup 收集的启动步骤数据.需要使用BufferingApplicationStartup 配置SpringApplication |
threaddump |
提供线程转存 |
如果你的应用程序是一个web应用程序(Spring MVC或者Spring WebFlux),你可以使用以下额外的端点:
ID | 描述 |
---|---|
heapdump |
返回堆转存文件。在HotSpot JVM,返回HPROF 格式文件。在OpenJ9 JVM,返回PHD格式文件 |
jolokia |
当Jolokia在类路径上时,在HTTP上暴露JMXbean(对于WebFlux是不可用的)。需要jolokia-core 依赖项 |
logfile |
返回日志文件内容(如果logging.file.name 或者logging.file.path 属性已经设置)。支持HHTPRange 数据头使用以回收日志文件的内容部分 |
prometheus |
以Prometheus服务可以抓取的格式暴露指标。需要micrometer-registry-prometheus 依赖项 |
默认情况下,所有的端点除了shutdown
都是启用的。为配置一个端点的可用,使用它的management.endpoint.
属性。下面的示例启用shutdown
端点:
management:
endpoint:
shutdown:
enabled: true
如果你更喜欢端点启用为可选择的加入而不是选择性退出,设置management.endpoints.enabled-by-default
属性为false
和使用个别的endpoint的enable
属性选择性回归加入。下面的示例启用info
端点并禁用其他所有端点:
management:
endpoints:
enabled-by-default: false
endpoint:
info:
enabled: true
禁用端点是完全的从应用程序上下文移除。如果你想只改变暴露端点这个技术,使用
include
和exclude
属性代替。
因为端点可能包含敏感信息,你应该小心考虑什么时候暴露他们。下面的表展示了默认内建端点的暴露:
ID | JMX | Web |
---|---|---|
auditevents |
是 | 否 |
beans |
是 | 否 |
caches |
是 | 否 |
conditions |
是 | 否 |
configprops |
是 | 否 |
env |
是 | 否 |
flyway |
是 | 否 |
health |
是 | 是 |
heapdump |
是 | 否 |
httptrace |
是 | 否 |
info |
是 | 否 |
integrationgraph |
是 | 否 |
jolokia |
N/A | 否 |
logfile |
N/A | 否 |
loggers |
是 | 否 |
liquibase |
是 | 否 |
metrics |
是 | 否 |
mappings |
是 | 否 |
prometheus |
N/A | 否 |
quartz |
是 | 否 |
scheduledtasks |
是 | 否 |
sessions |
是 | 否 |
shutdown |
是 | 否 |
startup |
是 | 否 |
threaddump |
是 | 否 |
为改变哪个端点暴露,使用以下特定的技术 include
和exclude
属性。
属性 | 默认的 |
---|---|
management.endpoints.jmx.exposure.exclude |
|
management.endpoints.jmx.exposure.include |
* |
management.endpoints.web.exposure.exclude |
|
management.endpoints.web.exposure.include |
health |
include
属性列出已经暴露端点的ID。exclude
属性列出不应该暴露端点列表的ID。exclude
属性优先于include
属性。你可以使用端点ID列表配置include
和exclude
属性。
例如,为停止暴露所有端点在JMX并只暴露health
和info
端点,使用以下属性:
management:
endpoints:
jmx:
exposure:
include: "health,info"
*
可以用来选择所有端点。例如,为在HTTP上暴露所有,除了env
和beans
端点,使用以下属性:
management:
endpoints:
web:
exposure:
include: "*"
exclude: "env,beans"
*
在YAML中有一个特定的含义,如果你想包含或者(排除)所有端点,所以一定要保证添加双引号标志。
如果你的应用程序公开暴露,我们强烈建议,你要使你的端点安全。
如果你想实现你自己的策略用于什么时候暴露端点,你可以注册
EndpointFilter
bean。
处于安全目的,默认情况下,只有/health
端点在HTTP上暴露。你可以使用management.endpoints.web.exposure.include
属性配置要暴露的端点。
设置
management.endpoints.web.exposure.include
之前,确保暴露的actuator不包含敏感信息,确保通过将他们放在防火墙之后来保证安全,或者通过像Spring Security的一些东西来保证安全。
如果Spring Security在类路径中并且没有其他WebSecurityConfigurerAdapter
或者SecurityFilterChain
bean存在,所有的actuator不同于Spring Boot自动配置保证安全的/health
。如果你定义了自定义的WebSecurityConfigureAdapter
或者SecurityFilterChain
bean,Spring Boot自动配置退出并让你完全控制actuator访问规则。
如果你希望对HTTP端点配置自定义的安全(例如,只允许拥有某个角色的用户访问他们),Spring Boot提供一些方便的RequestMatcher
对象,你可以与Spring Security结合使用。
一个典型的Spring Security配置可能看起来像下面的示例:
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import static org.springframework.security.config.Customizer.withDefaults;
@Configuration(proxyBeanMethods = false)
public class MySecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.requestMatcher(EndpointRequest.toAnyEndpoint());
http.authorizeRequests((requests) -> requests.anyRequest().hasRole("ENDPOINT_ADMIN"));
http.httpBasic(withDefaults());
return http.build();
}
}
前面的示例使用EndpointRequest.toAnyEndpoint()
匹配任意端点的请求并且确保所有具有ENDPOINT_ADMIN
角色。在EndpointRequest
上几个其他匹配方法也是可用的。请查看API文档(HTML或者PDF)了解细节。
如果你发布应用程序在防火墙强后面,你可能希望所有的actuator端点可以访问而无需验证身份。你可以通过改变management.endpoints.web.exposure.include
属性来这么做,如下:
management:
endpoints:
web:
exposure:
include: "*"
或者,如果Spring Security存在,你可能需要添加自定义安全配置来运行无身份认证的访问端点,如下示例所示:
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration(proxyBeanMethods = false)
public class MySecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.requestMatcher(EndpointRequest.toAnyEndpoint());
http.authorizeRequests((requests) -> requests.anyRequest().permitAll());
return http.build();
}
}
在前面的示例中,配置只应用到actuator端点。因为Spring Boot的安全配置在任何SecurityFilterChain bean存在时都是完全退出的,你需要规则配置额外的
SecurityFilterChain
bean应用到应用程序的其余部分。
因为Spring Boot依赖Spring Security的默认情况,CSRF保护是打开的。这表示当默认的安全配置在使用中时,需要POST
(shutdown 和loggers端点),PUT
,DELETE
的actuator端点返回403(禁止)错误。
如果你在创建非浏览器使用的服务,你我们建议完全禁用CSRF保护。
你可以在Spring Security参考指南中找到关于CSRF保护额外的信息。
端点自动化缓存响应以读取不带参数的操作。为配置端点缓存响应的时间数量,使用它的cache.time-to-live
属性。下面的例子设置beans
端点缓存10秒的存活时间:
management:
endpoint:
beans:
cache:
time-to-live: "10s"
management.endpoint.
前缀唯一标识正在配置的端点。
添加一个“展示页面”链接到所有的端点。默认情况下在/actuator
这个“展示页面”是可用的。
为禁用“展示页面”,添加以下属性到应用程序属性:
management:
endpoints:
web:
discovery:
enabled: false
当配置了自定义管理上下文路径时,“展示页面”自动从/actuator
移动到管理上下文的根路径。例如,如果管理上下文路径是/management
,展示的页面在/management
是可用的。当管理上下文路径设置为/
,展示页面是禁用的,避免其他映射冲突的可能性。
跨源资源共享(CORS)是W3C规范,让你以灵活的方式指定哪种跨域请求是授权的。如果你使用Spring MVC或者Spring WebFlux,你可以配置Actuator的web端点来支持这种场景。
CORS支持默认情况下是禁用的,当你已经设置management.endpoints.web.cors.allowed-origins
属性才会启用。以下配置允许GET
和POST
从example.com
域调用。
management:
endpoints:
web:
cors:
allowed-origins: "https://example.com"
allowed-methods: "GET,POST"
请查看
CorsEndpointProperties
了解完整的选项列表。
如果你添加带有@Endpoint
注解的@Bean
,任何带有@ReadOperation
,@WriteOperation
或者@DeleteOperation
方法是自动暴露在JMX上,在web应用程序中也会在HTTP上暴露。端点可以使用Spring MVC或者Spring WebFlux在HTTP上暴露。
下面的示例暴露了返回自定义对象的读操作:
@ReadOperation
public CustomData getData() {
return new CustomData("test", 5);
}
你也可以通过使用@JmxEndpoint
或者@WebEndpoint
写特定技术的端点。这些端点分别受限于他们的技术。例如,@WebEndpoint
直接通过HTTP暴露而不能通过JMX。
你可以通过@EndpointWebExtension
和@EndpointJmxExtension
写特定技术的扩展。这些注解允许你提供特定技术操作来增加现有端点。
最终,如果你需要访问特定的web框架功能,你可以实现servlet或者Spring @Controller
和@RestController
端点,但是代价是他们不能在JMX或者使用不同的web框架时可用。
在端点上的操作通过他们的参数接受输入。当在web上暴露时,这些参数的值取自URL的查询参数和JSON请求体。当在JXM暴露时,参数被映射到MBean的操作参数上。默认情况下需要参数。使用@javax.annotation.Nullable
或者@org.springframework.lang.Nullale
注解他们,可以使他们成为可选的。
你可以在JSON请求体中映射每一个根属性到端点的参数。考虑以下JSON请求体:
{
"name": "test",
"counter": 42
}
你可以使用这个调用一个写操作,取String name
和int counter
参数,如下示例所示:
@WriteOperation
public void updateData(String name, int counter) {
// injects "test" and 42
}
因为端点是与技术无关的,只有简单类型可以在方法签名中指定。特别是,声明一个单独的参数
CustomData
类型并定义name
和counter
属性是不支持。
为让输入可以被映射到操作方法参数,实现一个端点的Java代码应该使用
-parameters
编译,并且实现一个端点的Kotlin代码应该使用-java-parameters
编译。如果你使用Spring Boot的Gradle插件或者使用Maven和spring-boot-starter-parent
这将自动发生。
参数传入到端点操作方法是在必须的情况自动转换为所有的类型。调用操作方法之前,在JMX或者HTTP上接收的传入通过使用ApplicationConversionService
的实例以及使用@EndpointConverter
限定的任何Converter
或者GenericConverter
bean被转换为所需要的类型。
在@Endpoint
,@WebEndpoint
或者@EndpointWebExtension
上的操作是使用Spring MVC或者Spring WebFlux自动暴露在HTTP上。
请求断言是自动为每一个在web暴露的端点生成。
断言的路径取决于端点的ID和暴露的web端点的基础路径。默认的基础路径是/actuator
。例如,使用sessions
ID的端点在断言中使用/actuator/sessions
作为它的路径。
你可以通过使用@Selector
注解操作方法的一个或者更多参数进一步定制路径。这样的一个参数被添加到路径断言作为路径参数。当端点操作被调用,这个参数值被传入到操作方法。如果你想捕获所有剩下的路径元素,你可以添加@Selector(Match=ALL_REMAINING)
到最后的参数并且使其成为与String[]
兼容转换的类型。
断言的HTTP方法通过操作类型决定的,如下示例所示:
操作 | HTTP方法 |
---|---|
@ReadOperation |
GET |
@WriteOperation |
POST |
@DeleteOperation |
DELETE |
对于使用请求体的@WriteOperation
(HTTPPOST
),consumes
的断言子句是application/vnd.spring-boot.actuator.v2+json
,application/json
。对于所有其他操作,consumers
子句是空的。
produces
断言子句通过@DeleteOperation
,@ReadOperation
和@WriteOpertaion
注解的produces
属性决定的,这个属性是可选的。如果不使用它,produces
子句自动确定。
如果操作方法返回void
或者Void
,produces
子句是空的。如果操作方法返回org.springframework.core.io.Resource
,produces
子句是application/octet-stream
。对于所有其他操作,produces
子句是application/vnd.spring-boot.actuator.v2+json
,application/json
。
对于一个端点操作的默认的响应状态取决于操作类型(read,write或者delete)以及操作返回的内容(如果有的话)。
如果@ReadOperation
返回一个值,响应状态将是200(OK).如果他没有返回一个值,响应状态为404(Not Foound)。
如果@WriteOperation
或者@DeleteOperation
返回一个值,响应状态为200(OK).如果它没有返回一个值,响应状态为204(Not Content).
如果一个操作未使用参数或者一个参数被调用,不能转换为所需要的类型,操作方法将不会被调用,响应状态为400(Bad Request)。
你可以使用HTTP范围请求来请求HTTP资源部分。返回org.springframework.core.io.Resource
操作自动支持范围请求。
在web端点的操作或者特定的web端点扩展可以接受当前的java.security.Principal
或者org.springframework.boot.actuate.endpoint.SecurityContext
作为方法参数。前者是通常结合@Nullable
用来对身份验证和非身份验证用户提供不同的行为。后者通常用来使用它的isUserInRole(String)
方法提供身份认证检查。
servlet通过实现带有注解@ServletEndpoint
的类或者实现Suppllier
作为一个端点暴露。servlet端点提供了与servlet容器的高度集成,但是以可移植性作为代价。他们打算用来暴露现有的servlet作为一个端点。对于新的端点,应该尽可能首选@Endpoint
和@Webpoint
注解。
你可以使用@ControllerEndpoint
和@RestControllerEndpoint
只能通过Spring MVC或者spring WebFlux实现一个暴露的端点。使用Spring MVC和Spring WebFlux的标准的注解映射方法,例如@ReqestMapping
和GetMapping
,使用端点的ID用来当做路径的前缀。Controller 端点提供与Spring的web框架的深度集成,但是以可移植性作为代价。应该尽可能首选@Endpoint
和@Webpoint
注解。
你可以使用健康信息来检查运行中的应用程序的状态。当生产系统下降时,通常通过监控软件使用来提醒一些事情。这个信息是通过health
端点暴露的,取决于management.endpoint.health.show-details
和management.endpoint.health.show-components
属性,可以使用以下其中一个配置他们。
名称 | 描述 |
---|---|
Never |
不展示明细 |
when-authorized |
对授权用户展示。通过使用management.endpoint.health.roles 配置授权角色 |
always |
对所有用户展示 |
默认值是never
。当用户是端点角色的一个或者更多时,用户被认为已经授权。如果端点没有配置角色(默认情况),所有已经通过认证的用户被认为已经授权。你可以通过使用management.endpoint.health.roles
属性配置角色。
如果你已经对应用程序做了保护并且希望使用
always
,你的安全配置对已验证和未验证的用户必须许可访问health端点。
从HealthContributorRegistry
(默认情况下,你的ApplicationContext
中定义的所有的HealthContributor
实例)内容收集监控信息。Spring Boot包含多个自动配置的HealthContributors
,并且你也可以写你自己的。
HealthContributor
可以是HealthIndicator
或者CompositeHealthContributor
。HealthIndicator
提供真实的健康信息,包含Status
。CompositeHealthContirbutor
提供其他的HealthContributors
的集合。总之,contributor形成一个树形结构来表示整个系统的健康状况。
默认情况下,最终系统健康是通过StatusAggregator
推导的,其基于状态的顺序列表排序每一个HealthIndicator
的状态。在排序列表的第一个状态用来当做全部健康状态。如果没有HealthIndication
返回StatusAggregator
已知的状态,使用UNKNOWN
状态。
你可以在运行时使用
HealthContributorRegistry
注册并注销健康指标。
在适当的时候,Spring Boot自动配置下方表格所列的HealthIndicators
。你也可以通过配置management.health.key.enabled
启用或者禁用选择的指标,使用下面表格中所列出的key
。
key | 名称 | 描述 |
---|---|---|
cassandra |
CassandraDriverHealthIndicator |
检查Cassandra数据库是否启动 |
couchbase |
CouchbaseHealthIndicator |
检查Couchbase集群是否启动 |
db |
DataSourceHealthIndicator |
检查连接到数据库是否获得 |
diskspace |
DiskSpaceHealthIndicator |
检查低磁盘空间 |
elasticsearch |
ElasticsearchRestHealthIndicator |
检查Elasticsearch集群是否启动 |
hazelcast |
HazelcastHealthIndicator |
检查Hazelcast缓存是否启动 |
influxdb |
InfluxDbHealthIndicator |
检查InfluxDB服务器是否启动 |
jms |
JmsHealthIndicator |
检查JMS broker是否启动 |
ldap |
LdapHealthIndicator |
检查LDAP服务器是否启动 |
mail |
MailHealthIndicator |
检查mail服务器是否启动 |
mongo |
MongoHealthIndicator |
检查Mongo数据库是否启动 |
neo4j |
Neo4jHealthIndicator |
检查Neo4j数据库是否启动 |
ping |
PingHealthIndicator |
总是使用up 响应 |
rabbit |
RabbitHealthIndicator |
检查Rabbit服务器是否启动 |
redis |
RedisHealthIndicator |
检查Redis服务器是否启动 |
你可以通过设置
management.health.defaults.enabled
属性禁用他们所有。
额外的HealthIndicators
是可用的但是默认情况下是不启用的。
key | 名称 | 描述 |
---|---|---|
livenessstate |
LivenessStateHealthIndicator |
暴露“Liveness”(活跃的)应用程序可用性状态 |
readinessstate |
ReadinessStateHealthIndicator |
暴露“readiness”(就绪)应用程序可用状态 |
为提供自定义健康指标信息,你可以注册实现HealthIndicator
接口的Spring bean。你需要提供一个health()
方法的实现并且返回一个Health
返回。Health
响应应该包含状态并且可以随意包含用来展示的额外明细。下方的代码展示了简单的HealthIndicator
实现:
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class MyHealthIndicator implements HealthIndicator {
@Override
public Health health() {
int errorCode = check();
if (errorCode != 0) {
return Health.down().withDetail("Error Code", errorCode).build();
}
return Health.up().build();
}
private int check() {
// perform some specific health check
return ...
}
}
用于给定的
HealthIndicator
的标志符是不带HealthIndicator
后缀的bean的名称,如果它存在,在上面的示例中,在命名为name
入口健康信息是可用的。
健康指标通常在HTTP上调用并且需要任何连接超时之前响应。如果健康指标超过10s响应,Spring Boot将对任何健康指标记录警告信息日志。如果你想配置这个阈值,你可以使用
management.endpoint.health.logging.slow-indicator-threshold
属性。
除了Spring Boot的预定义的Status
类型,Health
可以返回自定义的表示新的系统状态Status
。这样的情况下,你也需要提供一个自定义的StatusAggregator
接口实现,或者你必须通过使用management.endpoint.health.status.order
配置属性配置默认的实现。
例如,假设使用FATAL
编码的新的Status
正被用来HealthIndicator
实现中的一个。为配置严重性顺序,添加以下属性到你的应用程序属性:
management:
endpoint:
health:
status:
order: "fatal,down,out-of-service,unknown,up"
在响应中的HTTP状态码反映出全部监控状态。默认情况下,OUT_OF_SERVICE
和DOWN
映射到503。任何未映射的健康状态,包含UP
,映射到200。如果在HTTP上访问健康端点,你可能也想注册自定义的状态映射。对DOWN
和OUT_OF_SERVICE
配置一个自定义的映射禁用默认的映射。如果你想保留默认的映射你必须与任何自定义映射一起明确配置他们。例如,下面的属性映射FATAL
到503(服务不可用)并且对DOWN
和OUT_OF_SERVICE
保留默认的映射:
management:
endpoint:
health:
status:
http-mapping:
down: 503
fatal: 503
out-of-service: 503
如果你需要更多的控制,你可以定义你自己的
HttpCodeStatusMapper
bean。
下方列表展示了对内建状态默认的状态映射:
状态 | 映射 |
---|---|
DOWN |
SERVICE_UNAVAILABLE (503 ) |
OUT_OF_SERVICE |
SERVICE_UNAVAILABLE (503 ) |
UP |
默认没有映射,所以HTTP状态为200 |
UNKNOWN |
默认没有映射,所以HTTP状态为200 |
对于响应式应用程序比如这些使用Spring WebFlux,ReactiveHealthContributor
提供一个非阻塞的约定来获得应用程序健状态。类似于传统的HealthContributor
,从ReactiveHealthContributorRegistry
的内容收集健康状态信息(默认情况下,在应用程序中定义的所有的HealthContributor
和ReactiveHealthContributor
实例)。不检查响应式API的常规的HealthContributors
会在弹性调度器上执行。
在响应式应用程序,在运行时你应该使用
ReactiveHealthContributorRegistry
注册或者注销健康指标。如果你需要注册一个常规的HealthContributor
,你应该使用ReactiveHealthContirbutor#adapt
封装它。
为从响应式API中提供自定义的健康信息,你可以注册实现了ReactiveHealthIndicator
接口的Sping bean。以下代码展示了一个简单的ReactiveHealthIndicator
实现:
import reactor.core.publisher.Mono;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class MyReactiveHealthIndicator implements ReactiveHealthIndicator {
@Override
public Mono<Health> health() {
return doHealthCheck().onErrorResume((exception) ->
Mono.just(new Health.Builder().down(exception).build()));
}
private Mono<Health> doHealthCheck() {
// perform some specific health check
return ...
}
}
为自动处理错误,考虑继承自
AbstractReactiveHealthIndicator
。
适当的时候,Spring Boot自动配置以下ReactiveHealthIndicators
:
key | 名称 | 描述 |
---|---|---|
cassandra |
CassandraDriverReactiveHealthIndicator |
检查Cassandra数据库是否启动 |
couchbase |
CouchbaseReactiveHealthIndicator |
检查Couchbase集群是否启动 |
elasticsearch |
ElasticsearchReactiveHealthIndicator |
检查Elasticsearch集群是否启动 |
mongo |
MongoReactiveHealthIndicator |
检查Mongo数据库是否启动 |
neo4j |
Neo4jReactiveHealthIndicator |
检查Neo4j数据库是否启动 |
redis |
RedisReactiveHealthIndicator |
检查Redis服务器是否启动 |
如果必须,响应式指标替换常规的那个。而且,任何没有显示处理的
HealthIndicator
自动被封装。
组织监控指标到一个组是非常有用的,你可以用于不同的目的。
要创建一个监控指标组,你可以使用management.endpoint.health.group.
属性并指定监控指标列表ID到include
或者exclude
。例如,要创建一个只有数据库指标的组,你可以如下定义:
management:
endpoint:
health:
group:
custom:
include: "db"
你仍可以通过点击localhost:8080/actuator/health/custom检查结果。
类似的,从包含所有其他指标的组中要创建一个不包含数据库指标的组,你可以如下定义:
management:
endpoint:
health:
group:
custom:
exclude: "db"
默认情况下,组继承与系统健康相同的StatusAggregator
和HttpCodeStatusMapper
设置。然而,你也可以在每个组的基础上定义这些。如果需要,你也可以重写show-details
和roles
属性:
management:
endpoint:
health:
group:
custom:
show-details: "when-authorized"
roles: "admin"
status:
order: "fatal,up"
http-mapping:
fatal: 500
out-of-service: 500
如果你需要注册自定义的
StatusAggregator
或者HttpCodeStatusMapper
bean用于与组一起使用,你可以使用Qualifier("grouname")
。
健康组也可以包含/排除CompositeHealthContributor
。你也可以包含/排除某一个CompositeHealthContirbutor
。可以使用组件的全限定名称做到这些,如下:
management.endpoint.health.group.custom.include="test/primary"
management.endpoint.health.group.custom.exclude="test/primary/b"
在上面的例子中,custom
组将包含名称为primary
的HealthContributor
,它是组合test
的一个组件。在这里,primary
本身是一个组合并且使用名称B
的HealthContributor
将从custom
组排除。
监控组可以在主端口或者管理端口额外的路径上使用,在云平台上是比较有用的,例如Kubernetes,在这样的环境下,处于安全目的,actuator端点通常使用一个单独的管理端口。使用单独的端口可能导致不可靠的健康检查,因为主应用程序可能不能正确的工作即使健康检查是成功的。健康组可以使用如下额外的路径配置:
management.endpoint.health.group.live.additional-path="server:/healthz"
这将使live
健康组在/healthz
的主服务器端口可用。这个前缀是强制的而且还必须是server:
(表示主要的服务器端口)或者management:
(表示管理端口,如果已经配置)路径必须是单独的路径片段。
DataSource
监控指标展示标准的数据源和路由数据源bean两者的健康状态。路由的数据源健康状态报货每一个它的目标数据源的健康状态。在健康端点的响应中,每一个路由数据源的目标使用它的路由键命名。如果在指标输出中,你不喜欢包括路由数据源,设置management.health.db.ignore-routing-data-sources
为true
。
应用程序部署在Kubernetes可以使用Container Probes提供关于他们内部状态的信息。依据你的Kubernetes配置,kubelete调用这些探针并对结果作出响应。
默认情况下,Spring Boot管理你的Application Avalilability State。如果部署到Kubernaetes环境,actuator从ApplicationAvailability
接口聚集Liveness
和Readiness
信息并在专用的健康指标中使用该信息:LivenessStateHealthIndicator
和ReadinessStateHealthIndicator
。在全局健康度端点展示这些指标(“/actuator/health
”)。他们作为单独的HTTP探针使用健康组暴露:“/actuator/health/liveness
"和”/actuator/health/readiness
"。
你仍可以使用以下端点信息配置你的Kubernetes基础设施:
livenessProbe:
httpGet:
path: "/actuator/health/liveness"
port: -port>
failureThreshold: ...
periodSeconds: ...
readinessProbe:
httpGet:
path: "/actuator/health/readiness"
port: -port>
failureThreshold: ...
periodSeconds: ...
应该被设置为actuator端点可用的端口。它可以是主要的服务器端口或者,如果"
management.server.prot
"属性已经设置,也可以是单独的管理端口。
这些健康组是自动启用,只有当应用程序运行在Kubernetes环境。你可以使用management.endpoint.health.probes.enabled
配置属性在任何环境启用他们。
如果应用程序的启动时间比配置的存活的时间长,Kubernetes提到
"startupProbe"
作为可能的解决方案。这个"startupProbe"
在这里不是必须的,因为直到所有的启动任务已经完成"readinessProbe"
才会失败。请查看在应用程序生命周期探针的行为是怎样的描述的章节。
如果你的Actuator端点被发布在一个单端的管理上下文,端点不使用相同的web基础设施(端口,连接池,框架组件)作为主要的应用程序。在这种情况下,即使主要的应用程序不能正确的工作,一个探针检测可以成功。(例如,他不能接收新的链接)。对于这种原因,在主要的服务器端口使liveness
和readiness
健康组可用是一个好主意。通过设置以下属性这些可以完成:
management.endpoint.health.probes.add-additional-paths=true
在主要的服务器端口上,在livez
上将使liveness
可用,在/readyz
上使/readiness
可用。
Actuator配置"liveness"和"readiness"探针作为Health Groups。这意味着所有的健康组特性对他们是可用的。例如,你可以配置额外的健康状态指标:
management:
endpoint:
health:
group:
readiness:
include: "readinessState,customCheck"
默认情况下,Spring Boot 不会将其他的健康状态指标添加到这些组。
"liveness"探针不应该取决于对于外部系统的健康状态检查。如果应用程序的活性状态坏掉了,Kubernetes尝试通过重启应用程序实例解决该问题。这表示如果一个外部系统(例如数据库,Web API或者外部缓存)失败,Kubernates可能重启所有的应用程序实例并创建级联失败。
至于“准备就绪”探针,应用程序开发者必须谨慎地选择检查外部系统。对此,在准备就绪探针中,Spring Boot 不包括任何额外的健康状态检查。如果应用程序准备就绪状态实例是未就绪的,Kubernates不会路由流量到该实例。一些外部系统不会通过应用程序实例共享,这种情况下,他们可以包含在准备就绪探针。其他的外部系统可能对应用程序不是必不可少的(应用程序可以有断路器和后备方案),在这种情况下,他们绝对不应该包含在内。不幸地,一个由所有应用程序实例共享的外部系统是常见的,并且你必须见机行事:在准备就绪探针中包含它并希望当外部服务关闭时应用程序退出服务,或者应用程序退出服务时并处理堆栈上层的故障,可能在调用方中使用断路器。
如果应该程序的所有示例是未就绪的,使用
type-ClusterIP
或者NodePort
的Kubernetes服务不会接收任何输入连接。没有HTTP响应(503等等),因为没有连接。使用type=LoadBalancer
的服务可能或者可能不接受连接,取决于提供者。一个有明确入口的服务也以一种依赖于实现的方式进行响应-入口服务本身必须决定如何处理来自下游的“连接拒绝”。HTTP 503 很可能同时存在于负载均衡和入口中。
而且,如果应用程序使用Kubernetes 自动缩放,它可能会对应用程序退出负载均衡作出不同的反映,取决于它的自动伸缩的配置。
一个重要的Kubernetes探针支持的方面是他的应用程序生命周期的一致性。在AvailabilityState
(它是在内存中的,应用程序的本地状态)和实际的探针(暴露该状态)是有显著的区别的。根据应用程序生命周期的各个阶段,探针可能是不可用的。
Spring Boot在应用程序启动和关闭期间推送应用程序事件,并且探针可以监听这些事件并保留AvailabilityState
信息。
下表展示AvailabilityState
和HTTP在不同的阶段连接的状态。
当Spring Boot应用程序启动:
启动阶段 | 活性状态 | 准备就绪状态 | HTTP服务器 | 备注 |
---|---|---|---|---|
启动中 | BROKEN |
REFUSING_TRAFFIC |
没有开始 | Kubernetes检查“活跃”探针,如果时间较长,重启应用程序 |
已启动 | CORRECT |
REFUSING_TRAFFIC |
拒绝请求 | 应用程序上下文已经刷新.应用程序执行启动任务,但还不接收流量 |
就绪 | CORRECT |
ACCEPTING_TRAFFIC |
接收请求 | 启动任务已经完成,应用程序接收流量 |
当应用程序关停时:
关停阶段 | 活性状态 | 准备就绪状态 | HTTP服务器 | 备注 |
---|---|---|---|---|
运行中 | CORRECT |
ACCEPTING_TRAFFIC |
接收请求 | 停机已经请求 |
优雅停机 | CORRECT |
REFUSING_TRAFFIC |
拒绝新的请求 | 如果启用,优雅停机将处理正在处理的请求 |
完成停机 | N/A | N/A | 服务器已经停机 | 应用程序上下文已经关闭并且应用程序已经关停 |
请查看Kubernetes容器生命周期章节了解关于Kubernates部署的信息。
应用程序信息暴露从你的ApplicationContext
中定义的所有的InfoContributor
bean收集的多个信息。Spring Boot包含多个自动配置的InfoContributor
bean,并且你可以写你自己的。
在适当的时候,Spring自动配置以下InfoContributor
:
ID | 名称 | 描述 | 先决条件 |
---|---|---|---|
build |
BuildInfoContributor |
暴露构建信息 | META-INF/build-info.properties 资源 |
env |
EnvironmentInfoContributor |
暴露来自Environment 的名称以info. 开头的任何属性 |
META-INF/build-info.properties 资源 |
git |
GitInfoContributor |
暴露git信息 | git.properties 资源 |
java |
JavaInfoContributor |
暴露java运行时信息 | 没有 |
os |
OsInfoContributor |
暴露操作系统信息 | 没有 |
个别的贡献者是否启用通过management.info.
属性控制。不同的贡献者在这个属性有不同的默认值,取决于他们的先决条件和他们所暴露的信息的性质。
由于没有先决条件的表示应该启用他们,env
,java
和os
贡献者默认情况下是禁用的。每一个可以通过设置它的management.info.
属性为true
启用。
build
和git
信息贡献者默认情况下启用。每一个可以通过设置它的management.info.
属性为false
禁用它。或者,要禁用每一个默认情况下通常启用的贡献者,设置management.info.defaults.enabled
属性为false
。
当env
贡献者启用,你可以自定义通过设置info.*
Spring 属性的info
端点所暴露的数据。在info
下的所有的Environment
属性是自动暴露的。例如,你可以将以下设置添加到application.properties
文件:
info:
app:
encoding: "UTF-8"
java:
source: "11"
target: "11"
你也可以在构建时展开信息属性,不是硬编码这些值。
假设你使用Maven,你可以如下重写上面的示例:info: app: encoding: "@project.build.sourceEncoding@" java: source: "@java.version@" target: "@java.version@"
info
端点的另一个有用的特性是他能够在项目构建时,发布关于git
源码仓库状态的信息。如果GitProperties
bean是可用的,你可以使用info
端点暴露这些属性。
如果在根类路径
git.properties
文件可用,GitProperties
bean是自动配置的。请查看“如果生成git信息”了解更多详情。
默认情况下,如果存在,端点暴露git.branch
,git.commit.id
,git.commit.time
属性。如果你不想要在端点响应中的任何这些属性,他们需要从git.properties
文件排除。如果你想展示全量的git信息(也就是,git.properties
的全部内容),使用management.info.git.mode
属性,如下:
management:
info:
git:
mode: "full"
要在info
端点完全禁用git提交信息,设置management.info.git.enabled
属性为false
,如下:
management:
info:
git:
enabled: false
如果BuildProperties
bean可用,info
端点也可以推送关于你的构建信息。如果在类路径中META-INF/build-info.properties
文件可用这些将发生。
Maven和Gradle插件可以同时生成该文件。请查看"如何生成构建信息"了解更多详情。
info
端点推送关于Java运行时环境信息,请查阅JavaInfo
了解更多详情。
info
端点推送关于操作系统信息,请查看QsInfo
了解更多信息。
为提供自定义应用程序信息,你可以注册实现InfoContributor
接口的Spring bean。
下方的示例使用单个值贡献了example
入口:
import java.util.Collections;
import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;
@Component
public class MyInfoContributor implements InfoContributor {
@Override
public void contribute(Info.Builder builder) {
builder.withDetail("example", Collections.singletonMap("key", "value"));
}
}
如果你访问info
端点,你应该看到包含以下额外条目响应:
{
"example": {
"key" : "value"
}
}
如果你在开发一个web应用程序,Spring Boot Actuator自动配置所有启用的端点通过HTTP暴露。默认的协议是使用端点的id
和/actuator
的前缀作为URL路径。例如,health
为/actuator/health
暴露的。
Actuator由Spring MVC和Spring WebFlux原生支持的。
Jackson是必须的依赖项,以便获取在API(HTML或者PDF)文档中记录正确的JSON响应 。
有时候,自定义用于管理端点的前缀是非常有用的。例如,你的应用程序可能已经准备使用/actuator
用于其他目的。你可以使用management.endpoints.web.base-path
属性改变你的管理端点前缀,如下示例所示:
management:
endpoints:
web:
base-path: "/manage"
前面的application.properties
历史修改端点从/actuator/{id}
到/manage/{id}
(例如,/manage/info
)。
除非管理端口已经配置以使用不同的HTTP端口暴露端口,
management.endpoints.web.base-path
与server.servlet.context-path
(对于servlet web应用程序)或者spring.webflux.base-path
(对于reactive web应用程序)有关。如果management.server.port
已经配置,management.endpoints.web.base-path
与management.servet.base-path
有关。
如果你想映射端点到不同的路径,你可以使用management.endpoints.web.path-mapping
属性。
以下示例重新将/actuator/health
映射到/healthcheck
:
management:
endpoints:
web:
base-path: "/"
path-mapping:
health: "healthcheck"
对于基于云部署,通过使用默认的HTTP端口暴露管理端点是明智的选择。然而,如果你应用程序运行在你自己的数据中心,你可以更喜欢使用不同的HTTP端口暴露端点。
你可以设置management.server.prot
属性以改变HTTP端口,如下示例所示:
management:
server:
port: 8081
在Cloud Foundry,默认情况下,对于HTTP和TCP路由,应用程序接收请求只在端口8080上。如果你想要在Cloud Foundry使用自定义的管理端口,你需要显示地设置应用程序路由,以便将流量转发到自定义端口。
当使用自定义端口配置,你也可以使用多种management.server.ssl
属性配置它自己的SSL配置管理服务器。例如,这样做,当主应用程序使用HTTPS,让管理服务器通过HTTP是可用,正如下方属性设置所展示的:
server:
port: 8443
ssl:
enabled: true
key-store: "classpath:store.jks"
key-password: "secret"
management:
server:
port: 8080
ssl:
enabled: false
或者,主服务器和管理服务器可以使用SSL,但是使用不同的key存储,如下:
server:
port: 8443
ssl:
enabled: true
key-store: "classpath:main.jks"
key-password: "secret"
management:
server:
port: 8080
ssl:
enabled: true
key-store: "classpath:management.jks"
key-password: "secret"
你可以自定义地址,通过设置management.server.address
属性,在地址管理端点是可用的。如果你想只监听一个外部或者面向ops的网络或者只监听来自localhost
的链接,这样做是有用的。
只有当端口与主服务器端口不同时,你可以在不同的地址监听。
以下示例application.properties
不允许远程管理链接:
management:
server:
port: 8081
address: "127.0.0.1"
如果你不想在HTTP上暴露端点,你可以设置管理端口为-1
,如下示例所示:
management:
server:
port: -1
你也可以通过使用management.ednpoints.web.exposure.exclude
属性实现这个功能,如下示例所示:
management:
endpoints:
web:
exposure:
exclude: "*"
Java Management Extensions(JMX)提供一个标准的机制来监控和管理应用程序。默认情况下,这个特性不会启用。你可以通过设置spring.jmx.enabled
配置属性为true
打开它。Spring Boot使用mbeanServer
ID暴露最合适的MBeanServer
作为bean。使用Spring JMX注解(@ManagedResource
,@ManagedAttribute
或者@ManagedOperation
)来注解你的任何bean都将被暴露给它。
如果你的平台提供一个标准的MBeanServer
,Spring Boot使用它,如果必须,默认为VMMBeanServer
。如果所有的MBeanServer
失败,创建一个新的MBeanServer
。
请查看JmxAutoConfiguration
类了解更多详情。
默认情况下,Spring Boot还将管理端点暴露为org.springframework.boot
域下的JMX MBean。要完全控制在JMX域注册的端点,考虑注册你自己的EndpointObjectNameFactory
实现。
MBean的名称通常生成自端点的id
。例如,health
端点作为org.springframework.boot:type=Endpoint,name=Health
暴露。
如果你的应用程序包含多余一个Spring ApplicationContext
,你可能会发现名称冲突。要解决这个问题,你可以设置spring.jmx.unique-names
属性为true
,以便MBean名称一直唯一。
你也可以定制在其下暴露的端点的JMX域。以下设置展示在application.properties
中这样做的一个示例:
spring:
jmx:
unique-names: true
management:
endpoints:
jmx:
domain: "com.example.myapp"
如果你不想通过JMX暴露端点,你可以设置management.endpoints.jmx.exposure.exclude
属性为*
,如下示例所示:
management:
endpoints:
jmx:
exposure:
exclude: "*"
Spring Boot Actuator包括展示的能力和配置运行时应用程序的日志级别。你可以查看整个列表或者个别的日志记录器的配置,该配置包括显示配置日志级别以及日志框架给它的有效日志记录级别。这些级别可以是以下中的一个:
TRACE
DEBUG
INFO
WARN
ERROR
FATAL
OFF
null
null
表示没有明确的配置要配置一个给定的日志记录器,将一部分实体POST
到资源URI,如下示例所示:
{
"configuredLevel": "DEBUG"
}
要“重置”特定的日志记录器级别(使用默认的配置代替),你可以将
null
值传入作为configuredLevel
。
Spring Boot Actuator提供对Micrometer依赖项管理和自动配置。支持众多监控系统的应用程序指标外观,包括:
要学习更多关于Micrometer的功能,请查看他的参考文档,特别是概念部分。
Spring Boot 自动配置一个组合的MeterRegistry
并将注册信息添加到在类路径中发现的每一个支持的实现组合。在你运行的类路径中存在一个依赖项micrometer-registry-{system}
就足以让Spring Boot配置注册表。
大多数注册表共享通用的特性。例如,你可以禁用一个常见的注册表即使Micrometer注册表是在类路径中。以下示例禁用Datadog:
management:
datadog:
metrics:
export:
enabled: false
你也可以通过特定的注册表属性禁用所有的注册表除非已经启用,如下示例所示:
management:
defaults:
metrics:
export:
enabled: false
Spring Boot也将任何自动配置的注册表到在Metrics
类上的全局静态组合的注册表,除非你明确告诉他不要这样做:
management:
metrics:
use-global-registry: false
你可以注册任意数量的MeterRegistryCustomizer
bean来进一步配置注册表,例如在使用注册表注册任意meter之前,应用通用的标签:
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyMeterRegistryConfiguration {
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return (registry) -> registry.config().commonTags("region", "us-east-1");
}
}
你可以通过更具体的描述泛型,将自定义应用到特定的注册表实现:
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.NamingConvention;
import io.micrometer.graphite.GraphiteMeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyMeterRegistryConfiguration {
@Bean
public MeterRegistryCustomizer<GraphiteMeterRegistry> graphiteMetricsNamingConvention() {
return (registry) -> registry.config().namingConvention(this::name);
}
private String name(String name, Meter.Type type, String baseUnit) {
return ...
}
}
Spring Boot 也配置内建的仪表装置,通过配置或者相关的注解标记来控制它。
这部分简单描述每一个支持的监控系统。
默认情况下,AppOptics注册表定期地推送指标到api.appoptics.com/vi/measurements
。要输出指标到SaaS AppOptics,你的API token必须提供:
management:
appoptics:
metrics:
export:
api-token: "YOUR_TOKEN"
默认情况下,指标被输出到在你本地运行的机器 的Atlas。你可以提供Atlas服务器的位置:
management:
atlas:
metrics:
export:
uri: "https://atlas.example.com:7101/api/v1/publish"
Datadog注册表周期性推送指标到datadoghq。要输出指标到Datadog
,你必须提供你的API键:
management:
datadog:
metrics:
export:
api-key: "YOUR_KEY"
如果你额外的提供一个应用程序的key(可选的),然后是原数据,比如仪表描述,类型和基本单元也将输出:
management:
datadog:
metrics:
export:
api-key: "YOUR_API_KEY"
application-key: "YOUR_APPLICATION_KEY"
默认情况下,指标将被发送到Datadog US站点(api.datadoghq.com
)。如果你的Datadog项目托管在其他站点上,或者你需要通过代理发送指标,直接配置URI:
management:
datadog:
metrics:
export:
uri: "https://api.datadoghq.eu"
你也可以改变指标被发送到Datadog的间隔:
management:
datadog:
metrics:
export:
step: "30s"
Dynatrace提供两项指标摄取API,这两个API都是为Micrometer实现的。你可以在这里发现关于Micrometer Dynatrace 摄取的文档。在v1
命名空间的配置属性只当输出到实现序列 v1 API时应用。在v2
命名空间的配置属性只当输出到指标v2 API时应用。注意在某一时间这个集成只能输出到v1
或者v2
的API版本,最好是v2
。如果device-id
(v1是必须的但是在v2中不使用)在v1
命名空间设置,指标将输出到v1
端点。否则,输出到v2
。
你可以两种方式使用v2 API:
自动配置:
对于通过OneAgent或者对Kubernaetes通过Dynatrace OperatorDynatrace的主机自动配置是可用的。
本地 OneAgent:如果OneAgent在主机中正在运行,指标自动化输出到本地OneAgent摄取端点。摄取端点将指标转发到Dynatrace后端。
Dynatrace Kubernetes Operator:当使用安装的Dynatrace Operator运行在Kubernetes中时,注册表将自动从操作符选择你的端点URI和API token。
这个是默认的行为,除了依赖于io.micrometer:micrometer-registry-dynatrace
外,不需要特殊的设置。
手工配置:
如果没有自动配置可用,Metrics v2 API的端点和API的token是必须的。API token必须有"摄取指标(metrics.ingest
)权限设置。我们建议将token的作用域限制到这一权限。你必须确保这个端点URI包含这个路径(例如,/api/v2/metrics/ingest
):
根据你的部署选项,Metrics API v2的URL 摄取端点是不同的:
https://{your-environment-id}.live.dynatrace.com/api/v2/metrics/ingest
https://{your-domain}/e/{your-environment-id}/api/v2/metrics/ingest
下方的示例使用example
环境id配置指标输出:
management:
dynatrace:
metrics:
export:
uri: "https://example.live.dynatrace.com/api/v2/metrics/ingest"
api-token: "YOUR_TOKEN"
当使用Dynatrace v2 API,下方可选的特性是可用的(更多细节可以在Dynatrace文档中找到):
false
强制Micrometer 返回1.9.x之前的行为。只有当迁移Micrometer从1.8.x到1.9.x 遭遇问题时,才应该使用它。它可以不指定一个URI和API token,如下示例所示。在这个情景中,使用自动化配置的端点:
management:
dynatrace:
metrics:
export:
# Specify uri and api-token here if not using the local OneAgent endpoint.
v2:
metric-key-prefix: "your.key.prefix"
enrich-with-dynatrace-metadata: true
default-dimensions:
key1: "value1"
key2: "value2"
use-dynatrace-summary-instruments: true # (default: true)
Dynatrace v1 API指标注册表通过使用TimeSeries v1 API定期推送指标到配置的URI。向后兼容现有设置,当device-id
已经设置(v1所需要的,不是在v2中使用的),指标被输出到Timeseries v1端点。为输出指标到Dynatrace,你的API token,device ID和URI必须指定:
management:
dynatrace:
metrics:
export:
uri: "https://{your-environment-id}.live.dynatrace.com"
api-token: "YOUR_TOKEN"
v1:
device-id: "YOUR_DEVICE_ID"
对于v1 API,你必须指定不带路径的基本的环境URI,因为v1端点路径是自动添加的。
除了API端点和token,你也可以改变其指标被发送到Dynatrace的间隔。默认输出间隔是60s
。以下示例设置输出间隔为30秒:
management:
dynatrace:
metrics:
export:
step: "30s"
你可以在Micrometer文档和Dynatrace文档中找到更多信息关于如何设置对Micrometer 的Dynatrace输出。
默认情况下,指标被输出到在你本机上运行的Elastic。你可以通过使用以下属性提供Elastic服务器位置来使用:
management:
elastic:
metrics:
export:
host: "https://elastic.example.com:8086"
默认情况下,指标被输出到在你本机上运行的Ganglia。你可以提供Ganglia服务器主机和端口,如下示例所示:
management:
ganglia:
metrics:
export:
host: "ganglia.example.com"
port: 9649
默认情况下,指标被输出到运行在你本机的Graphite
。你可以提供Graphite服务器主机和端口,如下示例所示:
management:
graphite:
metrics:
export:
host: "graphite.example.com"
port: 9004
Micrometer提供默认的HierarchicalNameMapper
,它管理维度meterID如何被映射到平面分层的名字。
要控制这个行为,定义你的
GraphiteMeterRegistry
和提供你自己的HierarchicalNameMapper
。一个自动配置的GraphiteConfig
和Clock
bean被提供,除非你定义你自己的:import io.micrometer.core.instrument.Clock; import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.config.NamingConvention; import io.micrometer.core.instrument.util.HierarchicalNameMapper; import io.micrometer.graphite.GraphiteConfig; import io.micrometer.graphite.GraphiteMeterRegistry; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) public class MyGraphiteConfiguration { @Bean public GraphiteMeterRegistry graphiteMeterRegistry(GraphiteConfig config, Clock clock) { return new GraphiteMeterRegistry(config, clock, this::toHierarchicalName); } private String toHierarchicalName(Meter.Id id, NamingConvention convention) { return ... } }
默认情况下,Humio注册表周期性推送指标到cloud.humio.com。为输出指标到SaaS Humio,你必须提供你的API token:
management:
humio:
metrics:
export:
api-token: "YOUR_TOKEN"
你应该也可以配置一个或者多个标签识别数据源到哪个指标被推送:
management:
humio:
metrics:
export:
tags:
alpha: "a"
bravo: "b"
默认情况下,指标使用默认的配置被输出到运行在本机的Influx v1实例。为输出指标到InfluxDB v2,为写入指标配置org
,bucket
和身份认证token
。你可以使用以下命令提供要使用的Influx服务器:
management:
influx:
metrics:
export:
uri: "https://influx.example.com:8086"
Micrometer 提供将分层的映射提供到JMX,主要是一种廉价且可移植的方式来本地展示指标。默认情况下,指标被输出到metrics
JMX域。你可以使用以下命令提供要使用的域:
management:
jmx:
metrics:
export:
domain: "com.example.app.metrics"
Micrometer提供默认的HierarchicalNameMapper
,它管理维度meterID如何映射到平面分层的名字:
要控制这种行为,定义你自己的
JmxMeterRegistry
和提供你自己的HierarchicalNameMapper
。自动配置的JmxConfig
和Clock
bean被提供,除非你定义你自己的:import io.micrometer.core.instrument.Clock; import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.config.NamingConvention; import io.micrometer.core.instrument.util.HierarchicalNameMapper; import io.micrometer.jmx.JmxConfig; import io.micrometer.jmx.JmxMeterRegistry; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) public class MyJmxConfiguration { @Bean public JmxMeterRegistry jmxMeterRegistry(JmxConfig config, Clock clock) { return new JmxMeterRegistry(config, clock, this::toHierarchicalName); } private String toHierarchicalName(Meter.Id id, NamingConvention convention) { return ... } }
默认情况下,指标被输出到运行在你本地机器上的KairosDB。你可以使用以下配置提供要使用的KairosDB 服务器:
management:
kairos:
metrics:
export:
uri: "https://kairosdb.example.com:8080/api/v1/datapoints"
New Relic注册表周期性推送指标到New Relic。要输出指标到New Relic,你必须提供你的API键和账户ID:
management:
newrelic:
metrics:
export:
api-key: "YOUR_KEY"
account-id: "YOUR_ACCOUNT_ID"
你也可以改变在指标被发送到New Relic的间隔:
management:
newrelic:
metrics:
export:
step: "30s"
默认情况下,通过REST调用推送指标,但是你也可以使用Java Agent API,如果在类路径上存在它:
management:
newrelic:
metrics:
export:
client-provider-type: "insights-agent"
最后,你可以通过定义你自己的NewRelicClientProvider
bean完全控制。
默认情况下,指标被输出到在你本机上运行的OpenTelemetry。你可以使用以下配置提供要使用的OpenTelemtry 指标端点的位置:
management:
otlp:
metrics:
export:
url: "https://otlp.example.com:4318/v1/metrics"
Prometheus期望通过抓取和轮询单个实例来获取指标。Spring Boot在/actuator/prometheus
提供一个actuator端点以适当的格式呈现Prometheus scrape。
默认情况下,端点是不可用的,必须公开。请查看暴露端点了解更多详情。
以下示例scrape_config
添加到prometheus.yml
:
scrape_configs:
- job_name: "spring"
metrics_path: "/actuator/prometheus"
static_configs:
- targets: ["HOST:PORT"]
Prometheus范例也是支持的。要启用这个特性,SpanContextSupplier
bean应用存在。如果你使用Spring Cloud Sleuth,它将为你自动配置,而且你还可以创建你想要的自己的bean。
请查看Prometheus Docs,因为这个特性需要在Prometheus端显示地启用,并且它只有在使用OpenMetrics格式时支持。
对于可能存在时间不长的临时或者批量作业无法抓取,你可以使用Promethus Pushgateway向Prometheus暴露指标。要启用Prometheus Pushgateway支持,添加以下依赖到你的项目:
<dependency>
<groupId>io.prometheusgroupId>
<artifactId>simpleclient_pushgatewayartifactId>
dependency>
当Prometheus Pushgateway依赖在类路径中已经存在并且management.prometheus.metrics.export.pushgateway.enable
属性已经设置为true
,PrometheusPushGatewayManager
bean是自动配置的。这个管理指标的推送到Prometheus Pushgateway。
你可以使用management.prometheus.metrics.exprot.pushgateway
下的属性调整PrometheusPushGatewayManager
。对于高级配置,你也可以提供你自己的PrometheusPushGatewayManager
bean。
SignalFx注册表周期性推送指标到SignalFx。要输出指标到SignalFx,你必须提供你的访问token:
management:
signalfx:
metrics:
export:
access-token: "YOUR_ACCESS_TOKEN"
你也可以改变指标发送到SignalFx的间隔:
management:
signalfx:
metrics:
export:
step: "30s"
Micrometer附带一个简单的,内存的后端,如果没有其他注册表配置,该后端自动作为应急计划使用。这让你看到在指标端点那些收集的指标。
一旦你使用任何其他可用的后端,内存后端禁用它自己。你也可以显示地禁用它:
management:
simple:
metrics:
export:
enabled: false
Stackdriver注册表周期性地推送指标到Stackdriver。要暴露指标到SaaS Stackdriver,你必须提供你的Google Cloud项目ID:
management:
stackdriver:
metrics:
export:
project-id: "my-project"
你也可以改变指标被发送到Stackdriver的间隔:
management:
stackdriver:
metrics:
export:
step: "30s"
StatsD注册表通过UDP急切地推送指标到StatsD代理。默认情况下,指标被暴露到在你本机运行的StatsD代理。你可以使用以下配置提供所使用的StatsD代理主机,端口和协议:
management:
statsd:
metrics:
export:
host: "statsd.example.com"
port: 9125
protocol: "udp"
你也可以改变StatsD行协议使用(它默认是Datadog):
management:
statsd:
metrics:
export:
flavor: "etsy"
Wavefront注册表周期性推送指标到Wavefront。如果你直接暴露指标到Wavefront,你必须提供你的API token:
management:
wavefront:
api-token: "YOUR_API_TOKEN"
或者,你可以使用Wavefront端或者在你的环境中的内部协议来转发指标数据到Wavefront API 主机:
management:
wavefront:
uri: "proxy://localhost:2878"
如果你推送指标到Wavefront代理(正如在Wavefront文档中描述的),主机必须是
proxy://HOST:PORT
格式。
你也可以改变指标发送到Wavefront的间隔:
management:
wavefront:
metrics:
export:
step: "30s"
Spring Boot为各种各样的技术提供自动的计量器注册。在大多数情景,默认提供合理的指标,可以将其推送到任意的支持的监控系统。
自动配置通过使用核心的Micrometer类启用JVM指标。JVM指标在jvm.
仪器名称发布的。
提供以下JVM指标:
自动配置通过使用核心的Micrometer类启用系统指标。系统指标通过system.
,process.
和dist.
仪器名称发布。
提供以下系统指标:
自动配置暴露应用程序启动时间指标:
application-started.time
:启用应用程序的时间application.ready.time
:应用程序就绪到服务请求的时间指标是通过应用程序的全量限定名称标记的。
自动配置对Logback和Log4j2启用事件指标。明细在log4j2.events.
或者logback.events.
仪器名称被发布。
自动配置启用所有可用的ThreadPoolTaskExecutor
和ThreadPoolTaskScheduler
bean的仪器,只要底层ThreadPoolExecutor
是可用的。指标通过执行器名称标记,执行器的名称来源bean名称。
自动配置启用所有Spring MVC控制器和函数处理器处理的请求的测量仪器,默认情况下,指标使用名称http.server.requests
生成。你可以通过management.metrics.web.server.request.metric-name
属性定制这个名称。
@Timed
注解支持在@Controller
类和@RequestMapping
方法上(请查看@Time 注解支持了解更多明细)。如果你不想记录所有Spring MVC请求的指标,你可以设置management.metrics.web.server.request.autotime.enabled
为false
并且只使用@Timed
注解代替。
标签 | 描述 |
---|---|
exception |
任何异常的普通的类名称,当处理请求时被抛出的异常 |
method |
请求的方法(例如,get 或者POST ) |
outcome |
请求的结果,基于响应的状态码。1xx是INFORMATIONAL ,2xx是SUCCESS ,3xx是REDIRECTION ,4xx是CLIENT_ERROR ,5xx是SERVER_ERROR |
status |
响应的HTTP状态码(例如200 或500 ) |
uri |
在变量替换之前的请求URI模板,如果可能的话,例如,/api/person/{id} |
要增加默认标签,提供一个或者多个实现WebMvcTagsContributor
的@Bean
。要替换默认的标签,提供实现了WebMvcTagsProvider
的@Bean
。
在这些情况中,在web控制器处理的异常不会作为请求指标标签被记录。应用程序可以通过将处理异常设置为请求属性来选择并记录异常。
默认情况下,处理所有的请求。要定制过滤器,提供实现了FilterRegistrationBean
的@Bean
。
自动配置启用通过Spring WebFlux控制器和函数式处理器处理的所有请求的测量仪器。默认情况下,指标通过名称http.server.requests
生成。你可以通过设置management.metrics.web.server.request.metric-name
属性定制名称。
@Timed
注解支持在@Controller
类和@RequestMapping
方法上(请查看@Timed 注解支持了解更多详情)。如果你不想为所有的Spring WebFlux请求记录指标,你可以设置management.metrics.web.server.request.autotime.enabled
为false
并仅仅使用@Timed
注解代替。
标签 | 描述 |
---|---|
exception |
任何异常的普通的类名称,当处理请求时被抛出的异常 |
method |
请求的方法(例如,get 或者POST ) |
outcome |
请求的结果,基于响应的状态码。1xx是INFORMATIONAL ,2xx是SUCCESS ,3xx是REDIRECTION ,4xx是CLIENT_ERROR ,5xx是SERVER_ERROR |
status |
响应的HTTP状态码(例如200 或500 ) |
uri |
在变量替换之前的请求URI模板,如果可能的话,例如,/api/person/{id} |
要增加默认的标签,提供一个或者多个实现WebFluxTagsContributor
的@Bean
。要替换默认的标签,提供实现WebFluxTagsProvider
的bean。
在这些情况中,在控制器中处理的异常和处理器函数不会作为请求指标标签记录的。应用程序可以通过设置处理异常作为请求参数选择和记录异常。
Spring Boot Actuator管理RestTemplate
和WebClient
的测量仪器。为此,你必须注入自动配置的构造器并使用它创建实例:
RestTemplateBuilder
用于RestTemplate
WebClient.Builder
用于WebClient
你也可以手工应用负责此检测的定制器,也就是MetricsRestTemplateCustomizer
和MetricsWebClientCustomizer
。
默认情况下,指标通过http.client.requests
生成。你可以通过设置management.metrics.web.client.request.metric-name
属性定制名称。
默认情况下,通过装有仪器的客户端生成的指标使用以下信息标记:
标签 | 描述 |
---|---|
clientName |
URI的主机部分 |
method |
请求放发(例如,GET 或者POST ) |
outcome |
请求结果,基于响应的状态码。1xx是INFORMATIONAL ,2xx是SUCCESS ,3xx是REDIRECTION ,4xx是CLIENT_ERROR ,5xx是SERVER_ERROR .其他是UNKNOWN |
status |
如果可用,响应的HTTP状态码(例如,200 或者500 )或者在IO问题情况下的IO_ERROR 。其他是CLIENT_ERROR |
uri |
在变量替换之前的请求的URI模板,如果可能(例如,api/person/{id} ) |
要定制标签,取决于你的客户端选择,你可以提供实现了RestTemplateExchangeTagsProvider
或者WebClientExchangeTagsProvider
的@Bean
。RestTemplateExchangeTags
和WebClientExchangeTags
中有方便的静态函数。
自动配置只有当MBeanRegistry
启用时才会启用Tomcat测量仪器。默认情况下,MBeanRegistry
是禁用的,但是你可以通过设置server.tomcat.mbeanregistry.enabled
为true
启用它。
Tomcat指标在tomcat.
仪器名称被发布。
自动配置启用所有启动时可用的Cache
实例的测量仪器,使用cache
前缀的指标。缓存监测仪器是基本的指标集合标准标准化。而且,特定的缓存指标也是可用的。
支持以下缓存类库:
CacheManager
的名称被标记,后者派生自bean的名称。只有启动时配置的缓存才会绑定到注册表。对于在缓存配置中没有定义的缓存,例如动态创建的缓存或者启动阶段之后程序化创建的缓存,需要显示的注册。我们提供了一个
CacheMetricsRegistrar
bean来简化这个过程。
自动配置启用所有有效的使用前缀为jdbc.connection
的指标的DataSource
对象的监测仪器。数据源监测会产生表示池中当前活动,空闲,允许的最大连接数,允许的最小连接数。
指标也可以通过基于bean名称计算的DataSource
的名称标记。
默认情况下,Spring Boot提供所有支持的数据源的元数据。如果你最喜欢的数据源不支持,你可以添加额外的
DataSourcePoolMetadataProvider
bean.请查看DataSourcePoolMetadataProvidersConfiguration
了解示例。
而且,特定的Hikari指标通过hikaricp
前缀暴露。每一个指标通过池的名称标记(你可以使用spring.datasource.name
控制)。
自动配置启用所有Spring Data Repository
方法调用的检测仪器。默认情况下,指标使用spring.data.repository.invocations
名称生成。你可以通过设置management.metrics.data.repository.metric-name
定制这个名称。
@Timed
注解支持在Repository
类和方法上的(请查看@Timed注解支持了解详情)。如果你不想记录所有Repository
调用的指标,你可以设置management.metrics.data.repository.autotime.enbaled
为false
并仅仅使用@Timed
注解代替。
默认情况下,仓库调用关联的指标使用以下信息标记:
标记 | 描述 |
---|---|
repository |
源Repository 简单的类名称 |
method |
被调用的Repository 方法名称 |
state |
结果状态(SUCCESS ,ERROR ,CANCELED 或者RUNNING ) |
exception |
来自调用抛出的任何异常的简单类名称 |
要替换默认的标签,提供实现了RepositoryTagsProvider
的@Bean
。
自动配置启用所有使用有效的名称为rabbitmq
的指标RabbitMQ连接工厂的监测仪器。
只要MeterRegistry
bean可用,SpringIntegration自动提供Micrpmeter支持。指标通过spring.integration.
仪器名称发布。
自动配置注册MicrometerConsumerListener
和MicrometerProducerListener
分别用于自动配置的消费者工厂和生产者工厂。它也注册KafkaStreamsMicrometerListener
用于StreamsBuilderFactoryBean
。对于更多细节,请查看Spring Kafka文档的Micrometer Native Metrics章节。
这个章节简单的描述了MongoDB的可用指标。
自动配置使用自动配置的MongoClient
的注册MongoMetricsCommandListener
。
为向底层的MongoDB驱动程序发出的每命令创建一个名称为mongodb.driver.commands
的定时器指标。默认情况下,每个指标使用以下信息标记:
标签 | 描述 |
---|---|
command |
发布的命令的名称 |
cluster.id |
将命令发送到集群的标志符 |
server.address |
将命令发送到服务器的地址 |
status |
命令的结果(SUCCESS 或者FAILED ) |
要替换默认的指标标签,定义MongoCommandTagsProvider
bean,如下示例所示:
import io.micrometer.core.instrument.binder.mongodb.MongoCommandTagsProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyCommandTagsProviderConfiguration {
@Bean
public MongoCommandTagsProvider customCommandTagsProvider() {
return new CustomCommandTagsProvider();
}
}
要禁用自动配置的命令指标,设置以下属性:
management:
metrics:
mongo:
command:
enabled: false
自动配置使用自动配置的MongoClient
注册MongoMetricsConnectionPoolListener
。
以下标准指标为连接池创建:
mongodb.driver.pool.size
报告链接池当前大小,包括空闲和使用中的成员。mongodb.driver.pool.checkedout
报告当前正在使用的链接数量。mongodb.driver.pool.waitqueuesize
报告来自池的连接的等待队列的当前大小。默认情况下,每一个指标使用以下信息标记:
标签 | 描述 |
---|---|
cluster.id |
连接池所对应的集群标志符 |
server.address |
连接池对应的服务器地址 |
要替换默认的指标标签,定义一个MongoConnectionPoolTagsProvider
bean:
import io.micrometer.core.instrument.binder.mongodb.MongoConnectionPoolTagsProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyConnectionPoolTagsProviderConfiguration {
@Bean
public MongoConnectionPoolTagsProvider customConnectionPoolTagsProvider() {
return new CustomConnectionPoolTagsProvider();
}
}
要禁用自动配置的链接池指标,设置以下属性:
management:
metrics:
mongo:
connectionpool:
enabled: false
自动配置通过使用Micrometer的JettyServerThreadPoolMetrics
绑定指标用于Jetty的ThreadPool
。Jetty的实例指标通过使用Micrometer的JettyConnectionMetrics
绑定,当server.ssl.enabled
设置为true
时,也可以通过Micrometer的JettySslHandshakeMetrics
。
你可以使用来自io.micrometer.core.annotation
包的@Timed
注解与前面描述的几个支持的技术。如果支持,你可以使用注解在类级别或者方法级别。
例如,以下代码展示你可以如何使用注解来对@RestController
中的所有请求映射增加监测:
import java.util.List;
import io.micrometer.core.annotation.Timed;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Timed
public class MyController {
@GetMapping("/api/addresses")
public List<Address> listAddress() {
return ...
}
@GetMapping("/api/people")
public List<Person> listPeople() {
return ...
}
}
如果你只是想监测单个映射,你可以在方法上使用注解而不是在类上:
import java.util.List;
import io.micrometer.core.annotation.Timed;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@GetMapping("/api/addresses")
public List<Address> listAddress() {
return ...
}
@GetMapping("/api/people")
@Timed
public List<Person> listPeople() {
return ...
}
}
如果你想要对特定的方法改变改变计时细节,你也可以组合类级别和方法级别注解:
import java.util.List;
import io.micrometer.core.annotation.Timed;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Timed
public class MyController {
@GetMapping("/api/addresses")
public List<Address> listAddress() {
return ...
}
@GetMapping("/api/people")
@Timed(extraTags = { "region", "us-east-1" })
@Timed(value = "all.people", longTask = true)
public List<Person> listPeople() {
return ...
}
}
使用
longTask = true
的@Timed
注解对方法启用一个长任务计时器。长任务计时器需要一个单独的指标名称,可以和短任务计时器一起使用。
自动配置注册MicrometerCommandLatencyRecorder
用于自动配置的LettuceConnectionFactory
。要了解更多细节,请查看Lettuce文档的Micrometer Metrics 部分。
要注册自定义指标,将MeterRegistry
注入到你的组件:
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tags;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final Dictionary dictionary;
public MyBean(MeterRegistry registry) {
this.dictionary = Dictionary.load();
registry.gauge("dictionary.size", Tags.empty(), this.dictionary.getWords().size());
}
}
如果你的指标依赖于其他bean,我们建议你使用MeterBinder
来注册他们:
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.binder.MeterBinder;
import org.springframework.context.annotation.Bean;
public class MyMeterBinderConfiguration {
@Bean
public MeterBinder queueSize(Queue queue) {
return (registry) -> Gauge.builder("queueSize", queue::size).register(registry);
}
}
使用MeterBinder
确保设置正确的依赖项关系并确保在检索指标的值时该bean是可用的。如果你发现你在组件或者应用程序之间重复地使用一套指标,那么MeterBinder
实现也是非常有用的。
默认情况下,来自所有
MeterBinder
bean的指标是自动绑定到Spring管理的MeterRegistry
。
如果你需要应用定制到特定的Meter
实例,你可以使用io.micrometer.core.instrument.config.MeterFilter
接口。
例如,如果你想重命名mytag.region
标签为mytag.area
用于所有的以com.example
开头的meter ID,你可以按照以下来做:
import io.micrometer.core.instrument.config.MeterFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyMetricsFilterConfiguration {
@Bean
public MeterFilter renameRegionTagMeterFilter() {
return MeterFilter.renameTag("com.example", "mytag.region", "mytag.area");
}
}
默认情况下,所有的
MeterFilter
bean是自动绑定到Spring管理的MeterRegistry
。确保通过使用Spring管理的MeterRegistry
注册你的指标,而不是Metrics
上的任何静态方法。这些使用全局注册表并不是Spring管理的。
常用标签通常用于对操作环境维度维度挖掘,例如主机,实例,地区,栈和其他。常用的标签被应用到所有meter并且可以被配置,如下示例所示:
management:
metrics:
tags:
region: "us-east-1"
stack: "prod"
前面的示例添加值分别为us-east-1
和prod
的region
和stack
标签到所有的meter。
如果你使用Graphite,常用标签的顺序是非常重要的。因为使用这个方法不能保证常用标签的顺序,Graphite用户建议定义自定义的
MeterFilter
代替。
除了MeterFilter
bean,你可以通过使用属性对每一个仪器基础应用一个限制的定制集合。每一个仪器定制应用到以给定名称开头的任何仪器ID。以下示例禁用以example.remote
开头ID的任何仪器:
management:
metrics:
enable:
example:
remote: false
以下属性允许每一个仪器定制:
*** Table 9. Per-meter customizations***
属性 | 描述 |
---|---|
management.metrics.enable |
是否阻止仪器发出任何指标 |
management.metrics.distribution.percentiles-histogram |
是否发布适合计算可聚集(跨维度)百分比近似值的柱状图 |
management.metrics.distribution.minimum-expected-value ,management.metrics.distribution.maximum-expected-value |
通过压缩期望值的范围发布少量柱状图桶 |
management.metrics.distribution.percentiles |
在你的应用程序中发布计算的百分比的值 |
management.metrics.distribution.expiry ,management.metrics.distribution.buffer-length |
给最近的样本更大的权重,使用一个可配置的缓冲长度,在一个可配置的期限的环缓冲区循环累计他们 |
management.metrics.distribution.slo |
发布一个使用你的服务级别目标定义的存储器的累积的柱状图 |
要了解关于percentiles-histogram
,percentiles
和slo
的概念的更多细节,请查看Micrometer文档的“Histograms and percentiles”部分。
Spring Boot提供metrics
端点,你可以使用它诊断地检查应用程序收集的指标。默认情况下这个端点是不可用的并必须暴露。请查看暴露端点了解更多详情。
导航到/actuator/metrics
展示可用仪器名称列表。你可以通过提供他的名字作为选择器深入展示关于特别的仪器信息–例如,/actuator/metrics/jvm.memory.max
。
在这里你使用的名字应该与代码中使用的名字匹配,不是与已经装运到用于监控系统经过命名约定规范化后的名字。换句话说,如果
jvm.memory.max
在Prometheus中显示为jvm_memory_max
,这是因为它的蛇形命名规则,当在metrics
端点检查仪器时,你应该仍使用jvm.memory.max
作为选择器。
你也可以添加任意数量的tag=KEY:VALUE
查询参数到URL的末尾以便在仪器上维度深入-例如,/actuator/metrics/jvm.memory.max?tag=area:nonheap
。
报告的测量值是所有匹配仪器名称和已经应用的任意标签的仪器统计的和。在前面的示例中,返回的
Value
统计是堆中“代码缓存”,“压缩的类空间”,“元空间”区域的内存足迹最大值的和。如果你想要只查看“元空间”的最大值大小,你可以添加额外的tag=id:Metaspace
– 也就是,/actuator/metrics/jvm.memory.max?tag=area:nonheap&tag=id:Metaspace
。
一旦Spring Security开始运作,Spring Boot Actuator有灵活的发布事件的审核框架(默认情况下,“身份认证成功”,“失败”和“访问受限”异常)。这个特性对于报告和实现基于身份验证失败的锁定策略是非常有用的。
你可以通过在应用程序配置中提供类型为AuditEventRepository
的bean启用审核。为了方便起见,Spring Boot提供一个InMemoryAuditEventRepository
。InMemoryAuditEventRepository
有限制功能,而我们建议只在开发环境使用它。对于生产环境,考虑创建自己的可替代的AuditEventRepository
实现。
要定制推送安全时间,你可以停工你自己的AbstractAuthenticationAuditListener
和AbstractAuthorizationAuditListener
实现。
你也可以为你自己的业务服务使用审核服务。为此,注入AuditEventRepository
bean到你自己的组件并直接使用它或者使用Spring的ApplicationEventPublisher
发布一个AuditApplicationEvent
(通过实现ApplicationEventPublisherAware
)。
你可以通过提供你的应用程序的配置中类型为HttpTraceRepository
的bean来启用HTTP追踪。为了方便起见,Spring Boot提供InMemoryHttpTraceRepository
,它存储对最后100(默认)请求响应的交换追踪。InMemoryHttpTraceRepository
与其他追踪解决方案相比是有限制的,我们建议只在开发环境使用它。对于生产环境,我们建议使用生产就绪追踪或者可观察的解决方案,例如Zipkip或者Spring Cloud Sleuth。或者,你可以创建你自己的HttpTraceRepository
。
你可以使用httptrace
端点来获得关于存储在HttpTraceRepository
中的请求-响应交换信息。
要自定义包含在每一个追踪的项目,使用management.trace.http.include
配置属性。对于高级定制,考虑注册你自己的HttpExchangeTracer
实现。
在spring-boot
模块,你可以发现创建文件的两个类,他们对过程控制是非常有用的。
ApplicationPidFileWriter
创建包含应用程序PID的文件(默认情况下,在应用程序文件名为application.pid
的目录)WebServerPortFileWriter
创建包含运行web服务器端口的文件(或者多个)( 默认情况下,在应用程序文件名为application.port
的目录)。默认情况下,这些写入是不激活的,但是你可以启用他们:
在META-INF/spring.factories
文件中,你可以激活写PID文件的监听器:
org.springframework.context.ApplicationListener=\
org.springframework.boot.context.ApplicationPidFileWriter,\
org.springframework.boot.web.context.WebServerPortFileWriter
你也可以通过调用SpringApplication.addListeners(...)
方法激活一个监听器并传到合适的Writer
类。这个方法也让你在Writer
构造器中定制文件名称和路径。
Spring Boot的actuator模块包括额外的支持,当你发布到兼容的Cloud Found实例时,它是激活的。/cloudfoundryapplication
路径提供一个可替代的安全路由到所有的@Endpoint
bean。
扩展的支持让Cloud Foundry管理 UI(比如你可以用来展示已发布的应用程序的web应用程序)通过Spring Bootactuator信息增强。例如,应用程序状态页可以包含全量的健康状态信息,而不是典型的"运行中"或者“停止”状态。
/cloudfoundryapplication
路径不能让常规用户直接访问。要使用这个端点,你必须使用请求传入一个验证的UAA token。
如果你想要全面禁用/cloudfoundryapplication
端点,你可以添加以下设置到你的application.properties
文件:
management:
cloudfoundry:
enabled: false
默认情况下,对/cloudfoundryapplication
端点的安全验证会对各种Cloud Foundry服务进行SSL调用。如果你的Cloud Foundry UAA或者Cloud Controller服务使用自签名的证书,你需要设置以下属性:
management:
cloudfoundry:
skip-ssl-validation: true
如果服务器的上下文路径已经配置到除了/
任何地方,在根应用程序Cloud Foundry端点是不可用的。例如,如果server.servlet.context-path=/app
,Cloud Foundry端点在/app/cloudfoundryapplication/*
是可用的。
如果你期望Cloud Foundry端点在/cloudfoundryapplication/*
一直可用,不管服务器的上下文路径,你需要在应用程序中显示地配置它。这个配置的不同,取决于web服务器的使用。对于Tomcat,你可以添加以下配置:
import java.io.IOException;
import java.util.Collections;
import jakarta.servlet.GenericServlet;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletContainerInitializer;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import org.apache.catalina.Host;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyCloudFoundryConfiguration {
@Bean
public TomcatServletWebServerFactory servletWebServerFactory() {
return new TomcatServletWebServerFactory() {
@Override
protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
super.prepareContext(host, initializers);
StandardContext child = new StandardContext();
child.addLifecycleListener(new Tomcat.FixContextListener());
child.setPath("/cloudfoundryapplication");
ServletContainerInitializer initializer = getServletContextInitializer(getContextPath());
child.addServletContainerInitializer(initializer, Collections.emptySet());
child.setCrossContext(true);
host.addChild(child);
}
};
}
private ServletContainerInitializer getServletContextInitializer(String contextPath) {
return (classes, context) -> {
Servlet servlet = new GenericServlet() {
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
ServletContext context = req.getServletContext().getContext(contextPath);
context.getRequestDispatcher("/cloudfoundryapplication").forward(req, res);
}
};
context.addServlet("cloudfoundry", servlet).addMapping("/*");
};
}
}
你可能想读关于图形工具,例如Graphite。
除此之外,你可以继续读关于"发布选项"或者抢先一步了解关于Spring Boot的构建工具插件的一些深入信息。
Spring Boot的灵活的打包选项在部署应用程序时提供了大量的选择。你可以部署Spring Boot应用程序到各种各样的云平台,虚拟/真实的机器或者在Unix系统使他们完全可执行。
这个部分涵盖一些更常用的部署场景。
Spring Boot的可执行jar是为大多数流行的云Paas(平台及服务)提供商准备的。这些提供商往往要求你“携带你自己的容器”。他们管理应用程序进程(不是特定的Java应用程序),所以他们需要中间层,以便使你的应用程序适应云中运行进程的概念。
两个比较流行的云提供商,Heroku和Cloud Foundry,利用“构建打包”方法。这个构建打包将你部署的代码封装在启动应用程序所需的任何内容中。它可能是JDK和java
调用,一个内嵌的web服务器,或者全面的应用程序服务器。构建打包是可插入的,但是理想情况下,你应该尽可能少的对它进行定制。这个减少不受你控制的功能的痕迹。它将开发环境和生产环境的差异减到最少。
在理想情况下,你的应用程序,比如Spring Boot可执行jar,需要运行的所有东西都打包其中。
在这部分,我们将了解如何让在入门章节我们开发的应用程序在云启动和运行。
Cloud Foundry提供默认的构建打包,如果没有其他指定的构建打包,默认的将生效。Cloud Foundry Java构建打包已经非常好的支持Spring应用程序,包括Spring Boot。你可以发布单独的可执行的jar以及传统的.war
打包的应用程序。
一旦你已经构建你的应用程序(例如,通过使用mvn clean package
)并且已经安装cf
命令行工具,使用cf push
命令部署你的应用程序,将你编译的.jar
的路径代入。在推送应用程序之前请确保使用cf
命令行客户端登陆。以下行展示了使用cf push
命令部署应用程序:
$ cf push acloudyspringtime -p target/demo-0.0.1-SNAPSHOT.jar
在前面的历史中,我们将
acloudyspringtime
代入为你给的cf
任何值作为应用程序的名称。
请查看cf push
文档了解更多选项。如果在相同的目录中存在Cloud Foundrymanifest.yml
文件,则认为它存在。
基于这点,cf
开始上传应用程序,生成类似于以下示例的输出:
Uploading acloudyspringtime... OK
Preparing to start acloudyspringtime... OK
-----> Downloaded app package (8.9M)
-----> Java Buildpack Version: v3.12 (offline) | https://github.com/cloudfoundry/java-buildpack.git#6f25b7e
-----> Downloading Open Jdk JRE 1.8.0_121 from https://java-buildpack.cloudfoundry.org/openjdk/trusty/x86_64/openjdk-1.8.0_121.tar.gz (found in cache)
Expanding Open Jdk JRE to .java-buildpack/open_jdk_jre (1.6s)
-----> Downloading Open JDK Like Memory Calculator 2.0.2_RELEASE from https://java-buildpack.cloudfoundry.org/memory-calculator/trusty/x86_64/memory-calculator-2.0.2_RELEASE.tar.gz (found in cache)
Memory Settings: -Xss349K -Xmx681574K -XX:MaxMetaspaceSize=104857K -Xms681574K -XX:MetaspaceSize=104857K
-----> Downloading Container Certificate Trust Store 1.0.0_RELEASE from https://java-buildpack.cloudfoundry.org/container-certificate-trust-store/container-certificate-trust-store-1.0.0_RELEASE.jar (found in cache)
Adding certificates to .java-buildpack/container_certificate_trust_store/truststore.jks (0.6s)
-----> Downloading Spring Auto Reconfiguration 1.10.0_RELEASE from https://java-buildpack.cloudfoundry.org/auto-reconfiguration/auto-reconfiguration-1.10.0_RELEASE.jar (found in cache)
Checking status of app 'acloudyspringtime'...
0 of 1 instances running (1 starting)
...
0 of 1 instances running (1 starting)
...
0 of 1 instances running (1 starting)
...
1 of 1 instances running (1 running)
App started
恭喜!应用程序现在已经运行了。
只要你的应用程序运行,你可以使用cf apps
命令验证部署的应用程序的状态,如下示例所示:
$ cf apps
Getting applications in ...
OK
name requested state instances memory disk urls
...
acloudyspringtime started 1/1 512M 1G acloudyspringtime.cfapps.io
...
默认情况下,关于运行应用程序的元数据以及服务连接信息已经作为环境变量公开给应用程序(例如:$VCAP_SERVICES
)。这个架构决策是由于Cloud Foundry的支持多语言特点(任何语言和平台支持作为构建打包)。过程作用域环境变量是语言无关的。
环境变量并不总是最简单的API,所以Spring Boot自动提取他们并将数据扁平化放入到属性,可以通过Spring的Environment
实现访问他们,如下示例所示:
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@Component
public class MyBean implements EnvironmentAware {
private String instanceId;
@Override
public void setEnvironment(Environment environment) {
this.instanceId = environment.getProperty("vcap.application.instance_id");
}
// ...
}
所以的Cloud Foundry属性是以vacp
开头。你可以使用vcap
以访问应用程序信息(例如应用程序的公共URL)和服务信息(例如数据库凭证)。请查看‘CloudFoundryVcapEnvironmentPostProcessor’Javadco了解完整详情。
Java CFEnv项目更适合像配置DataSource这样的任务。
Spring Boot通过检查"*_SERVICE_HOST"
和"*_SERVICE_PORT"
变量自动检测Kubernetes部署环境。你可以使用spring.main.colud-platform
配置属性覆盖这个检测。
Spring Boot帮助你管理应用程序的状态并且使用Actuator用HTTP Kubernetes Porbes导出它。
当Kubernetes删除应用程序实例,停机步骤同时涉及几个子系统:停机钩子,注销服务,从负载均衡中移除实例…因为关机过程并行发生(由于分布式系统的特性),在此期间存在一个窗口期,流量可以路由到一个也开始进行管理处理的pod。
你可以在预停止的处理器中定义一个休眠执行来防止请求被路由到一个已经准备开始停止的pod。这个休眠应该足够长,以便新的请求停止路由到pod,并且其持续时间因部署而异。预停止处理器可以通过使用在pod的配置文件的PodSpec进行配置,如下:
spec:
containers:
- name: "example-container"
image: "example-image"
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 10"]
一旦预停止钩子已经完成,SIGTERM将被发送到容器并且优雅停机将开始,允许任何剩下的处理中的请求完成。
当Kubernetes发送SIGTERM信号到pod,它等待一个被称为终止宽限期的特定时间(对此的默认时间是30秒)。如果容器在宽限期之后仍在运行,他们将发送SIGKILL 信号并且强制地移除。如果pod超过30秒关闭,这可能是因为你添加了
spring.lifecycle.timeout-per-shutdown-phase
,确保通过在Pod的YAML中设置terminationGracePeriodSeconds
选项增加终止宽限期。
Heroku是另一个有名的PaaS平台。要定制Heroku构建,你提供一个Procfile
,它提供了需要部署应用程序的咒语。Heroku分配一个端口给Java应用程序使用,然后保证路由到外部的URI有效。
你必须配置你的应用程序监听到正确的端口。以下示例展示用于我们启动器的REST应用程序的Procfile
:
web: java -Dserver.port=$PORT -jar target/demo-0.0.1-SNAPSHOT.jar
Spring Boot使-D
参数可以作为Spring Environment
实例的属性访问。server.port
配置属性被提供给内嵌的Tomcat或者Undertow实例然后他们启动时使用这个端口。$PORT
环境变量通过Heroku PaaS分配给我们的。
这应该是你需要的所有东西。Heroku部署最常见的部署工作流程是git push
代码到生产环境,如下示例所示:
$ git push heroku main
他将输出以下结果:
Initializing repository, done.
Counting objects: 95, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (78/78), done.
Writing objects: 100% (95/95), 8.66 MiB | 606.00 KiB/s, done.
Total 95 (delta 31), reused 0 (delta 0)
-----> Java app detected
-----> Installing OpenJDK 1.8... done
-----> Installing Maven 3.3.1... done
-----> Installing settings.xml... done
-----> Executing: mvn -B -DskipTests=true clean install
[INFO] Scanning for projects...
Downloading: https://repo.spring.io/...
Downloaded: https://repo.spring.io/... (818 B at 1.8 KB/sec)
....
Downloaded: https://s3pository.heroku.com/jvm/... (152 KB at 595.3 KB/sec)
[INFO] Installing /tmp/build_0c35a5d2-a067-4abc-a232-14b1fb7a8229/target/...
[INFO] Installing /tmp/build_0c35a5d2-a067-4abc-a232-14b1fb7a8229/pom.xml ...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 59.358s
[INFO] Finished at: Fri Mar 07 07:28:25 UTC 2014
[INFO] Final Memory: 20M/493M
[INFO] ------------------------------------------------------------------------
-----> Discovering process types
Procfile declares types -> web
-----> Compressing... done, 70.4MB
-----> Launching... done, v6
https://agile-sierra-1405.herokuapp.com/ deployed to Heroku
To [email protected]:agile-sierra-1405.git
* [new branch] main -> main
现在,你的应用程序应该启动并运行在Heroku。要了解更多细节,请查看部署Spring Boot应用程序到Heroku。
OpenShift有许多资源描述如何部署Spring Boot应用程序,包括:
Amazon Web Service提供多种方式安装Spring Boot应用程序,或者传统的web应用程序(war)或者带有内嵌web服务器的可执行jar文件。选项包括:
每一个有不同的特性和定价模式。在这个文档中,我们描述了使用AWS Elastic Beanstalk的方法
正如在官方Elastic Beanstalk Java 指南中所描述的,有两个主要选项来部署Java应用程序。你可以使用"Tomcat平台"或者“Java SE平台”。
这个选项应用到提供一个war文件的Spring Boot项目。无需特定的配置。你只需要遵循官方指南。
这个选项应用到提供一个jar文件的Spring Boot项目并运行在内嵌的web容器。Elastic Beanstalk环境在端口80运行一个nginx实例来代理运行在端口5000的真正的应用程序。为配置它,添加以下行到你的application.properties
文件:
server.port=5000
上传二进制文件而不是源文件
默认情况下,Elastic Beanstalk上传源文件并在AWS中编译他们。然而,最好是上传二进制文件代替。为此,添加类似于以下行到你的.elasticbeanstalk/config.yml
文件:deploy: artifact: target/demo-0.0.1-SNAPSHOT.jar
通过设置环境类型减少耗时
默认情况下,Elastic Beanstalk环境是负载均衡的。这个负载均衡器有明显消耗。为避免该消耗,设置环境类型为"单实例",正如在Amazon文档中描述的。你也可以通过使用CLI和以下命令创建单个实例环境:eb create -s
这个是访问AWS最简单的方式之一,但还有更多的事情需要涉及,比如如何将Elastic Beanstalk集成到CI/CD工具,使用Elastic Beanstalk Maven插件代替CLI等待。有博客包含这些更细节的主题。
CloudCaptain的工作原理是将Spring Boot可执行jar或者war转变为最小的VM镜像,可以不加修改地部署到VirtualBox或者AWS。CloudCaptain为Spring Boot提供了深度集成,并使用Spring Boot配置文件信息来自动化配置端口和健康度检查URL。CloudCaptain充分利用这个信息用于它生成的镜像以及用于它提供的所有资源(实例,安全组,灵活的负载均衡等等)。
一旦你已经创建一个ClouodCaptain账户,连接它到你的AWS账户,安装CloudCaptain客户端的最新版本并确保应用程序通过Maven或者Gradle构建(例如,使用mvn clean package
),你可以使用类似于以下命令部署你的Spring Boot应用程序到AWS:
$ boxfuse run myapp-1.0.jar -env=prod
请查看boxfuse run
文档了解更多选项。如果在当前目录存在boxfuse.conf
文件,则考虑它。
默认情况下,CloudCaptain在启动时激活Spring 名称为
boxfuse
配置文件。如果你的可执行jar或者war包含一个application-boxfuse.properties
文件,CloudCaptain基于它包含的属性文件进行配置。
在这一点上,CloudCaptain为你的应用程序创建一个镜像,上传它并配置和启动在AWS上的必须的资源,在输出中的结果类似于以下示例:
Fusing Image for myapp-1.0.jar ...
Image fused in 00:06.838s (53937 K) -> axelfontaine/myapp:1.0
Creating axelfontaine/myapp ...
Pushing axelfontaine/myapp:1.0 ...
Verifying axelfontaine/myapp:1.0 ...
Creating Elastic IP ...
Mapping myapp-axelfontaine.boxfuse.io to 52.28.233.167 ...
Waiting for AWS to create an AMI for axelfontaine/myapp:1.0 in eu-central-1 (this may take up to 50 seconds) ...
AMI created in 00:23.557s -> ami-d23f38cf
Creating security group boxfuse-sg_axelfontaine/myapp:1.0 ...
Launching t2.micro instance of axelfontaine/myapp:1.0 (ami-d23f38cf) in eu-central-1 ...
Instance launched in 00:30.306s -> i-92ef9f53
Waiting for AWS to boot Instance i-92ef9f53 and Payload to start at https://52.28.235.61/ ...
Payload started in 00:29.266s -> https://52.28.235.61/
Remapping Elastic IP 52.28.233.167 to i-92ef9f53 ...
Waiting 15s for AWS to complete Elastic IP Zero Downtime transition ...
Deployment completed successfully. axelfontaine/myapp:1.0 is up and running at https://myapp-axelfontaine.boxfuse.io/
现在,你的应用程序应该已经启动并在WAS上运行。
请查看关于在EC2部署Spring Boot应用程序的博客以及CloudCaptain Spring Boot集成文档来入门使用Maven构建来运行应用程序。
这个入门指南带你了解部署Spring Boot应用程序到Azure Spring Cloud或者Azure App Service。
Google Cloud有几个选项可以用来发动Spring Boot应用程序。最容易上手的可能是APP引擎,但是你也可以发现在容器中使用容器引擎或者在虚拟机使用计算引擎运行Spring Boot的方式。
要在App引擎中运行,首先,你可以在UI中创建一个项目,为你设置唯一的标志符,同时设置HTTP路由。将Java应用程序添加到项目中并保持为空,然后使用Google Cloud SDK从命令行或者CI构建将Spring Boot应用程序推送到该位置。
App引擎标准要求你使用WAR打包,按照这些步骤来部署App引擎标准应用程序到Google Cloud。
或者,App Engine Flex要求你创建一个app.yaml
文件来描述你app所需要的资源。通常,你将这个文件放入到src/main/appengine
,它应该类似于以下文件:
service: "default"
runtime: "java"
env: "flex"
runtime_config:
jdk: "openjdk8"
handlers:
- url: "/.*"
script: "this field is required, but ignored"
manual_scaling:
instances: 1
health_check:
enable_health_check: false
env_variables:
ENCRYPT_KEY: "your_encryption_key_here"
你可以通过添加项目ID到构建配置来部署app(例如,使用Maven插件),如下示例所示:
<plugin>
<groupId>com.google.cloud.toolsgroupId>
<artifactId>appengine-maven-pluginartifactId>
<version>1.3.0version>
<configuration>
<project>myprojectproject>
configuration>
plugin>
然后使用mvn appengine:deploy
部署(如果首先你需要身份认证,构建失败)
除了使用java -jar
运行Spring Boot应用程序,也可以制造在Unix系统完全可执行的应用程序。完全可执行的jar可以被执行就像任何其他可执行二进制或者使用init.d
或者systemd
注册它一样。当在常用的生产环境安装或者管理Spring Boot应用程序时是有帮助的。
完全可执行jar通过在文件前嵌一个额外的脚本运行。当前,一些工具不接收这种格式,所以你可能不会一直能使用这个技术,
jar -xf
提取一个已经制作为完全可执行的jar或者war文件可能默默地失败。建议如果你只打算直接执行它,你制作的jar或者war完全可执行,而不是使用java -jar
运行它或者将它部署到servlet容器。
zip64格式的jar文件不能被制作完全可执行。尝试这样做会导致jar文件在直接执行或者使用
java -jar
执行时报告被损坏。一个标准格式的jar文件包含一个或者多个zip64格式嵌套的jar可以完全可执行。
要使用Maven创建一个完全可执行的jar,使用以下插件配置:
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<executable>trueexecutable>
configuration>
plugin>
以下示例展示等价的Gradle配置:
tasks.named('bootJar') {
launchScript()
}
你仍可以通过键入./my-application.jar
(my-application
是你的artifact的名字)运行你的应用程序。目录包含被用作你应用程序的工作目录的jar。
默认的脚本支持大多数Linux发行版并且在CentOS和Ubuntu做了测试。其他平台,比如OS X和FreeBSD,需要一个自定义的embeddedLaunchScript
的使用。
Spring Boot应用程序可以使用init.d
或者systemd
很容易作为Unix/Linux服务启动。
如果你配置Spring Boot的Maven或者Gradle插件来生成完全执行jar,你不能使用一个自定义embeddedLaunchScript
,你的应用程序可以用作一个init.d
服务。为此,符号链接这个jar到init.d
来支持标准的start
,stop
,restart
和status
命令。
脚本支持一下特性:
/var/run//.pid
跟踪应用程序的PID/var/log/.log
假设你有安装在/var/myapp
的Spring Boot应用程序,要安装一个Spring Boot应用程序作为init.d
服务,创建一个符号链接,如下:
$ sudo ln -s /var/myapp/myapp.jar /etc/init.d/myapp
一旦安装,你可以以平常的方式启动或者停止服务。例如,在基于Debian的系统,你可以使用以下命令启动它:
$ service myapp start
如果你的应用程序启动失败,检查写入
/var/log/
日志文件是否有错误。.log
你也可以通过使用标准的操作系统工具给应用程序做标记来实现自动化启动。例如,在Debian,你可以使用以下命令:
$ update-rc.d myapp defaults <priority>
以下内容是关于如何使作为一个init.d服务运行的Spring Boot应用程序安全的参考的集合。本文并不是要详尽地列出加固应用程序及其运行环境所做的所有事情。
当root用户运行时,就像当root用户用来启动一个init.d服务这种情况一样,默认的可执行脚本作为在RUN_AS_USER
环境变量指定用户运行应用程序。当环境变量没有设置,使用拥有jar文件的用户代替。你应该从不使用root
用户运行应用程序,所以RUN_AS_USER
应该从不使用root并且你的应用程序的jar应该从不被root用户拥有。反而,创建一个特定的用户运行应用程序并设置RUN_AS_USER
环境变量或者使用chown
使他成为jar文件的拥有者,如下示例所示:
$ chown bootapp:bootapp your-app.jar
在这种情况,默认的可执行脚本作为bootapp
用户运行应用程序。
要减少应用程序用户被盗用的可能性,你应该考虑阻止它使用登陆Shell。例如,你可以设置账号的shell为
usr/sbin/nologin
。
你也应该采取措施来阻止应用程序的jar文件的修改。首先,配置它的权限以便它不能被写入并只能被他自己读和执行,如下示例所示:
$ chmod 500 your-app.jar
第二,你也应该采取措施来限制如果正在运行的应用程序或者账号被盗用的危害。如果一个攻击者获得访问,他们可能使jar文件可写并改变他们的内容。防范这种情况的一种方式是使用chattr
使其不可修改,如下示例所示:
$ sudo chattr +i your-app.jar
这个将防止任何用户,包括root,来修改jar。
如果root用来控制应用程序的服务,你使用.conf
文件来定制它的启动,通过root用户读取和评估.conf
文件。它应该被响应的保护。使用chmod
以便文件只能通过拥有者读取并使用chown
来使root为所有者,如下示例所示:
$ chmod 400 your-app.conf
$ sudo chown root:root your-app.conf
systemd
是System V初始系统的继承者并且现在被许多现在Linux发行版使用。尽管你可以继续使用init.d
脚本与systemd
,它也可以使用systemd
‘服务’脚本发动Spring Boot应用程序。
假设你有安装在/var/myapp
的Spring Boot应用程序,要安装Spring Boot应用程序为systemd
服务,创建一个名称为myapp.service
的脚本并将它放入到/etc/systemd/system
目录。以下脚本提供一个示例:
[Unit]
Description=myapp
After=syslog.target
[Service]
User=myapp
ExecStart=/var/myapp/myapp.jar
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
记住改变
Descrption
,User
和ExecStart
字段为你的应用程序。
ExecStart
字段没有声明脚本动作命令,他意味着默认使用run
命令。
注意,与作为init.d
服务运行时不同,运行应用程序的用户,PID文件和控制台日志文件是通过systemd
本身管理的,因为必须在’service’脚本中使用合理的字段配置。查阅服务单元配置管理页面了解更多详情。
要标记应用程序在系统启动时自动启动,使用以下命令:
$ systemctl enable myapp.service
运行man systemctl
了解更多详情。
通过Maven或者Gradle插件写的默认的内嵌启动脚本可以以许多方式定制。对于大多数人,使用默认的脚本连同一些定制通常是足够的。如果你发现你不能定制你所需要的东西,使用embeddedLaunchScript
选项来完全地写你自己的文件。
在将启动脚本写入到jar文件时定制它的元素通常是有意义的。例如,init.d脚本可以提供一个’描述’。因为你预先知道这个描述(你不需要更改),你可能在jar生成时提供它。
要定制编写的元素,使用embeddedLaunchScriptProperties
Spring Boot Maven插件选项或者Spring Boot Gradle插件的脚本的properties
属性。
默认的脚本支持以下属性替代:
名称 | 描述 | Gradle默认 | Maven默认 |
---|---|---|---|
mode |
脚本模式 | auto |
auto |
initInfoProvides |
"INIT INFO"的Provides 部分 |
${task.baseName} |
${project.artifactId} |
initInfoRequiredStart |
"INIT INFO"的Required-Start 部分 |
$remote_fs $syslog $network |
$remote_fs $syslog $network |
initInfoRequiredStop |
"INIT INFO"的Required-Stop 部分 |
$remote_fs $syslog $network |
$remote_fs $syslog $network |
initInfoDefaultStart |
"INIT INFO"的Default-Start 部分 |
2 3 4 5 |
2 3 4 5 |
initInfoDefaultStop |
"INIT INFO"的Default-Stop 部分 |
0 1 6 |
0 1 6 |
initInfoShortDescription |
"INIT INFO"的Short-Description 部分 |
${project.descrption} (求助于${task.baseName} )的单行版本 |
${project.name} |
initInfoDescription |
"INIT INFO"的Description 部分 |
${project.descrption} (求助于${task.baseName} ) |
${project.descrption} (求助于${task.baseName} ) |
initInfoChkconfig |
"INIT INFO"的chkconfig 部分 |
2345 99 01 |
2345 99 01 |
confFolder |
CONF_FOLDER 的默认值 |
包含jar的文件夹 | 包含jar的文件夹 |
inlinedConfScript |
依赖于应该内联在默认的启动脚本的文件脚本。这个可以用来设置环境变量,例如任何外部配置加载之前的JAVA_POTS |
||
logFolder |
LOG_FOLDER 的默认值。仅校验init.d 服务 |
||
logFilename |
LOG_FILENAME 的默认值。仅校验init.d 服务 |
||
pidFolder |
PID_FOLDER 的默认值。仅校验init.d 服务 |
||
pidFilename |
在PID_FOLDER 中PID文件名称的默认值。仅校验init.d 服务 |
||
useStartStopDaemon |
当start-stop-daemon 命令可用,是否应该使用它来控制进程 |
true |
true |
stopWaitTime |
STOP_WAIT_TIME 的默认值,以秒为单位。只校验init.d 服务 |
60 | 60 |
对于在jar已经被书写的之后需要定制的脚本的项目,你可以使用环境变量或者配置文件.
以下环境属性使用默认的脚本支持:
变量 | 描述 |
---|---|
MODE |
操作的"模式"。默认值取决于构建jar的方式,但是它通常auto (意味着它试图通过检测它是否是init.d 目录中的符号猜测它是否是一个初始化脚本)。你可以显示设置它为service 以便`stop |
RUN_AS_USER |
操作的"模式"。默认值取决于构建jar的方式,但是它通常auto (意味着它试图通过检测它是否是init.d 目录中的符号猜测它是否是一个初始化脚本)。你可以显示设置它为service 以便`stop |
USE_START_STOP_DAEMON |
如果start-stop-daemon 可用,是否使用它控制进程。默认为true |
PID_FOLDER |
pid文件夹的根名称(默认为/var/run ) |
LOG_FOLDER |
存放日志文件的文件夹名称(默认为/var/log ) |
CONF_FOLDER |
读取.conf文件的文件夹的名称(默认与jar文件夹一样) |
LOG_FILENAME |
在LOG_FOLDER 中日志文件的名称(默认 ) |
APP_NAME |
app名称.如果jar自符号链接运行,这个脚本猜测app名称。如果它不是一个符号链接或者你想显示地设置app名称,这个是有用的 |
RUN_ARGS |
传入到程序(Spring Boot应用)的参数 |
JAVA_HOME |
使用默认的PATH 发现java 可执行的位置,但是如果$JAVA_HOME/bin/.java 存在一个可执行jar,可以显示地设置它 |
JAVA_OPTS |
当启动时传入到JVM的选项 |
JARFILE |
jar文件明确的位置,以防脚本用来启动jar但是实际上没有jar嵌入 |
DEBUG |
如果不为空,在shell进程设置-x 标志,允许你查看脚本逻辑 |
STOP_WAIT_TIME |
在强制停机之前,停止应用程序所需等待的时间,以秒为单位(默认60 ) |
PID_FOLDER
,LOG_FOLDER
和LOG_FILENAME
变量只对于init.d
服务进行校验。对于systemd
,通过使用‘service’脚本实现等价的定制。请查看服务单元配置管理页面了解更多详情。
除了JARFILE
和APP_NAME
,在前面章节的设置列表可以通过使用.conf
文件配置。这个文件期望挨着jar文件并且有相同的名字只是以.conf
结尾而不是.jar
.例如,名称为/var/myapp/myapp.jar
的jar使用名称为/var/myapp/myapp.conf
配置文件,如下示例所示:
myapp.conf
JAVA_OPTS=-Xmx1024M
LOG_FOLDER=/custom/log/folder
要了解如何适当地保护这个文件,请查看针对使init.d service安全的参考。
一个Spring Boot应用程序通过使用winsw
可以作为Windows服务启动。
A(单独维护的示例) 描述了如何逐笔为Spring Boot应用程序创建Window服务。
请查看Cloud Foundry,Heroku,OpenShift和Boxfuse web站点了解关于PaaS可以提供的这种特性的更多信息。这里仅仅是四个最出名的Java PaaS提供商。因为Spring Boot非常适合基于云部署,所以你也可以大量地考虑其他提供商。
下一章节继续介绍Spring Boot CLI,或者你可以抢先一步阅读构建工具插件。
Spring Boot CLI是一个命令行工具,如果你想快速开发一个Spring 应用程序,你可以它。它让你运行Groovy脚本,这意味着你可以使用类似于类Java预发而无需那么多的样板代码。你也可以引导一个新的项目或者为其写你自己的命令。
Spring Boot CLI(command line interface)可以通过使用 SDKMAN!(SDK管理器)或者使用Homebrew或者如果你是OSX用户 来使用MacPorts进行手动安装。请查看在入门章节安装Spring Boot CLI来了解全面的安装介绍。
一旦你已经安装CLI,你可以通过键入spring
和按下Enter在命令行来使用它。如果你运行spring
没有任何参数,展示一个帮助画面,如下:
$ spring
usage: spring [--help] [--version]
<command> [<args>]
Available commands are:
run [options] <files> [--] [args]
Run a spring groovy script
_... more command help is shown here_
你可以键入spring help
来获取更多关于任何支持的命令的信息,如下示例所示:
$ spring help run
spring run - Run a spring groovy script
usage: spring run [options] <files> [--] [args]
Option Description
------ -----------
--autoconfigure [Boolean] Add autoconfigure compiler
transformations (default: true)
--classpath, -cp Additional classpath entries
--no-guess-dependencies Do not attempt to guess dependencies
--no-guess-imports Do not attempt to guess imports
-q, --quiet Quiet logging
-v, --verbose Verbose logging of dependency
resolution
--watch Watch the specified file for changes
version
命令提供一个快速的方式验证你正在使用哪个版本的Spring Boot,如下:
$ spring version
Spring CLI v3.0.0-SNAPSHOT
你可以通过使用run
命令编译和运行Grooy源码。Spring Boot CLI是完全自包含的,所以你不需要任何额外的Groovy安装。
以下示例展示了一个使用Groovy的“hello world”web应用程序书写:
@RestController
class WebApplication {
@RequestMapping("/")
String home() {
"Hello World!"
}
}
要编译和运行应用程序,键入以下命令:
$ spring run hello.groovy
要传入命令行参数到应用程序,使用--
来分隔命令与"spring"命令行参数,如下示例所示:
$ spring run hello.groovy -- --server.port=9000
要设置JVM命令行参数,你可以使用JAVA_OPTS
环境变量,如下示例所示:
$ JAVA_OPTS=-Xmx1024m spring run hello.groovy
当在Microsoft Windows设置
JAVA_OPTS
时,一定要引用全部说明,例如set "JAVA_OPTS=-Xms256m -Xmx2048m"
。这样做保证值正确传入到进程。
标准的Groovy包括一个@Grab
注解,它让你声明第三方类库依赖。这个有用的技术让Groovy与Maven或者Gradle相同的方式下载jar,但没有要求你使用构建工具。
Spring Boot进一步扩展这个技术,并尝试推导哪个类库可以基于你的代码“抓取”。例如,因为WebApplication
代码展示前面的使用@RestController
注解,Spring Boot 抓取“Tomcat”和“Spring MVC”.
以下项目用作“抓取点”:
项目 | 抓取 |
---|---|
JdbcTemplate ,NamedParameterJdbcTemplate ,DataSource |
JDBC应用程序 |
@EnableJms |
JMS应用程序 |
@EnableCaching |
缓存抽象 |
@Test |
JUnit. |
@EnableRabbit |
RabbitMQ. |
扩展Specification |
Spock测试. |
@EnableBatchProcessing |
Spring Batch. |
@MessageEndpoint @EnableIntegration |
Spring Integration. |
@Controller @RestController @EnableWebMvc |
Spring MVC + 内嵌Tomcat |
@EnableWebSecurity |
Spring Security. |
@EnableTransactionManagement |
Spring Transaction Management. |
请查看Spring Boot CLI源码中的
CompilerAutoConfiguration
的子类来精确理解定制是如何应用的。
Spring Boot通过让你指定一个没有group或者版本的依赖扩展Groovy的标准的@Grab
支持(例如,@Grab('freemarker')
)。这样做参考Spring Boot的默认依赖元数据来推导出artifact的group和版本。
为帮助减少Groovy代码的大小,自动包含几个import
语句。注意前面的示例如何引用@Component
,@RestController
,和@RequestMapping
无需使用全量限定名称或者import
语句。
许多Spring注解工作无需使用
import
语句。在添加引入之前,尝试运行你的应用程序来看看有什么失败。
不像同等的Java应用程序,你不需要在Groovy
脚本中包含一个public static void main(String[] args)
方法。SpringApplication
自动创建,使用你的编译的代码充当source
。
默认情况下,当解析@Grap
声明时,CLI使用在spring-boot-dependencies
中声明的依赖管理。额外的依赖管理,他覆盖了默认的依赖管理,使用@DependencyManagementBom
注解配置它。这个注解的值应该指定一个或者多个Maven BOM的坐标(groupId:artifactId:version
)
例如,考虑以下声明:
@DependencyManagementBom("com.example.custom-bom:1.0.0")
前面的声明在Maven仓库com/example/custom-versions/1.0.0/
下获得custom-bom-1.0.0.pom
。
当我们指定多个BOM时,他们按照声明他们的顺序应用,如下示例所示:
@DependencyManagementBom([
"com.example.custom-bom:1.0.0",
"com.example.another-bom:1.0.0"])
前面的示例表明在another-bom
中的依赖管理覆盖在custom-bom
中的依赖管理。
你可以使用@Grab
的任何地方使用@DependencyManagementBom
。然而,要保证依赖管理顺序的一致性,你最多可以在应用程序中使用@DependencyManagementBom
一次。
你可以使用“shell globbing”和接收文件输入的所有命令。这样做让你使用单个目录的多个文件,如下示例所示:
$ spring run *.groovy
你可以使用jar
命令打包你的应用程序到一个自包含的可执行jar文件,如下示例所示:
$ spring jar my-app.jar *.groovy
结果jar包含编译应用程序产生的类和所有应用程序依赖以便它可以使用java-jar
运行。jar文件也包含来自所有应用程序类路径的条目。你可以使用--include
和--exclude
显性地添加或者移除指向jar的路径。两者都是逗号分隔并且接收前缀,以“+”和“-”的形式表示他们应该从默认值中移除。默认包含如下:
public/**, resources/**, static/**, templates/**, META-INF/**, *
默认的排除如下:
.*, repository/**, build/**, target/**, **/*.jar, **/*.groovy
在命令行键入spring help jar
了解更多信息。
init
命令让你通过使用start.spring.io创建一个新的项目,而不用离开shell。如下示例所示:
$ spring init --dependencies=web,data-jpa my-project
Using service at https://start.spring.io
Project extracted to '/Users/developer/example/my-project'
上面的示例创建了my-project
目录和使用spring-boot-starter-web
和spring-boot-starter-data-jpa
基于Maven项目。你可以使用--list
标识列出这个服务的功能,如下示例所示:
$ spring init --list
=======================================
Capabilities of https://start.spring.io
=======================================
Available dependencies:
-----------------------
actuator - Actuator: Production ready features to help you monitor and manage your application
...
web - Web: Support for full-stack web development, including Tomcat and spring-webmvc
websocket - Websocket: Support for WebSocket development
ws - WS: Support for Spring Web Services
Available project types:
------------------------
gradle-build - Gradle Config [format:build, build:gradle]
gradle-project - Gradle Project [format:project, build:gradle]
maven-build - Maven POM [format:build, build:maven]
maven-project - Maven Project [format:project, build:maven] (default)
...
init
命令支持许多选项。请查看help
输出了解更多详情。例如,下面的命令创建一个使用Java 8 和war
打包的Gradle项目:
$ spring init --build=gradle --java-version=1.8 --dependencies=websocket --packaging=war sample-app.zip
Using service at https://start.spring.io
Content saved to 'sample-app.zip'
Spring Boot包括用于BASE和zsh shell的命令行补全脚本。如果你不使用这些脚本(假如你是一个Windows用户),你可以使用shell
命令来运行一个集成的shell,如下示例所示:
$ spring shell
Spring Boot (v3.0.0-SNAPSHOT)
Hit TAB to complete. Type \'help' and hit RETURN for help, and \'exit' to quit.
从内嵌的shell内部,你可以直接运行其他的命令:
$ version
Spring CLI v3.0.0-SNAPSHOT
内嵌的shell支持ANSI颜色输出以及tab
补全。如果你需要运行一个本地的命令,你可以使用!
开头 。要退出内嵌的shell,按ctrl-c
。
你可以通过使用install
命令添加扩展到CLI。这个命令使用一个或者多个格式为group:artifact:version
artifact坐标的集合,如下示例所示:
$ spring install com.example:spring-boot-cli-extension:1.0.0.RELEASE
除了安装你提供的坐标识别的artifact,所有的artifact的依赖项也被安装。
要卸载依赖项,使用uninstall
命令。正如install
命令,它使用一个或者多个格式为group:artifact:version
artifact坐标的集合,如下示例所示:
$ spring uninstall com.example:spring-boot-cli-extension:1.0.0.RELEASE
它卸载了通过你提供的坐标和他们依赖识别的artifact。
要卸载所有额外的依赖项,你可以使用--all
选项,如下示例所示:
$ spring uninstall --all
Spring Framework 4.0 对beans{}
“DSL”(从Grails借来的)有原生的支持,你可以通过使用相同的格式在Groovy应用程序脚本中嵌入bean定义。有时候这是一个好的方式来包含外部特性,比如中间件声明,如下示例所示:
@Configuration(proxyBeanMethods = false)
class Application implements CommandLineRunner {
@Autowired
SharedService service
@Override
void run(String... args) {
println service.message
}
}
import my.company.SharedService
beans {
service(SharedService) {
message = "Hello World"
}
}
你可以将类的声明与beans{}
混合在同一个文件中,只要他们保持在顶级。或者,如果你愿意,你可以将bean DSL放在一个单独的文件中。
Spring Boot CLI使用Maven Resolver,Maven的依赖解析引擎,来解析依赖项。CLI利用在~/.me/setting.xml
中发现的Maven配置配置Maven解析器。CLI支持以下配置设置:
请查看Maven的设置文档了解进一步信息。
在Github仓库有一些groovy 脚本的示例,你可以用来尝试Spring Boot CLI。源码中还有大量的Javadoc。
如果你发现你达到了CLI工具的限制,你可能想看下转换你的应用程序为完整的Gradle或者Maven构建的“Groovy项目”。下一章节涵盖Spring Boot的“构建工具插件”,可以在Gradle或者Maven中使用它。
Spring Boot为Maven和Gradel提供构建工具插件。插件提供大量的特性,包括可执行jar文件打包。这章节提供这两个插件更多细节,以及一些帮助,如果你需要扩展一个不支持的构建系统。如果你只是想入门,你可能想要阅读来自“使用Spring Boot开发”的“构建系统”
Spring Boot Maven插件在Maven中提供Spring Boot支持,让你打包可执行jar或者war归档并就地运行应用程序。要使用它,你必须使用Maven 3.2(或者更晚版本)。
请查看插件文档了解更多:
Spring Boot Gradle插件在Gradle中提供Spring Boot支持,让你打包可执行jar文件或war归档,运行Spring Boot应用程序,并使用通过spring-boot-dependencies
提供的依赖项。它要求Gradle 7.x(7.4或者更晚)。
请查看插件文档了解更多:
Spring Boot AntLib模块对Apache Ant提供基本的Spring Boot支持。你可以使用这个模块创建可执行jar。要使用这个模块,你需要在你的build.xml
声明一个额外的spring-boot
命名空间,如下示例所示:
<project xmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:spring-boot="antlib:org.springframework.boot.ant"
name="myapp" default="build">
...
project>
你需要记住使用-lib
选项启动Ant,如下示例所示:
$ ant -lib <directory containing spring-boot-antlib-3.0.0-SNAPSHOT.jar>
"使用Spring Boot"章节包括一个更完整的使用Apache Ant和
spring-boot-antlib
示例.
一旦spring-boot-antlib
命名空间已经声明,以下额外的任务是可用的:
你可以使用exejar
任务创建Spring Boot可执行jar.通过任务支持以下属性
属性 | 描述 | 要求 |
---|---|---|
destfile |
创建目的jar文件 | 是的 |
classes |
Java类文件根目录 | 是的 |
start-class |
要运行的主要应用程序 | 否(默认是找到的第一个声明main 方法的类) |
以下内嵌的元素可以与Task一起使用:
元素 | 描述 |
---|---|
resources |
一个或者多个Resource Collections, 描述的一组被添加到创建的jar文件内容的Resource |
lib |
一个或者多个Resource Collections 应该被加到一组jar类库,组成运行时应用程序的依赖类路径 |
这部分展示了Ant Task的两个示例:
指定启动类
<spring-boot:exejar destfile="target/my-application.jar"
classes="target/classes" start-class="com.example.MyApplication">
<resources>
<fileset dir="src/main/resources" />
resources>
<lib>
<fileset dir="lib" />
lib>
spring-boot:exejar>
检测启动类
<exejar destfile="target/my-application.jar" classes="target/classes">
<lib>
<fileset dir="lib" />
lib>
exejar>
findmainclass
任务被exejar
内部使用来定位声明main
的类。如果必须,你也可以直接在你的构建中使用这个任务。支持以下属性:
属性 | 描述 | 要求 |
---|---|---|
classesroot |
Java类文件的根目录 | 是的(除非指定mainclass ) |
mainclass |
可以用来缩短main 类搜索 |
否 |
property |
Ant属性,应该使用结果设置 | 否(如果没有指定,结果将被记录) |
这部分包含使用findmainclass
的三个示例:
查找和记录
<findmainclass classesroot="target/classes" />
查找和设置
<findmainclass classesroot="target/classes" property="main-class" />
覆盖和设置
<findmainclass mainclass="com.example.MainClass" property="main-class" />
如果你想使用一个构建系统除了Maven,Gradle,或者Ant,你可能需要开发你自己的插件。可执行jar需要遵循特定的格式和某个条目需要以未压缩形式书写(请查看在附录中可执行jar格式章节了解更多详情)。
Spring Boot Maven和Gradle插件两者利用spring-boot-loader-tools
来实际生成jar。如果你需要,你可以直接使用这个类库。
要重新打包现有的归档以便它变为一个自包含的可执行归档,使用org.springframework.boot.loader.tools.Repackager
。Repackage
类使用一个单构造器参数,他引用一个现有jar或者war归档。使用两个可用的repackage()
方法的其中一个要么替换原始文件要么写入一个新的目标。在他执行之前在repackager上可以配置多种设置。
当重新打包一个归档,你可以通过使用org.springframework.boot.loader.tools.Libraries
接口包含对依赖文件的引用。这里,我们不提供任何具体的Libraries
的实现因为他们通常是特定于构建系统。
如果你没有使用Repackager.setMainClass()
来指定一个主类,repacker使用ASM来读取类文件并尝试查找一个合适的带有public static void main(String[] args)
方法的类。如果超过一个候选被发现则抛出一个异常。
以下示例展示一个典型的重新打包实现:
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.springframework.boot.loader.tools.Library;
import org.springframework.boot.loader.tools.LibraryCallback;
import org.springframework.boot.loader.tools.LibraryScope;
import org.springframework.boot.loader.tools.Repackager;
public class MyBuildTool {
public void build() throws IOException {
File sourceJarFile = ...
Repackager repackager = new Repackager(sourceJarFile);
repackager.setBackupSource(false);
repackager.repackage(this::getLibraries);
}
private void getLibraries(LibraryCallback callback) throws IOException {
// Build system specific implementation, callback for each dependency
for (File nestedJar : getCompileScopeJars()) {
callback.library(new Library(nestedJar, LibraryScope.COMPILE));
}
// ...
}
private List<File> getCompileScopeJars() {
return ...
}
}
如果你对构建工具插件如何工作的感兴趣,你可以看下在Githubspring-boot-tools
模块。更多的可执行jar的技术格式详情可以在附录中找到。
如果你有特别的构建相关的问题,请查看“如何做”指南。