SpringMVC-异常处理

目录

HandlerExceptionResolver接口

使用注解实现异常分类管理(@ControllerAdvice 和 @ExceptionHandler)

使用 @ControllerAdvice 对不同的 Controller 分别捕获异常并处理


HandlerExceptionResolver接口

  • 在SpringMVC中,提供了一个全局异常处理器,用于对系统中出现的异常进行统一处理
  • 在一般的系统中,DAO层、Service层及Controller层出现异常都以“throws Exception”的形式向上层抛出,最后都会由SpringMVC的前端控制器(DispatcherServlet)统一交给全局异常处理器进行异常处理
  • 在SpringMVC中提供的HandlerExceptionResolver接口可以实现全局异常处理器
  • Spring MVC接口HandlerExceptionResolver用于抽象一个异常解析器
  • 这种异常解析器被用于分析请求处理器Handler映射或者执行过程中的异常,将这些异常转换成其他形式展示给用户

  • 可以看到,HandlerExceptionResolver接口中定义了一个名为resolveException的方法,该方法主要用于处理Controller中的异常
  • 参数“Exception ex”即为Controller或其下层抛出的异常
  • 参数“Object handler”就是处理器适配器要执行的Handler对象
  • resolveException方法的返回值类型是ModelAndView,也就是说,可以通过这个返回值来设置发送异常时的显示页面

  • 典型的做法是转换成一个错误视图,或者返回某个HTTP状态码给请求端
  • 使用HandlerExceptionResolver实现全局异常处理器;当抛出异常后,要有相应的符合用户体验的友好界面显示异常
  • 综合实例:
  • (1)创建自定义异常类,名称为OperationException

  • 注意:
  • Spring管理的事务,无论是声明式事务还是注解式事务默认是在抛出运行异常(RuntimeException异常)时,才会被Spring框架捕获到然后回滚
  • 该自定义异常类继承的是RuntimeException类,因为一般项目的Service层逻辑都会使用Spring提供的事务管理,当Service层需要抛出自定义异常时,如果该自定义异常继承的是Exception类,则Spring提供的事务管理将会失效,所以这里的自定义异常类继承的是RuntimeException类,这样才不会使Spring提供的事务管理失效
  • (2)创建全局异常处理器OperationExceptionResolver类,该类实现HandlerExceptionResolver接口,并且实现resolveException方法

  • (3)创建名称为error.jsp的页面,符合用户体验的友好界面,用于显示异常信息

  • Spring MVC 为HandlerExceptionResolver提供了四个实现类

(1)ExceptionHandlerExceptionResolver

  • 找到使用@ExceptionHandler注解的ServletInvocableHandlerMethod并调用,基于其执行结果构建ModelAndView

(2)SimpleMappingExceptionResolver

  • 映射异常类名到视图名称,处理时使用此映射关系构建ModelAndView,或者使用缺省视图

(3)ResponseStatusExceptionResolver

  • 如果异常是ResponseStatusException或者使用了注解@ResponseStatus,则利用这些信息将异常翻译成HTTP状态字调用相应的sendError,返回空ModelAndView
  • 注意:该异常解析器会递归检查异常的cause异常

(4)DefaultHandlerExceptionResolver

  • Spring MVC缺省异常处理器,解析时将标准MVC异常翻译成HTTP状态字调用相应对象的方法#sendError,返回一个空ModelAndView对象(注意:不是null)

使用注解实现异常分类管理(@ControllerAdvice 和 @ExceptionHandler)

  • 引言:
  • 在开发中,我们会有如下的场景:某个接口中,存在一些业务异常
  • 例如用户输入的参数校验失败、用户名密码不存在等
  • 当触发这些业务异常时,我们需要抛出这些自定义的业务异常,并对其进行处理
  • 一般我们要把这些异常信息的状态码和异常描述,友好地返回给调用者,调用者则利用状态码等信息判断异常的具体情况
  • 过去,我们可能需要在 controller 层通过 try/catch 处理
  • 首先 catch 自定义异常,然后 catch 其它异常
  • 对于不同的异常,我们需要在 catch 的同时封装将要返回的对象
  • 然而,这么做的弊端就是代码会变得冗长
  • 每个接口都需要做 try/catch 处理,而且一旦需要调整,所有的接口都需要修改一遍,非常不利于代码的维护,如下段代码所示:

  • 那么,有没有什么方法可以简便地处理这些异常信息呢?
  • 答案是肯定的
  • Spring 3.2 中,新增了 @ControllerAdvice 注解,可以用于定义 @ExceptionHandler、@InitBinder、@ModelAttribute,并应用到所有 @RequestMapping 中
  • 简单来说就是,可以通过 @ControllerAdvice 注解配置一个全局异常处理类,来统一处理 controller 层中的异常,于此同时 controller 中可以不用再写 try/catch,这使得代码既整洁又便于维护

  • 综合实例:定义自定义异常
  • (1)自定义业务异常类

  • (2)@ControllerAdvice + @ExceptionHandler 配置全局异常处理类

@ControllerAdvice

  • 类型:类注解;定义该类为全局异常处理类

@ExceptionHandler

  • 类型:方法注解;定义该方法为异常处理方法
  • value 的值为需要处理的异常类的 class 文件

  • 这样,就可以对不同的异常进行统一处理了
  • 通常,为了使 controller 中不再使用任何 try/catch,也可以在 GlobalExceptionHandler 中对 Exception 做统一处理
  • 这样其他没有用 @ExceptionHandler 配置的异常就都会统一被处理
  • 遇到异常时抛出异常即可
  • 在业务中,遇到业务异常的地方,直接使用 throw 抛出对应的业务异常即可
  • 例如:


注意:

  • 不一定必须在 controller 层本身抛出异常才能被 GlobalExceptionHandler 处理,只要异常最后是从 contoller 层抛出去的就可以被全局异常处理器处理
  • 异步方法中的异常不会被全局异常处理
  • 抛出的异常如果被代码内的 try/catch 捕获了,就不会被 GlobalExceptionHandler 处理了

优点:

  • 减少代码冗余,代码便于维护

缺点:

  • 只能处理 controller 层抛出的异常,对例如 Interceptor(拦截器)层的异常、定时任务中的异常、异步方法中的异常,不会进行处理

使用 @ControllerAdvice 对不同的 Controller 分别捕获异常并处理

  • 引言
  • 上文介绍了如何在 SpringBoot 工程中对 Controller 配置全局异常处理
  • 后来在实际工程中,又有了如下需求:有些接口在发生异常时,需要持久化错误信息,而有的接口则不需要
  • 如果使用了全局异常处理,那每次发生了异常,还需要判断是哪个接口发生的异常,进而选择是否持久化错误日志
  • 那能不能对全局异常进行配置,对不同类型的接口使用不同的全局异常进行处理呢?
  • 经过查阅文档发现,Spring 提供了对 @ControllerAdvice 注解的配置,我们可以通过配置 @ControllerAdvice 指定拦截范围
  • @ControllerAdvice 指定 Controller 范围
  • 根据 API,我们可以看到注解 @ControllerAdvice 有如下几种配置:

(1)basePackages

  • basePackages:指定一个或多个包,这些包及其子包下的所有 Controller 都被该 @ControllerAdvice 管理
  • 其中上面两种等价于 basePackages

(2)basePackageClasses

  • basePackageClasses:是 basePackages 的一种变形,指定一个或多个 Controller 类,这些类所属的包及其子包下的所有 Controller 都被该 @ControllerAdvice 管理

(3)assignableTypes

  • assignableTypes:指定一个或多个 Controller 类,这些类被该 @ControllerAdvice 管理

(4)annotations

  • annotations:指定一个或多个注解,被这些注解所标记的 Controller 会被该 @ControllerAdvice 管理

  • 例子
  • 这里用 assignableTypes 配置指定的 Controller 进行测试

(1)创建三个 Controller

  • 其中,BusinessException 是自定义的异常类

(2)创建两个全局异常处理类

(3)分别调用接口,查看错误日志

  • (1)调用 localhost:8080/test1

  • 返回:GlobalExceptionHandler1 服务错误

  • 即 MyController1 异常被 GlobalExceptionHandler1 全局异常类捕获

  • (2)调用 localhost:8080/test2

  • 返回:GlobalExceptionHandler2 服务错误

  • 即 MyController2 异常被 GlobalExceptionHandler2 全局异常类捕获

  • (3)调用 localhost:8080/test3

  • 返回:

  • 即 MyController3 异常没有被全局异常捕获

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

特征抽取-----机器学习pycharm软件

导入包 from sklearn.datasets import load_iris # 方法datasets_demo()数据集使用 from sklearn.feature_extraction import DictVectorizer # 方法dict_demo()字典特征抽取用 from sklearn.feature_extraction.text import CountVectorizer # 方法count_demo()文本特征抽…

民用激光雷达行业简析

01. 激光雷达是“机器之眼” • 激光雷达是一个通过发射激光并接受发射激光同时对其进行信号处理,从而获得周边物体距离等信息的主动测量装置。 • 激光雷达主要由光发射、光扫描、光接收三大模块组成。光发射模块集成了驱动、开关和光源等芯片。光接收模块集成了…

【AIGC】Diffusers:扩散模型的开发手册说明2

前言 扩散器被设计成一个用户友好且灵活的工具箱,用于构建适合您用例的扩散系统。工具箱的核心是模型和调度程序。然而 DiffusionPipeline 为方便起见将这些组件捆绑在一起,但您也可以解包管道并分别使用模型和调度程序来创建新的扩散系统。 解构 Stab…

文件备份管理软件系统

1、我解决的问题 避免因为硬盘故障,导致数据丢失; 避免因为中了病毒,文件被加密,无法取回; 避免了员工恶意删除文件; 规范企业内部的文件管理,使它井井有条; 防范于未然,不必再为可能的风险担忧; 2、我的优点 我支持定…

第二篇【传奇开心果系列】beeware的toga开发移动应用示例:手机应用视频播放器

传奇开心果博文系列 系列博文目录beeware的toga开发移动应用示例系列 博文目录一、项目目标二、编程思路三、初步实现项目目标示例代码四、第一次扩展示例代码五、第二次扩展示例代码六、第三次扩展示例代码七、第四次扩展示例代码八、第五次扩展示例代码九、第六次扩展示例代码…

1.19号网络

超时检测 概念 1> 在网络通信中,有很多函数是阻塞函数,会导致进程的阻塞,例如:accept、recv、recvfrom、等等 2> 为了避免进程在阻塞函数处,无休止的等待,我们可以设置一个超时时间,当…

详细分析MybatisPlus中的Page类(附实战)

目录 前言1. 基本知识2. 常用方法3. 实战 前言 由于工作中经常使用到MybatisPlus的框架,对此详细连接Page类有利于开发,更加游刃有余 对于该类的源码:baomidou / mybatis-plus 中的Page源码 MybatisPlus的框架:MyBatis-plus从入…

【操作系统基础】【CPU访存原理】:寄存 缓存 内存 外存、内存空间分区、虚拟地址转换、虚拟地址的映射

存储器怎么存储数据、内存空间分区、虚拟地址转换 计算机的存储器:寄存 缓存 内存 外存(按功能划分) 计算机的处理器需要一个存储器来存储大量的指令和数据以便自己不断取指执行和访问数据。 内存(内存就是运行内存&#xff0c…

java web 校园健康管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web校园健康管理系统是一套完善的java web信息管理系统 ,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发,数据库为Mysq…

宠物空气净化器怎么挑选?猫用空气净化器品牌性比价推荐

作为一个养猫家庭的主人,每天都要面对一个挑战——清理猫砂盆。那种难以形容的气味实在让人受不了。尤其是家里有小孩和老人,他们偶尔可能会出现过敏性鼻炎等问题,而抵抗力较差的人更容易受到影响。此外,一到换毛季节,…

【基础算法练习】二分模板

文章目录 二分模板题二分的思想C 版本的二分整数二分模板 Golang 版本的二分整数二分模板 例题:在排序数组中查找元素的第一个和最后一个位置题目描述C 版本代码Golang 版本代码 二分模板题 704. 二分查找,这道题目是最经典的二分查找,使用于…

Spring依赖注入之setter注入与构造器注入以及applicationContext.xml配置文件特殊值处理

依赖注入之setter注入 在管理bean对象的组件的时候同时给他赋值,就是setter注入,通过setter注入,可以将某些依赖项标记为可选的,因为它们不是在构造对象时立即需要的。这种方式可以减少构造函数的参数数量,使得类的构…

天津大数据培训班推荐,数据分析过程的常见错误

大数据”是近年来IT行业的热词,目前已经广泛应用在各个行业。大数据,又称海量信息,特点是数据量大、种类多、实时性强、数据蕴藏的价值大。大数据是对大量、动态、能持续的数据,通过运用分析、挖掘和整理,实现数据信息…

生产力工具|卸载并重装Anaconda3

一、Anaconda3卸载 (一)官方方案一(Uninstall-Anaconda3-不能删除配置文件) 官方推荐的方案是两种,一种是直接在Anaconda的安装路径下,双击: (可以在搜索栏或者使用everything里面搜…

Windows10上通过MSYS2编译FFmpeg 6.1.1源码操作步骤

1.从github上clone代码,并切换到n6.1.1版本:clone到D:\DownLoad目录下 git clone https://github.com/FFmpeg/FFmpeg.git git checkout n6.1.1 2.安装MSYS2并编译FFmpeg源码: (1).从https://www.msys2.org/ 下载msys2-x86_64-20240113.exe &#…

超优秀的三维模型轻量化、格式转换、可视化部署平台!

1、基于 HTML5 和 WebGL 技术,可在主流浏览器上进行快速浏览和调试,支持PC端和移动端 2、自主研发 AMRT 展示框架和9大核心技术,支持3D模型全网多端流畅展示与交互 3、提供格式转换、减面展UV、烘焙等多项单模型和倾斜摄影模型轻量化服务 4、…

Java实现对系统CPU、内存占用率的控制

背景:由于使用的业主的云资源,由于使用率低,会不持续的缩减服务器配置。为了避免后续由于新业务上线,需要更多资源的时候,无法再次获得资源(回收容易,申请难)。 问题:怎…

Git学习笔记(第9章):国内代码托管中心Gitee

目录 9.1 简介 9.1.1 Gitee概述 9.1.2 Gitee帐号注册和登录 9.2 VSCode登录Gitee账号 9.3 创建远程库 9.4 本地库推送到远程库(push) 9.5 导入GitHub项目 9.6 删除远程库 9.1 简介 9.1.1 Gitee概述 众所周知,GitHub服务器在国外,使用GitHub作为…

3.1集合-Set+集合-list

一、数据结构 1.1什么是数据结构 数据结构就是用来装数据以及数据与之间关系的一种集合,如何把相关联的数据存储到计算机,为后续的分析提供有效的数据源,是数据结构产生的由来。数据结构就是计算机存储、组织数据的方式。好的数据结构&…

数据结构·单链表

不可否认的是,前几节我们讲解的顺序表存在一下几点问题: 1. 中间、头部的插入和删除,需要移动一整串数据,时间复杂度O(N) 2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗 3. 增容一般是2倍的增…