Spring MVC 之 异常处理

news2025/6/6 13:52:01

使用Spring MVC可以很灵活地完成数据的绑定和响应,极大的简化了Java Web的开发。但Spring MVC提供的便利不仅仅如此,使用Spring MVC还可以很便捷地完成项目中的异常处理、自定义拦截器以及文件上传和下载等高级功能。本章将对Spring MVC提供的这些高级功能进行讲解。

异常处理

简单异常处理器

如果希望对Spring MVC中所有异常进行统一处理,可以使用Spring MVC提供的异常处理器HandlerExceptionResolver接口。

Spring MVC内部提供了HandlerExceptionResolver的实现类SimpleMappingExceptionResolver。它实现了简单的异常处理,通过该实现类可以将不同类型的异常映射到不同的页面,当发生异常的时候,实现类根据发生的异常类型跳转到指定的页面处理异常信息。实现类也可以为所有的异常指定一个默认的异常处理页面,当应用程序抛出的异常没有对应的映射页面,则使用默认页面处理异常信息。

案例演示

下面通过一个案例演示SimpleMappingExceptionResolver对异常的统一处理,案例具体实现步骤如下所示。

package com.lq.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Objects;

/**
 * @Author: Luqing Teacher
 * @CreateTime: 2025-03-13
 * @Description: ExceptionController
 * @Version: 1.0
 */


@Controller
public class ExceptionController {

    // 抛出空指针异常
    @RequestMapping("/showNullPointer")
    public void showNullPointer(){
        ArrayList<Object> list = new ArrayList<>();
        System.out.println(list.get(2));
    }

    // 抛出IO异常
    @RequestMapping("/showIOException")
    public void showIOException() throws FileNotFoundException {
        FileInputStream in = new FileInputStream("javaweb.xml");
    }

    // 抛出算术异常
    @RequestMapping("/showArithmetic")
    public void showArithmetic(){
        int a = 1/0;
    }
}

程序执行文件ExceptionController.java中的任意一个方法时,都会抛出异常。在异常发生时,如果要跳转到指定的处理页面,则需要在Spring MVC的配置文件spring-mvc.xml中使用SimpleMappingExceptionResolver指定异常和异常处理页面的映射关系。Spring MVC配置文件的部分配置如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!-- 配置 Spring MVC 要扫描的包 -->
    <context:component-scan base-package="com.lq.controller"/>
    <!-- 配置视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    <!-- 配置注解驱动 -->
    <mvc:annotation-driven />
    <!--配置静态资源的访问映射,此配置中的文件,将不被前端控制器拦截 -->
    <mvc:resources mapping="/js/**" location="/js/" />
    <!-- 注入 SimpleMappingExceptionResolver 异常处理器-->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <!-- 定义特殊处理的异常,类名或完全路径名作为key,对应的异常页面名作为值-->
        <property name="exceptionMappings">
            <props>
                <prop key="java.lang.NullPointerException">nullPointerExp.jsp</prop>
                <prop key="java.io.IOException">IOExp.jsp</prop>
            </props>
        </property>
        <!-- 为所有异常定义默认的异常页面,value为默认的异常页面名-->
        <property name="defaultErrorView" value="defaultExp.jsp"/>
        <!-- value定义在异常处理页面中获取异常信息的变量名,默认为exception -->
        <property name="exceptionAttribute" value="exp"/>
    </bean>
</beans>

在文件spring-mvc.xml中,已经指定了异常类别对应的异常处理页面,接下来创建这些异常处理页面。在此不对异常处理页面做太多处理,只在页面中展示对应的异常信息。

接下来在webapp下创建nullPointerExp.jsp、IOExp.jsp、defaultExp.jsp页面分别如下:(内容修改成指定的页面)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>空指针异常处理页面</title></head>
<body>
空指针异常处理页面-----${exp}
</body>
</html>

结果如下:

从图中所示的信息可以看出,程序在抛出异常时,会跳转到异常类型对应的异常处理页面中。如果抛出的异常没有在Spring MVC的配置文件中指定对应的异常处理页面,那么程序会跳转到指定的默认异常处理页面。

自定义异常处理器

resolveException()方法

除了使用SimpleMappingExceptionResolver进行异常处理,还可以自定义异常处理器统一处理异常。通过实现HandlerExceptionResolver接口,重写异常处理方法resolveException()来定义自定义异常处理器。当Handler执行并且抛出异常时,自定义异常处理器会拦截异常并执行重写的resolveException()方法,该方法返回值是ModelAndView类型的对象,可以在ModelAndView对象中存储异常信息,并跳转到异常处理页面。

案例演示

接下来通过一个案例演示自定义异常处理器分类别处理自定义异常和系统自带的异常,案例具体实现步骤如下所示。在src\main\java目录,创建一个路径为com.lq.exception的包,并在包中创建自定义异常类MyException:

package com.lq.exception;

/**
 * @Author: Luqing Teacher
 * @CreateTime: 2025-03-13
 * @Description:
 * @Version: 1.0
 */


public class MyException extends Exception {
    private String message;//异常信息
    public MyException(String message) {
        super(message);
        this.message = message;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

在ExceptionController类中,新增方法addData()用于抛出自定义异常,addData()方法的具体代码如下所示

@RequestMapping("/addData")
public String addData() throws MyException {
    throw new MyException("新增数据异常!");
}

在com.lq.controller包下,创建名称为MyExceptionHandler的自定义异常处理器。在MyExceptionHandler类中重写resolveException()方法,用于判断当前异常是自定义异常还是系统自带的异常,根据异常的种类不同,resolveException()方法返回不同的异常信息。使用自定义异常处理器,需要先将自定义异常处理器注册到Spring MVC中。MyExceptionHandler类的部分代码如下所示。

package com.lq.controller;

import com.lq.exception.MyException;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;

/**
 * @Author: Luqing Teacher
 * @CreateTime: 2025-03-13
 * @Description:
 * @Version: 1.0
 */

@Component
public class MyExceptionHandler implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        String msg;
        if(ex instanceof MyException) {
            msg = ex.getMessage();
        }else {
            Writer out = new StringWriter();
            PrintWriter s = new PrintWriter(out);
            ex.printStackTrace(s);
            String sysMsg = out.toString();
            msg = "<h1>你个傻冒,又出错了吧!!</h1>" + sysMsg;
        }
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("msg", msg);
        modelAndView.setViewName("error.jsp");
        return modelAndView;
    }
}

访问showNullPointer,出现下列页面

​访问addData

异常处理注解

@ControllerAdvice注解的作用

从Spring 3.2开始,Spring提供了一个新注解@ControllerAdvice,@ControllerAdvice有以下两个作用。

• 注解作用在类上时可以增强Controller,对Controller中被@RequestMapping注解标注的方法加一些逻辑处理。

• @ControllerAdvice注解结合方法型注解@ExceptionHandler,可以捕获Controller中抛出的指定类型的异常,从而实现不同类型的异常统一处理。

案例演示

接下来通过一个案例演示使用注解实现异常的分类处理,具体实现步骤如下所示。

在com.lq.controller包下,创建名称为ExceptionAdvice的异常处理器。ExceptionAdvice类中定义2个处理不同异常的方法,其中doMyException()方法用来处理Handler执行时抛出的自定义异常,doOtherException()方法用来处理Handler执行时抛出的系统异常。

package com.lq.controller;

import com.lq.exception.MyException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

/**
 * @Author: Luqing Teacher
 * @CreateTime: 2025-03-13
 * @Description:
 * @Version: 1.0
 */


@ControllerAdvice
public class ExceptionAdvice {

    @ExceptionHandler(value = MyException.class)
    public ModelAndView doMyException(Exception ex) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg", ex.getMessage());
        mv.setViewName("error.jsp");
        return mv;
    }

    @ExceptionHandler(value = Exception.class)
    public ModelAndView doOtherException(Exception ex) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg", "<h1>傻冒出错了吧!!哈哈!!</h1>");
        mv.setViewName("error.jsp");
        return mv;
    }

}

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

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

相关文章

ubuntu24.04 使用apt指令只下载不安装软件

比如我想下载net-tools工具包及其依赖包可以如下指令 apt --download-only install net-tools 自动下载的软件包在/var/cache/apt/archives/目录下

计算机网络安全问答数据集(1788条) ,AI智能体知识库收集! AI大模型训练数据!

继续收集数据集&#xff0c;话不多说&#xff0c;见下文&#xff01; 今天分享一个计算机网络安全问答数据集&#xff08;1788条)&#xff0c;适用于AI大模型训练、智能体知识库构建、安全教育系统开发等多种场景&#xff01; 一、数据特点 结构清晰&#xff1a;共计1788条&…

WinCC学习系列-高阶应用(WinCC REST通信)

WinCC作为一个经典SCADA系统&#xff0c;它是OT与IT数据无缝集成桥梁&#xff0c;自WinCC7.5版本开始&#xff0c;可以直接提供Rest服务用于其它系统数据访问和操作。 WinCC REST 服务允许外部应用程序访问 WinCC 数据。 外部应用程序可以通过 REST 接口读取和写入 WinCC 组态…

使用交叉编译工具提示stubs-32.h:7:11: fatal error: gnu/stubs-soft.h: 没有那个文件或目录的解决办法

0 前言 使用ST官方SDK提供的交叉编译工具、cmake生成Makefile&#xff0c;使用make命令生成可执行文件提示fatal error: gnu/stubs-soft.h: 没有那个文件或目录的解决办法&#xff0c;如下所示&#xff1a; 根据这一错误提示&#xff0c;按照网上的解决方案逐一尝试均以失败告…

macOS 连接 Docker 运行 postgres,使用navicat添加并关联数据库

下载 docker注册一个账号&#xff0c;登录 Docker创建 docke r文件 mkdir -p ~/.docker && touch ~/.docker/daemon.json写入配置&#xff08;全量替换&#xff09; {"builder": {"gc": {"defaultKeepStorage": "20GB",&quo…

指针的使用——基本数据类型、数组、结构体

1 引言 对于学习指针要弄清楚如下问题基本可以应付大部分的场景&#xff1a; ① 指针是什么&#xff1f; ② 指针的类型是什么&#xff1f; ③ 指针指向的类型是什么&#xff1f; ④ 指针指向了哪里&#xff1f; 2 如何使用指针 任何东西的学习最好可以总结成一种通用化的…

TK海外抢单源码/指定卡单

​ 抢单源码&#xff0c;有指定派单&#xff0c;打针&#xff0c;这套二改过充值跳转客服 前端vue 后端php 两端分离 可二开 可以指定卡第几单&#xff0c;金额多少&#xff0c; 前后端开源 PHP7.2 MySQL5.6 前端要www.域名&#xff0c;后端要admin.域名 前端直接静态 伪静…

【Linux】Linux 环境变量

参考博客&#xff1a;https://blog.csdn.net/sjsjnsjnn/article/details/125533127 一、环境变量 1.1 基本概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数如&#xff1a;我们在编写C/C代码的时候&#xff0c;在链接的时候&am…

OpenCV在图像上绘制文字示例

OpenCV计算机视觉开发实践&#xff1a;基于Qt C - 商品搜索 - 京东 OpenCV中除了提供绘制各种图形的函数外&#xff0c;还提供了一个特殊的绘制函数&#xff0c;用于在图像上绘制文字。这个函数是putText()&#xff0c;它是命名空间cv中的函数&#xff0c;其声明如下&#xff…

为什么要选择VR看房?VR看房有什么优点?

VR看房&#xff1a;革新传统&#xff0c;重塑体验 在当今社会&#xff0c;虚拟现实&#xff08;VR&#xff09;技术正以前所未有的速度渗透到我们生活的各个领域&#xff0c;其中VR看房作为房地产领域的重要创新。本文将讨论为什么要选择VR看房以及VR看房的主要优点&#xff0…

pytorch基本运算-范数

引言 前序学习进程中&#xff0c;已经对pytorch基本运算有了详细探索&#xff0c;文章链接有&#xff1a; 基本运算 广播失效 乘除法和幂运算 hadamard积、点积和矩阵乘法 上述计算都是以pytorch张量为运算元素&#xff0c;这些张量基本上也集中在一维向量和二维矩阵&#x…

Transformer实战——词嵌入技术详解

Transformer实战——词嵌入技术详解 0. 前言1. 词嵌入基础2. 分布式表示3. 静态嵌入3.1 Word2Vec3.2 GloVe 4. 使用 Gensim 构建词嵌入5. 使用 Gensim 探索嵌入空间6. 动态嵌入小结系列链接 0. 前言 在本节中&#xff0c;我们首先介绍词嵌入的概念&#xff0c;然后介绍两种实现…

[pdf、epub]300道《软件方法》强化自测题业务建模需求分析共257页(202505更新)

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 在本账号CSDN资源下载&#xff0c;或者访问链接&#xff1a; http://www.umlchina.com/url/quizad.html 如果需要提取码&#xff1a;umlc 文件夹中的“300道软件方法强化自测题2025…

Vue3入门指南:从零到精通的快速上手

齐爷学vue3 一、Vue3入门 vite&#xff1a;前端构架工具&#xff0c;构建速度快于webpack。轻量快速、对TS&#xff0c;JSX&#xff0c;CSS开箱即用、按需编译。 创建Vue3工程 1.在想要创建Vue3的位置打开cmd&#xff0c;执行如下命令。 npm create vuelatest 2.功能只选择…

吴恩达MCP课程(5):mcp_chatbot_prompt_resource.py

前提条件&#xff1a; 1、吴恩达MCP课程&#xff08;5&#xff09;&#xff1a;research_server_prompt_resource.py 2、server_config_prompt_resource.json文件 {"mcpServers": {"filesystem": {"command": "npx","args"…

设计模式——抽象工厂设计模式(创建型)

摘要 抽象工厂设计模式是一种创建型设计模式&#xff0c;旨在提供一个接口&#xff0c;用于创建一系列相关或依赖的对象&#xff0c;无需指定具体类。它通过抽象工厂、具体工厂、抽象产品和具体产品等组件构建&#xff0c;相比工厂方法模式&#xff0c;能创建一个产品族。该模…

基于LocalAI与cpolar技术协同的本地化AI模型部署与远程访问方案解析

文章目录 前言1. Docker部署2. 简单使用演示3. 安装cpolar内网穿透4. 配置公网地址5. 配置固定公网地址前言 各位极客朋友们!今天要向大家推荐一套创新性的本地部署方案——LocalAI技术架构。这款开源工具包能够将普通配置的笔记本电脑转化为具备强大算力的AI工作站,轻松实现…

霍尔效应传感器的革新突破:铟化铟晶体与结构演进驱动汽车点火系统升级

一、半导体材料革新&#xff1a;铟化铟晶体的电压放大机制 铟化铟&#xff08;InSb&#xff09;晶体因其独特的能带结构&#xff0c;成为提升霍尔电压的关键材料。相较于传统硅基材料&#xff0c;其载流子迁移率高出3-5倍&#xff0c;在相同磁场强度下可显著放大霍尔电压。其作…

无法运用pytorch环境、改环境路径、隔离环境

一.未建虚拟环境时 1.创建新项目后&#xff0c;直接运行是这样的。 2.设置中Virtualenv找不到pytorch环境&#xff1f;因为此时没有创建新虚拟环境。 3.选择conda环境&#xff08;全局环境&#xff09;时&#xff0c;是可以下载环境的。 运行结果如下&#xff1a; 是全局环境…

从0开始学vue:pnpm怎么安装

一、什么是 pnpm&#xff1f; pnpm&#xff08;Performant npm&#xff09;是新一代 JavaScript 包管理器&#xff0c;优势包括&#xff1a; 节省磁盘空间&#xff1a;通过硬链接和符号链接实现高效存储安装速度更快&#xff1a;比 npm/yarn 快 2-3 倍内置工作区支持&#xf…