springMVC-15 异常处理

异常处理-基本介绍

  • 基本介绍

1.Spring MVC通过HandlerExceptionResolver处理程序的异常,包括Handler映射、数据绑定以及目标方法执行时发生的异常。
2.主要处理Handler中用@ExceptionHandler注解定义的方法。
3.ExceptionHandlerMethodResolver内部若找不到@ExceptionHandler注解的话,会找@ControllerAdvice类的@ExceptionHandler注解方法,这样就相当于一个全局异常处理器

异常类型

1.局部异常

在注释了@Controller的处理器类Handler,内部写的异常处理,就是局部异常

需要使用注解@在其方法上进行标注

应用实例

处理原因:如果不处理异常,显示界面会非常的不友好

1.创建com/stein/springMVC/exception/MyExceptionHandler.java

注意:

        1)Handler要用@Component注入到容器中

        2)局部异常处理方法,用使用@ExceptionHandler进行注解

        3)@ExceptionHandler的参数,是填写异常类型,并且可以是数组的形式

@Controller
public class MyExceptionHandler {//一个正常的方法映射@RequestMapping("/arithmetic")public String exceptionDemo(Integer num){Integer result=100/num;System.out.println("result= "+result);return "success";}@ExceptionHandler({ArithmeticException.class, NullPointerException.class})public String exceptionHandler(Exception exception, HttpServletRequest request){System.out.println("exception= "+exception.getMessage());request.setAttribute("exception", exception.getMessage());return "exception_msg";}}

2.创建操作页面 web/exception.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>exception</title>
</head>
<body><h1>局部异常处理</h1><a href="<%=request.getContextPath()%>/arithmetic?num=0">点击显示算数异常</a>
</body>
</html>

3.创建异常显示页面,web/WEB-INF/page/exception_msg.jsp

<body><h1>出错啦>_<</h1><h2>出错信息:<%=request.getAttribute("exception")%></h2>
</body>

4.测试

然后显示出错信息

Debug代码

        异常是通过ExceptionHandlerMethodResolver.java类来处理的,它的异常处理机制比较多。通过Ctrl+N找到

        通过形参exceptionType拿到异常,然后再拿到处理异常的method,最后通过反射调用。

        这一步是通过默认的方法查找异常处理方法,没有找到就返回null

Method method = (Method)this.exceptionLookupCache.get(exceptionType);

        然后找到了我写的MyExceptionHandler.exceptionHanler(exception,request)方法

       

        不出意外的,找到了我写的异常处理方法

        最终返回前端页面进行展示

2.全局异常

应用实例

        全局异常处理机制:

        如果在ExceptionHandlerMethodResolver内部找不到@ExceptionHandler注解的话,
        会去@ControllerAdvice类找@ExceptionHandler注解方法,这样就相当于一个全局异常处理器

1.创建全局异常类,com/stein/springMVC/exception/GlobalException.java

//加入这个注解后,就表示是一个全局异常
//全局异常就不管是哪个Handler抛出的异常,都可以捕获
//控制通知
@ControllerAdvice
public class GlobalException {//注解参数用于指定,需要捕获的异常类型//1. 模拟NumberFormatException//2. 在之前的局部异常中,没有对NumberFormatException异常进行涵盖//3. 所以就会来找全局异常处理@ExceptionHandler({NumberFormatException.class, ClassCastException.class})public String global(Exception ex, HttpServletRequest request) {System.out.println("全局异常信息:"+ex.getMessage());request.setAttribute("exception", ex.getMessage());return "exception_msg";}
}

2.增加出现转换异常的方法,com/stein/springMVC/exception/MyExceptionHandler.java

    @RequestMapping("/global")public String globalExceptionDemo(String num){int i = Integer.parseInt(num);return "success";}

3.修改页面,增加装换异常访问请求exception.jsp

<body><h1>异常处理</h1><a href="<%=request.getContextPath()%>/arithmetic?num=0">点击显示局部异常</a><br><a href="<%=request.getContextPath()%>/global?num=hello">点击显示全局异常</a>
</body>

4.测试

        选择全局异常

        显示全局异常提示信息

5.postman测试

Debug处理流程

        依然点击全局异常

        断点不变,可以看到发生了数字格式化异常,这一步method没有找到处理异常方法,为null

        看到此时,method找不到在@Controller类中的局部异常处理方法,显示noMatchingExceptionHandler,没有匹配的异常处理

        找到了全局异常处理方法

         进入到处理方法

        最终成功显示异常信息

注意事项与细节

        异常处理时:局部异常优先级高于全局异常

        给局部异常处理添加上NumberFormatException.class后,局部异常优先处理

        局部异常exception= For input string: "hello"

3.自定义异常(类型)

        局部异常和全局异常,是通过作用范围来区分的。

        自定义异常,说的是自定义异常的类型。比如有ArithmeticException.class, NullPointerException.class,NumberFormatException.class这些异常了,我还需要自定义一个年龄异常AgeException.class

        通过@ResponseStatus注解,可以自定义该异常

        关系:那么自定义异常(类型),可以通过默认tomcat调用,或者局部异常、全局异常进行选择调用。像这样:

@ExceptionHandler({ArithmeticException.class, NullPointerException.class,NumberFormatException.class,ArithmeticException.class})
应用实例

1.创建自定义异常类型,com/stein/springMVC/exception/AgeException.java

//reason表示显示的错误原因
//value填写Http错误状态,是枚举类型的
@ResponseStatus(value = HttpStatus.BAD_REQUEST,reason = "年龄需要在1-120岁之间")
public class AgeException extends RuntimeException {
}

2.添加可能出现自定义异常的方法,MyExceptionHandler.java

    @RequestMapping("/age")public String age(int age){if(age>0 && age<120){return "success";}else {throw new AgeException();}}

3.添加访问链接,exception.jsp

<a href="<%=request.getContextPath()%>/age?age=121">点击显示自定义异常</a><br><br>

4.测试

        自定义异常(类型)

        返回结果


这个tomcat默认页面太生硬,想用自己页面显示

1.把AgeException.class添加到GlobalException.global()的注解中

@ExceptionHandler({NumberFormatException.class, ClassCastException.class,AgeException.class})

2.为了配合exception_msg.jsp的属性exception.getMessage()返回结果不为null,添加AgeException.java的构造器

@ResponseStatus(value = HttpStatus.BAD_REQUEST,reason = "年龄需要在1-120岁之间")
public class AgeException extends RuntimeException {public AgeException() {}public AgeException(String message) {super(message);}
}

3.业务代码中,完善message

    @RequestMapping("/age")public String age(int age){if(age>0 && age<120){return "success";}else {throw new AgeException("年龄需要在1-120岁之间");}}

4.再次测试

点击自定义异常后,出现了我们自己写的异常页面exception_msg.jsp

同样,这个自定义异常类型,添加到局部异常也可以生效,这儿就不演示了。

Debug处理流程

        跟全局异常Debug一样,参考走一遍即可。

统一处理异常信息

SimpleMappingExceptionResolver

  • 基本说明

1.如果希望对所有异常进行统一处理,可以使用SimpleMappingExceptionResolver
2.它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常
3.需要在ioc容器中配置

应用实例

1.配置SimpleMappingExceptionResolver

    <!--配置一个统一异常处理--><bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><!--这个属性用于设置异常映射,即当发生某种异常时,应该跳转到哪个视图。--><property name="exceptionMappings"><!--它包含一个`<props>`标签,这是Spring配置中用于定义`java.util.Properties`类型属性的方式。每个`<prop>`标签表示一个键值对。--><props><!--键(key)是异常类的全限定名--><!--值(value)是`arrEx`,是一个逻辑视图页面--><prop key="ArrayIndexOutOfBoundsException">arrEx</prop></props></property></bean>

2.按配置创建异常视图,web/WEB-INF/page/arrEx.jsp

<h1>朋友,当前页面异常>_<,如有疑问,可以联系管理员</h1>

3.增加出现数组越界的映射方法,MyExceptionHandler

@RequestMapping("/array")
public String array(){//两种写法都可以int[] ints = {1, 3, 6, 12};//int[] ints =new int[]{1,3,6,12};//越界异常System.out.println("ints[5]="+ints[5]);return "success";
}

4.添加访问页面的链接,exception.jsp

    <a href="<%=request.getContextPath()%>/array">点击测试统一异常处理</a><br><br>

5.测试

对未知异常统一处理

        异常的情况有很多,当无法对每一种异常都进行单独配置的时候,需要一种兜底的方案,就是对其他异常的统一处理。

应用实例

1.使用SimpleMappingExceptionResolver进行配置,web/WEB-INF/springMVC-servlet.xml

    <!--配置一个统一异常处理--><bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><!--这个属性用于设置异常映射,即当发生某种异常时,应该跳转到哪个视图。--><property name="exceptionMappings"><!--它包含一个`<props>`标签,这是Spring配置中用于定义`java.util.Properties`类型属性的方式。每个`<prop>`标签表示一个键值对。--><props><!--键(key)是异常类的全限定名--><!--值(value)是`arrEx`,是一个逻辑视图页面--><prop key="java.lang.ArrayIndexOutOfBoundsException">arrEx</prop><!--两种写法都可以,但是推荐上面一种,避免重名--><!--<prop key="ArrayIndexOutOfBoundsException">arrEx</prop>--><!--配置其他的未知异常--><!--key配置的是所有异常Exception--><!--响应的页面名称是allEx--><prop key="java.lang.Exception">allEx</prop></props></property></bean>

2.创建响应页面,web/WEB-INF/page/allEx.jsp

    <h1>哎呀,发生了未知异常>_<</h1>

3.添加未知异常映射方法,MyExceptionHandler.java

        这是一个字符串越界异常

    @RequestMapping("/unknown")public String unknownException(){String str="hello";System.out.println("str.charAt[5]="+str.charAt(5));return "success";}

4.添加访问链接,exception.jsp

    <a href="<%=request.getContextPath()%>/unknown">配置统一的未知异常处理</a><br><br>

5.测试

哎呀,发生了未知异常>_<

异常处理的优先级

       

 局部异常 > 全局异常 > SimpleMappingExceptionResolver > tomcat默认机制

1.对比测试局部异常、全局异常、SimpleMappingExceptionResolver的优先级,他们3个的范围都加上ArrayIndexOutOfBoundsException.class,然后进行数组越界异常测试。

        结果响应的只有局部异常:

局部异常exception= 5

2.接下来取消局部异常的参赛资格,取消其ArrayIndexOutOfBoundsException.class的设置,将剩下2个的进行对比。然后进行数组越界异常测试。

        此时,响应的是全局异常

全局异常信息:5

3.然后全局异常退出,删除其越界异常的设置,只保留SimpleMappingExceptionResolver的设置,进行越界测试。

        结果是按照SimpleMappingExceptionResolver配置的arrEx.jsp进行了响应

朋友,当前页面异常>_<,如有疑问,可以联系管理员

4.将SimpleMappingExceptionResolver的设置也取消,包括越界异常和所有异常。进行越界测试

        结果,Tomcat默认的异常机制开始生效了

        综上,确认了他们的优先级排序。

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

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

相关文章

视频汇聚EasyCVR平台v3.7.2发布:新增全局搜索、播放器默认解码方式等4大功能

EasyCVR视频汇聚平台带着全新的v3.7.2版本重磅登场&#xff01;此次升级&#xff0c;绝非简单的功能堆砌&#xff0c;而是从用户体验、操作效率以及系统性能等多维度进行的深度优化与革新&#xff0c;旨在为大家带来更加强大、稳定且高效的视频监控管理体验。 一、全局功能搜索…

三、kubectl使用详解

三、kubectl使用详解 文章目录 三、kubectl使用详解1、常用基础命令1.1 Kubectl命令格式1.2 查询一个资源1.3 创建一个资源1.4 修改一个资源1.5 删除一个资源1.6 其他 2、K8s隔离机制Namespace&#xff08;命名空间作用及使用&#xff09;2.1 什么是命名空间2.2 命名空间主要作…

JVM内存模型详解

JVM内存模型详解 Java虚拟机(JVM)内存模型是理解Java程序运行机制的核心&#xff0c;它定义了程序运行时数据的组织方式和访问规则。与Java内存模型(JMM)关注并发不同&#xff0c;JVM内存模型主要描述运行时数据区的结构和功能。 一、JVM内存模型概述 JVM内存模型将运行时数…

《对话式 AI 白皮书》共创者招募

在 AI Agent 技术不断演变的当下&#xff0c;共创一本不断演变的对话式 AI 白皮书&#xff0c;共同探索人机对话的新纪元。无论你是开发者、技术专家、生态伙伴还是创业者&#xff0c;都期待你的加入。 项目地址&#xff1a;https://github.com/RTE-Dev/book_era_convoai/ 在…

Flux功能介绍,完整使用示例,与Mono对比

以下是关于Reactor框架中Flux与Mono的功能介绍、使用示例及对比分析&#xff1a; Flux功能介绍 核心定义 Flux是Reactor库中的核心接口&#xff0c;表示一个异步的、包含零到多个元素的序列&#xff08;类似流式数据处理&#xff09;[3][4][7]。它可以处理无限长度的数据流&am…

Git使用基本指南

一、Git 基础配置 首先需要配置用户信息&#xff0c;让 Git 知道你是谁&#xff1a; git config --global user.name "你的名字" git config --global user.email "你的邮箱example.com" 如果需要查看配置信息&#xff0c;可以使用&#xff1a; git co…

【入门】【例17.3】 内功逼毒

| 时间限制&#xff1a;C/C 1000MS&#xff0c;其他语言 2000MS 内存限制&#xff1a;C/C 64MB&#xff0c;其他语言 128MB 难度&#xff1a;中等 分数&#xff1a;100 OI排行榜得分&#xff1a;12(0.1分数2难度) 出题人&#xff1a;root | 描述 黄蓉中了毒&#xff0c;在 t 时…

苹果芯片macOS安装版Homebrew(亲测)

在Linux服务器上安装一个软件常用yum&#xff0c;apt、dnf命令&#xff0c;同样macOS可以使用brew命令来安装软件。 brew会自动帮你下载、解压、安装和配置&#xff0c;更重要的是&#xff1a;它还会自动处理好软件之间的依赖关系&#xff0c;它将所有软件都安装在独立的统一目…

uniapp+vue3做小程序,获取容器高度

小程序获能用createSelectorQuery&#xff0c;如果是子组件&#xff0c;后面可以额外加一个参数in来指定获取dom的范围。小程序里面可以直接.in(this)&#xff0c;但是vue3没有this了&#xff0c;那就只能通过getCurrentInstance去获取当前实例代替this &#xff0c;注意这里需…

【网工】华为配置专题进阶篇①

目录 ■浮动路由和BFD配置 ▲浮动路由 基本配置示例 ▲BFD ▲验证命令 ▲测试连通性 ■路由综合实验RIP OSPF BGP ■浮动路由和BFD配置 ▲浮动路由 浮动路由&#xff1a;设置preference 浮动路由是一种备份路由机制&#xff0c;当主路由失效时&#xff0c;浮动路由会…

DeepLegal AI:智能法律文档审查与合规助手+MVP

1. 商业价值与市场机会 DeepLegal AI旨在革新法律行业中耗时且资源密集型的文档审查和合规流程。该应用将利用DeepSeek先进的语言模型能力&#xff0c;为律师事务所、企业法务部门和合规团队提供一个高效、准确且经济的解决方案。 市场机会&#xff1a; 法律科技市场正经历爆…

使用 Rust 编写简单计算器

在编程语言的世界中&#xff0c;Rust 以其安全性和高性能而闻名。今天&#xff0c;我们将通过一个简单的项目来探索 Rust 的魅力 —— 编写一个简单的命令行计算器。这个计算器将支持基本的算术运算&#xff08;加、减、乘、除&#xff09;&#xff0c;并且可以通过用户输入进行…

清华大学:《AI赋能教育 :高考志愿填报工具使用指南》下载

志愿填报的认知革命已经到来 “分数出来了&#xff0c;但不知道能上什么学校……” “喜欢这个专业&#xff0c;但不知道就业前景怎么样&#xff1f;” “到底是选热门专业还是选兴趣爱好&#xff1f;” 这些让百万家庭彻夜难眠的问题&#xff0c;你是否正在经历&#xff1f; …

【科技公司的管理】

如何打造高效、人性化的目标驱动型公司&#xff1f;——OKR管理法绩效薪酬体系全指南 你希望公司目标清晰、员工高效、多劳多得&#xff0c;同时避免马斯克式的“冷血管理”&#xff0c;兼顾员工生活需求。以下是系统性解决方案&#xff0c;涵盖目标设定&#xff08;OKR&#x…

小白成长之路--nginx基础配置(一)

文章目录 一、概述1.1 Nginx 特点1.2 Nginx 作用1.3Nginx工作原理 二、Nginx服务搭建2.1安装2.2 目录结构2.3 配置文件作用2.4 nginx,conf配置文件详解2.5 核心命令2.6 Nginx信号三.Nginx3.1启动 总结 一、概述 Nginx 是开源、高性能、高可靠的 Web服务器 和反向代理服务器&am…

从最基础的float布局开始学前端

前端学习其实不难&#xff0c;我们先从float布局讲起&#xff0c;写一个最简单的导航栏&#xff1a;Logo在左&#xff0c;导航链接在右。下面是示例代码&#xff1a; <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"…

12. TypeScript 高级类型

TypeScript 中的高级类型包括映射类型、条件类型、字面量类型和递归类型等强大结构。这些特性使开发者能够表达类型之间更复杂的关系&#xff0c;从而处理边缘情况&#xff0c;并定义更动态、更灵活的类型系统。 一、映射类型 TypeScript 映射类型&#xff08;Mapped Types&a…

韩国证券交易所(KRX)全生态接入系统技术白皮书

核心价值&#xff1a;为全球最活跃的衍生品市场&#xff08;日均交易量480亿美元&#xff09;提供 5μs延迟引擎全合规认证&#xff0c;助力中资机构抢占韩国78%衍生品交易份额 一、KRX市场机遇与准入壁垒 1.1 核心数据锚定&#xff08;2025Q2&#xff09; 指标数值全球竞争力…

【Clickhouse系列】增删改查:对比mysql

目录 1. 写入操作 (INSERT) 2. 删除操作 (DELETE) 3. 更新操作 (UPDATE) 4. 查询操作 (SELECT) 5. 总结对比表&#xff1a; 6. 参考链接 核心哲学差异&#xff1a; MySQL&#xff1a; 面向在线事务处理。核心目标是保证数据的强一致性、原子性和低延迟的单行操作&#x…

低压电工作业中,如何正确选用熔断器的额定电流?

在低压电工作业中&#xff0c;正确选用熔断器额定电流需综合考虑负载类型、额定电流等因素&#xff0c;具体方法如下&#xff1a; 照明电路&#xff1a;对于白炽灯负载&#xff0c;熔体额定电流可按被保护电路上所有白炽灯工作电流之和的 1.1 倍选取。若是日光灯和高压水银荧…