项目中的全局异常是如何处理的

简介: 项目中的全局异常处理通常包括对预期异常(程序员手动抛出)和运行时异常的管理。项目已提供`BaseException`作为基础异常类,用于手动抛出异常,并通过`GlobalExceptionHandler`进行全局处理。`

项目中的全局异常是如何处理的?

全局异常处理逻辑

一般项目开发有两种异常:

  • 预期异常(程序员手动抛出)
  • 运行时异常

在目前的项目中已经提供了全局异常处理器

  • BaseException  基础异常,如果业务中需要手动抛出异常,则需要抛出该异常
package com.zzyl.exception;
import com.zzyl.enums.BasicEnum;
import lombok.Getter;
import lombok.Setter;
/**
 * BaseException
 * @author itheima
 **/
@Getter
@Setter
public class BaseException extends RuntimeException {
    private BasicEnum basicEnum;
    public BaseException(BasicEnum basicEnum) {
        this.basicEnum = basicEnum;
    }
}

其中BaseException中的参数为一个枚举,可以在BasicEnum自定义业务中涉及到的异常

package com.zzyl.enums;
import com.zzyl.base.IBasicEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
 * 基础枚举
 *
 * @author itcast
 */
@Getter
@AllArgsConstructor
public enum BasicEnum implements IBasicEnum {
    SUCCEED(200, "操作成功"),
    SECURITY_ACCESSDENIED_FAIL(401, "权限不足!"),
    LOGIN_FAIL(401, "用户登录失败"),
    LOGIN_LOSE_EFFICACY(401, "登录状态失效,请重新登录"),
    SYSYTEM_FAIL(500, "系统运行异常"),
    //权限相关异常:1400-1499
    DEPT_DEPTH_UPPER_LIMIT(1400, "部门最多4级"),
    PARENT_DEPT_DISABLE(1401, "父级部门为禁用状态,不允许启用"),
    DEPT_NULL_EXCEPTION(1402, "部门不能为空"),
    POSITION_DISTRIBUTED(1403, "职位已分配,不允许禁用"),
    MENU_NAME_DUPLICATE_EXCEPTION(1404, "菜单路由重复"),
  
    //业务相关异常:1500-1599
    WEBSOCKET_PUSH_MSG_ERROR(1500, "websocket推送消息失败"),
    CLOSE_BALANCE_ERROR(1501, "关闭余额账户失败"),
    MONTH_BILL_DUPLICATE_EXCEPTION(1502, "该老人的月度账单已生成,不可重复生成"),
    MONTH_OUT_CHECKIN_TERM(1503, "该月不在费用期限内");
    /**
     * 编码
     */
    public final int code;
    /**
     * 信息
     */
    public final String msg;
}
  • GlobalExceptionHandler  全局异常处理器
package com.zzyl.exception;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.zzyl.base.ResponseResult;
import com.zzyl.enums.BasicEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import java.io.FileNotFoundException;
import java.nio.file.AccessDeniedException;
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /**
     * 处理自定义异常BaseException。
     * 返回自定义异常中的错误代码和错误消息。
     *
     * @param exception 自定义异常
     * @return 响应数据,包含错误代码和错误消息
     */
    @ExceptionHandler(BaseException.class)
    public ResponseResult<Object> handleBaseException(BaseException exception) {
        exception.printStackTrace();
        if (ObjectUtil.isNotEmpty(exception.getBasicEnum())) {
            log.error("自定义异常处理:{}", exception.getBasicEnum().getMsg());
        }
        return ResponseResult.error(exception.getBasicEnum());
    }
    /**
     * 处理其他未知异常。
     * 返回HTTP响应状态码500,包含错误代码和异常堆栈信息。
     *
     * @param exception 未知异常
     * @return 响应数据,包含错误代码和异常堆栈信息
     */
    @ExceptionHandler(Exception.class)
    public ResponseResult<Object> handleUnknownException(Exception exception) {
        exception.printStackTrace();
        if (ObjectUtil.isNotEmpty(exception.getCause())) {
            log.error("其他未知异常:{}", exception.getMessage());
        }
        return ResponseResult.error(500,exception.getMessage());
    }
}

项目中集成

程序员手动抛出业务异常

当床位新增失败的时候,可以直接抛出BaseException

@Override
public void addBed(BedDto bedDto) {
    Bed bed = BeanUtil.toBean(bedDto, Bed.class);
    bed.setCreateTime(LocalDateTime.now());
    bed.setCreateBy(1L);
    bed.setBedStatus(0);
    try {
        bedMapper.addBed(bed);
    } catch (Exception e) {
        throw new BaseException(BasicEnum.BED_INSERT_FAIL);
    }
}

测试:

当重复录入床位编号的时候,则会抛出:床位新增失败,而此时的执行逻辑就是走了全局异常处理器


不可知异常处理

比如,在文件上传的接口中,如果上传文件失败,则可以抛出RuntimeException异常,由于RuntimeException异常不是自定义异常,一旦触发就是走全局异常处理器的未知异常

/**
 * 文件上传
 *
 * @param file 文件
 * @return 上传结果
 * @throws Exception 异常
 */
@PostMapping("/upload")
@ApiOperation("文件上传")
public ResponseResult<String> upload(
        @ApiParam(value = "上传的文件", required = true)
        @RequestPart("file") MultipartFile file) throws Exception {
    // 校验是否为图片文件
    try {
        BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
    } catch (Exception e) {
        throw new RuntimeException("上传图片失败");
    }
    if (file.getSize() == 0) {
        throw new RuntimeException("上传图片不能为空");
    }
    // 获得原始文件名
    String originalFilename = file.getOriginalFilename();
    // 获得文件扩展名
    String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
    String fileName = UUID.randomUUID().toString() + extension;
    String filePath = fileStorageService.store(fileName, file.getInputStream());
    return ResponseResult.success(filePath);
}

结论:

  • 一旦文件上传失败,则会走全局异常处理器的未知异常
  • 如果系统抛出了其他异常,非BaseException,都会走未知异常
目录
相关文章
|
6月前
|
数据采集 机器学习/深度学习 自然语言处理
NLP助力非结构化文本抽取:实体关系提取实战
本文介绍了一套基于微博热帖的中文非结构化文本分析系统,通过爬虫代理采集数据,结合NLP技术实现实体识别、关系抽取及情感分析。核心技术包括爬虫模块、请求配置、页面采集和中文NLP处理,最终将数据结构化并保存为CSV文件或生成图谱。代码示例从基础正则规则到高级深度学习模型(如BERT-BiLSTM-CRF)逐步演进,适合初学者与进阶用户调试与扩展,展现了中文NLP在实际场景中的应用价值。
500 3
NLP助力非结构化文本抽取:实体关系提取实战
|
8月前
|
消息中间件 架构师 Apache
一本书精通Apache RocketMQ
一本书精通Apache RocketMQ
319 3
|
存储 缓存 NoSQL
分布式缓存中间件Redis入门
本文主要就介绍了以下什么是redis、redis的数据结构以及其简单使用。redis其实在日常的生产中使用到的机会还是很大的。所以学会redis也是提高自身硬实力的一种重要方式,这样才能在面试中取得好成绩。
4769 90
分布式缓存中间件Redis入门
|
安全 前端开发 网络安全
【Azure App Service】访问App Service应用报错 SSL: WRONG_VERSION_NUMBER(上海蓝云阻断页)
在Azure App Service上部署的应用遇到`SSL: WRONG_VERSION_NUMBER`错误。问题可能由不兼容的TLS版本引起,但即使将最小入站TLS版本改为1.2,问题仍存在。实际原因是上海蓝云的阻断页面,表明网站未完成ICP备案或有安全规定限制。解决方案包括:1) 对App Service绑定自定义域名并进行ICP备案,或2) 使用Application Gateway处理公网请求。在复杂环境中,需仔细排查和适配规则。
505 11
|
数据采集 消息中间件 分布式计算
系统架构+技术选型+用例说明|学习笔记
快速学习系统架构+技术选型+用例说明
系统架构+技术选型+用例说明|学习笔记
|
容器
Element UI 自定义环形进度条里的内容
Element UI 自定义环形进度条里的内容
591 2
|
监控 测试技术
深入分析软件测试中的风险评估与管理
【5月更文挑战第30天】 在软件开发生命周期中,风险无处不在,特别是在软件测试阶段。本文旨在探讨软件测试过程中如何有效地进行风险评估和管理,以确保软件质量和项目成功。文中将介绍风险评估的基本概念,提出一个结构化的风险识别和评估框架,并详细讨论如何通过定性和定量方法来管理测试风险。此外,文章还将展示一个案例研究,以说明所提策略在实际中的应用效果。
|
机器学习/深度学习 JSON 文字识别
OCR文字识别技术总结(一)
OCR (Optical Character Recognition,光学字符识别)是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,经过检测暗、亮的模式肯定其形状,而后用字符识别方法将形状翻译成计算机文字的过程;即,针对印刷体字符,采用光学的方式将纸质文档中的文字转换成为黑白点阵的图像文件,并经过识别软件将图像中的文字转换成文本格式,供文字处理软件进一步编辑加工的技术。如何除错或利用辅助信息提升识别正确率,是OCR最重要的课题,ICR(Intelligent Character Recognition)的名词也随之产生。
5329 0
OCR文字识别技术总结(一)
|
监控 JavaScript 数据安全/隐私保护
PON网络架构及数据传输方式
当前,光纤到户(FTTH)技术的领先方案是被称为PON的技术。这项技术最初主要用于为家庭和商业客户提供网络服务,但随着时间的推移,PON的应用范围已经扩展到大型企业园区(通过POL技术)乃至特定行业网络(F5G技术),成为一个迅猛发展的领域。
987 1
|
JSON JavaScript 前端开发
全面的.NET微信网页开发之JS-SDK使用步骤、配置信息和接口请求签名生成详解
全面的.NET微信网页开发之JS-SDK使用步骤、配置信息和接口请求签名生成详解
391 0