RestTemplate restTemplate = new RestTemplate();
final MappingJackson2XmlHttpMessageConverter converter = new MappingJackson2XmlHttpMessageConverter();
final List<MediaType> supportedMediaTypes = new LinkedList<MediaType>(converter.getSupportedMediaTypes());
supportedMediaTypes.add(MediaType.ALL);
converter.setSupportedMediaTypes(supportedMediaTypes);
restTemplate.getMessageConverters().add(converter);
ResponseEntity<MyDTO[]> response = restTemplate.getForEntity(urlBase, MyDTO[].class);
HttpHeaders headers = response.getHeaders();
URI location = headers.getLocation(); // Has my redirect URI
response.getBody(); //Always null
我的印象是 302 会自动被跟随。我的这个假设不正确吗?我现在需要选择这个位置并重新请求?
使用默认的
ClientHttpRequestFactory
实现 - 即 SimpleClientHttpRequestFactory - 默认行为是遵循位置标头的 URL(对于带有状态代码 3xx
的响应) - 但前提是初始请求是 GET
请求。
详情可以在这个类中找到——搜索以下方法:
protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
...
if ("GET".equals(httpMethod)) {
connection.setInstanceFollowRedirects(true);
}
这里是
HttpURLConnection.setInstanceFollowRedirects
方法的相关文档注释:
设置 HTTP 重定向(响应代码为 3xx 的请求)是否应该 自动后跟此 {@code HttpURLConnection} 实例。
默认值来自 followRedirects,默认为 true。
您是否尝试从一种协议重定向到另一种协议,例如从 http 到 https 或者反之亦然?如果是这样,自动重定向将不起作用。请参阅此评论:URLConnection 不遵循重定向
经过Java Networking工程师的讨论,我们认为 不应自动遵循从一种协议到另一种协议的重定向, 例如,从 http 到 https,反之亦然,这样做可能会 严重的安全后果
来自 https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4620571
否则,如果您调试
RestTemplate
代码,您将看到默认情况下 HttpURLConnection
已通过 getInstanceFollowRedirects() == true
正确设置。
使用 CommonsClientHttpRequestFactory(下面使用 HttpClient v3)时,您可以覆盖 postProcessCommonsHttpMethod 方法并设置为遵循重定向。
public class FollowRedirectsCommonsClientHttpRequestFactory extends CommonsClientHttpRequestFactory {
@Override
protected void postProcessCommonsHttpMethod(HttpMethodBase httpMethod) {
httpMethod.setFollowRedirects(true);
}
}
然后您可以像这样使用它(使用可选的,可能是预先配置的 HttpClient 实例),并且请求将遵循
location
标头作为响应:
RestTemplate restTemplate = new RestTemplate(
new FollowRedirectsCommonsClientHttpRequestFactory());
如果
RestTemplate
是 Spring Bean 并且由 RestTemplateBuilder
创建:
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
final var timeout = Duration.ofSeconds(5);
return builder
.requestFactory(() -> new SimpleClientHttpRequestFactory() {
@Override
protected void prepareConnection(HttpURLConnection connection,
String httpMethod) throws IOException {
super.prepareConnection(connection, httpMethod);
// always follow redirect for any request method
connection.setInstanceFollowRedirects(true);
}
})
.setConnectTimeout(timeout)
.setReadTimeout(timeout)
.build();
}
尝试像这样创建 RestTemplate (Spring 配置):
@Bean("smartRestTemplate")
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder
.setConnectTimeout(Duration.ofSeconds(..))
.setReadTimeout(Duration.ofSeconds(..))
.build();
}