SpringBoot开发指南-1
Spring Boot应用
创建自己的FailureAnalyzer
FailureAnalyzer是一种很好的方法,可以在启动时截获异常并将其转换为人类可读的消息,封装在FailureAnalysis中。springboot为应用程序上下文相关的异常、JSR-303验证等提供了这样一个分析器。你也可以创建你自己的。
AbstractFailureAnalyzer是FailureAnalyzer的一个方便的扩展,它检查要处理的异常中是否存在指定的异常类型。您可以从中扩展,以便您的实现只有在异常实际存在时才有机会处理它。如果由于任何原因,您无法处理异常,则返回null以使另一个实现有机会处理该异常。
FailureAnalyzer实现必须在META-INF/spring.factories注册。 以下示例注册ProjectConstraintViolationFailureAnalyzer:
org.springframework.boot.diagnostics.FailureAnalyzer=\ com.example.ProjectConstraintViolationFailureAnalyzer
如果需要访问BeanFactory或环境,则FailureAnalyzer可以分别实现BeanFactoryAware或EnvironmentAware。
自动配置故障排除
Spring Boot自动配置尽力做到“做正确的事情”,但有时事情失败了,很难解释原因。
在任何springboot应用程序上下文中都有一个非常有用的ConditionEvaluationReport。如果启用调试日志记录输出,则可以看到它。如果您使用spring-boot-actuator,还有一个条件端点以JSON格式呈现报告。使用该端点来调试应用程序,并查看在运行时springboot添加了哪些特性(哪些特性尚未添加)。
通过查看源代码和Javadoc可以回答更多的问题。阅读代码时,请记住以下经验法则:
- 查找名为*AutoConfiguration的类并读取其源代码。请特别注意@Conditional*注释,以了解它们启用哪些功能以及何时启用。将--debug添加到命令行或系统属性-Ddebug,以便在控制台上获取应用程序中所有自动配置决策的日志。在启用了执行器的运行应用程序中,查看条件端点(/actuator/conditions或等效的JMX)以获取相同的信息。
- 查找@ConfigurationProperties类(如ServerProperties),并从中读取可用的外部配置选项。@ConfigurationProperties注释有一个name属性,用作外部属性的前缀。因此,ServerProperties具有prefix=“server”,其配置属性为服务器端口, 服务器地址,以及其他。在启用了执行器的运行应用程序中,查看configprops端点。
- 寻找在Binder上使用bind方法以轻松的方式将配置值显式地从环境中拉出。它常与前缀连用。
- 查找直接绑定到Environment的@Value注释。
- 查找@ConditionalOnExpression注解使用SpEL表达式打开和关闭功能,通常使用从环境中解析的占位符进行计算。
在启动之前自定义Environment或ApplicationContext
SpringApplication有ApplicationListeners和applicationContextInitializer,它们用于将定制应用到上下文或环境中。springboot从META-INF/spring.factories许多这样的定制,供内部使用/春季工厂. 注册其他自定义项有多种方法:
- 在运行SpringApplication之前,通过调用SpringApplication上的addListeners和addInitializers方法
- 过设置context.initializer.classes或者context.listener.classes属性。
- 对于所有应用程序,通过添加META-INF/spring.factories并打包到jar文件,作为应用程序的库。
SpringApplication向侦听器发送一些特殊的ApplicationEvents(有些甚至在创建上下文之前),然后也为ApplicationContext发布的事件注册侦听器。还可以使用EnvironmentPostProcessor在刷新应用程序上下文之前自定义环境。每个实现都应该在META-INF/spring.factories注册,如下例所示:
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); } } }
Environment已经准备好了,所有通常的属性源都是springboot默认加载的。因此,可以从环境中获取文件的位置。前面的示例将自定义资源属性source添加到列表的末尾,以便在其他任何位置定义的键优先。自定义实现可以定义另一个顺序。
虽然在@SpringBootApplication上使用@PropertySource似乎是在Environment中加载自定义资源的一种方便方法,但我们不建议这样做。在刷新应用程序上下文之前,不会将此类属性源添加到环境中。这对于那些需要在刷新之前需要读取的属性来说是太迟的,如logging.*和spring.main.*
构建ApplicationContext层次结构(添加父上下文或根上下文)
可以使用ApplicationBuilder类创建父/子ApplicationContext层次结构。
创建非web应用程序
并非所有的Spring应用程序都必须是web应用程序(或web服务)。如果你想在main方法中执行一些代码,同时引导一个Spring应用程序来设置要使用的基础设施,那么可以使用springboot的SpringApplication特性。SpringApplication更改其ApplicationContext类,这取决于它是否认为需要web应用程序。你可以做的第一件事是将与服务器相关的依赖项(例如servlet API)从类路径中去掉。如果不能这样做(例如,从同一个代码基运行两个应用程序),则可以显式调用setWebApplicationType(WebApplicationType.NONE)或者设置applicationContextClass属性(通过Java API或使用外部属性)。希望作为业务逻辑运行的应用程序代码可以作为CommandLineRunner实现,并作为@Bean定义放入上下文中。
属性和配置
使用Maven自动扩展属性
通过使用资源筛选,您可以从Maven项目自动扩展属性。如果使用spring-boot-starter-parent,则可以使用@..@占位符引用Maven的“project properties”,如下例所示:
app.encoding=@project.build.sourceEncoding@ app.java.version=@java.version@
如果启用addResources标志,则spring-boot:run可以将src/main/resources直接添加到类路径(用于热重新加载)。这样做可以避免资源。相反,您可以使用exec:java或者自定义插件的配置。
如果不使用starter父元素,则需要在pom.xml文件:
<resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources>
您还需要在<plugins/>中包含以下元素:
<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>
如果在配置中使用标准Spring占位符(例如${placeholder}),则useDefaultDelimiters属性非常重要。如果该属性未设置为false,则生成可能会展开这些属性。
外部化SpringApplication的配置
SpringApplication有bean属性(主要是setter),因此您可以在创建应用程序时使用它的java api来修改其行为。或者,你可以在spring.main.*中设置来外部化配置。例如在application.properties可以有如下设置:
spring.main.web-application-type=none spring.main.banner-mode=off
这样设置springboot banner不会在启动时打印出来,应用程序也不会启动嵌入式web服务器。
使用在ApplicationContext中定义的值得注意外部配置值会覆盖ApplicationContext中定义的值。考虑以下应用:
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
实际的应用程序现在显示banner(已被配置覆盖)并使用三个源作为ApplicationContext(按以下顺序):demo.MyApp, com.acme.Config,和com.acme.ExtraConfig。
更改应用程序的外部属性的位置