SpringBoot启动遇到的异常问题及解决方案

目录
  • SpringBoot启动遇到异常
    • 1、问题
    • 2、异常
    • 3、异常
    • 4、异常
    • 5、异常
    • 6、异常
    • 7、异常
  • SpringBoot优雅的处理异常
    • 使用异常
    • 创建统一异常类
    • 测试

SpringBoot启动遇到异常

1、 问题

SpringBoot本身需要引入自身的一个parent,但是pom里面一般都已经存在了一个parent,这时就不能在引入springBoot的parent

解决方案:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>1.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>1.5.6.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

2、异常

Exception in thread "main" java.lang.IllegalArgumentException: Cannot instantiate interface org.springframework.context.ApplicationListener : org.springframework.boot.logging.ClasspathLoggingApplicationListener
。。。。。。
Caused by: java.lang.NoClassDefFoundError: org/springframework/context/event/GenericApplicationListener

解决方案:

这个问题可能是由于Spring的版本低导致,升级spring版本。亲测到4.2.5.RELEASE可以

<org.springframework.version>4.2.5.RELEASE</org.springframework.version>

3、异常

Exception in thread "main" java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.slf4j.impl.Log4jLoggerFactory loaded from file:/D:/maven/repository/org/slf4j/slf4j-log4j12/1.7.5/slf4j-log4j12-1.7.5.jar). If you are using WebLogic you will need to add 'org.slf4j' to prefer-application-packages in WEB-INF/weblogic.xml Object of class [org.slf4j.impl.Log4jLoggerFactory] must be an instance of class ch.qos.logback.classic.LoggerContext
at org.springframework.util.Assert.isInstanceOf(Assert.java:346)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext(LogbackLoggingSystem.java:221)

解决方案:

这个异常是由于打印日志的jar冲突导致,SpringBoot本身有打印日志的功能,如果跟本地的冲突,就需要去掉,如下

   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>1.3.3.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

4、异常

Cannot instantiate factory class: org.springframework.boot.autoconfigure.AutoConfigurationImportFilter

Caused by: java.lang.IllegalAccessException: Class org.springframework.core.io.support.SpringFactoriesLoader can not access a member of class org.springframework.boot.autoconfigure.condition.OnClassCondition with modifiers ""

解决方案:

这种可以检查org.springframework.boot的版本,可能是版本不兼容,我这里一开始设置的1.5.6.RELEASE,一直出异常,后来SpringBoot的版本改成全部改成1.3.3.RELEASE  把Spring的版本改成4.2.5.RELEASE,通过

5、 异常

SpringBoot启动

xport.annotation.AnnotationMBeanExporter -Unregistering JMX-exposed beans on shutdown ,tomcat也没有运行

可能原因1:

看看是否屏蔽了,检查 <artifactId>spring-boot-starter-web</artifactId> 这个下面是否屏蔽了spring-boot-starter-tomcat,

如果有,请去掉

<exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>

可能原因2:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>

将<scope>provided</scope>注释掉

6、异常

Caused by: java.lang.NoClassDefFoundError: org/springframework/beans/factory/ObjectProvider
Caused by: java.lang.ClassNotFoundException: org.springframework.beans.factory.ObjectProvider

解决方案:

这个异常最蛋疼,搞了半天是SpringBoot的版本不兼容,切换了一个版本到1.3.3.RELEASE 这里就好了

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>1.3.3.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

建议把<groupId>org.springframework.boot</groupId>这下下面的版本都改成1.3.3.RELEASE

7、异常

java.lang.NoSuchMethodError: org.springframework.expression.spel.SpelParserConfiguration.<init>(Lorg/springframework/expression/spel/SpelCompilerMode;Ljava/lang/ClassLoader

解决方案:

缺少jar

    <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-expression</artifactId>
                <version>4.2.5.RELEASE</version>
            </dependency>

SpringBoot优雅的处理异常

SpringBoot 统一异常处理

像这种统一异常的文章博客有许多,但是每个人使用都有自己的心得,我来总结一下自己使用的心得

统一异常,顾名思义,就是统一管理项目中会方法的异常,然后进行一个处理,Spring发生错误后,底层会去请求一个/error的地址,抛出对应的异常到页面上,对客户或者开发来说都不是特别的友好

使用统一异常处理的话,可以返回自定义的异常数据,阅读性提高,优雅的处理异常

使用异常

使用异常的方式很简单,Spring提供了两个注解:@ControllerAdvice和@ExceptionHandler

  • @ControllerAdvice:控制器增强,使@ExceptionHandler、@InitBinder、@ModelAttribute注解的方法应用到所有的 @RequestMapping注解的方法
  • @ExceptionHandler:异常处理器,此注解的作用是当出现其定义的异常时进行处理的方法

创建统一异常类

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.TypeMismatchException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.web.AbstractErrorController;
import org.springframework.boot.autoconfigure.web.ErrorAttributes;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.NoHandlerFoundException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.SQLException;
import java.util.Map;
/**
 * 全局异常处理
 * 一般情况下,方法都有异常处理机制,但不能排除有个别异常没有处理,导致返回到前台,因此在这里做一个异常拦截,统一处理那些未被处理过的异常
 *
 * @author ${author} on ${date}
 */
@ControllerAdvice
@Controller
@RequestMapping
public class GlobalExceptionHandler extends AbstractErrorController {
    private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    public GlobalExceptionHandler(ErrorAttributes errorAttributes) {
        super(errorAttributes);
    }
    @Value("${server.error.path:${error.path:/error}}")
    private static String errorPath = "/error";
    /**
     * sql异常
     *
     * @param req
     * @param rsp
     * @param ex
     * @return
     * @throws Exception
     */
    @ResponseBody
    @ExceptionHandler(SQLException.class)
    public Result<String> sqlException(HttpServletRequest req, HttpServletResponse rsp, Exception ex) {
        LOGGER.error("!!! request uri:{} from {} server exception:{}", req.getRequestURI(), RequestUtil.getIpAddress(req), ex == null ? null : ex);
        return ResponseMsgUtil.builderResponse(1002, ex == null ? null : ex.getMessage(), null);
    }
    /**
     * 500错误.
     *
     * @param req
     * @param rsp
     * @param ex
     * @return
     * @throws Exception
     */
    @ResponseBody
    @ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    public Result<String> serverError(HttpServletRequest req, HttpServletResponse rsp, Exception ex) throws Exception {
        LOGGER.error("!!! request uri:{} from {} server exception:{}", req.getRequestURI(), RequestUtil.getIpAddress(req), ex == null ? null : ex);
        return ResponseMsgUtil.builderResponse(1002, ex == null ? null : ex.getMessage(), null);
    }
    /**
     * 404的拦截.
     *
     * @param request
     * @param response
     * @param ex
     * @return
     * @throws Exception
     */
    @ResponseBody
    @ResponseStatus(code = HttpStatus.NOT_FOUND)
    @ExceptionHandler(NoHandlerFoundException.class)
    public Result<String> notFound(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {
        LOGGER.error("!!! request uri:{} from {} not found exception:{}", request.getRequestURI(), RequestUtil.getIpAddress(request), ex);
        return ResponseMsgUtil.builderResponse(404, ex == null ? null : ex.getMessage(), null);
    }
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseBody
    public Result<String> paramException(MissingServletRequestParameterException ex) {
        LOGGER.error("缺少请求参数:{}", ex.getMessage());
        return ResponseMsgUtil.builderResponse(99999, "缺少参数:" + ex.getParameterName(), null);
    }
    //参数类型不匹配
    //getPropertyName()获取数据类型不匹配参数名称
    //getRequiredType()实际要求客户端传递的数据类型
    @ExceptionHandler(TypeMismatchException.class)
    @ResponseBody
    public Result<String> requestTypeMismatch(TypeMismatchException ex) {
        LOGGER.error("参数类型有误:{}", ex.getMessage());
        return ResponseMsgUtil.builderResponse(99999, "参数类型不匹配,参数" + ex.getPropertyName() + "类型应该为" + ex.getRequiredType(), null);
    }
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseBody
    public Result<String> requestMethod(HttpRequestMethodNotSupportedException ex) {
        LOGGER.error("请求方式有误:{}", ex.getMethod());
        return ResponseMsgUtil.builderResponse(99999, "请求方式有误:" + ex.getMethod(), null);
    }
    @ExceptionHandler(MultipartException.class)
    @ResponseBody
    public Result<String> fileSizeLimit(MultipartException m) {
        LOGGER.error("超过文件上传大小限制");
        return ResponseMsgUtil.builderResponse(99999, "超过文件大小限制,最大10MB", null);
    }
    /**
     * 重写/error请求, ${server.error.path:${error.path:/error}} IDEA报红无需处理,作用是获取spring底层错误拦截
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "${server.error.path:${error.path:/error}}")
    public Result<String> handleErrors(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpStatus status = getStatus(request);
        if (status == HttpStatus.NOT_FOUND) {
            throw new NoHandlerFoundException(request.getMethod(), request.getRequestURL().toString(), new HttpHeaders());
        }
        Map<String, Object> body = getErrorAttributes(request, true);
        return ResponseMsgUtil.builderResponse(Integer.parseInt(body.get("status").toString()), body.get("message").toString(), null);
    }
    @Override
    public String getErrorPath() {
        return errorPath;
    }
}

从上面可以看出来,我定义了sql异常,500异常,404异常该做的事情,通过@ExceptionHandler注解来拦截程序中的异常,比如执行SQL时,抛出了异常,就会被统一异常给拦截,然后返回我们想要返回的数据

@ResponseStatus注解可加可不加,就是对响应码进行拦截,如代码上,对404响应码进行了拦截

最下面的handleErrors方法,是对Spring底层访问/error的时候进行了一次拦截,获取当前请求码,如果是404.抛出404的异常

优化处理异常怎么能没有自定义返回数据呢

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
/**
 * 返回数据结果集合
 */
public class Result<T> {
    private Integer code;
    private String resMsg;
    private T data;
    public Result() {
    }
    public Integer getCode() {
        return this.code;
    }
    public void setCode(Integer resCode) {
        this.code = resCode;
    }
    public String getResMsg() {
        return this.resMsg;
    }
    public void setResMsg(String resMsg) {
        this.resMsg = resMsg;
    }
    public T getData() {
        return this.data;
    }
    public void setData(T data) {
        this.data = data;
    }
    public String toJson() {
        return this.data == null ? JSON.toJSONString(this) : this.toJson(SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteMapNullValue);
    }
    public String toJson(SerializerFeature... features) {
        return features == null ? this.toJson() : JSON.toJSONString(this, features);
    }
    public String toString() {
        return "Result{code=" + this.code + ", resMsg='" + this.resMsg + '\'' + ", data=" + this.data + '}';
    }
}
/**
 * 返回数据结果集合
 * @author RuXuanWo on 2019/02/21
 */
public class ResponseMsgUtil {
    public ResponseMsgUtil() {
    }
    public static <T> Result<T> builderResponse(int code, String msg, T data) {
        Result<T> res = new Result();
        res.setCode(code);
        res.setResMsg(msg);
        res.setData(data);
        return res;
    }
    public static <T> Result<T> success(String msg) {
        return builderResponse(0, msg, null);
    }
    public static <T> Result<T> success(String msg, T data) {
        return builderResponse(0, msg, data);
    }
    public static <T> Result<T> success(T data) {
        return builderResponse(0, "Success", data);
    }
    public static <T> Result<T> success() {
        return builderResponse(0, "Success", null);
    }
    public static <T> Result<T> failure() {
        return builderResponse(1, "Failure", null);
    }
    public static <T> Result<T> failure(String msg) {
        return builderResponse(1, msg, null);
    }
    public static <T> Result<T> failure(T date) {
        return builderResponse(-1, "Failure", date);
    }
    public static <T> Result<T> illegalRequest() {
        return builderResponse(1008, "Illegal request", (T) null);
    }
    public static <T> Result<T> exception() {
        return builderResponse(1002, "request exception", (T) null);
    }
    public static <T> Result<T> paramsEmpty() {
        return builderResponse(1009, "the input parameter is null", (T) null);
    }
}

测试

将这些准备都做好以后,项目跑起来,访问一个接口,故意不传某个必填项,就会被统一异常拦截,如下

{
    code: 1002,
    data: null,
    msg: "Required String parameter 'id' is not present"
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • SpringBoot之自定义启动异常堆栈信息打印方式

    在SpringBoot项目启动过程中,当一些配置或者其他错误信息会有一些的规范的提示信息 *************************** APPLICATION FAILED TO START *************************** Description: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that's liste

  • SpringBoot打印启动时异常堆栈信息详解

    SpringBoot在项目启动时如果遇到异常并不能友好的打印出具体的堆栈错误信息,我们只能查看到简单的错误消息,以致于并不能及时解决发生的问题,针对这个问题SpringBoot提供了故障分析仪的概念(failure-analyzer),内部根据不同类型的异常提供了一些实现,我们如果想自定义该怎么去做? FailureAnalyzer SpringBoot提供了启动异常分析接口FailureAnalyzer,该接口位于org.springframework.boot.diagnosticspack

  • Springboot启动报错时实现异常定位

    首先大家了解什么是Spring Boot?Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.用我的话来理解,就是spring boot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架.Spring Boot作为Spring MVC的升级版,但是却没有太多的联系,换句话说你学

  • SpringBoot打印详细启动异常信息

    SpringBoot在项目启动时如果遇到异常并不能友好的打印出具体的堆栈错误信息,我们只能查看到简单的错误消息,以致于并不能及时解决发生的问题,针对这个问题SpringBoot提供了故障分析仪的概念(failure-analyzer),内部根据不同类型的异常提供了一些实现,我们如果想自定义该怎么去做? FailureAnalyzer SpringBoot提供了启动异常分析接口FailureAnalyzer,该接口位于org.springframework.boot.diagnosticspack

  • SpringBoot启动遇到的异常问题及解决方案

    目录 SpringBoot启动遇到异常 1.问题 2.异常 3.异常 4.异常 5.异常 6.异常 7.异常 SpringBoot优雅的处理异常 使用异常 创建统一异常类 测试 SpringBoot启动遇到异常 1. 问题 SpringBoot本身需要引入自身的一个parent,但是pom里面一般都已经存在了一个parent,这时就不能在引入springBoot的parent 解决方案: <dependency>             <groupId>org.springfra

  • springBoot启动报错log4j冲突的解决方案

    springBoot启动报错log4j冲突 先上一段报错内容 SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/D:/soft/apache-tomcat-8.5.31/webapps/ui/WEB-INF/lib/log4j-slf4j-impl-2.7.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found

  • SpringBoot使用Maven打包异常-引入外部jar的问题及解决方案

    由于项目需要,在需要打包的时候,由于引入的外部jar在本地是可以使用的,但是当打包后启动时报错,找不到对应的类. 使用 1.引入外部jar包 项目中简历文件夹lib 可以在resultces包下简历一个lib文件夹,将jar包扔进去: 在配置文件中引用 <dependency> <groupId>com.xx.xxx</groupId> //组织,随便命名 <artifactId>***</artifactId> //包的名字,随便命名 <

  • springboot启动feign项目报错:Service id not legal hostnam的解决

    目录 springboot启动feign项目报错:Service id not legal hostnam 在feign项目中,定义接口调用服务 启动时报出异常信息 度娘后发现问题所在 配置文件服务名做同样修改 Service id not legal hostname (pin_user) 错误信息 出现原因 解决方案 springboot启动feign项目报错:Service id not legal hostnam 在feign项目中,定义接口调用服务 @FeignClient(name=

  • 通过代码实例了解SpringBoot启动原理

    这篇文章主要介绍了通过代码实例了解SpringBoot启动原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 SpringBoot和Spring相比,有着不少优势,比如自动配置,jar直接运行等等.那么SpringBoot到底是怎么启动的呢? 下面是SpringBoot启动的入口: @SpringBootApplication public class HelloApplication { public static void main(Str

  • SpringBoot配置系统全局异常映射处理

    目录 一.异常分类 1.业务异常 2.系统异常 二.解决应用启动后404界面 1.引入页面Jar包 2.自定义首页接口 3.首页界面 4.运行效果 三.SpringBoot2.0中异常处理 1.项目结构图 2.自定义业务异常类 3.自定义异常描述对象 4.统一异常处理格式 5.简单的测试接口 四.源代码地址 一.异常分类 这里的异常分类从系统处理异常的角度看,主要分类两类:业务异常和系统异常. 1.业务异常 业务异常主要是一些可预见性异常,处理业务异常,用来提示用户的操作,提高系统的可操作性.

  • Springboot启动不检查JPA的数据源配置方式

    目录 Springboot启动不检查JPA的数据源配置 1.问题 2.方案 设置Springboot项目忽略JPA启动 解决方案 Springboot启动不检查JPA的数据源配置 1.问题 有时我们使用spring boot ,在依赖中配置了spring data jpa的依赖,此时spring boot启动时会自动检测数据源的配置,如果没有则报无数据源的错误. 但是这个依赖必须要有,因为代码需要根据一些条件选择是否启用数据源,则么办? 2.方案 在SpringApplication实例中设置如

  • SpringBoot启动yaml报错的解决

    SpringBoot启动yaml报错 报错找不到org.yaml里的一个方法 10:45:54.742 [main] ERROR org.springframework.boot.SpringApplication - Application run failed java.lang.NoSuchMethodError: org.yaml.snakeyaml.nodes.ScalarNode.getScalarStyle()Lorg/yaml/snakeyaml/DumperOptions$Sc

  • SpringBoot实战之处理异常案例详解

    前段时间写了一篇关于实现统一响应信息的博文,根据文中实战操作,能够解决正常响应的一致性,但想要实现优雅响应,还需要优雅的处理异常响应,所以有了这篇内容. 作为后台服务,能够正确的处理程序抛出的异常,并返回友好的异常信息是非常重要的,毕竟我们大部分代码都是为了 处理异常情况.而且,统一的异常响应,有助于客户端理解服务端响应,并作出正确处理,而且能够提升接口的服务质量. SpringBoot提供了异常的响应,可以通过/error请求查看效果: 这是从浏览器打开的场景,也就是请求头不包括content

  • SpringBoot启动自动终止也不报错的原因及解决

    目录 SpringBoot启动自动终止也不报错 原因 解决方案 springboot 启动一段时间之后自动挂掉的解决 解决办法 SpringBoot启动自动终止也不报错 Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. Disconnected from the target VM, address: '

随机推荐