RestTemplate源码解析及使用详解

一、RestTemplate服务调用

在前面Eureka的服务注册与发现中,我们使用了一个非常有用的对象RestTemplate。该对象会使用Ribbon的自动化配置,同时通过配置@LoadBalanced还能开启客户端负载均衡。这里我们详细介绍RestTemplate针对不同请求类型和参数类型的服务调用实现。

什么是RestTemplate?

RestTemplate是Spring提供的用于访问Rest服务的客户端,

RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。

调用RestTemplate的默认构造函数,RestTemplate对象在底层通过使用java.net包下的实现创建HTTP 请求,

可以通过使用ClientHttpRequestFactory指定不同的HTTP请求方式。

ClientHttpRequestFactory接口主要提供了两种实现方式

1、一种是SimpleClientHttpRequestFactory,使用J2SE提供的方式(既java.net包提供的方式)创建底层的Http请求连接。

2、一种方式是使用HttpComponentsClientHttpRequestFactory方式,底层使用HttpClient访问远程的Http服务,使用HttpClient可以配置连接池和证书等信息。

1、GET请求

在RestTemplate中,对GET请求可以通过如下两个方法进行调用实现。

1.1、getForEntity函数。

该方法返回的是ResponseEntity,该对象是对HTTP请求响应的封装,其中主要存储了HTTP的几个重要元素,
(url, requestMap,ResponseBean.class)这三个参数分别代表 REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。

RestTemplate restTemplate = new RestTemplate();
//在url中使用占位符并配合urlVariables参数实现GET请求的参数绑定。在第三个参数会替换url中{1}占位符
ResponseEntity<String>  responseEntity = restTemplate.getForEntity("http://USER-SERVICE/user?name={1}",String.class,"tom");
String body = responseEntity.getBody();

若我们希望返回的body是一个User对象类型,也可以这样实现:
 //http://USER-SERVICE/user?name=tom

 ResponseEntity<User> responseEntity = restTemplate.getForEntity("http://USER-SERVICE/user?name={1}", User.class, "tom");
 User body = responseEntity.getBody();

getForEntity函数还提供了以上三种不同的重载实现。

  • 1、getForEntity(String url, Class responseType, Object...urlVariables):

                    url:为请求的地址
                    responseType:为请求响应体body的包装类型
                    urlVariables:为url中参数绑定
              

  • 2、getForEntity(String url, Class responseType, Map urlVariables):

 urlVariables使用的是Map类型,所以在使用该方法进行参数绑定时需要在占位符中指定Map中参数的key值,比如url定义为http://USER-SERVICE/user?name={name}。在Map类型的urlVariables中,我们就需要put一个key值为name的参数来绑定url中的{name}占位符的值,比如:

RestTemplate restTemplate = new RestTemplate();
Map<String,String> params = new HashMap<>();
params.put("name","data");
ResponseEntity<String> responseEntity = restTemplate.getForEneity("http://USER-SERVICE/user?name={name}",String.class,params);
  • 3、getForEntity(URI uri, Class responseType):

该方法使用url对象来替代之前的url和urlVariables参数来指定访问地址和参数绑定。              

RestTemplate restTemplate = new RestTemplate();
UriComponents uriComponents = UriComponentsBuilder
    .fromUriString("http://USER-SERVICE/user?name={name}")
    .build()
    .expand("tom")
    .encode();
URI uri = uriComponents.toUri();
ResponseEntiy<String> responseEntity = restTemplate.getForEntity(uri,String.class);

1.2、getForObject函数

该方法可以理解为对getForEntity的进一步封装。
它通过HttpMessageConverterExtractor对HTTP的请求响应体body内容进行对象转换,实现请求直接返回包装好的对象内容。

RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(url,String.class);
//当body是一个User对象时:
User result = restTemplate.getForObject(url,User.class);

当不需要关注请求响应除body外的其他内容时,可以少一个从Response中获取body的步骤。它与getForEntity函数类似,也提供了三种不同的重载实现。

  • 1、getForObject(String url, Class responseType, Object ...urlVariables):与getForEntity的方法类似.

                        url参数指定访问的地址,
                        responseType参数定义该方法的返回类型,
                        urlVariables参数为url中占位符定义的参数。

  • 2、getForObject(String url, Class responseType, Map urlVariables):

在该函数中,使用Map类型的urlVariable替代上面数组形式的urlVariables,因此使用时在url中需要将占位符的名称与Map类型中的key一一对应配置。

  • 3、getForObject(URI uri, Class responseType):

该方法使用uri对象来替代之前的url和urlVariables参数使用。                

2、POST请求

在RestTemplate中,对POST请求时可以通过如下三种方式进行调用实现。

2.1、第一种postForEntity函数。

该方法同GET请求中getForEntity类似,会在调用后返回ResponseEntity<T>对象,其中T为请求响应的body类型。

如下使用postForEntity提交POST请求到USER-SERVICE服务的/user接口,提交的body内容为user对象,请求响应返回的body类型为String类型。

ResponseTemplate responseTemplate = new RestTemplate();
User user = new User("tom",30);
ResponseEntity<String> responseEntity = responseTemplate.postForEntity("http://USER-SERVICE/user", user, String.class);
String body = responseEntity.getBody();

 postForEntity也实现了三种不同的重载的方法。

  • postForEntity(String url, Object request, Class responseTemplate, Object ...urlVariables);
  • postForEntity(String url, Object request, Class responseTemplate, Map urlVariables);
  • postForEntity(URI url, Object request, Class responseType);

其中第一个重载函数和第二个重载函数中的urlVariables参数都用来对url中的参数进行绑定使用;responseType参数是对请求响应的body内容的类型定义。这里需要注意的是新增加的request参数,该对象可以是一个普通对象,也可以是一个HttpEntity对象。

如果是一个普通对象,而非HttpEntity对象的时候,RestTemplate会将请求对象转换为一个HttpEntity对象来处理,其中Object就是request的类型, request内容会被视作完整的body来处理; 而如果request是一个HttpEntity对象,那么就会被当做一个完整的HTTP请求对象来处理,这个request中不仅包含了body内容, 也包含了header的内容。                

2.2、第二种postForObject函数

该方法也跟getForObject的类型类似,他的作用是简化postForEntity的后续处理。通过直接将请求响应的body内容包装成对象来返回使用,比如下面的例子:

RestTemplate restTemplate = new RestTemplate();
User user = new User("tom",20);
String postResult = restTemplate.postForObject("http://USER-SERVICE/user/", user, String.class);

 postForObject函数也实现了三种不同的重载方法:

  • postForObject(String url, Object request, Class responseType, Object... urlVariables);
  • postForObject(String url, Object request, Class responseType, Map urlVariables);
  • postForObject(URI uri, Object request, Class responseType);

这三种函数除了返回对象类型不同,函数的传入参数均与postForEntity一致。                    

2.3、 第三种:postForLocation函数。

该方法实现了以post请求提交资源,并返回新的资源URI,比如下面的例子:              

User user = new User("tom", 40);
URI responseURI = restTemplate.postForLocation("http://USER-SERVICE/user/",user);

postForLocation函数也实现了三种不同的重载方式:

  • postForLocation(String url, Object request, Object... urlVariables);
  • postForLocation(String url, Object request, Map urlVariables);
  • postForLocation(URI uri, Object request);

由于postForLocation函数会返回新的资源URI,该URI相当于指定了返回类型,所有此方法实现的POST请求不需要postForEntity和postForObject那样指定responseType。其他的参数用法相同。

3、PUT请求

在RestTemplate中,对PUT请求可以通过put方法进行调用实现,比如:   

RestTemplate restTemplate = new RestTemplate();
Long id = 10001L;
User user = new User("tom", 20);
restTemplate.put("http://USER-SERVICE/user/{1}",user,id);

post函数也实现了三种不同的重载方法:

  • put(String url, Object request, Object... urlVariables);
  • put(String url, Object request, Map urlVariables);
  • put(URI uri, Object request);

 put函数为void类型,所以没有返回内容,也就没有其他函数定义的responseType参数,除此之外的其他传入参数定义与用法与postForObject一致。               

4、DELETE请求

在RestTemplate中,对DELETE请求可以通过delete方法进行调用实现,比如:       

RestTemplate restTemplate = new RestTemplate();
long id = 10001L;
restTemplate.delete("http://USER-SERVICE/user/{1}",id);

delete函数也实现了三种不同的重载方法:

  • delete(String url, Object... urlVariables);
  • delete(String url, Map urlVariables);
  • delete(URI url);            

二、源码解析

RestTemplate 解析:

https://blog.csdn.net/wangqiubo2010/article/details/81708643

【Spring-web】RestTemplate源码学习:

https://www.cnblogs.com/quiet-snowy-day/p/6210288.html

 

猜你喜欢

转载自blog.csdn.net/MyronCham/article/details/84820568