Springboot之访问web资源
在springmvc中,访问web资源是重要的知识。
其中springboot整合了主要两种访问web资源的方式。
RestTemplate访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-enf0xrnP-1591437322240)(C:\Users\18221\AppData\Roaming\Typora\typora-user-images\image-20200606163826291.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NujXUVNI-1591437322243)(C:\Users\18221\AppData\Roaming\Typora\typora-user-images\image-20200606172842857.png)]
(来源于极客时间丁雪丰老师课件)
以一个例子来说明访问方法:
1.restemplate 配置方式:
//一般采用builder模式进行构建和配置
//或者以构造器的方式进行构建
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
// return new RestTemplate();
return builder.build();
}
2.构建uri
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xx1kQl4K-1591437322248)(C:\Users\18221\AppData\Roaming\Typora\typora-user-images\image-20200606172153278.png)]
使用UriComponentBuilder类进行资源访问绑定,采用builder模式进行传参
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:8080/coffee/{id}")
.build(1);
3.确定资源访问方式:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6iQu3qc7-1591437322252)(C:\Users\18221\AppData\Roaming\Typora\typora-user-images\image-20200606170111427.png)]
(来源于极客时间丁雪丰老师课件)
例如:
//getForEntity()方法以get方式在指定的uri上查询资源并以entity——coffee类型访问实体list
ResponseEntity<Coffee> c = restTemplate.getForEntity(uri, Coffee.class);
log.info("Response Status: {}, Response Headers: {}", c.getStatusCode(), c.getHeaders().toString());
log.info("Coffee: {}", c.getBody());
//以post方式去更新资源,则需要创建一个Coffee类对象,作为请求体传进去,同时
//调用postForObject()方法来返回更新掉的资源类型
String coffeeUri = "http://localhost:8080/coffee/";
Coffee request = Coffee.builder()
.name("Americano")
.price(BigDecimal.valueOf(25.00))
.build();
Coffee response = restTemplate.postForObject(coffeeUri, request, Coffee.class);
log.info("New Coffee: {}", response);
String s = restTemplate.getForObject(coffeeUri, String.class);
log.info("String: {}", s);
RestTemplate访问之升级版
传递 HTTP Header
• RestTemplate.exchange()
• RequestEntity / ResponseEntity
官网上对于这个的介绍是
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j5xy5Zrt-1591437322255)(C:\Users\18221\AppData\Roaming\Typora\typora-user-images\image-20200606173437376.png)]
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());
类型转换
• JsonSerializer / JsonDeserializer
• @JsonComponent
解析泛型对象
• RestTemplate.exchange()
• ParameterizedTypeReference
在解析泛型对象时应借助ParameterizedTypeReference
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9dDoUcnO-1591437322258)(C:\Users\18221\AppData\Roaming\Typora\typora-user-images\image-20200606171908582.png)]
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的exchange()方法的介绍
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xkj0rbNU-1591437322259)(C:\Users\18221\AppData\Roaming\Typora\typora-user-images\image-20200606173046950.png)]
定制化RestTemplate
默认是实现SipleClientHttpRequestFactory
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cw9xbGWN-1591437322260)(C:\Users\18221\AppData\Roaming\Typora\typora-user-images\image-20200606174532167.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GTmieXZT-1591437322262)(C:\Users\18221\AppData\Roaming\Typora\typora-user-images\image-20200606174326914.png)]
这方面的应用可以以下面的例子来说明
1.定义一个链接保持时间的策略类,主要是通过实现ConnectionKeepAliveStrategy接口
public class CustomConnectionKeepAliveStrategy implements ConnectionKeepAliveStrategy {
private final long DEFAULT_SECONDS = 30;
@Override
public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
return Arrays.asList(response.getHeaders(HTTP.CONN_KEEP_ALIVE))
.stream()
.filter(h -> StringUtils.equalsIgnoreCase(h.getName(), "timeout")
&& StringUtils.isNumeric(h.getValue()))
.findFirst()
.map(h -> NumberUtils.toLong(h.getValue(), DEFAULT_SECONDS))
.orElse(DEFAULT_SECONDS) * 1000;
}
}
2.创建一个requestFactory
@Bean
public HttpComponentsClientHttpRequestFactory requestFactory() {
//先创建链接管理器对象,来设置最大链接个数
PoolingHttpClientConnectionManager connectionManager =
new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS);
connectionManager.setMaxTotal(200);
connectionManager.setDefaultMaxPerRoute(20);
//创建可关闭的httpclient
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.evictIdleConnections(30, TimeUnit.SECONDS)
.disableAutomaticRetries()
// 有 Keep-Alive 认里面的值,没有的话永久有效
//.setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)
// 换成自定义的
.setKeepAliveStrategy(new CustomConnectionKeepAliveStrategy())
.build();
//包装上这个属性
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory(httpClient);
return requestFactory;
}
4.调用的主要方法:
@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));
}
izedTypeReference<List>() {};
ResponseEntity<List> list = restTemplate
.exchange(coffeeUri, HttpMethod.GET, null, ptr);
list.getBody().forEach(c -> log.info(“Coffee: {}”, c));
}