当前位置: 首页 > article >正文

08-学成在线项目中统一异常处理的规范

项目中的异常处理

规范异常类型

在Service类的业务方法中有很多的参数合法性校验,当请求参数不合法的时候会抛出异常,但此时异常信息只会在控制台输出,前端界面并不会提示用户

实际开发中前端和后端需要做一些约定: 一般将错误提示信息统一以json格式返回给前端,以HTTP状态码决定当前请求是否出错(非200为操作异常)

{
    "timestamp":"2023-02-02T14:42:36.820+00:00",
    // 添加课程时设置一个负数的课程价格会报500异常
    "status":500,
    "error":"Internal Server Error",
    "message":"",
    "path":"/content/course"
}

为了统一处理异常信息,我们需要在业务方法中自定义并规范项目中抛出的异常类型,这样可以便于统一去捕获这一类或几类的异常

  • 对于业务方法中抛出的非项目自定义的异常类型即未知异常,则统一向用户提示指定的错误信息如执行过程异常请重试的

规范了异常类型, 我们还需要去捕获异常信息,使用try/catch方式去捕获代码比较臃肿,可以统一由SpringMVC提供的控制器增强类去完成异常的捕获

在这里插入图片描述

异常处理(base工程)

第一步: 添加依赖,在base基础工程实现统一异常处理,由于各模块依赖了base基础工程所以都可以使用异常处理

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

第二步: 定义一个枚举类CommonError,枚举一些通用的异常信息对象

package com.xuecheng.base.execption;
/**
* @description 通用错误信息
*/
public enum CommonError {
    UNKOWN_ERROR("执行过程异常,请重试"),
    PARAS_ERROR("非法参数"),
    OBJECT_NULL("对象为空"),
    QUERY_NULL("查询结果为空"),
    REQUEST_NULL("请求参数为空");
    private String errMessage;
    public String getErrMessage() {
        return errMessage;
    }
    CommonError(String errMessage) {
        this.errMessage = errMessage;
    }
}

第三步: 自定义项目的异常类型XueChengPlusException

package com.xuecheng.base.execption;
/**
* @description 学成在线项目异常类
*/
public class XueChengPlusException extends RuntimeException {
    private String errMessage;

    public String getErrMessage() {
        return errMessage;
    }
    public XueChengPlusException() {
        super();
    }
    public XueChengPlusException(String errMessage) {
        super(errMessage);
        this.errMessage = errMessage;
    }
    public static void cast(CommonError commonError) {
        throw new XueChengPlusException(commonError.getErrMessage());
    }
    public static void cast(String errMessage) {
        throw new XueChengPlusException(errMessage);
    }
}

第四步: 自定义响应异常信息的模型类

package com.xuecheng.base.execption;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RestErrorResponse implements Serializable {
    private String errMessage;
}

第五步: 定义全局异常处理器去捕获异常信息同时记录异常日志, 将异常信息封装到异常信息的模型类并响应给用户,实现微服务端全局异常处理

  • @ControllerAdvice或@RestControllerAdvice)(类上): 将当前类标识为异常处理的组件
  • @ExceptionHandler(方法或类上): 用于表明方法处理的异常类型,可以指定一个或多个
  • @ResponseStatus(方法或类上): 标记捕获异常的方法或类指定发生异常时异常处理器向前端响应的状态码和原因
package com.xuecheng.base.execption;
/**
* @description 全局异常处理器
*/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
    @ResponseBody
    @ExceptionHandler(XueChengPlusException.class)// 处理项目自定义异常类型
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) // 该异常枚举对象的错误码为500
    public RestErrorResponse customException(XueChengPlusException exception) {
        log.error("系统异常:{}", exception.getErrMessage());
        return new RestErrorResponse(exception.getErrMessage());
    }

    @ResponseBody
    @ExceptionHandler(Exception.class)// 未知类型的异常
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)// 该异常枚举对象的错误码为500
    public RestErrorResponse exception(Exception exception) {
        log.error("系统异常:{}", exception.getMessage());
        return new RestErrorResponse(exception.getMessage());
    }
}

异常处理测试(api工程)

第一步: 在内容管理服务的api工程中添加base工程的依赖

<dependency>
    <groupId>com.xuecheng</groupId>
    <artifactId>xuecheng-plus-base</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

第二步: 当业务方法中出现异常时抛出项目自定义的异常类型,这里以新增课程的业务方法为例进行代码修改

@Override
public CourseBaseInfoDto createCourseBase(Long companyId,AddCourseDto dto) {
    //合法性校验
    if (StringUtils.isBlank(dto.getName())) {
        throw new XueChengPlusException("课程名称为空");
    }

    if (StringUtils.isBlank(dto.getMt())) {
        throw new XueChengPlusException("课程分类为空");
    }

    if (StringUtils.isBlank(dto.getSt())) {
        throw new XueChengPlusException("课程分类为空");
    }

    if (StringUtils.isBlank(dto.getGrade())) {
        throw new XueChengPlusException("课程等级为空");
    }

    if (StringUtils.isBlank(dto.getTeachmode())) {
        throw new XueChengPlusException("教育模式为空");
    }

    if (StringUtils.isBlank(dto.getUsers())) {
        throw new XueChengPlusException("适应人群");
    }	

    if (StringUtils.isBlank(dto.getCharge())) {
        throw new XueChengPlusException("收费规则为空");
    }
    if(charge.equals("201001")){
        if(courseMarketNew.getPrice() ==null || courseMarketNew.getPrice().floatValue()<=0){
            throw new XueChengPlusException("课程的价格不能为空并且必须大于0");
        }
    }
}

第三步: 使用HTTP Client进行测试,故意将收费课程价格设置为负数, 查看捕获到的响应信息

在这里插入图片描述

POST http://localhost:53040/content/course

HTTP/1.1 500 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Fri, 03 Feb 2023 02:32:20 GMT
Connection: close

{
  "errMessage": "课程设置了收费,价格不能为空,且必须大于0"
}

http://www.kler.cn/a/148719.html

相关文章:

  • linux病毒编写+vim shell编程
  • 为什么海外服务器IP会被封
  • Java集合框架之Collection集合遍历
  • MyBatis——增删查改(XML 方式)
  • HTTP常见的状态码有哪些,都代表什么意思
  • C 语言 【模拟实现内存库函数】
  • C# WPF上位机开发(乘法计算小软件)
  • 面试:MyBatis问题
  • 论文阅读——DDeP(cvpr2023)
  • 2017年五一杯数学建模C题宜居城市问题值解题全过程文档及程序
  • Web前端开发技术:图像与多媒体文件
  • OpenCvSharp从入门到实践-(05)通道
  • ABAP算法 模拟退火
  • c语言 / 指针错误的几种情况
  • 从 0 到 1 开发一个 node 命令行工具
  • 【Linux驱动开发】环境搭建Linux驱动开发环境
  • EDA实验-----正弦信号发生器的设计(Quartus II )
  • asp.net core HttpContextAccessor类
  • springBoot的实现原理;SpringBoot是什么;使用SpringBoot的核心功能;springBoot核心注解以及核心配置文件
  • qt QString字符串常用转换
  • Vue3指令:搜索框输入防抖实现(附源码)
  • 单片机复位电路
  • 【华为OD题库-036】跳格子2-java
  • springBoot设置多数据源
  • uniapp地图基本使用及解决添加markers不生效问题?
  • Linux shell编程学习笔记31:alias 和 unalias 操作 命令别名