Spring 控制器 - 显示 JSON 而不是 Whitelabel 错误页面(在浏览器中)

clo*_*oze 4 java spring-mvc spring-boot

您好,有一个简单的 spring 控制器,在出现错误时返回 ResponseStatusException。

@RestController
@RequestMapping("/process")
public class ProcessWorkitemController {
    @Autowired MyService service;
    
    @GetMapping("/{id}")
    public ResponseEntity<?> findById(@PathVariable Long id) {
        Optional<MyObj> opt = service.getObj(id);
        opt.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, String.format("Process id %s not found", id), null));
        
        return ResponseEntity.ok(opt.get());
    }
}
Run Code Online (Sandbox Code Playgroud)

如果使用 SoapUI 调用,则效果很好:它向我显示一个 Json,如下所示:

{
   "timestamp": "2021-01-20T10:59:48.082+0000",
   "status": 404,
   "error": "Not Found",
   "message": "Process id 1 not found",
   "path": "/workspace-manager/process/1"
}
Run Code Online (Sandbox Code Playgroud)

当我使用浏览器调用相同的服务时,它会显示带有我的自定义错误消息的白标签错误页面。

即使在浏览器上我也想要一个 JSON 作为响应,这可能吗?

提前致谢。

Ari*_*tex 6

我会避免使用ResponseStatusException,特别是在构建需要统一方式处理异常的应用程序时。我会做以下事情:

  1. 创建一个新类并使用@RestControllerAdvice. 这实际上将成为应用程序异常处理的主要入口点。
  2. 创建处理不同类型异常的方法并使用来自异常的消息和/或信息返回响应。
  3. 只需从服务层或控制器层抛出此类异常,然后让异常处理程序处理它即可。

一个简单的例子如下(忽略内部类——只是为了节省空间)。

  1. 异常处理程序:
@RestControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler(ServiceException.class)
    public ResponseEntity<ExceptionResponse> handleException(ServiceException e) {
        return ResponseEntity
            .status(e.getStatus())
            .body(new ExceptionResponse(e.getMessage(), e.getStatus().value()));
    }

    public static class ExceptionResponse {

        private final String message;
        public String getMessage() { return message; }

        private final Integer code;
        public Integer getCode() { return code; }

        public ExceptionResponse(String message, Integer code) {
            this.message = message;
            this.code = code;
        }

    }

}
Run Code Online (Sandbox Code Playgroud)
  1. 基本服务异常:
package com.ariskourt.test.controllers;

import org.springframework.http.HttpStatus;

public abstract class ServiceException extends RuntimeException{

    public ServiceException(String message) {
        super(message);
    }

    public abstract HttpStatus getStatus();

}
Run Code Online (Sandbox Code Playgroud)
  1. 控制器
@RestController
@RequestMapping("/process")
public class ProcessController {

    @GetMapping("/{id}")
    public ResponseEntity<?> findById(@PathVariable Long id) {
        return Optional
        .of(1L)
        .filter(number -> number.equals(id))
        .map(ResponseEntity::ok)
        .orElseThrow(() -> new ProcessNotFoundException(String.format("Process with id %s not found", id)));
    }

}
Run Code Online (Sandbox Code Playgroud)

完成所有这些后,您应该采用统一的方式来处理异常,无论客户端如何,它都始终返回正确的消息。