【发布时间】:2018-12-07 14:25:26
【问题描述】:
我有一个 Spring Boot REST 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: cannot retry due to server authentication, in streaming mode 这样的异常。
ResponseEntity<String> responseEntity =
restTemplate.exchange(
this.validateTokenUrl,
HttpMethod.POST,
requestHttpEntity,
String.class);
但是,如果我将 HttpStatus 从 ExceptionHandler 更改为 HttpStatus.UNAUTHORIZED 除外,我可以从客户端获得真正的 ApiError 对象。什么可能导致此问题,我该如何解决?
编辑:创建了一个 github repo 来模仿我项目中的问题部分。
【问题讨论】:
-
我只是尝试使用“Controller”和“ControllerAdvice”而不是“RestController”和“RestControllerAdvice”注释。异常处理程序开始工作。
-
异常处理程序同时使用 Controller 和 RestController 以及两种类型的 Advices。我的问题是关于当 api 抛出 AuthenticationException 时从客户端获取 api 调用的结果。客户端在
restTemplate.exchange()上遇到错误,例如““localhost:8080/api/auth/validatetoken”的 POST 请求出现 I/O 错误:由于服务器身份验证,在流模式下无法重试”。所以我无法从 api 响应中获取ApiError类实例和详细信息。
标签: java spring spring-boot exception-handling resttemplate