繁体   English   中英

如何在 spring 引导中发送 400、401、405、403 和 500 错误的自定义响应?

[英]How to send custom response for 400, 401, 405, 403 and 500 errors in spring boot?

我想在 spring 引导中针对 400、401、405、403 和 500 错误发送自定义 JSON 响应。 对于这些错误 spring 启动有时会发送 HTML 响应,有时会发送空响应正文响应,有时会发送带有时间戳、异常、消息等的完整响应。我想要一个单一且一致的 Z0ECD11C1D7A287401D148A23BBD7 响应,例如所有这些错误的响应,

{
statusCode : 405,
message: "HTTP Method not allowed"
}

我使用@ControllerAdvice为很多异常发送自定义响应。 这些 400、401、405、403 和 500 错误我面临的问题是我不知道当这些错误发生时会引发哪些异常,以便我可以为它们编写@ExceptionHandlers 即使我不知道这是否可能,或者即使可能,但它是实现这一点的正确方法。

有没有办法在 Spring 引导中实现这一点?

所有传出异常都由 Spring Boot with BasicErrorController处理。

我们可以使用 controller 建议来处理/更改大多数异常消息。 但是,在到达 controller 之前抛出的异常,如NotFoundBadRequest等,再次由BasicErrorController处理

我们也可以通过覆盖BasicErrorController来改变它。

@RestController
@RequestMapping({"${server.error.path:${error.path:/error}}"})
@Slf4j
public class BasicErrorControllerOverride extends AbstractErrorController {

  public BasicErrorControllerOverride(ErrorAttributes errorAttributes) {
    super(errorAttributes);
  }

  @RequestMapping
  public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
    HttpStatus status = this.getStatus(request);
    Map<String, Object> errorCustomAttribute = new HashMap<>();
    errorCustomAttribute.put("custome_message", "error");
    errorCustomAttribute.put("custom_status_field", status.name());
    return new ResponseEntity(errorCustomAttribute, status);
  }

  @Override
  public String getErrorPath() {
    return "/error";
  }
}

错误消息现在将更改为如下所示

{
    "custome_message": "UNAUTHORIZED",
    "custom_status_field": "error"
}

Spring ResponseEntity 可用于此目的 -

return new ResponseEntity<>("Hello World!", HttpStatus.OK);

参考这个链接; https://www.baeldung.com/spring-response-entity

好吧,即使您不使用 spring,也有一些简单的做法,例如让您的所有响应类都从基础 class 扩展,就像这样,只是一个例子 -

public class StandardResponse{
    private int httpStatus;
  
    //getters and setters
}

public class ProductResponse extends StandardResponse{
    // product specific data
}

您可以使用 @ControllerAdvice 和 application/problem+json ( zalando/problem是一个很好的 java 实现)

这是一个例子: https://www.baeldung.com/problem-spring-web

以与 gaetan224 建议的类似方式,您可以使用 @ControllerAdvice 添加 controller 以自定义方式处理异常:

@ControllerAdvice
@RequestMapping(produces = "application/json")
@ResponseBody
public class RestControllerAdvice {
    
    @Autowired
    Environment env;

    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseEntity<?> unhandledPath(final NoHandlerFoundException e) {
         
        //This is for 405 METHOD NOT ALLOWED
        //Here you may want to return a ResponseEntity with a custom POJO as body.

    }
    
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResponseEntity<?> methodNotAllowed(final HttpRequestMethodNotSupportedException e) {
        
        //This is for 404 NOT FOUND
        //Here you may want to return a ResponseEntity with a custom POJO as body.

    }

}

在 Spring Security 中处理 403 UNAUTHORIZED 时,情况会有所不同。 您必须编写一个实现 AccessDeniedHandler 接口的@Component。 像这样的东西:

@Component
public class AccessEntryPoint implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest req,
                       HttpServletResponse res,
                       AccessDeniedException accessDeniedException) throws IOException, ServletException {
        
        ObjectMapper mapper = new ObjectMapper();
        res.setContentType("application/json;charset=UTF-8");
        res.setStatus(403);
        res.getWriter().write( /*Your custom object may go here*/ );
    }
}

但这还不够,您还必须使用以下方法在 WebSecurityConfigureAdapter 实现中设置自定义 AccessDeniedHandler 实现:

@Autowired
AccessEntryPoint accessDeniedHandler;

并将以下内容附加到您的配置方法调用链中:

.exceptionHandling().accessDeniedHandler(accessDeniedHandler).and()

编辑:我忘了添加,为了使 404 自定义处理程序工作,您必须在 application.properties 文件中添加这两行:

spring.resources.add-mappings=false
spring.mvc.throw-exception-if-no-handler-found=true

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM