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。

更改应用程序的外部属性的位置

 

posted @ 2020-08-23 10:20  codedot  阅读(321)  评论(0编辑  收藏  举报