Spring Boot从异常处理程序返回401状态自定义对象

时间:2018-06-28 13:19:16

标签: java spring spring-boot exception-handling resttemplate

我有一个Spring Boot rest API,该API具有一个LoginController,用于执行简单的身份验证过程。这是令牌验证操作。

@PostMapping("validatetoken")
public ResponseEntity<ValidateTokenResponse> validateToken(
        @RequestBody ValidateTokenRequest validateTokenRequest, HttpServletRequest request) throws Exception {

    if (StringUtils.isEmpty(validateTokenRequest.getToken())) throw new AuthenticationFailedException("token parameter cannot be null or empty");

    Boolean isValid = authenticationService.validateToken(request, validateTokenRequest.getToken());
    ValidateTokenResponse response = new ValidateTokenResponse();
    response.setIsValid(isValid);
    response.setToken(validateTokenRequest.getToken());
    return new ResponseEntity<>(response, isValid? HttpStatus.OK : HttpStatus.UNAUTHORIZED);
}

在我的api中,我捕获了ResponseEntityExceptionHandler中的所有错误,并以此方式转换了自定义对象。

@ExceptionHandler(AuthenticationFailedException.class)
@ResponseBody
protected ResponseEntity<Object> handleAuthenticationFailed(AuthenticationFailedException ex) {
    LogManager.error(ex);
    ApiError apiError = new ApiError(HttpStatus.UNAUTHORIZED);
    apiError.setMessage(ex.getMessage());
    return buildResponseEntity(apiError);
}

但是,当我想像下面那样使用RestTemplate来调用此api时,我得到了类似 java.net.HttpRetryException的异常:由于服务器身份验证,无法在流模式下重试

ResponseEntity<String> responseEntity =
    restTemplate.exchange(
        this.validateTokenUrl,
        HttpMethod.POST,
        requestHttpEntity,
        String.class);

但是,如果我将HttpStatusExceptionHandler更改为HttpStatus.UNAUTHORIZED除外,则可以从客户端获得真实的ApiError对象。是什么导致此问题,我该如何解决?

编辑:创建了一个github repo来模仿我项目中有问题的部分。

2 个答案:

答案 0 :(得分:0)

默认情况下,RestTemplate使用DefaultResponseErrorHandler。每当从REST API发送4xx / 5xx响应时,此错误处理程序就会引发异常。

如果要自定义错误处理,只需通过restTemplate.setErrorHandler注册自定义错误处理程序,即可在其中使用ResponseErrorHandler接口的实现。

答案 1 :(得分:0)

为清楚起见,我建议将带有以下详细信息的resttemplate自动连接到单独的配置文件中

@Bean
  public RestTemplate restTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.setErrorHandler(new ErrorHandler());

    SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
    requestFactory.setOutputStreaming(false);

    restTemplate.setRequestFactory(requestFactory);

    return restTemplate;
  }