传递 HTTP Header
- RestTemplate.exchange()
通过exchange传入一个RequestEntity - RequestEntity / ResponseEntity
RequestEntity和ResponseEntity 可以带上一些请求的http头
String uri = "http://example.com/hotels/{hotel}";
URI uriComponents = UriComponentsBuilder.fromUriString(uri).build(42);
RequestEntity<Void> requestEntity = RequestEntity.get(uriComponents) //因为是get请求,所以泛型为void,如果是post,那么就要换
.header("MyRequestHeader", "myvalue") //加入一个header,即http头
.build();
ResponseEntity<String> exchange = restTemplate.exchange(requestEntity, String.class);
String s = exchange.getHeaders().getFirst("MyResponseHeader");//取出第一个header
String body = exchange.getBody();
类型转换
- JsonSerializer / JsonDeserializer
json的序列化与反序列化 - @JsonComponent ( json的序列化与反序列化必须要有这个注解)
解析泛型对象(list链)
- RestTemplate.exchange()
需要传入ParameterizedTypeReference - ParameterizedTypeReference<<T.>>
提供的一个特殊的类,可以去定义一个泛型的类型
ParameterizedTypeReference<List<Coffee>> ptr =
new ParameterizedTypeReference<List<Coffee>>() {};
ResponseEntity<List<Coffee>> list = restTemplate
.exchange(coffeeUri, HttpMethod.GET, null, ptr);//将coffeeUri路径取回的结果转换成一个List<Coffee>
// ptr coffee链 HttpMethod.GET get请求
list.getBody().forEach(c -> log.info("Coffee: {}", c));
实例
@JsonComponent
public class MoneyDeserializer extends StdDeserializer<Money> {
protected MoneyDeserializer() {
super(Money.class);
}
@Override
public Money deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return Money.of(CurrencyUnit.of("CNY"), p.getDecimalValue());//CNY货币类型的Decimal类
}
}
@JsonComponent
public class MoneySerializer extends StdSerializer<Money> {
protected MoneySerializer() {
super(Money.class);
}
@Override
public void serialize(Money money, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeNumber(money.getAmount()); //取出money中的Amount,输出为一个数字
}
}
@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 RestTemplate restTemplate(RestTemplateBuilder builder) {
// return new RestTemplate();
return builder.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) //设置一个头 accept 告诉服务端,需要去接收的响应的类型为xml wait_serive 根据不同的头输出不同的响应
.build();
ResponseEntity<String> resp = restTemplate.exchange(req, String.class);//打印出来的为xml类型
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)) //使用Money类,进行金额的处理
.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);//将coffeeUri路径取回的结果转换成一个List<Coffee>
// ptr coffee链 HttpMethod.GET get请求 没有需要设置的头
list.getBody().forEach(c -> log.info("Coffee: {}", c));
}
}
结果
分析
通过设置头,将响应的类型设置为xml,当然,还可以设置为其他格式的。之后,输出的字符串即为该格式
通过new ParameterizedTypeReference<List<Coffee.>>() {}和restTemplate.exchange,实现了解析泛型对象(list链)的功能。
需要注意的是,我们不能直接获取list;
String coffeeUri = "http://localhost:8080/coffee/";
ArrayList<Coffee> list1 = new ArrayList<>();
list1 = restTemplate.getForObject(coffeeUri, list1.getClass());
list1.forEach(coffee -> log.info("c:{}",coffee.getClass()));
错误为:无法将LinkedHashMap转换为coffee类 它只认出是个list,但是 list中的对象没有认出来
整个报文的响应的处理中,没有找到一个类型的时候,它会把里面的对象变成LinkedHashMap,所以我们取出的是ArrayList<LinkedHashMap.>。即,这种方式,没有告诉服务器coffee类