1

我对 Java/Spring 领域相当陌生,我正在尝试在我的 Spring Boot 应用程序中使用 @ControllerAdvice。ControllerAdvice 捕获异常但不显示我的自定义响应。

以下是引发异常的RestController的快照

ResponseEntity<MyClass> response = new ResponseEntity<MyClass>(HttpStatus.OK);

    try {   
        response = restTemplate.exchange(url, HttpMethod.GET, entity, MyClass.class);
    } catch (HttpClientErrorException  ex) {        
        throw ex;
    }catch (HttpServerErrorException   ex) {
        logger.debug(ex.getMessage() + " Server Status Code - " + ex.getStatusCode());
    }
    catch(Exception ex) {
        logger.debug(ex.getMessage() + " Generic Exception ");
    }

以下是@ControllerAdvice

@ControllerAdvice
public class GlobalExceptionHandler extends Exception {

    @ExceptionHandler(HttpClientErrorException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResponse errorHandle(HttpClientErrorException ex) {

          String responseBody = ex.getResponseBodyAsString(); 

          ObjectMapper mapper = new ObjectMapper();
          mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
          ErrorResponse errorResponse = new ErrorResponse();
          try { 
              errorResponse = mapper.readValue(responseBody, ErrorResponse.class); 

          } catch (JsonMappingException e) { 
          e.printStackTrace(); 
          } catch (JsonProcessingException e) { 
              e.printStackTrace(); 
          }
        return errorResponse;
    }
}

其他类

@JsonIgnoreProperties
public class ErrorResponse {
    @JsonProperty("error")
    public Error error;

      @JsonProperty("version") 
      public String version;

}

public class Error {
    @JsonProperty("code")
    public String Code;

    @JsonProperty("message")
    public String Message;

    public String getCode() {
        return Code;
    }

    public void setCode(String code) {
        Code = code;
    }

    public String getMessage() {
        return Message;
    }

    public void setMessage(String message) {
        Message = message;
    }

}

我在使用POSTMAN时遇到的错误是

{
    "timestamp": "2019-11-20T05:42:24.126+0000",
    "status": 404,
    "error": "Not Found",
    "message": "400 Bad Request",
    "path": "myApi/somecontroller"
}

我在浏览器上得到的错误如下

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Tue Nov 19 23:40:26 CST 2019
There was an unexpected error (type=Not Found, status=404).
400 Bad Request

任何想法/建议为什么会出现这种行为?我期待 ErrorResponse 类的 JSON 表示。

更新

在此处输入图像描述

4

3 回答 3

0

这不是异常,这是错误场景

尝试使用以下代码。

@RestController
public class IndexController implements ErrorController{

    private static final String PATH = "/error";

    @RequestMapping(value = PATH)
    public String error() {
        return "Error handling";
    }

    @Override
    public String getErrorPath() {
        return PATH;
    }
}

Spring Boot 默认寄存器 BasicErrorController 需要覆盖

于 2019-11-20T05:55:12.810 回答
0

在进行了一些测试/搜索后,发现了这一点。使用以下控制器将能够实现

@ControllerAdvice
public class GlobalExceptionHandler extends Exception {

    @ExceptionHandler(value = { HttpClientErrorException.class })
    public ResponseEntity<Object> handleResourceNotFoundException(HttpClientErrorException ex) {
        String responseBody = ex.getResponseBodyAsString();
        HttpHeaders headers = new HttpHeaders();

        headers.setContentType(MediaType.APPLICATION_JSON);     
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        ErrorResponse errorResponse = new ErrorResponse(); 
        try { 
            errorResponse = mapper.readValue(responseBody, ErrorResponse.class);         
        } catch (JsonMappingException e) { 
            e.printStackTrace(); 
            } 
        catch (JsonProcessingException e) { 
                e.printStackTrace(); 
            }

        ResponseEntity<Object> response = new ResponseEntity<>(errorResponse, headers, HttpStatus.BAD_REQUEST);

        return response;
    }
}
于 2019-11-20T16:09:41.570 回答
0

在您的情况下,您有一个 Controller Advice 方法,该方法返回特定异常的 Json 响应。因此,检查浏览器 ui 中的响应是没有意义的,因为您需要通过另一个异常处理程序配置适当的错误页面,才能按您的意愿工作。否则会显示默认的 spring 白标错误页面。

对于其余的异常处理程序,我认为当您使用对象映射器创建实例时,JSON 结构没有得到正确转换。试一试:

@ControllerAdvice
public class GlobalExceptionHandler extends Exception {

    @ExceptionHandler(HttpClientErrorException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResponse errorHandle(HttpClientErrorException ex) {

          String responseBody = ex.getResponseBodyAsString(); // The response body structure is different, you should get the message and stacktrace separately and assign it to your own response object
          ErrorResponse errorResponse = new ErrorResponse();
          Error error = new Error();
          error.setMessage(ex.getMessage());
          error.setCode(HttpStatus.BAD_REQUEST);
          errorResponse.setError(error);
          return errorResponse;
    }
}

getResponseBodyAsString - 返回转换为字符串的响应正文。使用的字符集是响应“Content-Type”或“UTF-8”的字符集。

于 2019-11-20T06:32:37.047 回答