一次HTTP请求过程
- 构建请求对象:远程连接、网络请求等
- 执行远程调用:异常处理、状态码控制等
- 处理响应结果:数据结构转换
创建RestTemplate
RestTemplate优势:相较于传统Apache中的HttpClient客户端工具类,RestTemplate对于编码的简便性以及异常的处理等方面都做了很多改进。
无参构造函数
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
有参构造函数
@Bean
RestTemplate customRestTemplate(){
HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpComponentsClientHttpRequestFactory.setConnectionRequestTimeout(3000);
httpComponentsClientHttpRequestFactory.setConnectTimeout(3000);
httpComponentsClientHttpRequestFactory.setReadTimeout(3000);
}
RestTemplate 方法组
- Get:getForObject/getForEntity
- Post: postForLocation/postForObject/postForEntity
- Put: put
- Delete: delete
- Header: headForHeaders
- 不限:exchange/execute
使用RestTemplate - get方法组
@Nullable
<T> T getForObject(String var1, Class<T> var2, Object... var3) throws RestClientException;
@Nullable
<T> T getForObject(String var1, Class<T> var2, Map<String, ?> var3) throws RestClientException;
@Nullable
<T> T getForObject(URI var1, Class<T> var2) throws RestClientException;
<T> ResponseEntity<T> getForEntity(String var1, Class<T> var2, Object... var3) throws RestClientException;
<T> ResponseEntity<T> getForEntity(String var1, Class<T> var2, Map<String, ?> var3) throws RestClientException;
<T> ResponseEntity<T> getForEntity(URI var1, Class<T> var2) throws RestClientException;
getForEntity方法的返回值是一个ResponseEntity对象,在这个对象中还包含了HTTP消息头等信息,而getForObject方法返回的则是业务对象本身,这是两个方法组的主要区别。
使用RestTemplate - post方法组
使用RestTemplate - exchange方法组
RestTemplate 技巧
指定消息转换器:用于在获取返回结果时的数据转换
@Bean
RestTemplate customRestTemplate(){
HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpComponentsClientHttpRequestFactory.setConnectionRequestTimeout(3000);
httpComponentsClientHttpRequestFactory.setConnectTimeout(3000);
httpComponentsClientHttpRequestFactory.setReadTimeout(3000);
RestTemplate restTemplate = new RestTemplate(httpComponentsClientHttpRequestFactory);
ArrayList<HttpMessageConverter<?>> httpMessageConverters = new ArrayList<>();
httpMessageConverters.add(new GsonHttpMessageConverter());
restTemplate.setMessageConverters(httpMessageConverters);
return restTemplate;
}
设置拦截器
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(
//这段代码来自Spring Cloud 的 LoadBalanceAutoConfiguration
//通过@LoadBalanced 注解为RestTemplate 自动添加负载均衡机制
final LoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptor());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
}
}
通过实现ClientHttpRequestInterceptor接口,并调用setInterceptors方法可以将任意定义的拦截器注入到RestTemplate的拦截器列表中。
处理异常
@Bean
RestTemplate customRestTemplate(){
HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpComponentsClientHttpRequestFactory.setConnectionRequestTimeout(3000);
httpComponentsClientHttpRequestFactory.setConnectTimeout(3000);
httpComponentsClientHttpRequestFactory.setReadTimeout(3000);
RestTemplate restTemplate = new RestTemplate(httpComponentsClientHttpRequestFactory);
ArrayList<HttpMessageConverter<?>> httpMessageConverters = new ArrayList<>();
httpMessageConverters.add(new GsonHttpMessageConverter());
restTemplate.setMessageConverters(httpMessageConverters);
ResponseErrorHandler responseErrorHandler = new ResponseErrorHandler() {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
return true;
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
//添加定制化的异常
}
};
restTemplate.setErrorHandler(responseErrorHandler);
return restTemplate;
}
在RestTemplate中,默认情况下当请求状态码不是返回200时就会抛出异常并中断接下来的操作,如果要排除这个处理过程就需要覆盖默认的ResponseErrorHandler。
重试
@Retryable(value = RestClientException.class,maxAttempts = 5,backoff = @Backoff(multiplier = 2,delay = 2000))
public void learning(){
restTemplate.getForObject("localhost:8080/helloword",String.class,1);
}
需引入模块
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
主程序入口
@SpringBootApplication
@EnableRetry
public class LeariningApplication {
public static void main(String[] args) {
SpringApplication.run(LeariningApplication.class, args);
}
}
使用示例
@Retryable(value = RestClientException.class,maxAttempts = 5,backoff = @Backoff(multiplier = 2,delay = 2000))
public void learning(){
restTemplate.getForObject("localhost:8080/helloword",String.class,1);
}
@Retryable
注解的方法在发生异常时会重试,参数说明:- value:当指定异常发生时会进行重试 ,HttpClientErrorException是RestClientException的子类。
- include:和value一样,默认空。如果 exclude也为空时,所有异常都重试
- exclude:指定异常不重试,默认空。如果 include也为空时,所有异常都重试
- maxAttemps:最大重试次数,默认3
- backoff:重试等待策略,默认空
@Backoff
注解为重试等待的策略,参数说明:- delay:指定重试的延时时间,默认为1000毫秒
- multiplier:指定延迟的倍数,比如设置delay=2000,multiplier=2时,第一次重试为2秒后,第二次为4秒,第三次为8秒。