我有一个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);
但是,如果我将HttpStatus
从ExceptionHandler
更改为HttpStatus.UNAUTHORIZED
除外,则可以从客户端获得真实的ApiError
对象。是什么导致此问题,我该如何解决?
编辑:创建了一个github repo来模仿我项目中有问题的部分。
答案 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;
}