RestTemplate使用教程(超详细)

1,905 阅读4分钟

一、简介

我是在学习Ribbon的时候碰到了RestTemplate,因为自己比较菜,当时就很好奇这是个啥?所以就去花时间了解了一下。

RestTemplate是Spring官方提供的一个用于访问Rest的一个客户端,能够让你更加便捷的访问Http服务,相比于之前利用Apache的HttpClient开发Http服务,降低了开发难度、增加了效率。

但是在Spring的新版本中,官方已经不建议使用RestTemplate了,因为官方推出了WebClient,没错我这个彩笔又懵了,我又去花时间学习了下WebClient。我这里简单介绍一下两者的区别: WebClient在等待响应的同时不会阻塞正在执行的线程,采用的是异步编程,可以提高吞吐量,RestTemplate则是阻塞的,直到Http返回响应,才会处理下一个请求。关于WebClient详细介绍,请观看我另外一篇文章。

二、RestTemplate使用

需要创建两个客户端,其中一个为RestTemplate客户端,用于调用另外一个客户端Rest接口。

首先我们先搭建Rest服务,并启动,我这边Rest服务接口测试内容如下:

image.png

然后我们搭建RestTemplate服务,调用Rest服务接口,搭建步骤如下:

1、创建Spring boot项目

2、导入pom坐标

<dependency>
    <groupId>org.springfraemwork.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
<dependency>    

3、配置application.yml

server
    port: 8081

4、编写启动类

@SpringBootApplication
public class ClientRestApplication {
    public static void main(String[] args) {
        SpringApplication.run(ClientRestApplication.class);
    }
}

5、创建RestTemplate配置类,配置RestTemplate bean

@Configuration
public class ApiConfig {
    @Bean
//    @LoadBalanced
    public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
        return new RestTemplate(factory);
    }

    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setReadTimeout(5000);
        factory.setConnectTimeout(5000);
        return factory;
    }

}

注意配置类位置,要被启动类扫描到

6、创建RestTemplate Controller进行调用

@RestController
@RequestMapping("/test")
public class TestController {

    private final RestTemplate restTemplate;

    public TestController(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @GetMapping("/consumer")
    public String getPayment2() {
    //这里调用的第一个服务的接口
        return restTemplate.getForObject("http://localhost:8081/test/hello", String.class);
    }
}

7、结果演示

image.png

三、常用方法介绍

RestTemplate
HeadersExtractor
gsonPresent
jackson2SmilePresent
postForEntity
RestTemplate
delete
put
jackson2XmlPresent
put
exchange
postForEntity
ResponseEntityResponseExtractor
setUriTemplateHandler
exchange
execute
jaxb2Present
patchForObject
getUriTemplateHandler
optionsForAllow
jsonbPresent
exchange
getForEntity
postForLocation
postForObject
put
RestTemplate
optionsForAllow
patchForObject
handleResponse
patchForObject
responseEntityExtractor
postForLocation
execute
getForObject
exchange
uriTemplateHandler
acceptHeaderRequestCallback
exchange
delete
delete
nonNull
headForHeaders
errorHandler
romePresent
headForHeaders
httpEntityCallback
RestTemplate
execute
httpEntityCallback
headersExtractor
jackson2Present
getForEntity
exchange
getForObject
postForLocation
jackson2CborPresent
setMessageConverters
validateConverters
HttpEntityRequestCallback
doExecute
getMessageConverters
optionsForAllow
headForHeaders
initUriTemplateHandler
exchange
headersExtractor
messageConverters
getErrorHandler
setErrorHandler
getForObject
getForEntity
postForObject
postForObject
exchange
setDefaultUriVariables
postForEntity
AcceptHeaderRequestCallback

image.png

RestTemplate类中常用方法有很多,但是我们提取出来有用的几个方法,例如:

  • GET
  • POST
  • PUT
  • DELETE
  • HEAD
  • OPTIONS
  • EXCHANGE
  • EXECUTE

3.1 GET

关于调用GET请求,主要有两种方法,getForObject、getForEntity,我一一简单介绍一下:

getForEntity

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

@GetMapping("/consumer")
public String getPayment2() {
    ResponseEntity<String> forEntity = restTemplate.getForEntity("http://localhost:8081/test/hello", String.class);
    return forEntity.getBody() + "<hr>" +
            forEntity.getHeaders() +"<hr>" +
            forEntity.getStatusCode() + "<hr>" +
            forEntity.getStatusCodeValue();
}

返回结果:

image.png

在RestTemplate类中,getForEntity有三个重载,如下所示源码:

public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) throws RestClientException {
    RequestCallback requestCallback = this.acceptHeaderRequestCallback(responseType);
    ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
    return (ResponseEntity)nonNull(this.execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
}

public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {
    RequestCallback requestCallback = this.acceptHeaderRequestCallback(responseType);
    ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
    return (ResponseEntity)nonNull(this.execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
}

public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException {
    RequestCallback requestCallback = this.acceptHeaderRequestCallback(responseType);
    ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
    return (ResponseEntity)nonNull(this.execute(url, HttpMethod.GET, requestCallback, responseExtractor));
}

传递的参数:

  • url是调用的url连接地址,一般在微服务中是通过服务名调用,以便实现负载均衡。
  • responseType是返回的body类型。
  • 另外两个重载方法提供了两种传递参的方式,通过传参实现URL拼接调用有参数的地址。示例代码如下:
//首先对rest服务进行了修改

@GetMapping("/hello/{name}")
public String sayHello(@PathVariable("name") String name) {
    return "hello " + name;


//方式一
@GetMapping("/consumer/{name}")
public String getResult(@PathVariable("name") String name){
    ResponseEntity<String> forEntity = restTemplate.getForEntity("http://localhost:8081/test/hello/{name}", String.class,name);
    return forEntity.getBody() + "<hr>" +
            forEntity.getHeaders() +"<hr>" +
            forEntity.getStatusCode() + "<hr>" +
            forEntity.getStatusCodeValue();
}

//方式二
@GetMapping("/consumer/{name}")
public String getResult(@PathVariable("name") String name){
Map<String, String> map = new HashMap<>();
    map.put("name", "李四");
    ResponseEntity<String> forEntity = restTemplate.getForEntity("http://localhost:8081/test/hello/{name}", String.class,map);
    return forEntity.getBody() + "<hr>" +
            forEntity.getHeaders() +"<hr>" +
            forEntity.getStatusCode() + "<hr>" +
            forEntity.getStatusCodeValue();
}

另外还有一种

getForObject

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

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

@Nullable
public <T> T getForObject(URI url, Class<T> responseType) throws RestClientException {
    RequestCallback requestCallback = this.acceptHeaderRequestCallback(responseType);
    HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor(responseType, this.getMessageConverters(), this.logger);
    return this.execute(url, HttpMethod.GET, requestCallback, responseExtractor);
}