简单定制 RestTemplate

RestTemplate 支持的 HTTP 库

通用接口

  • ClientHttpRequestFactory

默认实现

  • SimpleClientHttpRequestFactory(什么都不配 自动用这个)

Apache HttpComponents

  • HttpComponentsClientHttpRequestFactory (常用)

Netty

  • Netty4ClientHttpRequestFactory(已经逐渐被淘汰)

OkHttp

  • OkHttp3ClientHttpRequestFactory(主要用于安卓)

连接复用

代码实现

		return Arrays.asList(response.getHeaders(HTTP.CONN_KEEP_ALIVE))//获取KEEP_ALIVE响应头
					.stream()//转换成文本
					.filter(header -> StringUtils.equalsIgnoreCase(header.getName(),"timeout")&&StringUtils.isNumeric(header.getValue()))//在里面找到timeout这个属性并判断有没有  判断Value是不是个数字    
					//如果是数字 将文本转换成long类型   如果转换失败 会使用默认值代替(30s) 如果没有取到这个头 也会使用默认值  如果有KEEP_ALIVE头,就使用KEEP_ALIVE头里面设置的timeout 没有的话 这个连接视为永久有效
					.findFirst()
					.map(header -> NumberUtils.toLong(header.getValue(),DEF))
					.orElse(DEF)*1000;

默认实现

  • org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy

实例

@SpringBootApplication
@Slf4j
public class CustomerServiceApplication implements ApplicationRunner {
	@Autowired
	private RestTemplate restTemplate;

	public static void main(String[] args) {
		new SpringApplicationBuilder()
				.sources(CustomerServiceApplication.class)
				.bannerMode(Banner.Mode.OFF)
				.web(WebApplicationType.NONE)
				.run(args);
	}


	@Bean
	public HttpComponentsClientHttpRequestFactory requestFactory() {
		PoolingHttpClientConnectionManager connectionManager =
				new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS);//构造一个连接池的连接管理器 生命周期30s
		connectionManager.setMaxTotal(200);//最大保持连接数
		connectionManager.setDefaultMaxPerRoute(20);//设置每个路由的最大连接

		CloseableHttpClient httpClient = HttpClients.custom()//定制HttpClients
				.setConnectionManager(connectionManager) //设置连接管理器
				.evictIdleConnections(30, TimeUnit.SECONDS)//空闲连接退出时间
				.disableAutomaticRetries()//关闭自动重试  重试:请求处理的时候,系统进行了处理,但是返回响应的时候,没有把响应返回,客户端,会认为该操作没有成功,会再次尝试。这对于打款之类的敏感操作是有问题的
				// 有 Keep-Alive 认里面的值,没有的话永久有效
				//.setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)  也可以使用官方提供的请求策略
				// 换成自定义的
				.setKeepAliveStrategy(new CustomConnectionKeepAliveStrategy())//设置请求策略
				.build();

		HttpComponentsClientHttpRequestFactory requestFactory =
				new HttpComponentsClientHttpRequestFactory(httpClient);//使用httpClient 构造请求工厂

		return requestFactory;
	}

	@Bean
	public RestTemplate restTemplate(RestTemplateBuilder builder) {
//		return new RestTemplate();

		return builder
				.setConnectTimeout(Duration.ofMillis(100))//设置连接超时
				.setReadTimeout(Duration.ofMillis(500))//设置读取超时
				.requestFactory(this::requestFactory)
				.build();
	}

	@Override
	public void run(ApplicationArguments args) throws Exception {
		URI uri = UriComponentsBuilder
				.fromUriString("http://localhost:8080/coffee/?name={name}")
				.build("mocha");
		RequestEntity<Void> req = RequestEntity.get(uri)
				.accept(MediaType.APPLICATION_XML)
				.build();
		ResponseEntity<String> resp = restTemplate.exchange(req, String.class);
		log.info("Response Status: {}, Response Headers: {}", resp.getStatusCode(), resp.getHeaders().toString());
		log.info("Coffee: {}", resp.getBody());

		String coffeeUri = "http://localhost:8080/coffee/";
		Coffee request = Coffee.builder()
				.name("Americano")
				.price(Money.of(CurrencyUnit.of("CNY"), 25.00))
				.build();
		Coffee response = restTemplate.postForObject(coffeeUri, request, Coffee.class);
		log.info("New Coffee: {}", response);

		ParameterizedTypeReference<List<Coffee>> ptr =
				new ParameterizedTypeReference<List<Coffee>>() {};
		ResponseEntity<List<Coffee>> list = restTemplate
				.exchange(coffeeUri, HttpMethod.GET, null, ptr);
		list.getBody().forEach(c -> log.info("Coffee: {}", c));
	}
}

结果

在这里插入图片描述

分析

定制RestTemplate,实际上就是定制一个HttpComponentsClientHttpRequestFactory和CustomConnectionKeepAliveStrategy,在定制的过程中,disableAutomaticRetries,最好是要加上,下游,同样,做一个请求的need

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值