SpringBoot自定义FailureAnalyzer过程解析

这篇文章主要介绍了SpringBoot自定义FailureAnalyzer,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

官网说明

1.1 创建自己的 FailureAnalyzer

FailureAnalyzer是一种在启动时拦截 exception 并将其转换为 human-readable 消息的好方法,包含在故障分析中。 Spring Boot 为 application context 相关的 exceptions,JSR-303 验证等提供了这样的分析器。实际上很容易创建自己的。

AbstractFailureAnalyzer是FailureAnalyzer的方便扩展,它检查 exception 中是否存在指定的 exception 类型来处理。你可以从中扩展,这样你的 implementation 只有在它实际存在时才有机会处理 exception。如果由于某种原因你无法处理 exception,return null给另一个 implementation 一个处理 exception 的机会。

FailureAnalyzer __mplement 将在META-INF/spring.factories中注册:以下寄存器ProjectConstraintViolationFailureAnalyzer:

org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer

1.2 排除故障 auto-configuration

Spring Boot auto-configuration 尽力'做正确的事',但有时事情会失败,而且很难说出原因。

在 Spring Boot ApplicationContext中有一个非常有用的ConditionEvaluationReport可用。如果启用DEBUG logging 输出,您将看到它。如果使用spring-boot-actuator,还有一个端点,用 JSON 呈现报表。使用它来调试 application 并查看 Spring Boot 在运行时添加了哪些 features(以及哪些没有)。

通过查看 source code 和 Javadoc 可以回答更多问题。一些经验法则:

  • 查找名为*AutoConfiguration的 classes 并读取它们的源,特别是@Conditional* 注释,以找出它们启用的 features 和何时启用。将--debug添加到命令 line 或 System property -Ddebug以在 console 上添加 log 在您的应用程序中做出的所有 auto-configuration 决策。在 running Actuator 应用程序中,查看autoconfig端点('/autoconfig'或 JMX 等效项)以获取相同的信息。
  • 查找@ConfigurationProperties(e.g. ServerProperties)的 classes 并从那里读取可用的外部 configuration 选项。 @ConfigurationProperties有一个name属性,作为外部 properties 的前缀,因此ServerProperties有prefix="server",其 configuration properties 是server.port,server.address等。在 running Actuator 应用程序中查看configprops端点。
  • 寻找使用RelaxedPropertyResolver从Environment中明确地提取 configuration 值。它通常与前缀一起使用。
  • 查找直接绑定到Environment的@Value 注释。这不如RelaxedPropertyResolver方法灵活,但允许一些轻松的 binding,特别是 OS 环境变量(因此CAPITALS_AND_UNDERSCORES是period.separated的同义词)。
  • 查找@ConditionalOnExpression 注释,以响应 SpEL 表达式打开和关闭 features,通常使用从Environment解析的占位符进行评估。

1.3 在启动之前自定义 Environment 或 ApplicationContext

SpringApplication具有ApplicationListeners和ApplicationContextInitializers,用于将自定义应用于 context 或环境。 Spring Boot 加载了许多此类自定义项,以便在META-INF/spring.factories内部使用。注册其他方法的方法不止一种:

  • 通过在_运行之前调用SpringApplication上的addListeners和addInitializers方法,以编程方式为每个 application。
  • 通过设置context.initializer.classes或context.listener.classes来声明每个 application。
  • 通过添加META-INF/spring.factories并打包_appar 全部用作 library 的 jar 文件来声明所有 applications。

SpringApplication向 listeners 发送一些特殊的ApplicationEvents(甚至在创建 context 之前的一些),然后为ApplicationContext发布的 events 注册 listeners

在使用EnvironmentPostProcessor刷新 application context 之前,还可以自定义Environment。每个 implementation 都应该在META-INF/spring.factories中注册:

org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor

implementation 可以加载任意 files 并将它们添加到Environment。例如,此 example 从 classpath 加载 YAML configuration 文件:

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, null);
    }
    catch (IOException ex) {
      throw new IllegalStateException(
          "Failed to load yaml configuration from " + path, ex);
    }
  }

}

Environment已经准备好了 Spring Boot 默认加载的所有常用 property 源。因此,可以从环境中获取文件的位置。此 example 在列表末尾添加custom-resource property 源,以便在任何其他常用位置中定义的 key 优先。自定义 implementation 显然可以定义另一个 order。

虽然在@SpringBootApplication上使用@PropertySource似乎方便且容易在Environment中加载自定义资源,但我们不推荐它为 Spring Boot 在ApplicationContext刷新之前准备Environment。通过@PropertySource定义的任何 key 都将被加载太晚而不会对 auto-configuration 产生任何影响。

代码示例

2.1 指定异常分析

SpringBoot内部提供的启动异常分析都是指定具体的异常类型实现的,最常见的一个错误就是端口号被占用(PortInUseException),虽然SpringBoot内部提供一个这个异常的启动分析,我们也是可以进行替换这一异常分析的,我们只需要创建PortInUseException异常的AbstractFailureAnalyzer,并且实现类注册给SpringBoot即可,实现自定义如下所示

/**
 * @author WGR
 * @create 2019/11/24 -- 23:00
 */
public class PortInUseFailureAnalyzer extends AbstractFailureAnalyzer<PortInUseException> {
  /**
   * logger instance
   */
  static Logger logger = LoggerFactory.getLogger(PortInUseFailureAnalyzer.class);

  @Override
  protected FailureAnalysis analyze(Throwable rootFailure, PortInUseException cause) {
    logger.error("端口被占用。", cause);
    return new FailureAnalysis("端口号:" + cause.getPort() + "被占用", "PortInUseException", rootFailure);
  }
}

注册启动异常分析

在上面我们只是编写了指定异常启动分析,我们接下来需要让它生效,这个生效方式比较特殊,类似于自定义SpringBoot Starter AutoConfiguration的形式,我们需要在META-INF/spring.factories文件内进行定义,如下所示:

org.springframework.boot.diagnostics.FailureAnalyzer=\
 com.topcheer.activiti.analyzer.PortInUseFailureAnalyzer

那我们为什么需要使用这种方式定义呢?

项目启动遇到的异常顺序不能确定,很可能在Spring IOC并未执行初始化之前就出现了异常,我们不能通过@Component注解的形式使其生效,所以SpringBoot提供了通过spring.factories配置文件的方式定义。

测试:启动2个8080端口

启动异常分析继承关系

自定义的运行异常一般都是继承自RuntimeException,如果我们定义一个RuntimeException的异常启动分析实例会是什么效果呢?

public class ProjectBootUnifiedFailureAnalyzer extends AbstractFailureAnalyzer<RuntimeException> {
  /**
   * logger instance
   */
  static Logger logger = LoggerFactory.getLogger(ProjectBootUnifiedFailureAnalyzer.class);

  @Override
  protected FailureAnalysis analyze(Throwable rootFailure, RuntimeException cause) {
    logger.error("遇到运行时异常", cause);
    return new FailureAnalysis(cause.getMessage(), "error", rootFailure);
  }
}

将该类也一并注册到spring.factories文件内,如下所示:

org.springframework.boot.diagnostics.FailureAnalyzer=\
com.topcheer.activiti.analyze.PortInUseFailureAnalyzer,\
com.topcheer.activiti.analyze.ProjectBootUnifiedFailureAnalyzer

运行项目并测试端口号被占用异常我们会发现,并没有执行ProjectBootUnifiedFailureAnalyzer内的analyze方法,而是继续执行了PortInUseFailureAnalyzer类内的方法。

那我们将PortInUseFailureAnalyzer这个启动分析从spring.factories文件内暂时删除掉,再来运行项目我们会发现这时却是会执行ProjectBootUnifiedFailureAnalyzer类内分析方法。

总结

根据本章我们了解了SpringBoot提供的启动异常分析接口以及基本抽象实现类的运作原理,而且启动异常分析存在分析泛型异常类的上下级继承关系,异常子类的启动分析会覆盖掉异常父类的启动分析,如果你想包含全部异常的启动分析可以尝试使用Exception作为AbstractFailureAnalyzer的泛型参数。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Spring boot创建自定义starter的完整步骤

    前言: Springboot的出现极大的简化了开发人员的配置,而这之中的一大利器便是springboot的starter,starter是springboot的核心组成部分,springboot官方同时也为开发人员封装了各种各样方便好用的starter模块,例如: spring-boot-starter-web//spring MVC相关 spring-boot-starter-aop //切面编程相关 spring-boot-starter-cache //缓存相关 starter的出现极大的

  • SpringBoot JS-SDK自定义微信分享的实现

    前言 在介绍使用微信自定义分享前,我们来先了解一下什么是自定义分享? 访问自定义微信外链地址页面,点击红色框位置进行分享给朋友或者朋友圈,具体操作如下图所示: 分享后图文消息如下图所示: 我们要做的就是自定义下图所示中红框中的信息. 闲话少说,接下来就正式开始自定义分享实战环节! 自定义分享实战 第一步需要先申请接口测试号并进行JS接口安全域名设置 访问如下链接进行接口测试号申请.点击访问选择接口测试号申请,如下图所示: 或者直接访问 :申请测试账号页面 如下图所示: 点击登录进行扫码登录,如下

  • springboot使用filter获取自定义请求头的实现代码

    有个钱包项目,本来用的是微服务这一套,后来感觉没必要,重构成了简单的springboot项目,但是token校验重构完之后出问题了,之前写filter走的是springgateway,基于GatewayFilter实现,重构了之后基于filter,然后当请求进入过滤器的时候,发现不能获取到请求的自定义请求头. String token = request.getHeader("token"); // null String id = request.getHeader("id

  • Spring Boot 如何自定义返回错误码错误信息

     说明 •在实际的开发过程中,很多时候要定义符合自己业务的错误码和错误信息,而不是统一的而不是统一的下面这种格式返回到调用端 INTERNAL_SERVER_ERROR(500, "Internal Server Error"), 下面我们来看看如何将我们自定义的错误码和错误信息返回到调用端. 1 自定义错误码 •首先我们要定义一个枚举类 public enum ErrorEnum { /* * 错误信息 * */ E_20011(20011, "缺少必填参数"),

  • 使用SpringBoot-JPA进行自定义保存及批量保存功能

    说明 SpringBoot版本:2.1.4.RELEASE java版本:1.8 文中所说JPA皆指spring-boot-starter-data-jpa 使用JPA保存一个Student对象 在JPA中保存一个对象,仅需要该对象,一个仓储即可. StudentDO实体类: @Getter @Setter @Entity @Table(name = "t_student") public class StudentDO { @Id @GeneratedValue(strategy =

  • springboot 自定义LocaleResolver实现切换语言

    我们在做项目的时候,往往有很多项目需要根据用户的需要来切换不同的语言,使用国际化就可以轻松解决. 我们可以自定义springboot中的LocaleResolver来进行简单的国际化处理,下面来通过简单Demo来简单的了解国际化. 在下面的Demo中,我用的是thymeleaf模板引擎标签的形式对国际化进行取值. 1.在pom中引入thymeleaf模板引擎 //引入thymeleaf <dependency> <groupId>org.springframework.boot&l

  • Springboot解决ajax+自定义headers的跨域请求问题

    1.什么是跨域 由于浏览器同源策略(同源策略,它是由Netscape提出的一个著名的安全策略.现在所有支持JavaScript 的浏览器都会使用这个策略.所谓同源是指,域名,协议,端口相同.),凡是发送请求url的协议.域名.端口三者之间任意一与当前页面地址不同即为跨域. 具体可以查看下表: 2.springboot如何解决跨域问题 1.普通跨域请求解决方案: ①请求接口添加注解@CrossOrigin(origins = "http://127.0.0.1:8020", maxAge

  • SpringBoot自定义FailureAnalyzer过程解析

    这篇文章主要介绍了SpringBoot自定义FailureAnalyzer,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 官网说明 1.1 创建自己的 FailureAnalyzer FailureAnalyzer是一种在启动时拦截 exception 并将其转换为 human-readable 消息的好方法,包含在故障分析中. Spring Boot 为 application context 相关的 exceptions,JSR-303 验

  • springboot自定义Starter过程解析

    自定义Starter命名规则 注意artifactId的命名规则,Spring官方Starter通常命名为spring-boot-starter-{name}如 spring-boot-starter-web, Spring官方建议非官方Starter命名应遵循{name}-spring-boot-starter的格式, 如mybatis-spring-boot-starter.这里创建的项目的artifactId为helloworld-spring-boot-starter 开发Starter

  • SpringBoot整合FastJson过程解析

    这篇文章主要介绍了SpringBoot整合FastJson过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.Maven依赖 <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.33</version> </dependency&

  • springboot自定义异常视图过程解析

    这篇文章主要介绍了springboot自定义异常视图过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.源码分析 先看源码再写自己的自定义异常视图 resolveErrorView()函数首先调用了一个返回ModelAndView的函数,该函数所需的参数是一个状态码的字符串,和一个map集合,该集合是错误信息 也就是下图这个函数 上图函数判断你是否提供了templates/error/下的动态错误页 如果提供了直接返回视图名和错误信息

  • python导入不同目录下的自定义模块过程解析

    这篇文章主要介绍了python导入不同目录下的自定义模块过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.代码目录结构 自定义的模块在Common包下,Study文件下SelectionSort.py文件导入自定义的模块 二.源码 2.1:SelectionSort.py文件 python导包默认是从sys.path中搜索的. sys.path结果如下:['D:\\PyCharm\\source\\Study', 'D:\\PyCha

  • 基于springboot集成hbase过程解析

    这篇文章主要介绍了基于springboot集成hbase过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 springboot-habse: https://github.com/spring-projects/spring-hadoop-samples/tree/master/hbase 依赖: <dependency> <groupId>org.springframework.data</groupId> &

  • springboot集成swagger过程解析

    这篇文章主要介绍了springboot集成swagger过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 springboot集成swagger 1.pom.xml中引入: <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2

  • springboot整合JPA过程解析

    这篇文章主要介绍了springboot整合JPA过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 接下来具体看看是怎么弄的. 1.新建一个springboot项目,选择web.data jdbc.data jpa.mysql driver. 2.建立以下目录及结构: pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&

  • Android自定义View过程解析

    Android自定义的view,主要是继承view,然后实现ondraw这个方法,来进行绘制. 1. 编写自己的自定义view 2. 加入逻辑线程 3. 提取和封装自定义view 4. 利用xml中定义样式来影响显示效果 一.编写自定义的view 1.在xml中使用自己的view <!-- 可以使用view的公共属性,例如背景 --> <com.niuli.view.MyView android:layout_width="match_parent" android:

  • SpringBoot 集成 Druid过程解析

    Druid是阿里巴巴开源平台上一个数据库连接池实现,它结合了C3P0.DBCP.PROXOOL等DB池的优点,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB连接池.更多资料说明大家可以查看官网 Github:https://github.com/alibaba/druid Druid官方已经编写好了相关的启动器,我们可以引入启动器,然后进行相关配置就可以使用Druid的各种功能.如果只是引入Druid依赖包,没有引入Druid的SpringBoot启动

随机推荐