基于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多线程之悲观锁与乐观锁攻略 概述 在多线程编程中,为了保证数据的安全,我们需要使用锁机制来控制对共享资源的访问。其中,悲观锁是一种传统的锁模式,它认为在每次访问共享资源时都有可能发生冲突,所以对共享资源进行加锁以防止其他线程的访问。而乐观锁则是一种更为轻量级的锁模式,它的思想是假设多线程之间没有冲突,当发生冲突时再进行处理。 本文将详细介绍悲观锁和乐…

    Java 2023年5月18日
    00
  • spring MVC中传递对象参数示例详解

    在 Spring MVC 中,我们可以通过多种方式传递参数,其中包括传递对象参数。本文将详细讲解 Spring MVC 中传递对象参数示例详解,包括如何定义对象、如何传递对象参数、如何接收对象参数等。 定义对象 在 Spring MVC 中,我们可以通过定义一个 POJO(Plain Old Java Object)类来表示一个对象。下面是一个简单的示例,演…

    Java 2023年5月18日
    00
  • 非常实用的Tomcat启动脚本实现方法

    非常实用的Tomcat启动脚本实现方法 在Linux环境下,通常我们会使用启动脚本的方式来启动Tomcat。而对于初学者来说,编写一个完整可靠的启动脚本不是一件容易的事情。本文将介绍一种非常实用的Tomcat启动脚本实现方法,帮助大家快速实现Tomcat的自动启动、关闭、查看状态等操作。 Step 1: 创建启动脚本 首先,我们需要创建一个启动脚本。为了让脚…

    Java 2023年5月19日
    00
  • 详解如何在Spring Security中自定义权限表达式

    在对Spring Security中自定义权限表达式的攻略之前,先简单介绍一下权限表达式的作用: Spring Security中的权限表达式用于在方法调用或请求访问时,判断当前用户是否具有访问权限。Spring Security提供了很多默认的权限表达式,例如”hasRole()”和”hasAnyRole()”等。但是,我们有时需要根据不同的业务需求来自定…

    Java 2023年5月20日
    00
  • Java将Object转换为数组的代码

    要将Java中的Object类型转换成数组,可以使用Java的反射机制来实现。具体的步骤如下: 1. 获取Object的Class对象 通过Object的getClass()方法获取一个Class对象,然后调用Class类的getComponentType()方法获取数组元素的类型,最后调用java.lang.reflect.Array的newInstanc…

    Java 2023年5月26日
    00
  • Java中的PrintWriter 介绍_动力节点Java学院整理

    Java中的PrintWriter是一种方便输出文本内容到文件或控制台的工具。下面我们将详细介绍PrintWriter的使用方法。 PrintWriter的构造函数 PrintWriter的构造函数可以接受多种参数,如下所示: PrintWriter(File file):使用指定的文件创建PrintWriter对象。 PrintWriter(OutputS…

    Java 2023年5月26日
    00
  • Java中jstat命令的使用详解

    Java中jstat命令的使用详解 什么是jstat命令? jstat是一个用于监控Java虚拟机(JVM)统计信息的命令行工具。使用jstat命令可以查看JVM堆、垃圾回收、类加载等方面的实时统计信息。jstat命令可以用于调试JVM性能问题和进行故障诊断。 jstat命令的语法 jstat命令有以下的语法: jstat [option vmid [int…

    Java 2023年5月26日
    00
  • Spring Security保护用户密码常用方法详解

    Spring Security保护用户密码常用方法详解 前言 在现代的Web开发中,安全性已经成为一个重要的问题。尤其是涉及到用户密码的相关处理,更是需要严格保护。 Spring Security是一个开源的Web安全框架,它提供了一些集成化的解决方案,可以快速、轻松地保护我们的应用程序的安全。这篇文章将介绍Spring Security保护用户密码的一些常…

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