002-01-RestTemplate-配置使用说明

一、概述

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

  简化了发起HTTP请求以及处理响应的过程,并且支持REST。

二、方法说明

1、使用配置RestTemplate,增加spring配置,applicationContext-spring-http.xml  

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
    <!-- 配置RestTemplate -->
    <!--Http client Factory-->
    <bean id="httpClientFactory" class="org.springframework.http.client.SimpleClientHttpRequestFactory">
        <property name="connectTimeout"  value="2000"/>
        <property name="readTimeout"  value="2000"/>
    </bean>
    <!--RestTemplate-->
    <bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
        <constructor-arg ref="httpClientFactory"/>
    </bean>
</beans>
View Code

2、默认提供方法

  RestTemplate免于编写乏味的样板代码,RestTemplate定义了33个与REST资源交互的方法,涵盖了HTTP动作的各种形式,其实这些方法只有11个独立的方法,而每一个方法都由3个重载的变种。  

DELETEdelete
GETgetForObject
 getForEntity
HEADheadForHeaders
OPTIONSoptionsForAllow
POSTpostForLocation
 postForObject
PUTput
anyexchange
 execute
delete():在特定的URL上对资源执行HTTP DELETE操作
exchange():在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity,这个对象是从响应体中映射得到的
execute():在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象
getForEntity():发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象
getForObject():GET资源,返回的请求体将映射为一个对象
headForHeaders():发送HTTP HEAD请求,返回包含特定资源URL的HTTP头
optionsForAllow():发送HTTP OPTIONS请求,返回对特定URL的Allow头信息
postForEntity():POST数据,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得到
postForLocation():POST数据,返回新资源的URL
postForObject():POST数据,返回的请求体将匹配为一个对象
put():PUT资源到特定的URL

3、每个一个方法又提供三种重载,以下是getForObject示例  

public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
public <T> T getForObject(URI url, Class<T> responseType)

  第一种、一个使用String作为URL格式,并使用可变参数列表指明URL参数
  第二种、一个使用String作为URL格式,并使用Map指明URL参数
  第三种、一个使用java.net.URI作为URL格式,不支持参数化URL 

4、xxxForObject()和xxxForEntity()区别

  除了返回类型,xxxForObject()方法就是xxxForEntity()方法的镜像。实际上,它们的工作方式大同小异。它们都执行根据URL检索资源的xxx请求。它们都将资源根据responseType参数匹配为一定的类型。唯一的区别在于xxxForObject()只返回所请求类型的对象,而xxxForEntity()方法会返回请求的对象以及响应的额外信息。

5、postForLacation()

  会在POST请求的请求体中发送一个资源到服务器端,返回的不再是资源对象,而是创建资源的位置。

6、exchange

  exchange方法可以在发送个服务器端的请求中设置头信息。

  与其它接口的不同:

    >允许调用者指定HTTP请求的方法(GET,POST,PUT等)

    >可以在请求中增加body以及头信息,其内容通过参数‘HttpEntity<?>requestEntity’描述

    >exchange支持‘含参数的类型’(即泛型类)作为返回类型,该特性通过‘ParameterizedTypeReference<T>responseType’描述。比如:

List<String> a = new ArrayList<String>();   
System.out.println(a.getClass());   
System.out.println(a.getClass().getGenericSuperclass());   
ParameterizedTypeReference pt = new ParameterizedTypeReference<ArrayList<String>>() {};   
System.out.println(pt.getType());  
View Code

    返回

class java.util.ArrayList  
java.util.AbstractList<E>  
java.util.ArrayList<java.lang.String>  
View Code

  使用

MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
headers.add("Accept", "application/json");
HttpEntity<Object> requestEntity = new HttpEntity<Object>(headers);

ResponseEntity<Spitter> response = rest.exchange("http://localhost:8080/Spitter/spitters/{spitter}",
    HttpMethod.GET, requestEntity, Spitter.class, spitterId);
View Code

7、excute

  所有的get、post、delete、put、options、head、exchange方法最终调用的都是excute方法。可以查看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);
    }
View Code

  excute方法只是将String格式的URI转成了java.net.URI,之后调用了doExecute方法。整个调用过程

  

8、doExcute

定义:

protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor)

这里需要了解两个接口:RequestCallback &ResponseExtractor<T>

8.1、RequestCallback

  用于操作请求头和body,在请求发出前执行。  

AcceptHeaderRequestCallback只处理请求头,用于getXXX()方法。
HttpEntityRequestCallback继承于AcceptHeaderRequestCallback可以处理请求头和body,用于putXXX()、postXXX()和exchange()方法。

  注意:DELETE、HEAD、OPTIONS没有使用这个接口。如delete

    public void delete(String url, Map<String, ?> uriVariables) throws RestClientException {
        this.execute(url, HttpMethod.DELETE, (RequestCallback)null, (ResponseExtractor)null, (Map)uriVariables);
    }

8.2、ResponseExtractor<T>

  解析HTTP响应的数据,而且不需要担心异常和资源的关闭。  

HeadersExtractor用于提取请求头。
HttpMessageConverterExtractor用于提取响应body。
ResponseEntityResponseExtractor使用HttpMessageConverterExtractor提取body(委托模式),然后将body和响应头、状态封装成ResponseEntity对象。

8.2.1、提取请求头HeadersExtractor

    private static class HeadersExtractor implements ResponseExtractor<HttpHeaders> {
        private HeadersExtractor() {
        }

        public HttpHeaders extractData(ClientHttpResponse response) throws IOException {
            return response.getHeaders();
        }
    }
View Code

8.2.2、提取响应body,HttpMessageConverterExtractor

提取分三步:

(1)提取器HttpMessageConverterExtractor寻找可用的转化器

  在默认的RestTemplate的构造函数中初始化了转化器集合,包括:

private final List<HttpMessageConverter<?>> messageConverters;
    public RestTemplate() {
        this.messageConverters = new ArrayList();
        this.errorHandler = new DefaultResponseErrorHandler();
        this.uriTemplateHandler = new DefaultUriBuilderFactory();
        this.headersExtractor = new RestTemplate.HeadersExtractor();
        this.messageConverters.add(new ByteArrayHttpMessageConverter());
        this.messageConverters.add(new StringHttpMessageConverter());
        this.messageConverters.add(new ResourceHttpMessageConverter(false));
        this.messageConverters.add(new SourceHttpMessageConverter());
        this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
        if(romePresent) {
            this.messageConverters.add(new AtomFeedHttpMessageConverter());
            this.messageConverters.add(new RssChannelHttpMessageConverter());
        }

        if(jackson2XmlPresent) {
            this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
        } else if(jaxb2Present) {
            this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
        }

        if(jackson2Present) {
            this.messageConverters.add(new MappingJackson2HttpMessageConverter());
        } else if(gsonPresent) {
            this.messageConverters.add(new GsonHttpMessageConverter());
        } else if(jsonbPresent) {
            this.messageConverters.add(new JsonbHttpMessageConverter());
        }

        if(jackson2SmilePresent) {
            this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());
        }

        if(jackson2CborPresent) {
            this.messageConverters.add(new MappingJackson2CborHttpMessageConverter());
        }

    }
View Code

转化器

可转化的类型
ByteArrayHttpMessageConverterbyte[]
StringHttpMessageConverterString
ResourceHttpMessageConverterResource
SourceHttpMessageConverterjavax.xml.transform.*
AllEncompassingFormHttpMessageConverterMultiValueMap
Jaxb2RootElementHttpMessageConverterXmlRootElement,XmlType(注解)
... 
MappingJackson2HttpMessageConverterJson

  注意:除了前五个,其他的转化器会由classloader尝试加载某个类来判断工程是否包含某个包,而后决定是否加入转化器集合。

    提取器遍历转化器集合以查找可用的转化器,其中MappingJackson2HttpMessageConverter总是在最后一个,因为该类实现了GenericHttpMessageConverter,算是一个通用转化器,只有在找不到合适的转化器时才轮到它。Spring提供了一个该类的实现,以保证总是能得到该类。

(2)转化器寻找可用的反序列化器

转化器持有一个反序列化器缓存集合,首先从缓存中寻找
如果已有可用的反序列化器,则直接返回。否则创建一个新的反序列化器。

反序列化器保存着待反序列化类的域、方法、构造器等信息,反序列化时就是使用构造器创建了一个新的实例。
以jackson为例,创建反序列化器的过程在jackson-databind-xxx.jar中,有兴趣的可以看一下。调用栈如下(由下往上找):
  BeanDeserializerFactory.addBeanProps/addObjectIdReader/addReferenceProperties/addInjectables
  BeanDeserializerFactory.buildBeanDeserializer
  BeanDeserializerFactory.createBeanDeserializer

(3)反序列化器执行反序列化

TOKEN

Json的一个或一组字符
START_OBJECT{
END_OBJECT}
START_ARRAY[
END_ARRAY]
VALUE_TRUEtrue
VALUE_FALSEfalse
... 

 

参看地址:

https://www.cnblogs.com/caolei1108/p/6169950.html

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html

 

 

      

转载于:https://www.cnblogs.com/bjlhx/p/8651739.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RestTemplate 是一个非常常用的 HTTP 客户端工具,但在使用过程中可能会遇到一些问题,以下是一些常见问题及解决方法: 1. 如何设置 RestTemplate 的请求头? 可以使用 HttpHeaders 类来设置请求头,例如: ``` RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", "Bearer token"); headers.set("Content-Type", "application/json"); HttpEntity<String> entity = new HttpEntity<>("body", headers); restTemplate.exchange(url, HttpMethod.POST, entity, String.class); ``` 2. 如何发送 GET 请求并接收 JSON 格式的响应? 可以使用 RestTemplate 的 getForObject 方法,例如: ``` RestTemplate restTemplate = new RestTemplate(); String result = restTemplate.getForObject(url, String.class); ``` 3. 如何发送 POST 请求并接收 JSON 格式的响应? 可以使用 RestTemplate 的 postForObject 方法,例如: ``` RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.set("Content-Type", "application/json"); HttpEntity<String> entity = new HttpEntity<>("body", headers); String result = restTemplate.postForObject(url, entity, String.class); ``` 4. 如何处理返回的响应状态码? 可以通过 ResponseEntity 来获取响应状态码和响应体,例如: ``` RestTemplate restTemplate = new RestTemplate(); ResponseEntity<String> response = restTemplate.getForEntity(url, String.class); if (response.getStatusCode() == HttpStatus.OK) { String result = response.getBody(); } else { // 处理失败逻辑 } ``` 5. 如何处理请求超时? 可以通过设置 RestTemplate 的超时时间来处理请求超时,例如: ``` RestTemplate restTemplate = new RestTemplate(); SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); requestFactory.setConnectTimeout(5000); requestFactory.setReadTimeout(5000); restTemplate.setRequestFactory(requestFactory); ``` 以上是一些常见的 RestTemplate 使用问题及解决方法,希望对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值