SpringBoot啟動(dòng)遇到的異常問題及解決方案
SpringBoot啟動(dòng)遇到異常
1、 問題
SpringBoot本身需要引入自身的一個(gè)parent,但是pom里面一般都已經(jīng)存在了一個(gè)parent,這時(shí)就不能在引入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
解決方案:
這個(gè)問題可能是由于Spring的版本低導(dǎo)致,升級(jí)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)
解決方案:
這個(gè)異常是由于打印日志的jar沖突導(dǎo)致,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的版本,可能是版本不兼容,我這里一開始設(shè)置的1.5.6.RELEASE,一直出異常,后來SpringBoot的版本改成全部改成1.3.3.RELEASE 把Spring的版本改成4.2.5.RELEASE,通過
5、 異常
SpringBoot啟動(dòng)
xport.annotation.AnnotationMBeanExporter -Unregistering JMX-exposed beans on shutdown ,tomcat也沒有運(yùn)行
可能原因1:
看看是否屏蔽了,檢查 <artifactId>spring-boot-starter-web</artifactId> 這個(gè)下面是否屏蔽了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
解決方案:
這個(gè)異常最蛋疼,搞了半天是SpringBoot的版本不兼容,切換了一個(gè)版本到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優(yōu)雅的處理異常
SpringBoot 統(tǒng)一異常處理
像這種統(tǒng)一異常的文章博客有許多,但是每個(gè)人使用都有自己的心得,我來總結(jié)一下自己使用的心得
統(tǒng)一異常,顧名思義,就是統(tǒng)一管理項(xiàng)目中會(huì)方法的異常,然后進(jìn)行一個(gè)處理,Spring發(fā)生錯(cuò)誤后,底層會(huì)去請求一個(gè)/error的地址,拋出對(duì)應(yīng)的異常到頁面上,對(duì)客戶或者開發(fā)來說都不是特別的友好
使用統(tǒng)一異常處理的話,可以返回自定義的異常數(shù)據(jù),閱讀性提高,優(yōu)雅的處理異常
使用異常
使用異常的方式很簡單,Spring提供了兩個(gè)注解:@ControllerAdvice和@ExceptionHandler
@ControllerAdvice
:控制器增強(qiáng),使@ExceptionHandler、@InitBinder、@ModelAttribute注解的方法應(yīng)用到所有的 @RequestMapping注解的方法@ExceptionHandler
:異常處理器,此注解的作用是當(dāng)出現(xiàn)其定義的異常時(shí)進(jìn)行處理的方法
創(chuàng)建統(tǒng)一異常類
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; /** * 全局異常處理 * 一般情況下,方法都有異常處理機(jī)制,但不能排除有個(gè)別異常沒有處理,導(dǎo)致返回到前臺(tái),因此在這里做一個(gè)異常攔截,統(tǒng)一處理那些未被處理過的異常 * * @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錯(cuò)誤. * * @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("缺少請求參數(shù):{}", ex.getMessage()); return ResponseMsgUtil.builderResponse(99999, "缺少參數(shù):" + ex.getParameterName(), null); } //參數(shù)類型不匹配 //getPropertyName()獲取數(shù)據(jù)類型不匹配參數(shù)名稱 //getRequiredType()實(shí)際要求客戶端傳遞的數(shù)據(jù)類型 @ExceptionHandler(TypeMismatchException.class) @ResponseBody public Result<String> requestTypeMismatch(TypeMismatchException ex) { LOGGER.error("參數(shù)類型有誤:{}", ex.getMessage()); return ResponseMsgUtil.builderResponse(99999, "參數(shù)類型不匹配,參數(shù)" + ex.getPropertyName() + "類型應(yīng)該為" + 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報(bào)紅無需處理,作用是獲取spring底層錯(cuò)誤攔截 * * @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注解來攔截程序中的異常,比如執(zhí)行SQL時(shí),拋出了異常,就會(huì)被統(tǒng)一異常給攔截,然后返回我們想要返回的數(shù)據(jù)
@ResponseStatus注解可加可不加,就是對(duì)響應(yīng)碼進(jìn)行攔截,如代碼上,對(duì)404響應(yīng)碼進(jìn)行了攔截
最下面的handleErrors方法,是對(duì)Spring底層訪問/error的時(shí)候進(jìn)行了一次攔截,獲取當(dāng)前請求碼,如果是404.拋出404的異常
優(yōu)化處理異常怎么能沒有自定義返回?cái)?shù)據(jù)呢
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; /** * 返回?cái)?shù)據(jù)結(jié)果集合 */ 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 + '}'; } }
/** * 返回?cái)?shù)據(jù)結(jié)果集合 * @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); } }
測試
將這些準(zhǔn)備都做好以后,項(xiàng)目跑起來,訪問一個(gè)接口,故意不傳某個(gè)必填項(xiàng),就會(huì)被統(tǒng)一異常攔截,如下
{ ?? ?code: 1002, ?? ?data: null, ?? ?msg: "Required String parameter 'id' is not present" }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
啟用設(shè)置org.slf4j.Logger打印并輸出日志方式
這篇文章主要介紹了啟用設(shè)置org.slf4j.Logger打印并輸出日志方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11Springboot?前后端分離項(xiàng)目使用?POI?生成并導(dǎo)出?Excel的操作方法
在做一個(gè)?SpringBoot?前后端分離項(xiàng)目的時(shí)候,需要將數(shù)據(jù)存到?Excel中,用戶可以下載?Excel,具體實(shí)現(xiàn)是采用?Apache?強(qiáng)大的?POI,本文給大家介紹Springboot?前后端分離項(xiàng)目使用?POI?生成并導(dǎo)出?Excel相關(guān)知識(shí),感興趣的朋友一起看看吧2023-09-09Java Dubbo協(xié)議下的服務(wù)端線程使用詳解
Dubbo是阿里開源項(xiàng)目,國內(nèi)很多互聯(lián)網(wǎng)公司都在用,已經(jīng)經(jīng)過很多線上考驗(yàn)。Dubbo內(nèi)部使用了Netty、Zookeeper,保證了高性能高可用性,使用Dubbo可以將核心業(yè)務(wù)抽取出來,作為獨(dú)立的服務(wù),逐漸形成穩(wěn)定的服務(wù)中心2023-03-03Java微服務(wù)分布式調(diào)度Elastic-job環(huán)境搭建及配置
Elastic-Job在配置中提供了JobEventConfiguration,支持?jǐn)?shù)據(jù)庫方式配置,會(huì)在數(shù)據(jù)庫中自動(dòng)創(chuàng)建JOB_EXECUTION_LOG和JOB_STATUS_TRACE_LOG兩張表以及若干索引,來記錄作業(yè)的相關(guān)信息2023-02-02Spring boot項(xiàng)目集成Camel FTP的方法示例
這篇文章主要介紹了Spring boot項(xiàng)目集成Camel FTP的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-10-10一個(gè)JAVA小項(xiàng)目--Web應(yīng)用自動(dòng)生成Word
前段時(shí)間接到一個(gè)Web應(yīng)用自動(dòng)生成Word的需求,現(xiàn)整理了下一些關(guān)鍵步驟拿來分享一下。2014-05-05java使用HttpSession實(shí)現(xiàn)QQ訪問記錄
這篇文章主要介紹了java使用HttpSession實(shí)現(xiàn)QQ的訪問記錄的相關(guān)資料,需要的朋友可以參考下2016-03-03Java NIO原理圖文分析及代碼實(shí)現(xiàn)
本文主要介紹Java NIO原理的知識(shí),這里整理了詳細(xì)資料及簡單示例代碼和原理圖,有需要的小伙伴可以參考下2016-09-09