统一异常处理

一、什么是统一异常处理

1、制造异常

    //异常测试
    @ApiOperation(value = "异常测试")
    @GetMapping("exceptionTest")
    public R exceptionTest(){
        int a = 1/0;
        return R.ok();
    }

2、什么是统一异常处理

我们想让异常结果也显示为统一的返回结果对象,并且统一处理系统的异常信息,那么需要统一异常处理。

二、统一异常处理

1、创建统一异常处理器

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());
    }

}

2、创建自定义异常类

    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();

        }

    }

3、自定义异常信息

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;
    }

}

4、业务中需要的位置抛出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=== 

 

posted @ 2022-10-15 15:20  程序员小明1024  阅读(128)  评论(0编辑  收藏  举报