Spring Boot 项目是不是经常失败,显示一大堆的错误信息,如端口重复绑定时会打印以下异常:

***************************
APPLICATION FAILED TO START
*************************** Description: Embedded servlet container failed to start. Port 8080 was already in use. Action: Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.

这个大家应该很熟悉了吧!

错误信息大家都能看懂,但很不友好,那么,Spring Boot 是怎么实现这样一个异常错误信息输出的呢?今天栈长分享一个 Spring Boot 启动失败的简单易懂的玩法,让新来的实习生 1 秒都能看出问题。

如果你对 Spring Boot 还不是很熟悉,或者只是会简单的使用,那还是建议你深入学习下吧,推荐这个 Spring Boot 学习仓库,欢迎 Star 关注:

https://github.com/javastacks/spring-boot-best-practice

Failure Analyzers 介绍

Spring Boot 中注册了许多 "Failure Analyzers",即 "失败分析器",Spring Boot 中的启动失败的场景都是由这些失败分析器拦截处理的。

Spring Boot 提供了 FailureAnalyzers 接口:

package org.springframework.boot.diagnostics;

/**
* A {@code FailureAnalyzer} is used to analyze a failure and provide diagnostic
* information that can be displayed to the user.
*
* @author Andy Wilkinson
* @since 1.4.0
*/
@FunctionalInterface
public interface FailureAnalyzer { /**
* Returns an analysis of the given {@code failure}, or {@code null} if no analysis
* was possible.
* @param failure the failure
* @return the analysis or {@code null}
*/
FailureAnalysis analyze(Throwable failure); }

这个接口的目的就是: 分析启动失败异常并显示给用户有用的诊断信息。

Spring Boot 内置注册的所有失败分析器在这个文件里面:

/org/springframework/boot/spring-boot/2.3.5.RELEASE/spring-boot-2.3.5.RELEASE-sources.jar!/META-INF/spring.factories

注册的所有失败分析器列表:

# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.context.properties.NotConstructorBoundInjectionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer

再回到上面的端口重复绑定启动失败异常,就是注册了 PortInUseFailureAnalyzer 这个失败分析器,可以看到 PortInUseFailureAnalyzer 失败分析器就在注册列表里面。

再来看下 PortInUseFailureAnalyzer 的源码:

/**
* A {@code FailureAnalyzer} that performs analysis of failures caused by a
* {@code PortInUseException}.
*
* @author Andy Wilkinson
*/
class PortInUseFailureAnalyzer extends AbstractFailureAnalyzer<PortInUseException> { @Override
protected FailureAnalysis analyze(Throwable rootFailure, PortInUseException cause) {
return new FailureAnalysis("Web server failed to start. Port " + cause.getPort() + " was already in use.",
"Identify and stop the process that's listening on port " + cause.getPort() + " or configure this "
+ "application to listen on another port.",
cause);
} }

只要应用启动过程上抛出了 PortInUseException 异常就会被这个失败分析器拦截并输出可读性的错误信息,现在知道绑定重复绑定错误是怎么输出的了。

自定义 Failure Analyzers

从内置的失败分析器中可以发现,所有的分析器都继承了这个抽象基类是:AbstractFailureAnalyzer,它实现了 FailureAnalyzer 接口,一般基于这个抽象基类就可以实现自定义失败分析器的扩展。

下面栈长通过两个示例带大家了解下,如何扩展或者自定义一个 FailureAnalyzer

1、重写端口失败分析器

比如说上面的PortInUseFailureAnalyzer 输出内容是英文的,不是很直观的看出,我们可以自己实现一个中文的端口失败分析器。

很简单,创建一个失败分析器继承 AbstractFailureAnalyzer 抽象类即可:

/**
* 来源微信公众号:Java技术栈
*/
package cn.javastack.springboot.features.analyzer; import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;
import org.springframework.boot.web.server.PortInUseException; public class PortInUseFailureAnalyzer extends AbstractFailureAnalyzer<PortInUseException> { @Override
protected FailureAnalysis analyze(Throwable rootFailure, PortInUseException cause) {
return new FailureAnalysis("你启动的端口 " + cause.getPort() + " 被占用了.",
"快检查下端口 " + cause.getPort() + " 被哪个程序占用了,或者强制杀掉进程.",
cause);
} }

重写 analyze 方法,并返回一个 FailureAnalysis 对象,FailureAnalysis 类的三个主要信息分别是:

public FailureAnalysis(String description, String action, Throwable cause) {
this.description = description;
this.action = action;
this.cause = cause;
}

即要展示的:可读性的错误描述、建议的检查修复动作、原始异常。

然后在自己的资源目录下创建 META-INF/spring.factories 文件,内容添加:

org.springframework.boot.diagnostics.FailureAnalyzer=\
cn.javastack.springboot.features.analyzer.PortInUseFailureAnalyzer

启动输出:

***************************
APPLICATION FAILED TO START
*************************** Description: 你启动的端口 8080 被占用了. Action: 快检查下端口 8080 被哪个程序占用了,或者强制杀掉进程.

这样重新实现一下是不是要清楚多了?实习生都能看懂!

2、自定义失败分析器

下面再来自定义一个全新的失败分析器,让大家能更清楚的认识失败分析器。

我们在创建 Bean 的过程中手动抛出一个自定义的异常:

/**
* 来源微信公众号:Java技术栈
*/
@Bean
public CommandLineRunner commandLineRunner(){
throw new JavastackException("Java技术栈异常");
}

添加一个失败分析器拦截该异常:

/**
* 来源微信公众号:Java技术栈
*/
package cn.javastack.springboot.features.analyzer; import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis; public class JavastackFailureAnalyzer extends AbstractFailureAnalyzer<JavastackException> { @Override
protected FailureAnalysis analyze(Throwable rootFailure, JavastackException cause) {
return new FailureAnalysis("Java技术栈发生异常了……",
"赶快去检查一下吧!",
cause);
} }

添加注册:

org.springframework.boot.diagnostics.FailureAnalyzer=\
cn.javastack.springboot.features.analyzer.PortInUseFailureAnalyzer,\
cn.javastack.springboot.features.analyzer.JavastackFailureAnalyzer

启动输出:

***************************
APPLICATION FAILED TO START
*************************** Description: Java技术栈发生异常了…… Action: 赶快去检查一下吧!

如果不注册该失败分析器,这个自定义的异常就不会被内置的失败分析器拦截,就会输出大堆的异常信息,使用失败分析器能很直观的看出是什么错误及怎么修复这个错误。

总结

Spring Boot 提供的失败分析器以友好的错误信息和修复建议代替了大堆的错误异常信息,可以帮助我们更直观的定位应用启动故障,你学会了吗?

本文的所有示例源代码都已上传到了 Github:

https://github.com/javastacks/spring-boot-best-practice

欢迎大家 Star 关注,后续会不断更新。

学习更多 Spring Boot 教程,请关注公众号Java技术栈,在后台回复:boot,历史 Spring Boot 教程我都整理好了。

最后,别忘了点在看、转发哦,需要你的鼓励~

版权申明:本文系公众号 "Java技术栈" 原创,原创实属不易,转载、引用本文内容请注明出处,禁止抄袭、洗稿,请自重,尊重他人劳动成果和知识产权。

近期热文推荐:

1.600+ 道 Java面试题及答案整理(2021最新版)

2.终于靠开源项目弄到 IntelliJ IDEA 激活码了,真香!

3.阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!

4.Spring Cloud 2020.0.0 正式发布,全新颠覆性版本!

5.《Java开发手册(嵩山版)》最新发布,速速下载!

觉得不错,别忘了随手点赞+转发哦!

Spring Boot 老启动失败,这次再也不怕了!的更多相关文章

  1. 【Spring boot】启动过程源码分析

    启动过程结论 推测web应用类型. spi的方式获取BootstrapRegistryInitializer.ApplicationContextInitializer.ApplicationCont ...

  2. spring boot无法启动,或者正常启动之后无法访问报404的解决办法

    以前用spring boot都是用idea的自动创建,或者是用的Jhipster创建的,就没有深究怎么去搭建.但是今天晚上心血来潮,想自己搭一个demo来整合一些技术,于是就花一点时间来手动搭.因为今 ...

  3. spring boot容器启动详解

    目录 一.前言 二.容器启动 三.总结 =======正文分割线====== 一.前言 spring cloud大行其道的当下,如果不了解基本原理那么是很纠结的(看见的都是约定大于配置,但是原理呢?为 ...

  4. 让Spring Boot项目启动时可以根据自定义配置决定初始化哪些Bean

    让Spring Boot项目启动时可以根据自定义配置决定初始化哪些Bean 问题描述 实现思路 思路一 [不符合要求] 思路二[满足要求] 思路三[未试验] 问题描述 目前我工作环境下,后端主要的框架 ...

  5. Spring boot自定义启动字符画(banner)

    spring boot项目启动时会打印spring boot的ANSI字符画,可以进行自定义. 如何自定义 实现方式非常简单,我们只需要在Spring Boot工程的/src/main/resourc ...

  6. spring boot 项目启动无任何反应

    遇到的问题 spring boot项目启动后无任何报错,ps有进程,nohub无日志 定位 更换jar包,问题依然存在,将jar包放到其他服务器,运行正常,排除打包问题 同服务器其他系统运行正常,但停 ...

  7. Spring Boot定制启动图案

    启动图案 Spring Boot在启动的时候会显示一个默认的Spring的图案,对应的类为SpringBootBanner. . ____ _ __ _ _ /\\ / ___'_ __ _ _(_) ...

  8. Spring Boot 设置启动时banner

    Spring Boot项目再启动的时候默认会在控制台输出一个字符banner图案,如下图: 我们可以通过下面的方法关闭启动时显示字符banner图案: 关闭banner方法一: public stat ...

  9. spring boot应用启动原理分析

    spring boot quick start 在spring boot里,很吸引人的一个特性是可以直接把应用打包成为一个jar/war,然后这个jar/war是可以直接启动的,不需要另外配置一个We ...

随机推荐

  1. HDU2065 "红色病毒"问题 【组合数学 二项式定理】

    HDU2065 "红色病毒"问题 Description: 医学界发现的新病毒因其蔓延速度和Internet上传播的"红色病毒"不相上下,被称为"红色 ...

  2. Consonant Fencity Gym - 101612C 暴力二进制枚举 Intelligence in Perpendicularia Gym - 101612I 思维

    题意1: 给你一个由小写字母构成的字符串s,你可以其中某些字符变成大写字母.如果s中有字母a,你如果想把a变成大写,那s字符串中的每一个a都要变成A 最后你需要要出来所有的字符对,s[i]和s[i-1 ...

  3. 2017, X Samara Regional Intercollegiate Programming Contest M. Last Man Standing (贪心,双指针)

    题意:有\(n\)个吃鸡玩家,在某个时间段给你他们每个人的杀敌数,判断数据是否合法,并输出每个人对应的杀敌情况. 题解:刚开始写的是直接暴力枚举,向后去找并且标记,然后存到vector最后输出,结果一 ...

  4. Hyper-V安装CentOS修改分辨率

    grubby --update-kernel=ALL --args="video=hyperv_fb:1600x900" reboot https://blog.csdn.net/ ...

  5. docker-理论题01

    1.什么是docker?答:docker是开源的应用容器引擎:开发人员把他们的应用及依赖包打包发布到容器当中. 2.docker和VMware的区别? 答:docker是半解耦,VMware是解耦:d ...

  6. PHP 弱类型 && CODE/COMMADN injection

    CODE/COMMAND INJECTION CODE INJECTION https://www.freebuf.com/sectool/168653.html EXAMPLE1 <?php ...

  7. zzuli-2259 matrix

    题目描述 在麦克雷的面前有N个数,以及一个R*C的矩阵.现在他的任务是从N个数中取出 R*C 个,并填入这个矩阵中.矩阵每一行的法值为本行最大值与最小值的差,而整个矩阵的法值为每一行的法值的最大值.现 ...

  8. JavaScript调试技巧之console.log()

    与alert()函数类似,console.log()也可以接受变量并将其与别的字符串进行拼接: 代码如下: //Use variable var name = "Bob"; con ...

  9. IDEA 安装常用操作一

    关于IDEA的下载,破解自行百度 一.安装完成的常用设置 SDK选择.编译版本的选择,单项目选择,全局选择 maven配置,单项目,全局配置 二.IDEA如何安装lombok https://www. ...

  10. reStructuredText(.rst) && read the docs

    Read the Docs   &&  reStructuredText (.rst)  && markdown 1. github master 分支,创建 docs ...