简单定制 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

发布了61 篇原创文章 · 获赞 6 · 访问量 1112

猜你喜欢

转载自blog.csdn.net/weixin_43790623/article/details/104061305