Spring RestTemplate整理

标签: SpringBoot JAVA rest spring
20人阅读 评论(0) 收藏 举报
分类:

一、什么是RestTemplate?


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


调用RestTemplate的默认构造函数,RestTemplate对象在底层通过使用java.net包下的实现创建HTTP 请求,可以通过使用ClientHttpRequestFactory指定不同的HTTP请求方式。 

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


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

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


通过使用RestTemplate仅仅只需要写几行代码,就可以完成直接使用httpclient很多行代码的事情,具体见:https://spring.io/blog/2009/03/27/rest-in-spring-3-resttemplate



二、RestTemplate 构造


RestTemplate有三个构造函数:


1.默认构造函数,默认使用SimpleClientHttpRequestFactory,使用JDK自带的java.net包进行网络传输。


2.public RestTemplate(ClientHttpRequestFactory requestFactory)。传入一个ClientHttpRequestFactory,ClientHttpRequestFactory在Spring中的实现有很多个,如HttpComponentsClientHttpRequestFactory,Netty4ClientHttpRequestFactory等,ClientHttpRequestFactory接口的实现类中存在timeout属性等等

SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(1000);
requestFactory.setReadTimeout(1000);

RestTemplate restTemplate = new RestTemplate(requestFactory);
可以在springboot的某个自定义的configure类中的restTemplate 构造方法上添加

@Bean
RestTemplate restTemplate(){
    SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
    requestFactory.setConnectTimeout(1000);
    requestFactory.setReadTimeout(1000);
    RestTemplate restTemplate = new RestTemplate(requestFactory);
    return restTemplate;
}
将RestTemplate 实例注入spring容器中。
调用时可以通过:

@Autowired
private RestTemplate  restTemplate;

来使用。

3.public RestTemplate(List> messageConverters),使用SpringMvc的应该对HttpMessageConverter很熟悉了,RestTemplate默认会给我们设置好常用的HttpMessageConverter,一般很少使用到这个构造方法。


三、RestTemplate 对HTTP Method的支持




四、RestTemplate 使用实例


4.1、GET请求:


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


使用RestTemplate,对GET请求可以通过如下下面的二种方法实现:


(一)、getForEntity函数


该方法返回ResponseEntity,该对象是Spring对Http请求响应的封装,其中主要存储了HTTP的几个重要元素,比如说HTTP请求码的枚举对象HttpStatus(404,405,500等错误码),它的父类事HttpEntity中还存储着HTTP请求的头信息对象HttpHeaders以及泛型类型的请求体对象。


getForEntity有三种重载的方法:

第一种方式:

@Override
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
            throws RestClientException {

        RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
        return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
    }

该方法提供了三个参数,url就是请求的地址,responseType返回的数据类型,uriVariables为url中参数绑定。会顺序对应url中占位符定义的数字顺序。

第二种方式:

@Override
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
            throws RestClientException {

        RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
        return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
    }

url参数和responseType和上面一致,只有第三个参数uriVariables是不同的类型,这里使用了Map<String, ?>类型,所以使用该方法进行参数绑定时需要在占位符中指定Map中参数的key值,我们需要向map中put
一个key为id和name的值来对应{id}和{name}


第三种方式:

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

该方法使用URI对象来替代之前的url和urlVariables参数来指定访问地址和参数来指定访问地址和参数绑定。URI是JDK java.net包下的一个类,它表示一个统一的资源标识符引用.


示例:


Controller类:

/**
 * projectName: quna-app
 * fileName: UserController.java
 * packageName: com.mongodb.fendo.controller
 * date: 2018-04-13 13:16
 * copyright(c) 上海xxxxx有限公司
 */
package com.mongodb.fendo.controller;

import com.mongodb.fendo.entity.UserEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @version: V1.0
 * @author: fendo
 * @className: UserController
 * @packageName: com.mongodb.fendo.controller
 * @description: 用户Controller
 * @data: 2018-04-13 13:16  
 **/
@Controller
@RequestMapping(value = "/user")
public class UserController {

    @GetMapping("getNameById")
    @ResponseBody
    public String getNameById(@RequestParam int id, @RequestParam String name){
        if(1==id && "fendo".equals(name)){
            return "name="+name+",age="+27;
        }else {
            return "name="+name;
        }
    }
    @GetMapping("/getUserById")
    @ResponseBody
    public UserEntity getUserEntityById(@RequestParam int id,@RequestParam String name){
        UserEntity user = new UserEntity();

        if(id == 1 && "fendo".equals(name)){
            user.setId("1");
            user.setName("fendo");
            user.setAge("21");
        }

        if(id ==2 && "arm".equals(name)){
            user.setId("2");
            user.setName("arm");
            user.setAge("24");
        }

        return user;
    }

    @GetMapping("/getUserByname")
    @ResponseBody
    public String getUserByname(@RequestParam String name){
        if("fendo".equals(name)){
            return "123456798";
        }else{
            return "哈哈";
        }
    }


}  

测试类:

package com.mongodb.fendo;

import com.alibaba.fastjson.JSONObject;
import com.mongodb.fendo.entity.UserEntity;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;

/**
 * @version V1.0
 * @Author fendo
 * @ClassName RestTemplateTest
 * @PackageName com.mongodb.fendo
 * @Description RestTemplate测试类
 * @Data 2018-04-15 0:07
 **/
@RunWith(SpringRunner.class)
@SpringBootTest
public class RestTemplateTest {


    @Autowired
    RestTemplate restTemplate;

    @Test
    public void getNameById(){
        int id = 2;
        String name = "qqqqq";
        String username = restTemplate.getForEntity("http://localhost:8088/user/getNameById?id={1}&name={2}",String.class,new Object[]{id,name}).getBody();
        System.out.println(username);
    }

    @Test
    public void getUserEntityById(){
        Map<String,Object> params = new HashMap<>();
        params.put("id",1);
        params.put("name","fendo");
        UserEntity user = restTemplate.getForEntity("http://localhost:8088/user/getUserById?id={id}&name={name}",UserEntity.class,params).getBody();
        System.out.println(user.toString());
    }

    @Test
    public void getUserByname(){
        String name = "fendo";
        UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://localhost:8088/user/getUserByname?name={name}").build().expand(name).encode();
        URI uri = uriComponents.toUri();
        String response = restTemplate.getForEntity(uri,String.class).getBody();
        System.out.println(response);
    }

}


(二)、getForObject函数


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

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

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

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

测试类:

    @Test
    public void Test(){
        String name = "fendo";
        String userEntity = restTemplate.getForObject("http://localhost:8088/user/getUserByname?name={name}",String.class,new Object[]{name});
        System.out.println(userEntity);

        Map<String,Object> params = new HashMap<>();
        params.put("id",1);
        params.put("name",name);
        UserEntity user = restTemplate.getForObject("http://localhost:8088/user/getUserById?id={id}&name={name}",UserEntity.class,params);
        System.out.println(user.toString());

        UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://localhost:8088/user/getUserByname?name={name}").build().expand(name).encode();
        URI uri = uriComponents.toUri();
        String response = restTemplate.getForObject(uri,String.class);
        System.out.println(response);
    }


4.2、POST请求

public <T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
            throws RestClientException
public <T> T postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
            throws RestClientException
public <T> T postForObject(URI url, Object request, Class<T> responseType) throws RestClientException


在RestTemplate中,对post请求时可以通过如下三个方法进行调用实现:


第一种:postForEntity函数


其包含三种重载的方法。第一个重载方法和第二个重载函数的uriVariables参数都用来对url中的参数进行绑定使用,responseType是返回对象的类型定义。增加的request参数,该参数可以是一个普通对象,也可以是一个HttpEntity对象。如果是一个普通对象,而非HttpEntity对象的时候,RestTemplate会将普通对象转换成HttpEntity对象。其中Object中不仅包含了body内容,也包含了header的内容。


@Override
public <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
            throws RestClientException {

        RequestCallback requestCallback = httpEntityCallback(request, responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
        return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}

@Override
public <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
            throws RestClientException {

        RequestCallback requestCallback = httpEntityCallback(request, responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
        return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}

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

定义接口:
    @PostMapping("/queryUser1")
    @ResponseBody
    public List<String> queryUser1(@RequestBody UserEntity user){
        String id = user.getId();
        if("1".equals(id)){
            return Arrays.asList("fendo,arm".split(","));
        }else{
            return Arrays.asList("admin.sfe".split(","));
        }
    }

    @PostMapping("/queryUser2")
    @ResponseBody
    public String queryUser2(@RequestParam String id,@RequestParam String name){
        if("1".equals(id)){
            return "user is " + name;
        }
        return "user is not exist";
    }

测试:
    @Test
    public void TEST_POST(){
        UserEntity userEntity = new UserEntity();
        userEntity.setName("fendo");
        userEntity.setAddress("北京");
        userEntity.setAge("23");
        userEntity.setCreate_date(new Date());
        userEntity.setEmail("2312892206");
        userEntity.setSex(1);
        userEntity.setUser_id("123456789" + Math.random());
        UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://localhost:8088/user/queryUser1").build();
        URI uri = uriComponents.toUri();
        List<String> stringList = restTemplate.postForEntity(uri,userEntity,List.class).getBody();
        for (int i = 0; i < stringList.size(); i++) {
            System.out.println(stringList);
        }


        HttpHeaders headers = new HttpHeaders();
        MultiValueMap<String, Object> parammap = new LinkedMultiValueMap<>();
        parammap.add("id","1");
        parammap.add("name","fendo");
        HttpEntity<Map> entity = new HttpEntity<>(parammap,headers);
        String result = restTemplate.postForEntity("http://localhost:8088/user/queryUser2",entity,String.class).getBody();
        System.out.println(result);

    }


第二种:getForObject函数

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

接口:
    @PostMapping("/getUserEntity")
    @ResponseBody
    public UserEntity getUserEntity(UserEntity userEntity){
        System.out.println(userEntity.toString());
        UserEntity user = new UserEntity();
        user.setId("1");
        user.setName("fendo");
        user.setAge("21");
        return user;
    }

测试类:
    @Test
    public void Test_m(){

        HttpHeaders headers = new HttpHeaders();
        MultiValueMap<String, Object> parammap = new LinkedMultiValueMap<>();
        parammap.add("id", 1);
        parammap.add("name","fendo");
        HttpEntity<Map> entity = new HttpEntity<>(parammap,headers);
        UserEntity user = restTemplate.postForObject("http://localhost:8088/user/getUserEntity",entity,UserEntity.class);
        System.out.println(user.toString());
    }

postForObject函数也提供了三个重载的方法

@Override
public <T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
            throws RestClientException {

        RequestCallback requestCallback = httpEntityCallback(request, responseType);
        HttpMessageConverterExtractor<T> responseExtractor =
                new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
        return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}

@Override
public <T> T postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
            throws RestClientException {

        RequestCallback requestCallback = httpEntityCallback(request, responseType);
        HttpMessageConverterExtractor<T> responseExtractor =
                new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
        return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}

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

第三种: 使用postForLocation函数

postForLocation也是提交新资源,提交成功之后,返回新资源的URI,postForLocation的参数和前面两种的参数基本一致,只不过该方法的返回值为Uri,这个只需要服务提供者返回一个Uri即可,该Uri表示新资源的位置。
        URI uri = restTemplate.postForLocation("http://localhost:8080/xxxx",user);
        System.out.println("uri=="+uri);

postForLocation函数也提供了三种不同的重载方法
@Override
public URI postForLocation(String url, Object request, Object... uriVariables) throws RestClientException {
        RequestCallback requestCallback = httpEntityCallback(request);
        HttpHeaders headers = execute(url, HttpMethod.POST, requestCallback, headersExtractor(), uriVariables);
        return headers.getLocation();
}

@Override
public URI postForLocation(String url, Object request, Map<String, ?> uriVariables) throws RestClientException {
        RequestCallback requestCallback = httpEntityCallback(request);
        HttpHeaders headers = execute(url, HttpMethod.POST, requestCallback, headersExtractor(), uriVariables);
        return headers.getLocation();
}

@Override
public URI postForLocation(URI url, Object request) throws RestClientException {
        RequestCallback requestCallback = httpEntityCallback(request);
        HttpHeaders headers = execute(url, HttpMethod.POST, requestCallback, headersExtractor());
        return headers.getLocation();
}


postForEntity和postForLocation的区别?

postForEntity返回ResponseEntity,与getForEntity相同 
postForLocation返回URI,返回的是response header中的location信息,一般用于资源定位。


查看评论

Spring之在客户端访问RESTful业务

 RestTemplate 是客户端访问RESTful
  • luccs624061082
  • luccs624061082
  • 2014-11-07 15:57:35
  • 12688

spring RestTemplate使用

最近看到spring RestTemplate,觉得挺好用的,就研究总结了一下,第一次写。。。 RestTemplate可使用http的所有方式进行请求,本文主要说明下get,post的使用,其他的...
  • LV003
  • LV003
  • 2017-02-14 00:38:12
  • 2926

Spring模拟HTTP请求——RestTemplate类使用的理解

Spring模拟HTTP请求——RestTemplate类使用的理解 上一阶段wab项目由于需要跨系统访问,从同事之前写的代码中发现了RestTemplate类,才知道Spring已经对wab请求已经...
  • madmk
  • madmk
  • 2017-07-31 13:46:31
  • 3413

Spring RestTemplate

  • 2010年11月28日 09:50
  • 1007KB
  • 下载

spring restTemplate配置

id="pollingConnectionManager" class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager"> ...
  • a294039255
  • a294039255
  • 2017-06-26 17:51:36
  • 1748

spring的RestTemplate

参考资料:spring-framework-reference: 1.Accessing RESTful services on the Client 2.Bean scopes下的Session s...
  • xiejx618
  • xiejx618
  • 2015-02-12 16:52:14
  • 6744

Spring RestTemplate 详解

我们在web开发中发布的restapi大多数的时候是由XMLHttpRequest对象来消费的。即JavaScript客户端。 但是我们rest api是跨语言的。不仅仅JavaScript可以调用...
  • u013803262
  • u013803262
  • 2017-03-27 10:51:13
  • 785

Spring boot resttemplate 其实也可以当成http client来用

这段时间都在用Spring boot,真的是非常的方便,去除了繁琐的copy文件搭建项目的问题。在这期间遇到了一个要请求别人服务器接口的问题,一开始是用到了http client来请求的,但是个人觉得...
  • ZW_KK
  • ZW_KK
  • 2017-12-24 21:58:36
  • 260

Spring Boot中RestTemplate的使用

RestTempla
  • cxd275050943
  • cxd275050943
  • 2017-12-08 15:04:39
  • 318

Spring RestTemplate 实践

什么是RestTemplate?RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率...
  • catoop
  • catoop
  • 2016-03-18 10:02:09
  • 11568
    相关交流

    JAVA架构: 665329131

    个人资料
    持之以恒
    等级:
    访问量: 107万+
    积分: 1万+
    排名: 1161
    最新评论