RestTemplate 用法详解(一)

本文详细介绍了Spring的RestTemplate工具,用于执行HTTP请求,支持GET、POST、PUT、DELETE等方法。通过RestTemplate,可以方便地进行RESTful操作。文章通过实例展示了如何设置超时时间、解决乱码问题,并提供了POST请求的多种使用方式,包括postForEntity、postForObject和postForLocation,分别对应不同的返回类型。此外,还展示了如何传递JSON字符串和JavaBean对象作为请求参数。

RestTemplate 简介

        RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。RestTemplate 继承自 InterceptingHttpAccessor 并且实现了 RestOperations 接口,其中 RestOperations 接口定义了基本的 RESTful 操作,这些操作在 RestTemplate 中都得到了实现。接下来我们就来看看这些操作方法的使用。

RestTemplate实战使用

        写一个工具类RestUtil,在实际项目中往往使用单例模式来设计RestTemplate

/**
 * RestAPI 调用器
 */
private final static RestTemplate RT;

static {
	SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
	// 设置连接超时时间,单位为毫秒
	requestFactory.setConnectTimeout(30000);
	// 设置读取超时时间,单位为毫秒
	requestFactory.setReadTimeout(30000);
	RT = new RestTemplate(requestFactory);
	// 解决乱码问题
	RT.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
}

public static RestTemplate getRestTemplate() {
	return RT;
}

 在其他地方需要使用时只需一列下行代码即可:

private static RestTemplate restTemplate = RestUtil.getRestTemplate();

POST请求

        POST请求中有三个方法,分别是postForEntity,postForObject,postForLocation。这三类方法最直观的就是返回值类型定义不同,具体如下代码所示:

public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException {
	RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
	ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
	return (ResponseEntity)nonNull(this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables));
}

@Nullable
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException {
	RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
	HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor(responseType, this.getMessageConverters(), this.logger);
	return this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, (Object[])uriVariables);
}

@Nullable
// 返回值为URI对象,因为Post请求最常用来添加数据,如果需要将刚刚添加成功的数据的URL返回来,此时就可以使用这个方法
public URI postForLocation(String url, @Nullable Object request, Object... uriVariables) throws RestClientException {
	RequestCallback requestCallback = this.httpEntityCallback(request);
	HttpHeaders headers = (HttpHeaders)this.execute(url, HttpMethod.POST, requestCallback, this.headersExtractor(), uriVariables);
	return headers != null ? headers.getLocation() : null;
}

        参数类型分别为:

        1)String url        请求的url路径       

        2)@Nullable Object request        可为空的请求对象

        3)Class<T> responseType        返回类型的类定义

        4)Object... uriVariables        动态的uri参数,可传递多个

        5)Map<String, ?> uriVariables        以Map方式存储的uri参数

1、postForEntity方法

        参数可以是key/value类型也可以是json串

(一)传递key/value参数

        首先在服务端写一个Post请求的接口

@PostMapping(value = "/synchronizationCar")
public String synchronizationCar(@RequestBody MultiValueMap map) {
	System.out.println(map.get("name"));
	System.out.println(map.get("sex"));
	System.out.println(map.get("description"));
	return  "";
}

        客户端请求代码如下:

public static void main(String[] args) {
	HttpHeaders headers = new HttpHeaders();
	MultiValueMap map = new LinkedMultiValueMap();
	map.add("name", "雷锋");
	map.add("sex", "男");
	map.add("description", "乐于助人的好人");
	HttpEntity entity = new HttpEntity<>(map, headers);
	ResponseEntity<String> json = restTemplate.postForEntity("http://localhost:8099/basics/bisBasicsCar/synchronizationCar", entity, String.class);
}

(二)传递json字符串

        首先服务端解析代码如下:

@PostMapping(value = "/synchronizationCar")
public String synchronizationCar(@RequestBody String s) {
	JSONObject jsonObject = JSONObject.parseObject(s);
	JSONArray jsonArray = jsonObject.getJSONArray("data");
	List<BisBasicsCar> list = jsonArray.toJavaList(BisBasicsCar.class);
	System.out.println(list.size());
	return  "ok";
}

        客户端请求代码如下:

private void basicsSynchronization(){

	//车辆表
	List<BisBasicsCar> list = bisBasicsCarMapper.selectList(null);
	HttpHeaders headers = new HttpHeaders();
	headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
	JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(list));
	//object
	JSONObject jsonObject = new JSONObject();
	jsonObject.put("data", jsonArray);
	HttpEntity entity = new HttpEntity<>(jsonObject, headers);
//        String json = restTemplate.postForObject("http://localhost:8099/basics/bisBasicsCar/synchronizationCar", entity, String.class);
	ResponseEntity<String> json = restTemplate.postForEntity("http://localhost:8099/basics/bisBasicsCar/synchronizationCar", entity, String.class);
	if (json != null){
		/*JSONArray users = json.getJSONArray("data");
		list = users.toJavaList(BisBasicsCar.class);*/
	}
}

        此处注意的有以下几点:

        1、key/value传参要使用LinkedMultiValueMap而不是HashMap

        2、笔者使用的json转换是借用alibaba的第三方包fastjson

        3、server端要接收参数需要用@RequestBody注解,不然无法接收到参数

2、postForObject方法

        先看下源码中关于postForObject有三种不同传参的方法

@Nullable
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException {
	RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
	HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor(responseType, this.getMessageConverters(), this.logger);
	return this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, (Object[])uriVariables);
}

@Nullable
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {
	RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
	HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor(responseType, this.getMessageConverters(), this.logger);
	return this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, (Map)uriVariables);
}

@Nullable
public <T> T postForObject(URI url, @Nullable Object request, Class<T> responseType) throws RestClientException {
	RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
	HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor(responseType, this.getMessageConverters());
	return this.execute(url, HttpMethod.POST, requestCallback, responseExtractor);
}

        参数可以是Json字符串,JavaBean对象,也可以是map,其中本质都是使用了HttpEntity对象

(一)传递Json字符串

        传递Json字符串需要手动的将Json字符串添加到HttpEntity,具体做法如下:

public void test(){
	//车辆表
	List<BisBasicsCar> list = bisBasicsCarMapper.selectList(null);
	HttpHeaders headers = new HttpHeaders();
	headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
	JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(list));
	//object
	JSONObject jsonObject = new JSONObject();
	jsonObject.put("data", jsonArray);
	HttpEntity entity = new HttpEntity<>(jsonObject, headers);//@1
	String json = restTemplate.postForObject("http://localhost:8099/basics/bisBasicsCar/synchronizationCar", entity, String.class);
}

        @1:将Json字符串添加到HttpEntity 对象中

(二)传递JavaBean

        有两种做法,一种是手动把JavaBean添加到HttpEntity对象中,一种直接传JavaBean对象

public void test2(){
	BisBasicsCar bisBasicsCar = new BisBasicsCar();
	bisBasicsCar.setCarType("轿车");
	bisBasicsCar.setDriver("司机王师傅");
	bisBasicsCar.setLicenseNumber("沪A888888");
	HttpHeaders headers = new HttpHeaders();
	HttpEntity entity = new HttpEntity<>(bisBasicsCar, headers);//@1
	String json = restTemplate.postForObject("http://localhost:8099/basics/bisBasicsCar/synchronizationCar", entity, String.class);
}

public void test3(){
	BisBasicsCar bisBasicsCar = new BisBasicsCar();
	bisBasicsCar.setCarType("轿车");
	bisBasicsCar.setDriver("司机王师傅");
	bisBasicsCar.setLicenseNumber("沪A888888");
	String json = restTemplate.postForObject("http://localhost:8099/basics/bisBasicsCar/synchronizationCar", bisBasicsCar, String.class);//@2
}

        @1:手动将JavaBean加入到HttpEntity 对象中

        @2:直接传JavaBean对象

        为什么说本质上都是使用了HttpEntity对象呢?

        是因为源码中有这样一段代码:

public HttpEntityRequestCallback(@Nullable Object requestBody, @Nullable Type responseType) {
	super(responseType);
	if (requestBody instanceof HttpEntity) {
		this.requestEntity = (HttpEntity)requestBody;
	} else if (requestBody != null) {
		this.requestEntity = new HttpEntity(requestBody);
	} else {
		this.requestEntity = HttpEntity.EMPTY;
	}

}

        程序会自动判断,如果不是HttpEntity对象就手动添加一次

3、postForLocation

        postForLocation也是提交新资源,提交成功之后,返回新资源的URI,postForLocation的参数和前面两种的参数基本一致,只不过该方法的返回值为Uri,这个只需要服务提供者返回一个Uri即可,该Uri表示新资源的位置。

        然后看下列实际代码中会发现,最终还是使用了HttpEntity对象

public HttpEntityRequestCallback(@Nullable Object requestBody) {
	this(requestBody, (Type)null);//@1
}

public HttpEntityRequestCallback(@Nullable Object requestBody, @Nullable Type responseType) {//@2
	super(responseType);
	if (requestBody instanceof HttpEntity) {
		this.requestEntity = (HttpEntity)requestBody;
	} else if (requestBody != null) {
		this.requestEntity = new HttpEntity(requestBody);
	} else {
		this.requestEntity = HttpEntity.EMPTY;
	}

}

        Java多态的方法,但是还在@1的位置处调用了@2的方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zfy_220

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值