服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|JavaScript|易语言|

服务器之家 - 编程语言 - Java教程 - Spring Boot 项目启动失败的解决方案

Spring Boot 项目启动失败的解决方案

2021-08-18 12:20Java技术栈 Java教程

这篇文章主要介绍了Spring Boot 项目启动失败的解决方案,帮助大家更好的理解和学习使用Spring Boot,感兴趣的朋友可以了解下

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

?
1
2
3
4
5
6
7
8
9
10
11
***************************
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 接口:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 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 的源码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * 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 抽象类即可:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 类的三个主要信息分别是:

?
1
2
3
4
5
public FailureAnalysis(String description, String action, Throwable cause) {
 this.description = description;
 this.action = action;
 this.cause = cause;
}

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

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

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

启动输出:

?
1
2
3
4
5
6
7
8
9
10
11
***************************
APPLICATION FAILED TO START
***************************
 
Description:
 
你启动的端口 8080 被占用了.
 
Action:
 
快检查下端口 8080 被哪个程序占用了,或者强制杀掉进程.

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

2、自定义失败分析器

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

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

?
1
2
3
4
@Bean
public CommandLineRunner commandLineRunner(){
 throw new JavastackException("Java技术栈异常");
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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);
 }
 
}

添加注册:

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

启动输出:

?
1
2
3
4
5
6
7
8
9
10
11
***************************
APPLICATION FAILED TO START
***************************
 
Description:
 
Java技术栈发生异常了……
 
Action:
 
赶快去检查一下吧!

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

总结

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

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

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

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

以上就是Spring Boot 项目启动失败的解决方案的详细内容,更多关于Spring Boot 项目启动失败的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/javastack/p/14468724.html

延伸 · 阅读

精彩推荐
  • Java教程Java进阶教程之String类

    Java进阶教程之String类

    这篇文章主要介绍了Java进阶教程之String类,String类对象是不可变对象(immutable object),String类是唯一一个不需要new关键字来创建对象的类,需要的朋友可以参考下...

    junjie5132019-11-27
  • Java教程Spring boot 使用JdbcTemplate访问数据库

    Spring boot 使用JdbcTemplate访问数据库

    SpringBoot 是为了简化 Spring 应用的创建、运行、调试、部署等一系列问题而诞生的产物。本文重点给大家介绍spring boot 使用JdbcTemplate访问数据库,需要的朋友...

    唐亚峰 | battcn4712021-04-27
  • Java教程Java实现获取指定个数的不同随机数

    Java实现获取指定个数的不同随机数

    今天小编就为大家分享一篇关于Java实现获取指定个数的不同随机数,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随...

    希尔伯特11542021-06-27
  • Java教程详解spring中使用solr的代码实现

    详解spring中使用solr的代码实现

    本篇文章主要介绍了详解spring中使用solr的代码实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    周游列国之仕子2962020-10-28
  • Java教程Java Excel透视表相关操作实现代码

    Java Excel透视表相关操作实现代码

    这篇文章主要介绍了Java Excel透视表相关操作实现代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以...

    E_iceblue5332020-08-25
  • Java教程java 中遍历取值异常(Hashtable Enumerator)解决办法

    java 中遍历取值异常(Hashtable Enumerator)解决办法

    这篇文章主要介绍了java 中遍历取值异常(Hashtable Enumerator)解决办法的相关资料,用迭代器取值时抛出的异常:java.util.NoSuchElementException: Hashtable Enumerato...

    JsonLiangyoujun1972020-12-15
  • Java教程java实现验证码类生成中文验证码

    java实现验证码类生成中文验证码

    java实现的汉字输入验证码,主要包含两个类,一个是生成验证码,一个是判断验证码输入是否正确,实现原理非常简单,将汉字和干扰线生成图片并将汉字保...

    java技术网4682019-10-29
  • Java教程Struts2学习笔记(3)-DMI动态调用方式

    Struts2学习笔记(3)-DMI动态调用方式

    本文主要介绍Struts2的DMI动态调用的两种方式,简单实用,希望能给大家做一个参考。 ...

    meaijojo3262020-05-14