Spring Boot 应用程序中的异常处理

x33g5p2x  于2022-10-06 转载在 Spring  
字(4.0k)|赞(0)|评价(0)|浏览(618)

在本教程中,我们将如何在 Spring Boot REST Applications 中自定义 Exceptions 以满足我们的需求。

异常处理是开发应用程序和服务的关键要素。 Spring Boot 提供了良好的默认异常处理机制。

要了解Spring Boot 提供的默认异常处理是如何工作的,让我们开始请求一个不存在的 URL:

curl -s http://localhost:8080/unknown | jq

{

"timestamp": "2020-04-01T13:12:00.327+0000",

"status": 404,

“error": "Not Found",

"message”: "No message available",

"path": "/unknown"

}

需要注意的关键事项如下:

  • 响应头的 HTTP 状态为 404 – 未找到资源
  • Spring Boot 返回一个有效的 JSON 消息作为响应,其中的消息说明找不到资源

从端点抛出异常

让我们创建一个引发异常的资源,并向其发送 GET 请求,以了解应用程序如何对运行时异常做出反应。

检查以下代码片段:

@RequestMapping("/list") public List < Customer > findAll() {
  throw new RuntimeException("Some Exception Occured");
}

让我们在 http://localhost:8080/list/ 向前面的服务发出 GET 请求

响应如下代码所示:

curl -s http://localhost:8080/list | jq 

{
"timestamp": "2020-04-01T13:15:11.091+0000",
"status": 500,
"error": "Internal Server Error",
"message": "Some Exception Occured",
"path": "/list"
}

需要注意的一些重要事项如下:

  • 响应头的 HTTP 状态为 500 ;内部服务器错误
  • Spring Boot 还返回包含错误的消息。

创建自定义异常

让我们看一个使用自定义异常类的更复杂的示例

@RequestMapping("/find/{id}") public Customer findOne(@PathVariable int id) {
  Customer c = repository.findCustomer(id);
  if (c != null) return c;
  else throw new CustomerNotFoundException(id);
}

如您所见,在这种情况下,如果您的搜索没有返回数据,我们将抛出 CustomerNotFoundException。

在这种情况下,如果我们返回一个 500 Internal Server Error 它对客户端来说就没有那么有意义了,客户端无法猜测如何修复这个错误。另一方面,如果我们返回一个状态码为 404 的错误,那就更合适了。

我们可以使用带有 @ExceptionHandlerControllerAdvice 来处理自定义异常,它将处理自定义异常,填充并返回自定义响应,如下所示。

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler {
  @ExceptionHandler(CustomerNotFoundException.class)
  public void springHandleNotFound(HttpServletResponse response) throws IOException {
    response.sendError(HttpStatus.NOT_FOUND.value());
  }
}

这是 CustomerNotFoundException 类:

package com.example.testrest;

public class CustomerNotFoundException extends RuntimeException {
  public CustomerNotFoundException(int id) {
    super("Customer id not found : " + id);
  }
}

因此,现在如果您请求未找到的客户,您将收到带有 CustomerNotFoundException 错误消息和状态 404 的 JSON 作为响应,而不是一般的 500 错误:

curl -s http://localhost:8080/find/9 | jq 

{
"timestamp": "2020-04-01T14:01:47.637+0000",
"status": 404,
"error": "Not Found",
"message": "Customer id not found : 9",
"path": "/one/9"
}

如何自定义所有异常响应

要覆盖所有异常的默认 JSON 错误响应,只需创建一个扩展 DefaultErrorAttributes 的类。让我们看看如何在错误属性列表中添加应用程序版本:

import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.WebRequest;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
@Component public class MyErrorAttributes extends DefaultErrorAttributes {
  private static final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
  @Override public Map < String, Object > getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
    Map < String, Object > errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace);
    Object timestamp = errorAttributes.get("timestamp");
    if (timestamp == null) {
      errorAttributes.put("timestamp", dateFormat.format(new Date()));
    } else {
      errorAttributes.put("timestamp", dateFormat.format((Date) timestamp));
    }
    // Custom Attribute
    errorAttributes.put("app.version", "2.2");
    return errorAttributes;
  }
}

在这种情况下,返回的 JSON 将是:

curl -s http://localhost:8080/query/9 | jq

{
  "timestamp": "2020/04/01 16:25:29",
  "status": 404,
  "error": "Not Found",
  "message": "No message available",
  "path": "/query/9",
  "app.version": "2.2"
}

本教程的源代码:https://github.com/fmarchioni/masterspringboot/tree/master/exception

相关文章