统一异常处理
//异常测试 @ApiOperation(value = "异常测试") @GetMapping("exceptionTest") public R exceptionTest(){ int a = 1/0; return R.ok(); }
2、什么是统一异常处理
我们想让异常结果也显示为统一的返回结果对象,并且统一处理系统的异常信息,那么需要统一异常处理。
二、统一异常处理
package com.stu.service.base.handler; import com.stu.service.base.exception.CustomException; import com.stu.service.base.result.R; import com.stu.service.base.utils.ExceptionUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; /****************************** * 用途说明:统一异常处理 * 作者姓名: Administrator * 创建时间: 2022-04-17 23:32 ******************************/ @Slf4j @ControllerAdvice public class GlobalExceptionHandler { /*********************************** * 用途说明:自定义异常 * 返回值说明: com.stu.service.base.result.R ***********************************/ @ExceptionHandler(CustomException.class) @ResponseBody public R customException(CustomException e){ // e.printStackTrace(); log.error(e.getMessage()); log.error(ExceptionUtils.getMessage(e)); return R.error().message(e.getMessage()).code(e.getCode()); } /*********************************** * 用途说明:数字异常 * 返回值说明: com.stu.service.base.result.R ***********************************/ @ExceptionHandler(ArithmeticException.class) @ResponseBody public R arithmeticException(Exception e){ log.error(ExceptionUtils.getMessage(e)); return R.error().message(e.getMessage()); } /*********************************** * 用途说明:全局异常 * 返回值说明: com.stu.service.base.result.R ***********************************/ @ExceptionHandler(Exception.class) @ResponseBody public R error(Exception e){ log.error(ExceptionUtils.getMessage(e)); return R.error().message(e.getMessage()); } }
package com.stu.service.base.exception; import com.stu.service.base.result.ResultCodeEnum; import lombok.Data; /****************************** * 用途说明:自定义异常 * 作者姓名: Administrator * 创建时间: 2022-04-18 0:00 ******************************/ @Data public class CustomException extends RuntimeException{ private Integer code; public CustomException(ResultCodeEnum resultCodeEnum){ super(resultCodeEnum.getMessage()); //this.message = resultCodeEnum.getMessage(); this.code = resultCodeEnum.getCode(); } }
package com.stu.service.base.result; import lombok.Getter; import lombok.ToString; /** * 前后端数据交换状态码 */ @Getter @ToString public enum ResultCodeEnum { SUCCESS(true, 20000, "成功"), UNKNOWN_REASON(false, 20001, "未知错误"), UPDATE_ERROR(false, 20002, "更新失败"), BAD_SQL_GRAMMAR(false, 21001, "sql 语法错误"), JSON_PARSE_ERROR(false, 21002, "json 解析异常"), PARAM_ERROR(false, 21003, "参数不正确"), FILE_UPLOAD_ERROR(false, 21004, "文件上传错误"), FILE_DELETE_ERROR(false, 21005, "文件刪除错误"), EXCEL_DATA_IMPORT_ERROR(false, 21006, "Excel 数据导入错误"), VIDEO_UPLOAD_ALIYUN_ERROR(false, 22001, "视频上传至阿里云失败"), VIDEO_UPLOAD_TOMCAT_ERROR(false, 22002, "视频上传至业务服务器失败"), VIDEO_DELETE_ALIYUN_ERROR(false, 22003, "阿里云视频文件删除失败"), FETCH_VIDEO_UPLOADAUTH_ERROR(false, 22004, "获取上传地址和凭证失败"), REFRESH_VIDEO_UPLOADAUTH_ERROR(false, 22005, "刷新上传地址和凭证失败"), FETCH_PLAYAUTH_ERROR(false, 22006, "获取播放凭证失败"), URL_ENCODE_ERROR(false, 23001, "URL编码失败"), ILLEGAL_CALLBACK_REQUEST_ERROR(false, 23002, "非法回调请求"), FETCH_ACCESSTOKEN_FAILD(false, 23003, "获取 accessToken 失败"), FETCH_USERINFO_ERROR(false, 23004, "获取用户信息失败"), LOGIN_ERROR(false, 23005, "登录失败"), COMMENT_EMPTY(false, 24006, "评论内容必须填写"), PAY_RUN(false, 25000, "支付中"), PAY_UNIFIEDORDER_ERROR(false, 25001, "统一下单错误"), PAY_ORDERQUERY_ERROR(false, 25002, "查询支付结果错误"), ORDER_EXIST_ERROR(false, 25003, "课程已购买"), GATEWAY_ERROR(false, 26000, "服务不能访问"), CODE_ERROR(false, 28000, "验证码错误"), LOGIN_PHONE_ERROR(false, 28009, "手机号码不正确"), LOGIN_MOBILE_ERROR(false, 28001, "账号不正确"), LOGIN_PASSWORD_ERROR(false, 28008, "密码不正确"), LOGIN_DISABLED_ERROR(false, 28002, "该用户已被禁用"), REGISTER_MOBLE_ERROR(false, 28003, "手机号已被注册"), LOGIN_AUTH(false, 28004, "需要登录"), LOGIN_ACL(false, 28005, "没有权限"), SMS_SEND_ERROR(false, 28006, "短信发送失败"), SMS_SEND_ERROR_BUSINESS_LIMIT_CONTROL(false, 28007, "短信发送过于频繁"), DIVIDE_ZERO(false, 29001, "除零错误"), DATA_NULL(false, 30001, "数据不存在!"), DATA_EXITS(false, 30002, "数据已存在!"), DATA_NODE_EXITS(false, 30003, "该章节下存在视频课程,请先删除视频课程!"); private final Boolean success; private final Integer code; private final String message; ResultCodeEnum(Boolean success, Integer code, String message) { this.success = success; this.code = code; this.message = message; } }
CustomException
package com.stu.service.edu.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.stu.service.base.exception.CustomException; import com.stu.service.base.result.ResultCodeEnum; import com.stu.service.edu.entity.Chapter; import com.stu.service.edu.entity.Video; import com.stu.service.edu.entity.vo.ChapterVo; import com.stu.service.edu.mapper.ChapterMapper; import com.stu.service.edu.service.ChapterService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.stu.service.edu.service.VideoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * <p> * 课程 服务实现类 * </p> * * @author stu * @since 2022-05-08 */ @Service public class ChapterServiceImpl extends ServiceImpl<ChapterMapper, Chapter> implements ChapterService { @Autowired private ChapterMapper chapterMapper; @Autowired private VideoService videoService; /*********************************** * 用途说明:课程章节信息 * 返回值说明: java.util.List<com.stu.service.edu.entity.vo.ChapterVo> ***********************************/ @Override public List<ChapterVo> listChapters(String courseId) { return chapterMapper.listChapters(courseId); } /*********************************** * 用途说明:删除课程章节,判断是否有视频,有的话不能删除 * 返回值说明: boolean ***********************************/ @Override public boolean removeById(String id) { QueryWrapper<Video> queryWrapper = new QueryWrapper(); queryWrapper.eq("chapter_id",id); int count = videoService.count(queryWrapper); if(count > 0 ){ throw new CustomException(ResultCodeEnum.DATA_NODE_EXITS); } return baseMapper.deleteById(id) > 0; } }
5、ExceptionUtils
package com.stu.service.base.utils; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; /****************************** * 用途说明: * 作者姓名: Administrator * 创建时间: 2022-04-18 22:26 ******************************/ public class ExceptionUtils { /*********************************** * 用途说明: * 返回值说明: java.lang.String ***********************************/ public static String getMessage(Exception e) { StringWriter sw = null; PrintWriter pw = null; try { sw = new StringWriter(); pw = new PrintWriter(sw); // 将出错的栈信息输出到printWriter中 e.printStackTrace(pw); pw.flush(); sw.flush(); } finally { if (sw != null) { try { sw.close(); } catch (IOException e1) { e1.printStackTrace(); } } if (pw != null) { pw.close(); } } return sw.toString(); } }
6、测试除零异常
启动程序,访问带有除零异常的接口,在自定义异常类里输出3种log,分别输出e.getMessage(),ExceptionUtils.getMessage(e),e
/*********************************** * 用途说明:数字异常 * 返回值说明: com.stu.service.base.result.R ***********************************/ @ExceptionHandler(ArithmeticException.class) @ResponseBody public R arithmeticException(Exception e){ // e.printStackTrace(); log.error("e.getMessage() ==START=== "+e.getMessage()+" ==END=== "); log.error("ExceptionUtils.getMessage(e) ==========START=== "+ExceptionUtils.getMessage(e)+" ==END=== "); log.error("eeeeeeeeeeee ==========START=== "+e+" ==END=== "); return R.error().message(e.getMessage()); }
输出log
2022-10-15 15:50:34 |ERROR |http-nio-9110-exec-6 |GlobalExceptionHandler.java:41 |com.stu.service.base.handler.GlobalExceptionHandler |e.getMessage() ==START=== / by zero ==END=== 2022-10-15 15:50:36 |ERROR |http-nio-9110-exec-6 |GlobalExceptionHandler.java:42 |com.stu.service.base.handler.GlobalExceptionHandler |ExceptionUtils.getMessage(e) ==========START=== java.lang.ArithmeticException: / by zero at com.stu.service.edu.controller.admin.TeacherController.findAllTeacher(TeacherController.java:100) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:744) ==END=== 2022-10-15 15:50:36 |ERROR |http-nio-9110-exec-6 |GlobalExceptionHandler.java:43 |com.stu.service.base.handler.GlobalExceptionHandler |eeeeeeeeeeee ==========START=== java.lang.ArithmeticException: / by zero ==END===