文章目录
- Spring Boot Application
- 嵌入式Web服务器
- 配置Web服务器
- 使用Spring Security进行测试
- Jersey
- Http Clients
- Logging
- Data存取
- 配置自定义DataSource
- 配置两个DataSource
- 使用Spring Data Repositories
- 将@Entity定义与Spring 配置分开
- 配置JPA属性
- 配置Hibernate命名策略
- 配置Hibernate二级缓存
- 在Hibernate组件中使用依赖注入
- 使用自定义EntityManagerFactory
- 使用两个`EntityManager`
- 使用传统`persistence.xml`文件
- 使用Spring Data Jpa和Mongo Repositories
- 定制Spring Data的支持
- 将Spring Data Repository 公开为Rest Endpoints
- 配置JPA使用的组件
- Database初始化
- Messaging
- Batch Applications
- Actuator
- Security
- 热更新
- Build
- 传统部署
Spring Boot Application
###创建FailureAnalyzer
FailureAnalyzer
是拦截启动时将异常转化为人类可读消息的一种方法
- 实现
AbstractFailureAnalyzer
扩展 - 注册
org.springframework.boot.diagnostics.FailureAnalyzer=\ com.example.ProjectConstraintViolationFailureAnalyzer
###自动配置故障排除
- 通过conditions端点以JSON形式呈现报告
- 通过查看源代码和Javadoc
- 查找被调用的类
*AutoConfiguration
并阅读其源代码。特别注意@Conditional*
注释,以了解它们启用了哪些功能以及何时启用。添加–debug到命令行或系统属性-Ddebug以在控制台上获取在您的应用中做出的所有自动配置决策的日志。在启用了执行器的运行应用程序中,查看conditions端点(/actuator/conditions或等效的JMX)以获取相同信息。 - 查找属于
@ConfigurationProperties
(例如ServerProperties)的类,然后从中读取可用的外部配置选项。该@ConfigurationProperties注释具有一个name充当前缀外部性能属性。因此,ServerProperties拥有prefix="server"和它的配置性能server.port,server.address以及其他。在启用了执行器的运行应用程序中,查看configprops端点。 - 寻找对
bind
方法的使用,以一种轻松的方式Binder将配置值明确地拉出Environment。它通常与前缀一起使用。 - 查找
@Value
直接绑定到的注释Environment。 - 寻找
@ConditionalOnExpression
注释以响应SpEL表达式来打开或关闭功能,这些注释通常使用从中解析的占位符进行评估Environment。
- 查找被调用的类
启动之前自定义环境或ApplicationContext
SpringApplication
具有被应用于自定义context或环境的ApplicationListeners
和ApplicationContextInitializers
- 注册自定义项
- 在运行之前,调用
SpringApplication
的addListeners
和addInitializers
方法通过对每个应用程序编程 - 通过设置
context.initializer.classes
和context.listener.classes
属性,以声明方式针对每个应用程序 - 通过添加
META-INF/spring.factories
和打包jar文件声明性地对于所有应用程序,这些文件被应用程序用作库
- 在运行之前,调用
- 自定义环境
org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor
- 从类路径中加载YAML配置文件
public class EnvironmentPostProcessorExample implements EnvironmentPostProcessor { private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { Resource path = new ClassPathResource("com/example/myapp/config.yml"); PropertySource<?> propertySource = loadYaml(path); environment.getPropertySources().addLast(propertySource); } private PropertySource<?> loadYaml(Resource path) { if (!path.exists()) { throw new IllegalArgumentException("Resource " + path + " does not exist"); } try { return this.loader.load("custom-resource", path).get(0); } catch (IOException ex) { throw new IllegalStateException("Failed to load yaml configuration from " + path, ex); } } }
建立ApplicationContext层次结构
使用ApplicationBuilder
类创建ApplicationContext
层次结构
创建非Web应用程序
使用SpringApplication
功能,根据是否需要Web Application确定更改ApplicationContext
##属性和配置
在构建时自动扩展属性
使用现有的构建配置自动扩展它们,而不是对项目的构建配置中指定某些属性进行硬编码
- 使用Maven自动扩展属性
- 如果使用
spring-boot-starter-parent
,使用@..@
占位符引用
在app.encoding=@project.build.sourceEncoding@ app.java.version=@java.version@
pom.xml build
元素中配置
此外需要在plugins元素中配置<resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources>
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.7</version> <configuration> <delimiters> <delimiter>@</delimiter> </delimiters> <useDefaultDelimiters>false</useDefaultDelimiters> </configuration> </plugin>
- 如果使用
- 使用Gradle扩展属性
SpringApplication外部配置
在配置文件中添加
spring.main.web-application-type=none
spring.main.banner-mode=off
- 外部配置定义的属性会覆盖JavaAPI中得值
外部配置new SpringApplicationBuilder() .bannerMode(Banner.Mode.OFF) .sources(demo.MyApp.class) .run(args);
实际应用中使用外部配置spring.main.sources=com.acme.Config,com.acme.ExtraConfig spring.main.banner-mode=console
###更改应用程序外部属性的位置
默认情况下,不同源的属性以环境定义的顺序添加到Spring中 - 修改位置
- 添加
@PropertySource
- 配置属性
spring.config.name
,默认为application作为文件得根路径 - 配置属性
spring.config.location
:要加载的文件,可以通过系统属性、环境变量或命令行覆盖
- 添加
使用命令行参数
如在命令行上配置--port=9000
而不是--server.port=9000
- 使用占位符
server.port=${port:8080}
对外部属性使用YAML
YAML是JSON的超级,用于分层格式存储外部属性
spring:
application:
name: cruncher
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost/test
server:
port: 9000
创建application.yaml
放置类路径的根目录下
- 配置
spring.application.name=cruncher spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost/test server.port=9000
设置Active Spring Profiles
使用-D
指定打包环境
java -jar -D spring.profiles.active=production demo-0.0.1-SNAPSHOT.jar
在配置文件中指定
spring.profiles.active=production
根据环境更改配置
YAML文件实际上是由---
行分割的文档序列,每个文档分别解析为展平图
- 如果YAML文档包含
spring.profiles
密钥,则将配置文件值(以逗号分隔的配置文件列表)输入到SpringEnvironment.acceptsProfiles()
方法中。如果这些配置文件中的任何一个处于活动状态,那么该文档将包含在最终合并中(否则,它不会包含在此文档中)server: port: 9000 --- spring: profiles: development server: port: 9001 --- spring: profiles: production server: port: 0
外部属性的内置选项
Spring Boot在运行时将外部属性绑定到应用程序中。使用@ConfigurationProperties
和@Value
以及偶尔使用Binder
绑定值
嵌入式Web服务器
###使用其他服务器
- 默认服务器
- spring-boot-starter-web默认包含tomcat
- webflux默认包含reactor-netty
- 配除Tomcat
<properties> <servlet-api.version>3.1.0</servlet-api.version> </properties> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <!-- Exclude the Tomcat dependency --> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <!-- Use Jetty instead --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency>
禁用web服务器
spring.main.web-application-type=none
更改Http端口
默认8080,配置server.port
修改端口,server.port=0扫描可用端口
在运行时发现HTTP端口
从日志输出或ServletWebServerApplicationContext
通过其WebServer端口访问服务器正在运行的端口
- 通过
@LocalServerPort
将实际端口注入到测试中@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) public class MyWebIntegrationTests { @Autowired ServletWebServerApplicationContext server; @LocalServerPort int port; // ... }
启动Http影响压缩
server.compression.enabled=true
- 通过
server.compression.min-response-size
设置压缩字节,默认至少2018个字节 - 通过
server.compression.mime-types
设置内容类型,如text/html
配置SSL
server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=another-secret
配置Http/2
使用erver.http2.enabled
配置启用http/2支持
配置Web服务器
- 适用于带有
spring-boot-starter-web
的Tomcat@Component public class MyTomcatWebServerCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> { @Override public void customize(TomcatServletWebServerFactory factory) { // customize the factory here } }
Server | Servlet stack | Reactive stack |
---|---|---|
Tomcat | TomcatServletWebServerFactory | TomcatReactiveWebServerFactory |
Jetty | JettyServletWebServerFactory | JettyReactiveWebServerFactory |
Undertow | UndertowServletWebServerFactory | UndertowReactiveWebServerFactory |
Reactor | N/A | NettyReactiveWebServerFactory |
###将Servlet、Filters、Listeners添加到应用程序
- 两种方法
- 使用Spring Bean添加Servlet、Filters、Listeners
- 使用类路径扫描
- 禁用Servlet或过滤器的注册
@Bean public FilterRegistrationBean registration(MyFilter filter) { FilterRegistrationBean registration = new FilterRegistrationBean(filter); registration.setEnabled(false); return registration; }
配置访问日志
server.tomcat.basedir=my-tomcat
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms)
在前端代理服务器后面运行
如果代理添加常规X-Forwarded-For
和X-Forwarded-Proto
标头(大多数代理服务器都这样做),则绝对链接应正确呈现,只要application.properties中server.forward-headers-strategy
将设置为NATIVE
或FRAMEWORK
- 自定义Tomcat代理
- 配置header
forwarded
server.tomcat.remote-ip-header=x-your-remote-ip-header server.tomcat.protocol-header=x-your-protocol-header
- 添加自定义匹配
server.tomcat.internal-proxies=192\\.168\\.\\d{1,3}\\.\\d{1,3}
- 配置header
使用Tomcat启用Multiple Connectors
向TomcatServletWebServerFactory添加org.apache.catalina.connector.Connector
允许多个Connectors,包括HTTP和HTTPS连接器
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addAdditionalTomcatConnectors(createSslConnector());
return tomcat;
}
private Connector createSslConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
try {
File keystore = new ClassPathResource("keystore").getFile();
File truststore = new ClassPathResource("keystore").getFile();
connector.setScheme("https");
connector.setSecure(true);
connector.setPort(8443);
protocol.setSSLEnabled(true);
protocol.setKeystoreFile(keystore.getAbsolutePath());
protocol.setKeystorePass("changeit");
protocol.setTruststoreFile(truststore.getAbsolutePath());
protocol.setTruststorePass("changeit");
protocol.setKeyAlias("apitester");
return connector;
}
catch (IOException ex) {
throw new IllegalStateException("can't access keystore: [" + "keystore"
+ "] or truststore: [" + "keystore" + "]", ex);
}
}
使用Tomcat LegacyCookieProcessor
默认情况,嵌入式Tomcat不支持Cookie格式的"Version 0",会出现错误
java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value
考虑更新为服务Cookie规范或者将Tomcat配置为使用LegacyCookieProcessor
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> cookieProcessorCustomizer() {
return (factory) -> factory
.addContextCustomizers((context) -> context.setCookieProcessor(new LegacyCookieProcessor()));
}
启用Tomcat的MBean注册表
默认是禁用的,减少Tomcat内容占用
server.tomcat.mbeanregistry.enabled=true
使用Undertow启用多个监听器
@Bean
public UndertowServletWebServerFactory servletWebServerFactory() {
UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
@Override
public void customize(Builder builder) {
builder.addHttpListener(8080, "0.0.0.0");
}
});
return factory;
}
@ServerEndPoint创建WebSocket端点
在Spring Boot应用程序中使用的嵌入式容器使用@ServerEndpoint
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
##Spring MVC
编写JOSN REST服务
只要Jackson2在类路径上,SpringBoot中的所有@RestController
默认都是JSON响应
@RestController
public class MyController {
@RequestMapping("/thing")
public MyThing thing() {
return new MyThing();
}
}
编写XML REST服务
- 添加依赖
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency>
- 如果无法使用Jackson的XML扩展可以使用JAXB,添加
@XmlRootElement
注释
较新的Java版本添加依赖@XmlRootElement public class MyThing { private String name; // .. getters and setters }
<dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> </dependency>
自定义Jackson ObjectMapper
Spring MVC使用HttpMessageConverters协商HTTP交换中的内容转换,如果已添加Jackson,已获得所提供的默认转换器Jackson2ObjectMapperBuilder
自定义@ResponseBody渲染
Spring通过HttpMessageConverters呈现@ResponseBody的响应
处理分段文件上传
java.servlet.http.Part
API支持上传文件,默认情况Spring Boot用单个请求配置为多个文件
- 作为参数接收时,
MulitipartFile
支持
关闭Spring MVC DDispatcherServlet
默认情况下,所有内容从根目录提供。关闭默认需要自定义
- 映射地址
spring.mvc.servlet.path=/acme
关闭默认的MVC配置
在@Configuration
上添加@EnableWebMVC
注解
自定义ViewResolvers
- ViewResolvers是Spring MVC的核心组件,将
@Controller
视图名称转为实际的View实现 - 主要用于UI应用程序而不是REST风格的服务
WebMvcAutoConfiguration
添加的ViewResolver
- 名为“defaultViewResolver”的
InternalResourceViewResolver
.查找可以通过使用DefaultServlet
渲染的物理资源(包括静态资源和JSP页面) - 名为“beanNameViewResolver"的
BeanNameViewResolver
.是视图解析链的有用成员,可以拾取与被解析View
名称相同的所有bean - 当当时类型为视图 View类型的bean时添加名称”viewResolver“的
ContentNegotiatingViewResolver
.是"master"解析器,委派给其他所有的解析器,并查找与客户端发送的"Accept"头部信息匹配的内容 - 使用Themeleaf,需要名为”thymeleafViewResolver“的
ThymeleafViewResolver
.通过在视图名称前后加上前缀和后缀查找资源。默认前缀为"classpath:/templates",后缀为".html"
- 名为“defaultViewResolver”的
使用Spring Security进行测试
Spring Security提供了以特定身份运行测试的支持
@Test
@WithMockUser(roles="ADMIN")
public void requestProtectedUrlWithUser() throws Exception {
mvc
.perform(get("/"))
...
}
Jersey
使用Spring Security保护Jersey endpoints
在ResourceConfig
设置jersey.config.server.response.setStatusOverSendError
设置为true
@Component
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(Endpoint.class);
setProperties(Collections.singletonMap("jersey.config.server.response.setStatusOverSendError", true));
}
}
与另一个Web框架使用Jersey
首先通过配置spring.jersey.type
应用程序属性配置为filter
,以将Jersey配置为使用过滤器而不是Servlet,其次,配置ResourceConfig
请求以转发可能导致404的请求
@Component
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(Endpoint.class);
property(ServletProperties.FILTER_FORWARD_ON_404, true);
}
}
Http Clients
配置RestTemplate使用代理
static class ProxyCustomizer implements RestTemplateCustomizer {
@Override
public void customize(RestTemplate restTemplate) {
HttpHost proxy = new HttpHost("proxy.example.com");
HttpClient httpClient = HttpClientBuilder.create().setRoutePlanner(new DefaultProxyRoutePlanner(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);
}
}).build();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
}
}
配置使用基于Reactor Netty 的WebClient的TcpClient
当Reactor Netty在类路径上时,将自动配置基于Reactor Netty 的WebClient。
要自定义客户端对网络连接的处理,需提供ClientHttpConnector
Bean
@Bean
ClientHttpConnector clientHttpConnector(ReactorResourceFactory resourceFactory) {
TcpClient tcpClient = TcpClient.create(resourceFactory.getConnectionProvider())
.runOn(resourceFactory.getLoopResources()).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 60000)
.doOnConnected((connection) -> connection.addHandlerLast(new ReadTimeoutHandler(60)));
return new ReactorClientHttpConnector(HttpClient.from(tcpClient));
}
Logging
添加依赖项会添加日志记录
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
设置级别
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR
文件位置
logging.file.name = ****
默认情况下使用logback.xml
配置
配置Logback for Logging
自定义配置需要在application.properties
添加标准的Logback配置文件
- 标准
logback.xml
配置<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/defaults.xml"/> <include resource="org/springframework/boot/logging/logback/console-appender.xml" /> <root level="INFO"> <appender-ref ref="CONSOLE" /> </root> <logger name="org.springframework.web" level="DEBUG"/> </configuration>
- System属性
- ${PID}: 当前进程ID
- ${LOG_FILE}: 是否在Boot的外部配置中设置的
logging.file.path
- ${LOG_PATH}: 是否在Boot的外部配置种设置的
logging.file.path
- ${LOG_EXCEPTION_CONVERSTON_WORD}:是否在Boot的外部配置中设置的
logging.exception-conversion-word
- ${ROLLING_FILE_NAME_PATTERN}:是否在Boot的外部配置中设置的
logging.pattern.rolling-file-name
- System属性
配置仅文件输出的Logback
禁用控制台日志记录并且仅将输入写入文件,需要导入file-appender.xml
但不导入conso-appender.xml
的logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
<include resource="org/springframework/boot/logging/logback/file-appender.xml" />
<root level="INFO">
<appender-ref ref="FILE" />
</root>
</configuration>
添加logging.file.name到application.properties
logging.file.name=myapplication.log
配置Log4j进行日志记录
如果Spring Boot在类路径中,支持Log4j2进行日志记录配置。
- 使用Starters组装依赖项,必须排除Logback,然后改为 include log4j2.
- 不使用Starters,除了log4j2之外,需要提供spring-jcl
- 在Maven种设置启动器
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency>
使用YAML或JSON配置Log4j2
-
依赖项及文件格式
格式 依赖项 文件名 YAML com.fasterxml.jackson.core:jackson-databind+
com.fasterxml.jackson.dataformat:jackson-dataformat-yamllog4j2.yaml
log4j2.ymlJSON com.fasterxml.jackson.core:jackson-databind log4j3.json
log4j2.json
Data存取
配置自定义DataSource
- 在Bean种定义数据源
@Bean
@ConfigurationProperties(prefix="app.datasource")
public DataSource dataSource() {
return new FancyDataSource();
}
- 通过设置属性定义数据源
app.datasource.url=jdbc:h2:mem:mydb
app.datasource.username=sa
app.datasource.pool-size=30
- 使用
DataSourceBuilder
创建数据源
@Bean
@ConfigurationProperties("app.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
- 通过设置属性定义JDBC数据源
app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.pool-size=30
为了兼容Hikari没有url属性但有jdbcUrl属性
app.datasource.jdbc-url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.maximum-pool-size=30
- 创建具有
DataSourceBuilder
的HikarDataSource
@Bean
@ConfigurationProperties("app.datasource")
public HikariDataSource dataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
配置两个DataSource
配置多个DataSource,必须将其中一个DataSource
实例标记为@Primary
- 创建自定义
DataSource
,自动配置将退出。与自定配置在主数据源上提供功能完全相同功能集示例:@Bean @Primary @ConfigurationProperties("app.datasource.first") public DataSourceProperties firstDataSourceProperties() { return new DataSourceProperties(); } @Bean @Primary @ConfigurationProperties("app.datasource.first.configuration") public HikariDataSource firstDataSource() { return firstDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build(); } @Bean @ConfigurationProperties("app.datasource.second") public BasicDataSource secondDataSource() { return DataSourceBuilder.create().type(BasicDataSource.class).build(); }
多个数据源必须进行高级定制。
app.datasource.first.url=jdbc:mysql://localhost/first
app.datasource.first.username=dbuser
app.datasource.first.password=dbpass
app.datasource.first.configuration.maximum-pool-size=30
app.datasource.second.url=jdbc:mysql://localhost/second
app.datasource.second.username=dbuser
app.datasource.second.password=dbpass
app.datasource.second.max-total=30
将相同概念应用于辅助服务器DataSource
app.datasource.first.url=jdbc:mysql://localhost/first
app.datasource.first.username=dbuser
app.datasource.first.password=dbpass
app.datasource.first.configuration.maximum-pool-size=30
app.datasource.second.url=jdbc:mysql://localhost/second
app.datasource.second.username=dbuser
app.datasource.second.password=dbpass
app.datasource.second.max-total=30
使用Spring Data Repositories
Spring Data 可以创建各种类型的@Reoisutory
接口的实现.只要@Repositories和@EnableAutoConfiguration包含在同一包中,SpringBoot就会处理所有操作
将@Entity定义与Spring 配置分开
Spring Boot会用过@EnableAutoConfiguration
发现的内容尝试猜测定义的@Entity
的位置。使用@EntityScan
注释获取更多操作
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
@EntityScan(basePackageClasses=City.class)
public class Application {
}
配置JPA属性
Spring Data Jpa提供了一些vendor-independent配置选项(例如用于SQL日志记录),并且Spring Boot将这些选项作为了外部配置属性公开
配置Hibernate命名策略
Hibernate使用两种命名策略将名称从对象模型映射到相应的数据库名称。通过设置pring.jpa.hibernate.naming.physical-strategy
和spring.jpa.hibernate.naming.implicit-strategy
属性配置物理和隐式策略实现的标准类名。
如果对应Bean可用,Hibernate自动配置为使用它们
默认Spring Boot使用配置物理命名策略SpringPhysicalNamingStrategy
- 使用Hibernate5默认设置
或配置Beanspring.jpa.hibernate.naming.physical-strategy = org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
@Bean public PhysicalNamingStrategy physicalNamingStrategy() { return new PhysicalNamingStrategyStandardImpl(); }
配置Hibernate二级缓存
- 使用JCache,添加
org.hibernate:hibernate-jcache
依赖,添加HibernatePropertiesCustomizer
Bean@Configuration(proxyBeanMethods = false) public class HibernateSecondLevelCacheExample { @Bean public HibernatePropertiesCustomizer hibernateSecondLevelCacheCustomizer(JCacheCacheManager cacheManager) { return (properties) -> properties.put(ConfigSettings.CACHE_MANAGER, cacheManager.getCacheManager()); } }
在Hibernate组件中使用依赖注入
默认情况Spring Boot通过实现注册一个使用BeanFactory的BeanContainer实现以实现转换器和实体监听器可以使用常规依赖项注入。
也可以通过注册HibernatePropertiesCustomizer
删除或更改hinernate。resources.beans.container
属性禁用或调整此行为
使用自定义EntityManagerFactory
添加entityManagerFactory
的@Bean
完全控制EntityManagerFactory
的配置
使用两个EntityManager
即使默认设置EntityManagerFactory
工作正常,也需要定义一个新的配置,否则,该类型的第二个bean的存在将关闭默认值
- 直接从Spring ORM操作
// add two data sources configured as above @Bean public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory( EntityManagerFactoryBuilder builder) { return builder .dataSource(customerDataSource()) .packages(Customer.class) .persistenceUnit("customers") .build(); } @Bean public LocalContainerEntityManagerFactoryBean orderEntityManagerFactory( EntityManagerFactoryBuilder builder) { return builder .dataSource(orderDataSource()) .packages(Order.class) .persistenceUnit("orders") .build(); }
- 使用Spring Data,配置
@EnableJpaRepositories
@Configuration(proxyBeanMethods = false) @EnableJpaRepositories(basePackageClasses = Customer.class, entityManagerFactoryRef = "customerEntityManagerFactory") public class CustomerConfiguration { ... } @Configuration(proxyBeanMethods = false) @EnableJpaRepositories(basePackageClasses = Order.class, entityManagerFactoryRef = "orderEntityManagerFactory") public class OrderConfiguration { ... }
使用传统persistence.xml
文件
默认情况下,Spring Boot不会搜索或使用persitence.xml文件,需要自定义LocalEntityManagerFactoryBean
并在其中设置持久性单元名称
使用Spring Data Jpa和Mongo Repositories
Spring Data Jpa和Spring Data Mongo默认会自动创建Repository实现。需要使用@EnableJpaRepositories
和@EnableMongoRepositories
注释兵提供Repository
接口的位置
定制Spring Data的支持
spring.data.web
命名空间,Spring Data REST 使用spring.data.rest
命名空间
将Spring Data Repository 公开为Rest Endpoints
Spring Boot 公开了属性用于自定义RepositoryRestConfiguration。使用RepositoryRestConfigurer Bean提供其他定制
配置JPA使用的组件
配置JPA使用的组件之前,确保在JPA之前初始化该组件。
- 自定义配置组件
/** * {@link EntityManagerFactoryDependsOnPostProcessor} that ensures that * {@link EntityManagerFactory} beans depend on the {@code elasticsearchClient} bean. */ @Component static class ElasticsearchEntityManagerFactoryDependsOnPostProcessor extends EntityManagerFactoryDependsOnPostProcessor { ElasticsearchEntityManagerFactoryDependsOnPostProcessor() { super("elasticsearchClient"); } }
Database初始化
使用不同的方式初始化SQL数据库,具体取决于堆栈是什么
使用JPA初始化数据库
JPA具有用于DDL生成的功能,可以将其设置为在启动时针对数据库运行。通过外部属性控制
- spring.data.generate-ddl:布尔值,打开过关闭该功能,并且与供应商无关
- spring.jpa.hibernate.ddl-auto:枚举,是一种Hibernate功能,更精细的控制行为
使用Hibernate初始化数据库
设置spring.jpa.hibernate.ddl-auto
:none
、validate
、upodate
、create
、create-drop
。默认create-drop
初始化DataBase
Spring Boot 自动创建schema(DDL脚本)并对其和DataSource进行初始化。从根路径加载sql对应文件
初始化Spring Batch DataSource
Spring Batch随大多数流行的数据库平台预包装了SQL初始化脚本,并可以检测数据库类型且在启动时执行这些脚本。
- 启动
spring.batch.initialize-schema =always
使用高级数据库迁移工具
在启动时执行Flyway数据库迁移
添加org.flywaydb:flyway-core
依赖
在启动时执行Liquibase数据库迁移
添加org.liquibase:liquibase-core
Messaging
禁用Transacted JMS Session
如果JMS代理不支持事务处理会话,必须完全禁用事务支持
- 禁用事务性会话
@Bean public DefaultJmsListenerContainerFactory jmsListenerContainerFactory( ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer) { DefaultJmsListenerContainerFactory listenerFactory = new DefaultJmsListenerContainerFactory(); configurer.configure(listenerFactory, connectionFactory); listenerFactory.setTransactionManager(null); listenerFactory.setSessionTransacted(false); return listenerFactory; }
Batch Applications
在启动时执行Spring Batch Jobs
在上下文中的某个位置添加@EnableBatchProcessing
可以启用Spring Batch配置
Actuator
更改Actuator Endpoints的Http端口或地址
在独立应用程序中,Actuator HTTP端口默认于主HTTP端口相同,设置management.server.port
属性使应用程序在其他端口上侦听。要侦听完全不同的网络地址,设置属性managerment.server.address
自定义"whitelabel"错误页面
通常使用View
解析error
名称或@Controller
处理/error
路径
Sanitize sensible values
Spring Boot会对一些密钥使用明智的默认设置,如:对以单词password、secret、key或token结尾的密钥进行处理,也可以改用正则表达式,如将*credentials.*
将单词credentials
保留为键一部分的任何键
Security
关闭Spring Boot Security配置
如果定义了一个@Configuration
的WebSecurityConfigurerAdapter
,将默认关闭Spring Boot默认的Webapp安全设置
更改UserDetailsService并添加用户账户
如果提供了AuthenticationManager
、AuthenticationProvider
或UserDetailsService
类型的@Bean
,默认的InMemoryUserDetailsManager
类型的@Bean
不创建
在代理服务器上运行时启用HTTPS
对于所有应用程序而言,确保所有主要端点仅可通过HTTPS进行访问都是一项重要的工作。
- 标准行为为由某些请求标头(
x-forwarded-for
和x-forwarded-proto
)的存在或不存在决定 - 添加属性打开valve
server.tomcat.remote-ip-header=x-forwarded-for server.tomcat.protocol-header=x-forwarded-proto
- Spring Security配置为要求所有请求使用安全通道
@Configuration(proxyBeanMethods = false) public class SslWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { // Customize the application security http.requiresChannel().anyRequest().requiresSecure(); } }
热更新
重新加载静态内容
推荐使用spring-boot-devtools
,因为提供了开发时的一些功能,如对快速应用程序重新启动和LiveReload的支持以及何止的开发时配置(例如模板缓存)
重新加载默认,无需重新启动容器
- Thymeleaf模板
- 设置
spring.themeleaf,cache = false
- 设置
- FreeMarker模板
- 设置
spring.freemarker.cache = false
- 设置
- Groovy模板
- 设置
spring.groovy.template.cache=false
- 设置
快速启用重启
spring-boot-devtools
模块包括对应用程序自动重启的支持
重新加载Java类而不重新启动容器
干净重新加载更改的Java类
Build
生成构建信息
- 使用Maven生成构建信息,为
build-info
目标添加执行<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.2.1.RELEASE</version> <executions> <execution> <goals> <goal>build-info</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
生成Git信息
Maven用户,添加与配置创建生成git.properties
<build>
<plugins>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
</plugin>
</plugins>
</build>
自定义依赖版本
添加自定义版本号
<properties>
<slf4j.version>1.7.5<slf4j.version>
</properties>
使用Maven创建可执行JAR
spring-boot-maven-plugin
用于创建可执行的"fat"jar。
- 声明插件
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
- 不适用父POM,也可以使用该插件,但是必须添加
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.2.1.RELEASE</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
使用SpringBoot应用程序作为依赖项
Spring Boot默认不作为依赖项,通常方法是将公用的代码以到单独的模块中,然后作为依赖项
- 为了产生两个工作,一个用作依赖项,一个可以执行,必须指定分类器.
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <classifier>exec</classifier> </configuration> </plugin> </plugins> </build>
运行可执行Jar时提取特定的库
可执行Jar中的大多数嵌套库不需要解压即可运行,但是某些库会有问题。
- 指示使用Maven插件将JRuby标记为解包
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <requiresUnpack> <dependency> <groupId>org.jruby</groupId> <artifactId>jruby-complete</artifactId> </dependency> </requiresUnpack> </configuration> </plugin> </plugins> </build>
创建带有排除项的不可执行的Jar
- 排除
application.yml
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <artifactId>maven-jar-plugin</artifactId> <executions> <execution> <id>lib</id> <phase>package</phase> <goals> <goal>jar</goal> </goals> <configuration> <classifier>lib</classifier> <excludes> <exclude>application.yml</exclude> </excludes> </configuration> </execution> </executions> </plugin> </plugins> </build>
远程调试以Maven开头的Spring Boot应用程序
将远程调试器附加到使用Maven启动的Spring Boot应用程序,可以使用maven plugin的jvmArguments
属性
在不使用Ant的情况下从Ant构建可执行存档spring-boot-antlib
- 使用
spring-boot-antlib
模块操作- 将类和资源文件打包在
BOOT-INF/classes
目录中 - 在
BOOT-INF/lib
jar或BOOT-INF/lib
war的嵌套目录中添加运行时依赖项。注意:不要压缩存档中的条目 - 在
BOOT-INF/lib-provided
jar或WEB-INF/lib-provided
war 的嵌套目录中添加(嵌入式容器)依赖项。注意:不要压缩存档中的条目。 - 添加
spring-boot-loader
添加到存档的根目录
= 使用适当的启动器作为清单中的Main-Class
属性,并指定其所需的其他属性作为清单条目
- 将类和资源文件打包在
- And构建归档文档
<target name="build" depends="compile"> <jar destfile="target/${ant.project.name}-${spring-boot.version}.jar" compress="false"> <mappedresources> <fileset dir="target/classes" /> <globmapper from="*" to="BOOT-INF/classes/*"/> </mappedresources> <mappedresources> <fileset dir="src/main/resources" erroronmissingdir="false"/> <globmapper from="*" to="BOOT-INF/classes/*"/> </mappedresources> <mappedresources> <fileset dir="${lib.dir}/runtime" /> <globmapper from="*" to="BOOT-INF/lib/*"/> </mappedresources> <zipfileset src="${lib.dir}/loader/spring-boot-loader-jar-${spring-boot.version}.jar" /> <manifest> <attribute name="Main-Class" value="org.springframework.boot.loader.JarLauncher" /> <attribute name="Start-Class" value="${start-class}" /> </manifest> </jar> </target>
传统部署
创建可部署的War包
- 第一步:是提供一个
SpringBootServletInitializer
子类并覆盖configure
方法.这样是利用了Spring Framework的Servlet3.0支持,并允许在由Servlet容器启动应用程序时对其进行配置.
通常。主类更新为集成SpringBootServletInitializer
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 第二步:更新构建配置,以使项目生成war文件而不是jar文件
<packaging>war</packaging>
- 第三步:确保嵌入式servlet容器不干扰war文件所部署到的servlet容器
<dependencies> <!-- … --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <!-- … --> </dependencies>
将现有应用程序转换为Spring Boot
- 转换过程
- 扩展
SpringBootServletIntializer
并添加@SpringBootApplication
注释创建war包
@SpringBootApplication public class Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { // Customize the application or call application.sources(...) to add sources // Since our example is itself a @Configuration class (via @SpringBootApplication) // we actually don't need to override this method. return application; } }
- 将静态资源移动到根目录
/public
或/static
或/resources
或/META-INF/resources
中 - 将
Servlet
或ServletRegistration
类型的@Bean
安装在容器中,等同于web.xml中的和 - 创建
Filter
或FilterRegistrationBean
类型的@Bean
,等同于和 - 通过
@ImportResource
引入Application xml文件 - 像
Application
中添加main
方法使其变为可执行文件
- 扩展
- 应用程序类别
- 没有web.xml的Servlet 3.0+应用程序
- 带有web.xml的应用程序
- 具有上下文层次结构的应用程序
- 没有上下文层次结构的应用程序
j将War部署到WebLogic
将Spring Boot应用程序部署到WebLogic,必须确保servlet初始化程序直接实现WebApplicationInitializer
- WebLogic的典型初始化程序
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.web.WebApplicationInitializer; @SpringBootApplication public class MyApplication extends SpringBootServletInitializer implements WebApplicationInitializer { }
使用Logback,需要设置WebLogic首选打包版本,而不是服务器预先安装的版本。
- 在
WEB-INF/weblogic.xml
配置<?xml version="1.0" encoding="UTF-8"?> <wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app https://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd"> <wls:container-descriptor> <wls:prefer-application-packages> <wls:package-name>org.slf4j</wls:package-name> </wls:prefer-application-packages> </wls:container-descriptor> </wls:weblogic-web-app>
使用Jedis代替Lettuce
默认情况,SpringBoot Stater(spring-boot-starter-data-redis
)使用Lettuce。需要排除该依赖,使用Jedis
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>