springboot 错误处理
在 java web开发过程中,难免会有一些系统异常或人为产生一些异常。在 RESTful springboot 项目中如何优雅的处理?
分析:在RESTful 风格的springboot 项目中,返回的都是 body 对象,所以定义一个结果基类,其中包含 status,message,data(请求方法的返回结果),是比较合适的。
如果定义多个异常类进行处理,会比较麻烦。比如StudentNotExistsException、StudentExistsException。。。等,并且不能指定错误码,不方便前端根据错误码进行处理。
说明:一般的spring mvc模型处理流程如下
一般controller层 -> Service层 -> Dao层。
1.controller层,接受请求,进行分页,DTO对象封装操作。
2.service层,执行逻辑,控制并发,事务。
3.Dao层,与数据库交互。
使用一个学生表的处理进行说明:
1、定义常见的错误枚举 StudentExceptionEnum
public enum StudentExceptionEnum {
STUDENT_NOT_EXIST(,"学生不存在,请确认后再查"),
STUDENT_EXIST(,"学生已存在"); private Integer status;
private String comment; StudentExceptionEnum(Integer status, String comment) {
this.status = status;
this.comment = comment;
} public Integer getStatus() {
return status;
} public void setStatus(Integer status) {
this.status = status;
} public String getComment() {
return comment;
} public void setComment(String comment) {
this.comment = comment;
}
}
2 定义一个基本的处理结果类 RequestResult
@Data
public class RequestResult {
private String message;
private Integer status;
private Object data; public RequestResult(String message, Integer status, Object data) {
this.message = message;
this.status = status;
this.data = data;
} public RequestResult(String message, Integer status) {
this.message = message;
this.status = status;
} public RequestResult(String message, StudentExceptionEnum requestExceptionEnum) {
this.message = message;
this.status = requestExceptionEnum.getStatus();
} public RequestResult() {
status = ;
message = "ok";
} public static RequestResult OK(Object data) {
RequestResult result = new RequestResult();
result.setData(data);
return result;
} public static RequestResult EXCEPTION(String message, Integer status) {
return new RequestResult(message, status);
} public static RequestResult EXCEPTION(String message, StudentExceptionEnum requestExceptionEnum) {
return new RequestResult(message, requestExceptionEnum);
} }
3 实体类 Student
@Data
public class Student implements Serializable{
private String id;
private String nickname;
private String name;
private int age;
private String sex;
private String address; @Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}
4 处理请求,添加学生,nickname 必填项。此处只显示 Service 片段代码
@Override
public RequestResult addStudent(Student student) {
if (studentDao.queryIdByNickname(student.getNickname()) == null) {
studentDao.addStudent(student);
System.out.println("添加成功");
student = studentDao.queryByNickname(student.getNickname());
return RequestResult.OK(student);
} else {
return RequestResult.EXCEPTION("用户" + student.getNickname() + "已存在", StudentExceptionEnum.STUDENT_EXIST);
}
}
5 此时,已经完成了基本的处理情况。下面就进行基本的测试了
5.1 添加一个新同学信息
5.2 再次添加让其出现异常测试
二、到此基本已大功告成,但是,对于基本的运行时异常没有处理,直接返回给前端会很不友好。所以要定义一个全局的 RuntimeException 异常处理类。
此处需要使用的关键标注: @ExceptionHandler
用法有两种 1)在处理请求的 Controller 中添加 @ExceptionHandler,此时该方法只会处理该 Controller 抛出的异常。
2)将其用在全局的异常处理类中,全局异常处理类需要使用 @RestControllerAdvice 或 @ControllerAdvice 标记
我们需要处理全局的 RuntimeException,所以我们使用第二种方法。当然,这样处理是为了客户友好型,我们还是要处理这种错误,怎么办?就需要将错误的信息记录下来,方便以后分析处理。此处使用 logger 进行记录。代码如下
@RestControllerAdvice
public class BaseExceptionHandler {
private static Logger logger = LoggerFactory.getLogger(BaseExceptionHandler.class); @ExceptionHandler(value = RuntimeException.class)
public RequestResult exceptionHandler(HttpServletRequest request,Exception e) {
logError(request,e);
return RequestResult.EXCEPTION("内部处理异常,工程师正在抓紧抢修,请稍后再来...",);
} public static void logError(HttpServletRequest request, Exception e) { logger.error("请求地址:" + request.getRequestURL());
logger.error("请求方法:" + request.getMethod());
logger.error("请求IP:" + getRemoteIp(request));
logger.error("错误详情:");
StackTraceElement[] error = e.getStackTrace();
for (StackTraceElement stackTraceElement : error) {
logger.error(stackTraceElement.toString());
}
} public static String getRemoteIp(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == || "unknown".equalsIgnoreCase(ip)) {
if (ip == null || ip.length() == || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} else if (ip.length() > ) {
String[] ips = ip.split(",");
for (int index = ; index < ips.length; index++) {
String strIp = (String) ips[index];
if (!("unknown".equalsIgnoreCase(strIp))) {
ip = strIp;
break;
}
}
}
return ip;
}
}
进行测试看是否生效:
修改添加学生信息代码如下:
public RequestResult addStudent(Student student) {
int a = /; if (studentDao.queryIdByNickname(student.getNickname()) == null) {
studentDao.addStudent(student);
System.out.println("添加成功");
student = studentDao.queryByNickname(student.getNickname());
return RequestResult.OK(student);
} else {
return RequestResult.EXCEPTION("用户'" + student.getNickname() + "'已存在", StudentExceptionEnum.STUDENT_EXIST);
}
}
进行测试
后台打印错误信息
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : 请求地址:http://localhost:8080/demo1/student
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : 请求方法:POST
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : 请求IP::::::::
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : 错误详情:
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : com.huitong.demo.service.StudentService.addStudent(StudentService.java:)
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : com.huitong.demo.controller.StudentController.addStudent(StudentController.java:)
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:)
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:)
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : java.lang.reflect.Method.invoke(Method.java:)
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:)
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:)
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:)
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:)
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:)
-- ::19.125 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:)
-- ::19.129 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:)
-- ::19.129 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:)
-- ::19.129 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:)
-- ::19.129 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:)
-- ::19.129 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : javax.servlet.http.HttpServlet.service(HttpServlet.java:)
-- ::19.129 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : javax.servlet.http.HttpServlet.service(HttpServlet.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:)
-- ::19.130 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:)
-- ::19.131 ERROR --- [nio--exec-] c.h.d.controller.BaseExceptionHandler : java.lang.Thread.run(Thread.java:)
-- ::19.133 WARN --- [nio--exec-] .m.m.a.ExceptionHandlerExceptionResolver : Resolved exception caused by Handler execution: java.lang.ArithmeticException: / by zero
springboot 错误处理的更多相关文章
- SpringBoot系列五:SpringBoot错误处理(数据验证、处理错误页、全局异常)
声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念: SpringBoot 错误处理 2.具体内容 在之前的程序里面如果一旦出现了错误之后就会出现一堆的大白板,这个白板会 ...
- springboot错误: 找不到或无法加载主类
一:当在eclipse启动spring boot项目时出现问题: springboot错误: 找不到或无法加载主类 解决办法: 1,通过cmd命令行,进入项目目录进行,mvn clean instal ...
- springboot 错误求解决
最近再学习springboot这个好东西,结果给当成白老鼠了,我使用的是idea 2018 来测试 一个简单的界面跳转 ,结果报错了,在网上搜了好半天没搜到相应的解决方案,很头疼,希望哪位大神能 ...
- 学习小片段——springboot 错误处理
一:先看看springboot默认的错误处理机制 springboot默认会判断是否是浏览器(http请求头Accept是否含有 text/html)来选择返回html错误页面或json错误信息 原因 ...
- springboot错误页面处理
springboot作为微服务的便捷框架,在错误页面处理上也有了一些新的处理,不同于之前的pringmvc500的页面处理是比较简单的,用java config或者xml的形式,定义如下的Bean即可 ...
- springboot 错误页面的配置
springboot的错误页面,只需在templates下新建error文件夹,将404.500等错误页面放进去即可, springboot会自动去里面查找
- Springboot 错误处理机制
SpringBoot默认的错误处理机制 即我们常见的白色的ErrorPage页面 浏览器发送的请求头: 如果是其他的请求方式,比如客户端,则相应一个json数据: 原理:是通过 ErrorMvcAut ...
- springboot错误1 Failed to execute goal org.springframework.boot:spring-boot-maven-plugin
关于Springboot打包错误的问题 | Failed to execute goal org.springframework.boot:spring-boot-maven-plugin https ...
- SpringBoot错误经验
1.在application.properties 添加 debug=true,可以看见项目的执行流程有助于调bug 2.如果错误显示端口号被占用 cmd 步骤1 查看端口号应用情况:netstat ...
随机推荐
- linux2.6.30.4内核移植(2)——Nand Flash驱动移植
内核源码:linux2.6.30.4 交叉编译工具:3.4.5 移植linux内核至:TQ2440 工作基础:http://www.cnblogs.com/nufangrensheng/p/36696 ...
- 与web有关的小知识
为什么修改了host未生效:http://www.cnblogs.com/hustskyking/p/hosts-modify.html htm.html.shtml网页区别 Vuex简单入门 详说c ...
- AppScan--图解Web扫描工具IBM Security App Scan Standard
App Scan用法: 首先打开IBM Security AppScan Standard 工具 点击 创建新的扫描 -> 点击”常规扫描“ ->之后你就会看到如下图: ...
- MySql绿色版安装步骤和方法,以及配置文件修改,Mysql服务器启动
MySql绿色版Windows安装步骤和方法,以及配置文件修改,Mysql服务器启动 支持“标准”Markdown / CommonMark和Github风格的语法,也可变身为代码编辑器: 支持实时预 ...
- 12 个非常实用的 jQuery 代码片段
jQuery是一个非常流行而且实用的JavaScript前端框架,本文并不是介绍jQuery的特效动画,而是分享一些平时积累的12个jQuery实用代码片段,希望对你有所帮助. 导航菜单背景切换效果 ...
- 【Android】ant编译aidl的错误
使用ant编译Android应用程序工程时,出现的错误: 错误信息(Cygwin): [aidl] This application has requested the Runtime to term ...
- Xamarin.Android其他类型的服务
一.前言 前面我们已经学了关于服务的很多知识,但是对于真实的开发那些远远不够,通过这节我们将学习其他类型的服务,比如前台服务.IntentService和消息服务.下面我们开始进入正题. 二.前台服务 ...
- python之模块pydoc
# -*- coding: cp936 -*- #python 27 #xiaodeng import pydoc #主要用于从python模块中自动生成文档,这些文档可以基于文本呈现,也可以生成we ...
- 小米路由Mini刷Breed, 潘多拉和LEDE
1. 下载breed,地址 http://breed.hackpascal.net/ 2. 下载小米Mini的开发板rom, 地址 http://www1.miwifi.com/miwifi_down ...
- 【linux环境】Linux环境 php连接oracle11g数据库(相关插件已备份至U盘)
1.环境:centos6 . LNMP(linux环境都可以,跟服务器没啥大关系) 2.前期准备:弄清楚 项目php的运行目录,php.ini的配置目录,php-config的运行目录 3.安装先知: ...