springboot启动报错,springboot实现异常处理
目录
跳靴启动遇到异常1、 问题2、异常3、异常4、异常5、 异常6、异常7、异常跳羚优雅的处理异常使用异常创建统一异常类测试
SpringBoot启动遇到异常
1、 问题
跳靴本身需要引入自身的一个父母,但是砰的一声里面一般都已经存在了一个父母,这时就不能在引入跳羚的父母
解决方案:
依赖关系groupIdorg.springframework.boot/groupId artifactId spring-boot-starter-web/artifactId version1.3.3.RELEASE/version/依赖关系groupIdorg.springframework.boot/groupId artifact id spring-boot-dependencies/artifact id version1.5.6.RELEASE/version typepom/type scope import/scope/dependency
2、异常
线程"主要"中的异常Java。郎。illegalargumentexception :无法实例化接口org。spring框架。语境。应用程序监听器: org。spring框架。靴子。伐木。class pathloggingapplicationlistener : Java。郎。noclassdeffounderror : org/spring framework/context/event/GenericApplicationListener
解决方案:
这个问题可能是由于弹簧的版本低导致,升级弹簧版本。亲测到发布可以
版本4 .2 .5 .发布/组织。spring框架。版本
3、异常
线程“主”Java。郎。illegalargumentexception :记录器工厂不是回溯日志记录器上下文,但回溯位于类路径中。请移除回溯或竞争的实现(从文件:/d :/maven/repository/org/slf4j/slf4j-log4j 12/1。7 .5/slf4j-log4j 12-1。7 .5 .冲突加载的类org。slf4j。impl。日志4 jloggerfactory).如果使用WebLogic,则需要将" org.slf4j "添加到WEB-INF/weblogic.xml中的首选应用程序包中。类[组织。slf4j。impl。日志4 jloggerfactory]的对象必须是org。spring框架。靴子。日志备份。返回日志。日志备份。经典。记录器上下文at组织。spring框架。util。断言。isinstanceof(assert。Java 3360346)中类栗色服务质量。日志备份。日志备份。回溯的实例
gingSystem.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/ObjectProviderCaused 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@RequestMappingpublic 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"}
以上为个人经验,希望能给大家一个参考,也希望大家多多支持盛行IT。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。