gpt4 book ai didi

spring-mvc - Spring MVC 3.2 异常响应映射

转载 作者:行者123 更新时间:2023-12-01 01:55:25 28 4
gpt4 key购买 nike

Spring 3.2.15,这里是基于 MVC 的 REST API(不是 Spring Boot,很遗憾!)。我正在尝试实现满足以下条件的异常映射器/处理程序:

  • 无论发生什么(成功或错误),Spring 应用程序总是返回一个响应实体 MyAppResponse (见下文);和
  • 在成功处理请求的情况下,返回 HTTP 状态 200(典型);和
  • 在处理请求并发生异常的情况下,我需要控制特定异常到特定 HTTP 状态码的映射
  • Spring MVC 框架错误(例如 BlahException )必须映射到 HTTP 422
  • 自定义应用异常(exception),例如我的 FizzBuzzException有自己的状态映射方案:
  • FizzBuzzException -> HTTP 401
  • FooBarException -> HTTP 403
  • OmgException -> HTTP 404
  • 所有其他异常,即非 Spring 异常和非自定义应用程序异常(上面列出的 3 个)应该产生 HTTP 500
  • MyAppResponse对象是:
    // Groovy pseudo-code
    @Canonical
    class MyAppResponse {
    String detail
    String randomNumber
    }

    它看起来像 ResponseEntityExceptionHandler也许可以为我做到这一点,但我没有看到森林通过树木w.r.t。它是如何传递参数的。我希望我可以做类似的事情:
    // Groovy-pseudo code
    @ControllerAdvice
    class MyAppExceptionMapper extends ResponseEntityExceptionHandler {
    ResponseEntity<Object> handleFizzBuzzException(FizzBuzzException fbEx, HttpHeaders headers, HttpStatus status) {
    // TODO: How to reset status to 401?
    status = ???

    new ResponseEntity(fbEx.message, headers, status)
    }

    ResponseEntity<Object> handleFooBarException(FooBarException fbEx, HttpHeaders headers, HttpStatus status) {
    // TODO: How to reset status to 403?
    status = ???

    new ResponseEntity(fbEx.message, headers, status)
    }

    ResponseEntity<Object> handleOmgException(OmgException omgEx, HttpHeaders headers, HttpStatus status) {
    // TODO: How to reset status to 404?
    status = ???

    new ResponseEntity(omgEx.message, headers, status)
    }

    // Now map all Spring-generated exceptions to 422
    ResponseEntity<Object> handleAllSpringExceptions(SpringException springEx, HttpHeaders headers, HttpStatus status) {
    // TODO: How to reset status to 422?
    status = ???

    new ResponseEntity(springEx.message, headers, status)
    }

    // Everything else is a 500...
    ResponseEntity<Object> handleAllOtherExceptions(Exception ex, HttpHeaders headers, HttpStatus status) {
    // TODO: How to reset status to 500?
    status = ???

    new ResponseEntity("Whoops, something happened. Lol.", headers, status)
    }
    }

    知道如何完全实现此映射逻辑以及实体的要求为 MyAppResponse实例而不仅仅是一个字符串?

    然后,用 @ControllerAdvice 注释类我唯一需要做的就是配置 Spring 以使用它?

    最佳答案

    要减少 @bond-java-bond 答案,您不需要构建 ResponseEntity自己:

  • 使用@ResponseStatus对于每个 handleSomeException方法(例如 @ResponseStatus(HttpStatus.UNAUTHORIZED) )
  • 返回自定义 MyAppResponse从那些方法

  • 但是如果每种异常都以相同的方式处理(仅通过 HTTP 状态区分)我建议减少 MyAppExceptionMapper像这样:
    @ControllerAdvice
    public class MyAppExceptionMapper {
    private final Map<Class<?>, HttpStatus> map;
    {
    map = new HashMap<>();
    map.put(FizzBuzzException.class, HttpStatus.UNAUTHORIZED);
    map.put(FooBarException.class, HttpStatus.FORBIDDEN);
    map.put(NoSuchRequestHandlingMethodException.class, HttpStatus.UNPROCESSABLE_ENTITY);
    /* List Spring specific exceptions here as @bond-java-bond suggested */
    map.put(Exception.class, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    // Handle all exceptions
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseEntity<MyAppResponse> handleException(Exception exception) {
    MyAppResponse response = new MyAppResponse();
    // Fill response with details

    HttpStatus status = map.get(exception.getClass());
    if (status == null) {
    status = map.get(Exception.class);// By default
    }

    return new ResponseEntity<>(response, status);
    }
    }

    优点:
  • 很短。
  • 没有代码重复。
  • 效果稍微好一点。
  • 易于扩展。

  • 此外,您可以将映射配置移到外部并将其注入(inject)。

    如何配置 MVC Dispatcher Servlet

    首先,检查是否 mvc-dispatcher-servlet.xml (或另一个 contextConfigLocation 来自 web.xml )包含:
    <context:component-scan base-package="base.package"/>
    <mvc:annotation-driven/>

    其次,检查@ControllerAdvice注解类和@Controller注解类是否都属于 base.package的子包.

    Exception Handling in Spring MVC 上查看完整示例或 Spring MVC @ExceptionHandler Example更多细节。

    关于spring-mvc - Spring MVC 3.2 异常响应映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41190981/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com