【Spring实战】27 统一异常处理最佳实践

文章目录

    • 1. 自定义异常
    • 2. 统一异常处理
    • 3. 配置
    • 4. 应用
    • 5. 启动类
    • 6. 启动服务
    • 7. 验证
    • 8. 优点
    • 总结

在 Spring 项目中,有效的异常处理是确保应用程序稳定性用户体验的关键因素之一。通过实现统一异常处理,我们能够更好的管理和响应应用程序中的各种异常情况。本文将介绍在 Spring 项目中如何实现统一异常处理的最佳实践。

1. 自定义异常

首先,我们需要定义一些自定义异常类,以便能够区分和处理不同类型的异常。这样我们就可以在异常处理器中根据异常类型进行不同的处理。例如:此处我们定义了两种异常,找不到资源异常和校验失败异常。

ResourceNotFoundException.java

表示资源未找到的异常

package com.cheney.demo.exception;

public class ResourceNotFoundException extends RuntimeException {

    public ResourceNotFoundException() {
        super("Resource not found");
    }

    public ResourceNotFoundException(String message) {
        super(message);
    }

    public ResourceNotFoundException(String message, Throwable cause) {
        super(message, cause);
    }
}

ValidationException.java

表示验证失败的异常

package com.cheney.demo.exception;

public class ValidationException extends RuntimeException {

   public ValidationException() {
       super("Validation failed");
   }

   public ValidationException(String message) {
       super(message);
   }

   public ValidationException(String message, Throwable cause) {
       super(message, cause);
   }
}

上述两个自定义异常类的代码中:

  • 我们继承了 RuntimeException,这是一个运行时异常,它通常用于表示程序无法继续执行的情况。
  • 我们提供了多个构造函数,以便在创建异常实例时能够传递不同的信息和异常原因。
  • 构造函数中的 super 调用是为了将异常信息传递给父类,以便在异常发生时能够捕获和记录相关信息。

2. 统一异常处理

接下来,我们创建一个全局异常处理类,使用 @ControllerAdvice 注解标记,该类将捕获整个应用程序中抛出的异常,并通过 @ExceptionHandler 方法进行处理。

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
public class GlobalExceptionHandler {

    // 处理找不到资源异常
    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ResponseEntity<String> handleNotFoundException(ResourceNotFoundException ex) {
        return new ResponseEntity<>("找不到资源!", HttpStatus.NOT_FOUND);
    }

    // 处理校验失败异常
    @ExceptionHandler(ValidationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseEntity<String> handleValidationException(ValidationException ex) {
        return new ResponseEntity<>("校验失败!", HttpStatus.BAD_REQUEST);
    }

    // 处理其他异常
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseEntity<String> handleException(Exception ex) {
        return new ResponseEntity<>("服务器异常!", HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

在这个类中,我们通过 @ExceptionHandler 注解为不同类型的自定义异常定义了处理方法。每个方法都返回适当的HTTP响应码和消息。

3. 配置

确保在 Spring 配置文件中,server.error.include-stacktrace 配置项被设置为 never,以确保不将堆栈跟踪信息返回给客户端:

pom.xml

server.error.include-stacktrace=never

4. 应用

在你的控制器中,当出现需要处理的异常时,抛出相应的自定义异常:

package com.cheney.demo.controller;

import com.cheney.demo.exception.ResourceNotFoundException;
import com.cheney.demo.exception.ValidationException;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("demo")
public class DemoController {

    @GetMapping("resource")
    public ResponseEntity<Resource> checkResource() {
        // 业务逻辑,然后根据判断抛出异常
        throw new ResourceNotFoundException();
        // 正常返回
    }

    @GetMapping("validation")
    public ResponseEntity<Resource> checkValidation() {
        // 业务逻辑,然后根据判断抛出异常
        throw new ValidationException();
        // 正常返回
    }

    @GetMapping("other")
    public ResponseEntity<Resource> checkOther() throws Exception {
        // 业务逻辑,然后根据判断抛出异常
        throw new Exception();
        // 正常返回
    }
}

5. 启动类

DemoApplication.java

package com.cheney.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

6. 启动服务

在这里插入图片描述

7. 验证

1)访问下面 URL 验证 GlobalExceptionHandler 中的 handleNotFoundException 方法

http://localhost:8080/demo/resource

在这里插入图片描述

2)访问下面 URL 验证 GlobalExceptionHandler 中的 handleValidationException 方法

http://localhost:8080/demo/validation

在这里插入图片描述

3)访问下面 URL 验证 GlobalExceptionHandler 中的 handleException 方法

http://localhost:8080/demo/other

在这里插入图片描述

8. 优点

  • 一致性

    统一异常处理确保应用程序在不同地方抛出的异常都能够得到一致的处理方式。无论是在控制器、服务层、还是其他组件中,都能够通过相同的规则进行异常处理,保持了一致性。

  • 代码可读性

    通过将异常处理集中在一个地方,提高了代码的可读性。不同类型的异常有各自的处理逻辑,开发人员无需在每个地方都编写相同的异常处理代码,而是集中在全局异常处理器中进行维护。

  • 减少重复代码

    统一异常处理减少了代码中的冗余和重复,使得开发者能够更专注于业务逻辑而不是异常处理。这有助于减少错误,并提高开发效率。

  • 集中式问题追踪

    当应用程序遇到问题时,异常信息被集中记录,使得问题的诊断和修复更加方便。全局异常处理器允许你自定义日志输出、监控或通知等行为,方便问题的集中式追踪。

  • 用户友好的错误响应

    通过全局异常处理,可以为不同类型的异常定义适当的用户友好的错误响应。这有助于提高用户体验,让用户更容易理解发生了什么问题。

  • 安全性

    统一异常处理可以处理安全相关的异常,比如认证失败、权限不足等。通过在全局异常处理器中处理这些异常,可以更好地保护应用程序的安全性。

  • 灵活性

    全局异常处理允许开发者灵活地定义处理不同类型异常的策略。你可以根据具体的业务需求,为每种异常类型定义特定的处理方式,而不是在每个地方都硬编码相同的异常处理逻辑。

总结

通过这种方式,当你的应用程序中的任何地方抛出自定义异常时,全局异常处理类将捕获它并相应地处理异常。这提供了一种一致的方式来处理异常,提高了代码的可读性和可维护性。通过实现这些步骤,你可以在 Spring 项目中轻松实现统一异常处理,确保应用程序在面对异常情况时表现出一致的行为,提高用户体验和开发效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/306231.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue elementUI Tree 树形控件的使用方法

用清晰的层级结构展示信息&#xff0c;可展开或折叠。 效果演示 trees.vue代码 <template><div><!-- 树形控件 --><el-tree :data"treesList" :props"treesProps" show-checkbox node-key"id"default-expand-all :defau…

关于TLS相关安全配置问题

近期被信安部门反馈了TLS几个安全漏洞。 SSL/TLS协议信息泄露漏洞(CVE-2016-2183)【原理扫描】SSL/TLS 受诫礼(BAR-MITZVAH)攻击漏洞(CVE-2015-2808)【原理扫描】SSL/TLS 服务器瞬时 Diffie-Hellman 公共密钥过弱【原理扫描】SSL/TLS RC4 信息泄露漏洞(CVE-2013-2566)【原理扫…

步进电机介绍

一、什么是步进电机&#xff1a; 步进电机是一种将电脉冲信号转换成相应角位移或线位移的电动机。每输入一个脉冲信号&#xff0c;转子就转动一个角度或前进一步&#xff0c;其输出的角位移或线位移与输入的脉冲数成正比&#xff0c;转速与脉冲频率成正比。因此&#xff0c;步…

FPGA之按键消抖

目录 1.原理 2.代码 2.1 key_filter.v 2.2 tb_key_filter.v 1.原理 按键分为自锁式按键和机械按键&#xff0c;图左边为自锁式按键 上图为RS触发器硬件消抖&#xff0c;当按键的个数比较多时常常使用软件消抖。硬件消抖会使用额外的器件占用电路板上的空间。 思路就是使用延…

c++临时对象的探讨及相关性能提升

产生临时对象的情况 我们定义一个类进行测试 class tempVal { public:int v1, v2;tempVal(int v1 0, int v2 0);tempVal(const tempVal& t) :v1(t.v1), v2(t.v2) {cout << "调用拷贝构造函数" << endl;}virtual ~tempVal() {cout << "…

第九届云计算与大数据分析国际会议(ICCCBDA 2024)即将召开!

​ 第九届云计算与大数据分析国际会议&#xff08;ICCCBDA 2024&#xff09;将于2024年4月25-27日在中国成都召开。ICCCBDA自创办以来&#xff0c;已经成功召开了八届。此次会议将介绍一些当前和未来的前沿技术趋势、创新方案、研究成果&#xff0c;以及和云计算和大数据分析相…

数据讲述中国故事!和鲸助力中国综合社会调查(CGSS)数据分析与可视化大赛圆满收官

中国综合社会调查&#xff08;Chinese General Social Survey&#xff0c;CGSS&#xff09;始于 2003 年&#xff0c;由中国人民大学中国调查与数据中心&#xff08;NSRC&#xff09;常年负责其相关实施工作&#xff0c;作为我国最早具全国性、综合性、连续性的学术社会调查项目…

http跟https有什么区别?

HTTPS和HTTP的概念&#xff1a; HTTP&#xff1a;是互联网上应用最为广泛的一种网络协议&#xff0c;是一个客户端和服务器端请求和应答的标准&#xff08;TCP&#xff09;&#xff0c;用于从WWW服务器传输超文本到本地浏览器的传输协议&#xff0c;它可以使浏览器更加高效&am…

探索前端跨组件通信:EventBus在Vue和React中的应用

本文作者系360奇舞团前端开发工程师 EventBus 简介 事件总线&#xff08;Event Bus&#xff09;是一种用于组件间通信的模式&#xff0c;通常用于解决组件之间的解耦和简化通信的问题。在前端框架中&#xff0c;如 Vue.js&#xff0c;事件总线是一个常见的概念。基本上&#xf…

【hcie-cloud】【21】容器详解【容器网络说明、容器存储说明、容器镜像说明、dockerfile详述、缩略词】【下】

文章目录 容器介绍&#xff0c;容器工作机制、容器常用命令说明容器网络容器网络简介容器常用网络类型 - Bridge容器常用网络类型 - Host容器常用网络类型 - None其他容器网络类型【Macvlan、Overlay、IPvlan】容器网络相关配置 容器存储容器中应用数据的存储容器持久化存储配置…

HTML5 article标签,<time>...</time>标签和pubdate属性的运用

1、<article>...</article>标签的运用 article标签代表文档、页面或应用程序中独立的、完整的、可以独自被外部引用的内容。它可以是一篇博客或报竟杂志中的文章、一篇论坛帖子、一段用户评论或一个独立的插件&#xff0c;或者其他任何独立的内容。把文章正文放在h…

【HarmonyOS4.0】第四篇-ArkUI基础实战

一、ArkUI框架简介 ArkUI开发框架是方舟开发框架的简称&#xff0c;它是一套构建 HarmonyOS / OpenHarmony 应用界面的声明式UI开发框架&#xff0c;它使用极简的UI信息语法、丰富的UI组件以及实时界面语言工具&#xff0c;帮助开发者提升应用界面开发效率 30%&#xff0c;开发…

(23)Linux的软硬连接

前言&#xff1a;上一章我们讲解了 inode&#xff0c;为文件系统收了尾&#xff0c;这几章我们充分地讲解完了文件系统的知识点&#xff0c;现在我们开始开始学习软硬链接了。 软硬链接 1、Linux 下的快捷方式&#xff1a;软链接 上一章我们介绍完了 inode &#xff0c;我们…

试用统信服务器操作系统UOS 20

作者&#xff1a;田逸&#xff08;formyz&#xff09; 试用统信Linux操作系统UOS&#xff0c;想了解一下用已有的Linux经验能否轻松驾驭它。以便在某些场景下&#xff0c;可以多一种选择。本次试验在Proxmox VE 8&#xff08;以下简称PVE 8&#xff09;平台下进行&#xff0c;采…

【题解】—— LeetCode一周小结

1.经营摩天轮的最大利润 题目链接&#xff1a; 1599. 经营摩天轮的最大利润 你正在经营一座摩天轮&#xff0c;该摩天轮共有 4 个座舱 &#xff0c;每个座舱 最多可以容纳 4 位游客 。你可以 逆时针 轮转座舱&#xff0c;但每次轮转都需要支付一定的运行成本 runningCost 。摩…

JRT打印元素绘制协议之-A4Double

以前打印相信很多人因为A4打印两个报告头大过&#xff0c;M要把一堆报告既有A4的也有A5的还有微生物的&#xff0c;可能输出Page还不那么严谨。要么换页不对叠加了、要么多空白页、中间夹杂A4报告就更加头大。也有的人为了打印页码的共几页而头大。 借助新设计的优势&#xff…

uni-app中轮播图实现大图预览

参考效果 当轮播图滑动切换的时候更新自定义下标&#xff0c;当图片被点击的时候大图预览。 参考代码 商品详情页轮播图交互 <script setup lang"ts"> // 轮播图变化时 const currentIndex ref(0) const onChange: UniHelper.SwiperOnChange (ev) > …

TAX税类小知识

历史及发展 我国作为流转税为主国家&#xff0c;目前经历3类税制&#xff1a;统收统付--包干制---分税制&#xff0c; 分别对应时间为建国--改革开放--93年朱提出分税延续至今&#xff1b; 未来趋势必然是完善所得税。 ps:流转税是间接税&#xff0c;间接转嫁给消费者&#…

TypeScript基础

ts学习 目录概述需求&#xff1a; 设计思路实现思路分析1.TypeScript 基础类型2.TypeScript 变量声明3.TypeScript 接口4.TypeScript 类5.TypeScript 函数5.TypeScript 泛型5.TypeScript 枚举TypeScript 类型推论TypeScript 类型兼容性TypeScript 高级类型TypeScript 迭代器和生…

深度解析Dubbo的基本应用与高级应用:负载均衡、服务超时、集群容错、服务降级、本地存根、本地伪装、参数回调等关键技术详解

负载均衡 官网地址&#xff1a; http://dubbo.apache.org/zh/docs/v2.7/user/examples/loadbalance/ 如果在消费端和服务端都配置了负载均衡策略&#xff0c; 以消费端为准。 这其中比较难理解的就是最少活跃调用数是如何进行统计的&#xff1f; 讲道理&#xff0c; 最少活跃数…