基于SpringMVC的全局异常处理器介绍

【基于SpringMVC的全局异常处理器介绍】完整攻略

前言

在开发 Web 应用程序时,异常是不可避免的问题。当 Web 应用程序运行时发生异常时,SpringMVC 提供了一种集中处理异常的方式 -- 全局异常处理器。本文将详细介绍基于 SpringMVC 的全局异常处理器的使用方法以及示例。

步骤1:新建全局异常处理类

我们需要使用一个能够捕获应用程序中所有异常的全局异常处理器类。可以通过定义一个简单的类,然后添加一个带有 throwable 参数和返回错误信息的方法来实现。请参考以下代码块:

@ControllerAdvice
public class GlobalExceptionHandler {


    @ExceptionHandler(value = Exception.class)
    public ResponseEntity<ErrorResponse> defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        // TODO: 错误处理逻辑

    }
}

在代码中的 @ControllerAdvice 注解使得该类成为一个全局异常处理器,在整个应用程序容器中任何位置发生的异常都会被此处进行捕捉;@ExceptionHandler 注解则标明了该方法需要捕捉的异常类型。

步骤2:定义错误处理逻辑

当异常发生时,全局异常处理器会将异常的信息封装到一个自定义的错误响应对象中,然后将其返回给客户端。我们需要将捕捉到的异常、请求的 url 和一些额外的异常信息封装到这个自定义的对象中,并最终将它返回给客户端。

自定义的错误响应对象应该包含以下几个属性:

  • status: HTTP 状态码。

  • message: 错误描述信息。

  • timestamp: 错误发生时间戳。

请参考以下代码块:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ErrorResponse {
    private int status;
    private String message;
    private long timestamp;
 }

在代码中使用了 Lombok 注解 @Data 来简化 getter/setter、toString 等方法的编写。

为了将异常、url 和时间戳封装到错误响应对象中,可以使用如下代码块:

@ExceptionHandler(value = Exception.class)
public ResponseEntity<ErrorResponse> defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
    int statusCode = getStatus(req);
    ErrorResponse errorResponse = new ErrorResponse(statusCode, e.getMessage(), System.currentTimeMillis());
    return new ResponseEntity<>(errorResponse, HttpStatus.valueOf(statusCode));
  }

  private int getStatus(HttpServletRequest request) {
      Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
      if (statusCode != null) {
          return statusCode;
      }
      return HttpStatus.INTERNAL_SERVER_ERROR.value();
  }

在代码中,getStatus() 方法可以获取 HTTP 状态码,将异常信息、url 和时间戳作为 ErrorResponse 对象的属性,最后将其作为 HTTP 响应返回给客户端。

步骤3:测试全局异常处理器

最后,我们需要测试全局异常处理器是否生效。可以使用 Restful API 调用该异常处理器,将异常信息封装到 Json 对象中,POST 方法调用该 API,并打印 HTTP 响应。请参考以下代码块:

{
  "message":"This is an unexpected error.",
  "stackTrace":"java.lang.NullPointerException\nat com.example.demo.DemoController.index(DemoController.java:20)\n",
}
@Test
public void testException() throws Exception {
    HttpRequest request = HttpRequest.POST("http://localhost:8080/api/error")
            .contentType("application/json")
            .send("{\"message\":\"This is an unexpected error.\",\"stackTrace\":\"java.lang.NullPointerException\\nat com.example.demo.DemoController.index(DemoController.java:20)\\n\"}");
    String response = request.body();
    System.out.println(response);
}

示例1:DTO 对象校验异常处理

一个常见的异常场景是对象校验异常,如果我们在代码中实现校验逻辑,那么我们需要在每个控制器处理请求时都做好异常处理工作。但是全局异常处理器为我们提供了一种更优雅的处理方式。我们只需要在我们的 DTO 对象中添加注解如 @NotBlank@NotNull 等,SpringMVC 将为我们自动进行对象校验,并捕获异常。代码如下:

@PostMapping("/user")
public User createUser(@Valid @RequestBody User user) {
    // ...
}

在这个代码块中,我们使用 @Valid 注解在 POST /user API 中自动进行 User 对象的校验,如果 User 对象校验不通过,全局异常处理器会捕捉到这个异常,并返回一个 400 Bad Request 的 HTTP 响应。

示例2:未捕获异常处理

还有一种常见的场景是未捕获的运行时异常。例如,一个 IndexOutOfBoundsException 异常很有可能是由数组越界等原因导致的。如果在我们的代码中未将其捕获处理,那么 SpringMVC 将会将异常直接返回给客户端,并显示 500 Internal Server Error 的 HTTP 响应。但是使用全局异常处理器,我们可以将异常信息封装到一个自定义的错误响应对象中,并返回一个更可读性更好的 HTTP 响应。对于这种场景,我们可以使用以下方法:

@GetMapping("/exception")
public void throwException() {
    throw new RuntimeException("Unexpected exception occurs.");
}

在这个 API 中,我们使用 throw new RuntimeException() 来手动触发一个未被捕获的运行时异常。当我们向这个 API 发送请求时,全局异常处理器将捕获这个异常,并返回一个 500 Internal Server Error 的 HTTP 响应,其中包含了自定义的异常信息。

结语

通过本文的介绍,你学会了如何使用 SpringMVC 提供的全局异常处理器来集中处理 Web 应用程序中的异常,使得代码更加简洁、优雅,更好地满足了异常处理的需求。并且,我们分别从对象校验异常和未捕获的异常两个场景给出了实际的代码示例。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:基于SpringMVC的全局异常处理器介绍 - Python技术站

(0)
上一篇 2023年5月16日
下一篇 2023年5月16日

相关文章

  • java随机数生成具体实现代码

    当我们需要在程序中产生随机数时,Java API提供了几种不同的方法:Math类中的静态方法和java.util.Random类。 Math类生成随机数的实现代码 Math类中提供了一个random()方法来产生任意范围的随机数。通过random()方法返回一个0.0到1.0之间的随机数,对于大于1.0的范围,可以通过数学运算来实现。下面是一个产生1-100…

    Java 2023年5月23日
    00
  • JavaScript实现简单音乐播放器

    现在我来为您详细讲解如何使用JavaScript实现简单音乐播放器的完整攻略。 1. 准备工作 在开始编写代码前,首先需要了解我们需要准备哪些工具和文件。常用的音乐播放器需要包含如下文件: HTML页面:用于展示具体的播放器界面; CSS文件:用于美化页面样式; JavaScript文件:用于实现音乐播放功能。 如果您还没有准备以上文件,可以按照以下步骤进行…

    Java 2023年6月15日
    00
  • java堆栈类使用实例(java中stack的使用方法)

    标题:Java堆栈类使用实例 堆栈概述 堆栈(Stack)是一种特殊的线性数据结构,它只允许在一端进行插入和删除操作。堆栈遵循先进后出(Last-In-First-Out)的原则,即最后插入的元素最先删除。 Java中提供了Stack类来实现堆栈,Stack类继承了Vector类,并添加了支持堆栈的方法。 Stack类的常用方法 Stack类提供了以下常用方…

    Java 2023年5月26日
    00
  • Java Apache Commons报错“ValidatorException”的原因与解决方法

    “ValidatorException”是Java的Apache Commons类库中的一个异常,通常由以下原因之一引起: 验证错误:如果验证失败,则可能会出现此异常。例如,可能会尝试验证无效的输入。 配置错误:如果配置文件中存在错误,则可能会出现此异常。例如,可能会使用错误的文件路径或文件名。 以下是两个实例: 例1 如果验证失败,则可以尝试使用有效的输入…

    Java 2023年5月5日
    00
  • List集合多线程并发条件下不安全如何解决

    List集合在多线程并发条件下存在线程安全问题,主要是由于多个线程在同时对List进行增删改操作,会产生竞争条件。在此情况下,如果不进行处理,会导致List集合数据不一致或者抛出ConcurrentModificationException异常等问题。下面是解决List集合多线程并发不安全的完整攻略: 方案1:使用线程安全的List集合 Java提供了多个线…

    Java 2023年5月26日
    00
  • Mybatis逆工程jar包的修改和打包

    接下来我将为你详细讲解Mybatis逆工程Jar包的修改和打包的完整攻略。 准备 在开始修改和打包Mybatis逆工程Jar包之前,我们需要准备好如下内容: Mybatis逆工程Jar包:mybatis-generator-core-x.x.x.jar,可以从 MyBatis 官网下载。 用于修改和打包Jar包的 IDE,如 Eclipse 或 Intell…

    Java 2023年5月26日
    00
  • Spring Boot 2.X优雅的解决跨域问题

    Spring Boot 2.X优雅的解决跨域问题 在前后端分离的开发模式下,跨域问题是一个常见的问题。在Spring Boot 2.X中,我们可以通过配置来优雅地解决跨域问题。本文将手把手教你如何在Spring Boot 2.X中解决跨域问题,包括配置跨域、使用注解解决跨域等。 1. 配置跨域 在Spring Boot 2.X中,我们可以通过配置来解决跨域问…

    Java 2023年5月14日
    00
  • Spring Boot与Spring MVC Spring对比及核心概念

    下面是关于“Spring Boot与Spring MVC Spring对比及核心概念”的完整攻略。 Spring Framework简介 Spring Framework是一个全栈的Java框架,它为企业级应用程序提供了一个全面的编程和配置模型。它包括许多独立的模块,可以根据需要选择使用。一些最常用的模块是Spring Core容器、Spring MVC W…

    Java 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部