我正在使用RestTemplate
对我们的服务进行HTTP调用,该服务返回一个简单的JSON响应。我根本不需要解析那个JSON。我只需要返回我从该服务中获得的任何内容。
所以我将它映射到String.class
并将实际的JSON response
作为字符串返回。
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(url, String.class);
return response;
现在的问题是 -
我想在点击URL后提取HTTP Status codes
。如何从上面的代码中提取HTTP状态代码?我是否需要以目前的方式对其进行任何更改?
更新: -
这是我尝试过的,我能够得到回复和状态代码。但是我总是需要像下面那样设置HttpHeaders
和Entity
对象吗?
RestTemplate restTemplate = new RestTemplate();
//and do I need this JSON media type for my use case?
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
//set my entity
HttpEntity<Object> entity = new HttpEntity<Object>(headers);
ResponseEntity<String> out = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
System.out.println(out.getBody());
System.out.println(out.getStatusCode());
几个问题 - 我需要有MediaType.APPLICATION_JSON
,因为我只是调用url返回响应,它可以返回JSON或XML或简单的字符串。
使用返回RestTemplate#exchange(..)
的ResponseEntity
方法。这使您可以访问状态行和标题(显然是身体)。
如果你不想像我一样留下RestTemplate.get/postForObject...
方法背后的漂亮抽象,并且不喜欢在使用RestTemplate.exchange...
(Request-和ResponseEntity,HttpHeaders等)时需要使用样板文件,那么还有另外一个选项可以访问HttpStatus代码。
只需用RestTemplate.get/postForObject...
和org.springframework.web.client.HttpClientErrorException
的try / catch包围通常的org.springframework.web.client.HttpServerErrorException
,就像在这个例子中一样:
try {
return restTemplate.postForObject("http://your.url.here", "YourRequestObjectForPostBodyHere", YourResponse.class);
} catch (HttpClientErrorException | HttpServerErrorException httpClientOrServerExc) {
if(HttpStatus.NOT_FOUND.equals(httpClientOrServerExc.getStatusCode())) {
// your handling of "NOT FOUND" here
// e.g. throw new RuntimeException("Your Error Message here", httpClientOrServerExc);
}
else {
// your handling of other errors here
}
org.springframework.web.client.HttpServerErrorException
在这里添加了50x
的错误。
现在你可以简单地对你想要的所有StatusCode做出反应 - 除了适当的一个,与你的HTTP方法相匹配 - 比如GET
和200
,它们不会作为例外处理,因为它是匹配的。但是,如果您正在实施/使用RESTful服务,这应该是直截了当的:)
private RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(url,HttpMethod.GET, requestEntity,String.class);
响应包含'body','headers'和'statusCode'
获取statusCode:response.getStatusCode();
有些人可能会陷入一些稍微棘手的用例(正如我所做的那样)。考虑以下:
支持Page对象以便与RestTemplate和ParameterizedTypeReference一起使用:
休息寻呼响应:
import java.util.ArrayList;
import java.util.List;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
public class RestResponsePage<T> extends PageImpl<T>{
private static final long serialVersionUID = 3248189030448292002L;
public RestResponsePage(List<T> content, Pageable pageable, long total) {
super(content, pageable, total);
}
public RestResponsePage(List<T> content) {
super(content);
}
public RestResponsePage() {
super(new ArrayList<T>());
}
}
使用ParameterizedTypeReference
将产生以下结果:
ParameterizedTypeReference<RestResponsePage<MyObject>> responseType =
new ParameterizedTypeReference<RestResponsePage<MyObject>>() {};
HttpEntity<RestResponsePage<MyObject>> response = restTemplate.exchange(oauthUrl, HttpMethod.GET, entity, responseType);
打电话给#exchange:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<?> entity = new HttpEntity<>(headers);
response = restTemplate.exchange("localhost:8080/example", HttpMethod.GET, entity, responseType);
现在这里是“棘手”的部分。
试图调用交换的getStatusCode
将是不可能的,因为不幸的是,编译器将不会意识到“预期”类型的response
。
这是因为泛型是通过类型擦除实现的,它在编译期间删除了有关泛型类型的所有信息(read more - source)
((ResponseEntity<RestResponsePage<MyObject>>) response).getStatusCode()
在这种情况下,您必须显式地将变量强制转换为所需的类以获取statusCode
(和/或其他属性)!
exchange(...)有效但如果你想要更少的代码,你可以使用
org.springframework.boot.test.web.client.TestRestTemplate.getForEntity(...)
返回包含StatusCode的实体。将您的示例代码更改为:
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
HttpStatus statusCode = response.getStatusCode();
要测试它,您可以使用我的单元测试中的这个片段:
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
assertResponseHeaderIsCorrect(response, HttpStatus.OK);
/**
* Test the basics of the response, non-null, status expected, etc...
*/
private void assertResponseHeaderIsCorrect(ResponseEntity<String> response, HttpStatus expectedStatus) {
assertThat(response).isNotNull();
assertThat(response.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON_UTF8);
assertThat(response.getStatusCode()).isEqualTo(expectedStatus);
}
把这么多的代码放到我的HttpStatus statusCode = ((ResponseEntity<Object>) responseOfEsoft).getStatusCode();
就足够了
如果你想从RestTemplate包括4XX和5XX的所有HTTPStatus,你将不得不向restTemplate提供一个ResponseErrorHandler,因为默认处理程序将在4XX或5XX的情况下抛出异常
我们可以这样做:
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
@Override
public boolean hasError(HttpStatus statusCode) {
return false;
}
});
ResponseEntity<YourResponse> responseEntity =
restTemplate.getForEntity("http://your.url.here", YourResponse.class);
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.XXXX);