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

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

服务器之家 - 编程语言 - Java教程 - SpringBoot启动遇到的异常问题及解决方案

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

2022-07-31 14:14EmineWang Java教程

这篇文章主要介绍了SpringBoot启动遇到的异常问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

SpringBoot启动遇到异常

1、 问题

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

解决方案:

?
1
2
3
4
5
6
7
8
9
10
11
12
<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可以

?
1
<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本身有打印日志的功能,如果跟本地的冲突,就需要去掉,如下

?
1
2
3
4
5
6
7
8
9
10
11
   <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,

如果有,请去掉

?
1
2
3
4
<exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>

可能原因2:

?
1
2
3
4
5
<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 这里就好了

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

?
1
2
3
4
5
    <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:异常处理器,此注解的作用是当出现其定义的异常时进行处理的方法

创建统一异常类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
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的异常

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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 + '}';
    }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
 * 返回数据结果集合
 * @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);
    }
}

测试

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

?
1
2
3
4
5
{
    code: 1002,
    data: null,
    msg: "Required String parameter 'id' is not present"
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/a718515028/article/details/77095131

延伸 · 阅读

精彩推荐