RestTemplate使用总结

RestTemplate简介

近几年来,以信息为中心的表述性状态转移(Representational State Transfer,REST)已经称为替代传统SOAP Web 服务的流行方案.
REST是将资源的状态以最适合客户端或服务端的形式从服务器端转移到客户端(或者反过来)

在REST中,资源通过URL进行识别和定位。至于RESTful URL的结构并没有严格的规则,但是 URL应该能够识别资源,而不是简单的发一条命令到服务器上。
借助 RestTemplate,Spring应用能够方便地使用REST资源
Spring的 RestTemplate访问使用了模版方法的设计模式.
模版方法将过程中与特定实现相关的部分委托给接口,而这个接口的不同实现定义了接口的不同行为.
RestTemplate定义了36个与REST资源交互的方法,其中的大多数都对应于HTTP的方法。
其实,这里面只有11个独立的方法,其中有十个有三种重载形式,而第十一个则重载了六次,这样一共形成了36个方法。

1
2
3
4
5
6
7
8
9
10
11
delete()   //在特定的URL上对资源执行HTTP DELETE操作
exchange() //在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity,这个对象是从响应体中映射得到的
execute() //在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象
getForEntity() //发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象
getForObject() //发送一个HTTP GET请求,返回的请求体将映射为一个对象
postForEntity() //POST 数据到一个URL,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得到的
postForObject() // POST 数据到一个URL,返回根据响应体匹配形成的对象
headForHeaders() //发送HTTP HEAD请求,返回包含特定资源URL的HTTP头
optionsForAllow() //发送HTTP OPTIONS请求,返回对特定URL的Allow头信息
postForLocation() // POST 数据到一个URL,返回新创建资源的URL
put() // PUT 资源到特定的URL

实际上,由于Post 操作的非幂等性,它几乎可以代替其他的CRUD操作.

如何使用

SpringBoot 项目,创建RestTemplate的配置类RestTemplateConfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
public class RestTemplateConfig {

@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory){
return new RestTemplate(factory);
}

@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(5000);//单位为ms
factory.setConnectTimeout(5000);//单位为ms
return factory;
}
}

在Controller里注入RestTemplate

1
2
@Autowired
private RestTemplate restTemplate;

Get请求

在 RestTemplate中,发送一个GET请求,我们可以通过如下两种方式

getForEntity


getForEntity 方法的返回值是一个ResponseEntity,ResponseEntity是 Spring 对 HTTP 请求响应的封装,包括了几个重要的元素,如响应码、contentType、contentLength、响应消息体等。比如下面一个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RequestMapping("/hello")
public String getHello() {
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://localhost:8000/spark", String.class);
String body = responseEntity.getBody();
HttpStatus statusCode = responseEntity.getStatusCode();
int statusCodeValue = responseEntity.getStatusCodeValue();
HttpHeaders headers = responseEntity.getHeaders();
StringBuffer result = new StringBuffer();
result.append("responseEntity.getBody():").append(body).append("<hr>")
.append("responseEntity.getStatusCode():").append(statusCode).append("<hr>")
.append("responseEntity.getStatusCodeValue():").append(statusCodeValue).append("<hr>")
.append("responseEntity.getHeaders():").append(headers).append("<hr>");
return result.toString();
}

getForEntity 的第一个参数为要调用的服务的地址,getForEntity第二个参数 String.class 表示希望返回的 body 类型是 String

输出结果

在调用服务提供者提供的接口时,可能需要传递参数,有两种不同的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RequestMapping("/hello1")
public String Hello() {
// String name = "张三";
// ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://localhost:8000/spark/hello?name={name}", String.class, name);
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://localhost:8000/spark/hello?name={1}", String.class, "张三");
return responseEntity.getBody();
}
@RequestMapping("/hello2")
public String Hello2() {
Map<String, String> map = new HashMap<>();
map.put("name", "李四");
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://localhost:8000/spark/hello?name={name}", String.class, map);
return responseEntity.getBody();
}

可以用一个数字做占位符,最后是一个可变长度的参数,来{}替换前面的占位符,也可以前面使用 name={name} 这种形式,最后一个参数是一个 map,map 的 key 即为前边占位符的名字,map的 value 为参数值

服务提供者不仅可以返回String,也可以返回一个自定义类型的对象,比如服务提供者中有如下方法

1
2
3
4
@RequestMapping(value = "/getbook", method = RequestMethod.GET)
public Book book1() {
return new Book("三国演义", 90, "罗贯中", "花城出版社");
}

在服务消费者中通过如下方式来调用

1
2
3
4
5
@RequestMapping("/book")
public Book book1() {
ResponseEntity<Book> responseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/getbook1", Book.class);
return responseEntity.getBody();
}

getForObject

getForObject 函数实际上是对 getForEntity 函数的进一步封装,如果你只关注返回的消息体的内容,对其他信息都不关注,此时可以使用 getForObject,例子如下

1
2
3
4
5
6
7
@RequestMapping("/hello2")
public String Hello2() {
Map<String, String> map = new HashMap<>();
map.put("name", "李四");
String responseEntity = restTemplate.getForObject("http://localhost:8000/spark/hello?name={name}", String.class, map);
return responseEntity;
}

其他用法与getForEntity类似

Post请求

在 RestTemplate 中,POST 请求可以通过如下三个方法来发起

postForEntity


该方法和get请求中的getForEntity方法类似,如下例子

1
2
3
4
5
6
7
8
9
10
@RequestMapping("/hello3")
public String Hello3() {
String[] args = {"arg1","arg2","arg3"};

HashMap<String,Object> postData = new LinkedHashMap<>();
postData.put("name", "dxy");
postData.put("args", args);
ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://localhost:8000/spark/hello", postData, String.class);
return responseEntity.getBody();
}

方法的第一参数表示要调用的服务的地址,方法的第二个参数表示上传的参数,方法的第三个参数表示返回的消息体的数据类型,特别注意上传的参数里如果有列表参数,则可以用String[]来存放列表

postForObject


如果你只关注,返回的消息体,可以直接使用postForObject。用法和getForObject一致。

1
2
3
4
5
6
7
8
9
10
@RequestMapping("/hello3")
public String Hello3() {
String[] args = {"arg1","arg2","arg3"};

HashMap<String,Object> postData = new LinkedHashMap<>();
postData.put("name", "dxy");
postData.put("args", args);
String responseEntity = restTemplate.postForObject("http://localhost:8000/spark/hello", postData, String.class);
return responseEntity;
}

postForLocation

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

PUT 请求

在 RestTemplate 中,PUT 请求可以通过 put 方法调用,put 方法的参数和前面介绍的 postForEntity 方法的参数基本一致,只是 put 方法没有返回值而已

DELETE 请求

与put请求类似

总结

基本上RestTemplate常用的方法都总结了,说实话,RestTemplate用起来真方便

打赏

请我喝杯咖啡吧~

支付宝
微信