RestTemplate的高阶用法

传递 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类

发布了59 篇原创文章 · 获赞 6 · 访问量 902

猜你喜欢

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