Spring MVC 中,处理异常的 6种方式

server/2024/12/22 11:21:55/

异常处理是每个 Java程序员需要面对的一个问题,在Spring中,提供了多种机制来处理控制器抛出的异常,确保应用程序在面对各种错误情况时能够优雅地响应。这篇文章,我们来详细分析Spring MVC中,几种优雅处理异常的方式。

1. 使用@ExceptionHandler注解

@ExceptionHandler注解允许在单个Controller中定义处理特定异常的方法。当 Controller的方法抛出指定的异常时,Spring会调用相应的处理方法。

如下示例,展示了如何在 Controller层优雅处理异常:

@Controller
public class MyController {@RequestMapping("/example")public String example() {// 可能抛出异常的业务逻辑if (1/0) {throw new CustomException("自定义异常发生");}return "success";}@ExceptionHandler(CustomException.class)public ModelAndView handleCustomException(CustomException ex) {ModelAndView mav = new ModelAndView();mav.addObject("message", ex.getMessage());mav.setViewName("errorPage");return mav;}
}

优点: 简单直观,适用于单个控制器的异常处理。

缺点: 如果多个控制器需要相同的异常处理逻辑,需要在每个控制器中重复定义。

2. 使用@ControllerAdvice注解

@ControllerAdvice是一种全局的异常处理方式,可以应用于所有 Controller。通过将异常处理逻辑集中在一个地方,可以避免代码重复,提高维护性。

如下示例,展示了如何使用 @ControllerAdvice 优雅处理全局异常:

@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(CustomException.class)public ModelAndView handleCustomException(CustomException ex) {ModelAndView mav = new ModelAndView();mav.addObject("message", ex.getMessage());mav.setViewName("errorPage");return mav;}@ExceptionHandler(Exception.class)public ModelAndView handleGeneralException(Exception ex) {ModelAndView mav = new ModelAndView();mav.addObject("message", "发生了一个错误: " + ex.getMessage());mav.setViewName("errorPage");return mav;}
}

优点:

  • 全局统一管理异常处理逻辑。
  • 代码更清晰,易于维护。

缺点:

  • 全局处理不适用于需要针对某些控制器有特殊处理需求的情况,需结合其他方法使用。

3. 实现HandlerExceptionResolver接口

HandlerExceptionResolver 是一种更底层的异常处理机制,通过实现该接口,开发者可以自定义异常解析逻辑。

如下示例,展示了如何实现 HandlerExceptionResolver接口优雅处理异常:

public class MyExceptionResolver implements HandlerExceptionResolver {@Overridepublic ModelAndView resolveException(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex) {ModelAndView mav = new ModelAndView();if (ex instanceof CustomException) {mav.addObject("message", ex.getMessage());mav.setViewName("customErrorPage");} else {mav.addObject("message", "未知错误");mav.setViewName("errorPage");}return mav;}
}

配置
在 Spring 配置文件中注册自定义异常解析器:

<bean class="com.example.MyExceptionResolver"/>

优点

  • 高度灵活,可以处理各种复杂的异常情景。

缺点

  • 需要更多的配置和实现工作。
  • 不如注解方式直观,适用性较低。

4. 使用@ResponseStatus注解

@ResponseStatus注解可以用于自定义异常对应的 HTTP 状态码和错误信息,当抛出带有该注解的异常时,Spring会自动设置相应的状态码。

如下示例,展示了如何使用 @ResponseStatus注解优雅处理异常:

@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "资源未找到")
public class ResourceNotFoundException extends RuntimeException {public ResourceNotFoundException(String message) {super(message);}
}

使用:


@Controller
public class MyController {@RequestMapping("/resource")public String getResource() {// 假设资源未找到throw new ResourceNotFoundException("资源ID不存在");}
}

优点:

  • 简单快捷,适用于直接映射到特定 HTTP 状态码的异常情况。

缺点:

  • 无法返回自定义的错误页面或更复杂的错误信息。

5. 使用ResponseEntity和@RestControllerAdvice

在构建 RESTful API时,常用ResponseEntity来返回自定义的错误响应,并结合 @RestControllerAdvice可以全局处理异常并返回 JSON 格式的错误信息。

如下示例,展示了如何使用ResponseEntity和*@RestControllerAdvice*来处理 RESTful API的异常:

@RestControllerAdvice
public class RestExceptionHandler {@ExceptionHandler(CustomException.class)public ResponseEntity<ErrorResponse> handleCustomException(CustomException ex) {ErrorResponse error = new ErrorResponse("CUSTOM_ERROR", ex.getMessage());return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);}@ExceptionHandler(Exception.class)public ResponseEntity<ErrorResponse> handleGeneralException(Exception ex) {ErrorResponse error = new ErrorResponse("GENERAL_ERROR", "内部服务器错误");return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);}
}public class ErrorResponse {private String errorCode;private String errorMessage;// 构造方法、getter 和 setter
}

优点

  • 适用于 RESTful 服务,能够返回结构化的错误信息(如 JSON)。
  • 全局统一管理,易于维护。

缺点

  • 需要定义额外的错误响应类。

6. 使用@ControllerAdvice和@ExceptionHandler

如果使用 Spring Boot,可以更便捷地使用 @ControllerAdvice 结合自动配置实现异常处理。

如下示例,展示了如何使用 @ControllerAdvice@ExceptionHandler来处理异常:

@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(MethodArgumentNotValidException.class)public ResponseEntity<ValidationErrorResponse> handleValidationExceptions(MethodArgumentNotValidException ex) {ValidationErrorResponse errors = new ValidationErrorResponse();ex.getBindingResult().getAllErrors().forEach((error) -> {errors.addError(((FieldError) error).getField(), error.getDefaultMessage());});return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);}// 其它异常处理方法
}

优点

  • 与 Spring Boot 无缝集成,减少配置。
  • 提供了诸多便利的功能,如自动处理验证错误等。

7. 总结

本文,我们分析了 Spring MVC优雅处理异常的几种方法以及代码示例,我们可以根据具体需求选择合适的方法:

  • 局部控制器处理:使用 @ExceptionHandler 注解,适用于单个控制器的特定异常处理。
  • 全局处理:使用 @ControllerAdvice@RestControllerAdvice,适用于跨多个控制器的统一异常处理。
  • 自定义解析:实现 HandlerExceptionResolver 接口,适用于需要高度自定义的异常处理逻辑。
  • 状态码注解:使用 @ResponseStatus 注解,适用于简单的异常状态码映射。
  • RESTful API:结合 ResponseEntity 和全局异常处理,返回结构化的错误响应。

从实际工作来看,@ControllerAdvice@RestControllerAdvice是使用频率最高的一种方式。


http://www.ppmy.cn/server/152219.html

相关文章

前端零基础学习Day-Eight

CSS字体和文本样式 CSS文字样式 字体&#xff1a;font-family 语法&#xff1a;font-family:[字体1][,字体2][,…] p{font-family:“微软雅黑”,“宋体”,“黑体”;} 含空格字体名和中文&#xff0c;用英文引号括起 属性值&#xff1a;具体字体名&#xff0c;字体集 字体集&…

如何在 Debian 12 上安装和使用 Vuls 漏洞扫描器

简介 Vuls 是一款无代理、免费且开源的 Linux 和 FreeBSD 漏洞扫描器。Vuls 主要用 Go 语言编写&#xff0c;可以在任何地方运行。你可以在云端、本地和 Docker 上运行 Vuls&#xff0c;并且它支持主要的发行版。Vuls 提供高质量的扫描&#xff0c;支持多个漏洞数据库&#xf…

Pytorch | 从零构建ResNet对CIFAR10进行分类

Pytorch | 从零构建ResNet对CIFAR10进行分类 CIFAR10数据集ResNet核心思想网络结构创新点优点应用 ResNet结构代码详解结构代码代码详解BasicBlock 类ResNet 类ResNet18、ResNet34、ResNet50、ResNet101、ResNet152函数 训练过程和测试结果代码汇总resnet.pytrain.pytest.py 前…

uniApp使用腾讯地图提示未添加maps模块

uniApp使用腾讯地图&#xff0c;打包提示未添加maps模块解决方案 这是报错信息&#xff0c;在标准基座运行的时候是没问题的&#xff0c;但是打包后会提示未添加&#xff0c;可以通过在mainfest里面把地图插件上腾讯地图的key更换高德地图的key&#xff0c;定位服务可以继续用腾…

讲PPT 需要注意的事项

目录 1-逐字稿多少字&#xff1f; 2-在整个过程中要有学生上台展示的环节。&#xff08;对于讲课适用&#xff09; 3-多演练两遍&#xff0c;需要提前谋划好&#xff0c;走2-3遍&#xff0c;把时间卡好 4-PPT上的文字颜色要加强 5-PPT上的字号 6-逐字稿 1-逐字稿多少字&am…

利用 Jsoup 进行高效 Web 抓取与 HTML 处理

Jsoup 是一款 Java 的 HTML 解析器&#xff0c;可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API&#xff0c;可通过 DOM&#xff0c;CSS 以及类似于 JQuery 的操作方法来取出和操作数据。 官网&#xff1a;https://jsoup.org/ 中文文档&#xff1a;Jsou…

rabbitMq的status报错Error: unable to perform an operation on node ‘rabbit……

遇到下图这个错大部分问题可能是由于 RabbitMQ CLI 工具的 Erlang Cookie 与服务器上的不匹配而导致连接问题。Erlang Cookie 在 RabbitMQ 节点之间进行身份验证和安全通信时起着重要作用。 可以在c盘搜索一下看下两个.erlang.cookie文件中的内容是否一致&#xff0c;不一致的…

学习记录:electron主进程与渲染进程直接的通信示例【开箱即用】

electron主进程与渲染进程直接的通信示例 1. 背景&#xff1a; electronvue实现桌面应用开发 2.异步模式 2.1使用.send 和.on的方式 preload.js中代码示例&#xff1a; const { contextBridge, ipcRenderer} require(electron);// 暴露通信接口 contextBridge.exposeInMa…