02-Spring REST Template教程02

02-Spring REST Template教程02

说明:本文主要整理了spring-boot中rest template的使用方法,通过对 依赖、生产、主要方法的简要介绍,读者可以较快掌握Spring Boot Rest客户端的简单编码,文章也针对实际代码编写过程中的一些进阶要求,做了简要说明,这里包括:泛型对象转换、复杂对象序列化及反序列化定制、依赖其他库、链接复用、优化策略。

代码学习仓库如下所示:

1 gradle依赖

spring-boot-starter-web依赖中已经包含了REST Template的相关依赖,这里只需要包含了spring-boot-starter-web依赖即可。

implementation 'org.springframework.boot:spring-boot-starter-web'

2 RestTemplate构造

Spring Boot 中没有自动配置 RestTemplate,但是Spring Boot 提供了 RestTemplateBuilder,下面代码是一个相关RestTemplate的简单装配,用户可以根据需求灵活设置RestTemplateBuilder设置先关参数。

  • RestTemplateBuilder.build()
	@Bean
	public RestTemplate restTemplate(RestTemplateBuilder builder) {
		return new RestTemplate();
		//return builder.build();
	}

3 RestTemplate常用方法

GET 请求
• getForObject() / getForEntity()
POST 请求
• postForObject() / postForEntity()
PUT 请求
• put()
DELETE 请求
• delete()

4 RestTemplate 进阶

4.1 解析泛型对象

		URI uriGetAll = UriComponentsBuilder
				.fromUriString("http://localhost:8081/coffee/")
				.build(1);
		ParameterizedTypeReference<List<Coffee>> ptr =
				new ParameterizedTypeReference<List<Coffee>>() {};
		ResponseEntity<List<Coffee>> list = restTemplate
				.exchange(uriGetAll, HttpMethod.GET, null, ptr);
		list.getBody().forEach(c -> cLog.info("GET-ALL Coffee: {}", c));

4.2 类型转换

某些时候对于复杂对象,json解析无法得到正确或者符合用户要求的结果,此时可以通过@JsonComponent注解标注的自定义解析器及序列化器完成相关对象的解析及序列化定制。

标准序列化器

package com.fwding.spring.resttemplate.httpcomponents.model;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.joda.money.Money;
import org.springframework.boot.jackson.JsonComponent;

import java.io.IOException;

@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());
    }
}

标准解析器

package com.fwding.spring.resttemplate.httpcomponents.model;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.springframework.boot.jackson.JsonComponent;

import java.io.IOException;

@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());
    }
}

4.3 其他依赖库

  • Apache HttpComponents
    • HttpComponentsClientHttpRequestFactory
  • Netty
    • Netty4ClientHttpRequestFactory
  • OkHttp
    • OkHttp3ClientHttpRequestFactory

4.4 底层优化策略

连接管理理

  • PoolingHttpClientConnectionManager
  • KeepAlive 策略略

超时设置

  • connectTimeout / readTimeout

SSL校验

  • 证书检查策略略

4.5 连接复用

默认实现
• org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy

package geektime.spring.springbucks.customer.support;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.http.HttpResponse;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;

import java.util.Arrays;

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;
    }
}

6 RestTemplate完整样例演示

简单样例方法,仅针对spring rest template的常用方法作了说明和验证,这里需要结合上一个子项目02-01-rest controller+ swagger教程 进行配合演示。

package com.fwding.spring.resttemplate.httpcomponents;

import com.fwding.spring.resttemplate.httpcomponents.model.Coffee;
import com.fwding.spring.resttemplate.httpcomponents.model.NewCoffeeRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.Banner;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.util.List;

@SpringBootApplication
public class RestTemplateComplexDemoApplication implements ApplicationRunner {
	private static final Logger cLog = LoggerFactory.getLogger(RestTemplateComplexDemoApplication.class);
	@Autowired
	private RestTemplate restTemplate;

	public static void main(String[] args) {
		new SpringApplicationBuilder()
				.sources(RestTemplateComplexDemoApplication.class)
				.bannerMode(Banner.Mode.OFF)
				//设置web运行模式,这里设置为不启动
				.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 {
		//GET-方式1-直接构造字符串
		URI uri = UriComponentsBuilder
				.fromUriString("http://localhost:8081/coffee/{id}")
				.build(1);
		Coffee result = restTemplate.getForObject(uri, Coffee.class);
		cLog.info("--1--> coffee result:" + result);
		//GET-方式2-uri+变量方式
		Coffee result2 =
				restTemplate.getForObject("http://localhost:8081/coffee/{id}", Coffee.class, "2");
		cLog.info("--2--> coffee result:" + result2);

		//POST
		NewCoffeeRequest request = new NewCoffeeRequest("MOCHA", 100L);
		Coffee coffeePost = restTemplate.postForObject("http://localhost:8081/coffee/", request, Coffee.class);
		cLog.info("--3--> coffee result:" + coffeePost);

		//GET-泛型对象解析-LIST
		URI uriGetAll = UriComponentsBuilder
				.fromUriString("http://localhost:8081/coffee/")
				.build(1);
		ParameterizedTypeReference<List<Coffee>> ptr =
				new ParameterizedTypeReference<List<Coffee>>() {};
		ResponseEntity<List<Coffee>> list = restTemplate
				.exchange(uriGetAll, HttpMethod.GET, null, ptr);
		list.getBody().forEach(c -> cLog.info("GET-ALL Coffee: {}", c));
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值