当前位置:首页 > 资讯 > 正文

RestTemplate 简单使用

RestTemplate 简单使用

RestTemplate 是一个执行HTTP请求的同步阻塞式工具类,它仅仅只是在 HTTP 客户端库(例如 JDK HttpURLConnection,Apache HttpComponents,okHttp 等)基础上,封装了更加简单易用的模板方法 API,方便程序员利用已提供的模板方法发起网络请求和处理,能很大程度上提升我们的开发效率。

是Spring用于同步client端的核心类,简化了与http服务的通信,并满足RestFul原则,程序代码可以给它提供URL,并提取结果。默认情况下,RestTemplate默认依赖jdk的HTTP连接工具。当然你也可以 通过setRequestFactory属性切换到不同的HTTP源,比如Apache HttpComponents、Netty和OkHttp。

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-web</artifactId>
  <version>5.2.6.RELEASE</version></dependency>
@Testpublic void simpleTest() {
    RestTemplate restTemplate = new RestTemplate();
    String url = "http://jsonplaceholder.typicode.com/posts/1";
    String str = restTemplate.getForObject(url, String.class);
    System.out.println(str);
}

RestTemplate 使用 转换器(HttpMessageConverter) 来处理请求数据和返回数据, 非 Spring 环境下有些包不全,会导致某些转换器不可用,例如将 javabean转换为json的 MappingJackson2XmlHttpMessageConverter 转换器, 所以要使用所有转换器的话需要额外添加这些转换器依赖的包,Spring环境的依赖包是包含这些缺失包的,不用额外添加

         <!--  HttpMessageConverter :  MappingJackson2HttpMessageConverter-->
 
        <dependency>
           <groupId>com.fasterxml.jackson.core</groupId>
           <artifactId>jackson-databind</artifactId>
           <version>2.13.1</version>
       </dependency>
       <dependency>
           <groupId>com.fasterxml.jackson.core</groupId>
           <artifactId>jackson-annotations</artifactId>
           <version>2.13.1</version>
       </dependency>
 
       <dependency>
           <groupId>com.fasterxml.jackson.core</groupId>
           <artifactId>jackson-core</artifactId>
           <version>2.13.1</version>
       </dependency>
 
 
        <!-- HttpMessageConverter : MappingJackson2XmlHttpMessageConverter -->
       <dependency>
           <groupId>com.fasterxml.jackson.dataformat</groupId>
           <artifactId>jackson-dataformat-xml</artifactId>
           <version>2.13.1</version>
       </dependency>
// 文件:  RestTemplate.java// 行数: 137行
 package org.springframework.web.client; 
public RestTemplate() {        this.messageConverters.add(new ByteArrayHttpMessageConverter());        this.messageConverters.add(new StringHttpMessageConverter());        this.messageConverters.add(new ResourceHttpMessageConverter(false));        try {            this.messageConverters.add(new SourceHttpMessageConverter<>());
        }        catch (Error err) {            // Ignore when no TransformerFactory implementation is available
        }        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());
        } 
        this.uriTemplateHandler = initUriTemplateHandler();
    }
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId></dependency>
@Configurationpublic class RestTemplateConfig { 
    /**
     * 没有实例化RestTemplate时,初始化RestTemplate
     * @return
     */
    @ConditionalOnMissingBean(RestTemplate.class)    @Bean
    public RestTemplate restTemplate(){
        RestTemplate restTemplate = new RestTemplate();        return restTemplate;
    }
}
@Configurationpublic class RestTemplateConfig { 
 
    /**
     * 没有实例化RestTemplate时,初始化RestTemplate
     * @return
     */
    @ConditionalOnMissingBean(RestTemplate.class)    @Bean
    public RestTemplate restTemplate(){
        RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());        return restTemplate;
    } 
    /**
     * 使用HttpClient作为底层客户端
     * @return
     */
    private ClientHttpRequestFactory getClientHttpRequestFactory() {        int timeout = 5000;
        RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(timeout)
                .setConnectionRequestTimeout(timeout)
                .setSocketTimeout(timeout)
                .build();
        CloseableHttpClient client = HttpClientBuilder
                .create()
                .setDefaultRequestConfig(config)
                .build();        return new HttpComponentsClientHttpRequestFactory(client);
    }
 
}
@Autowiredprivate RestTemplate restTemplate;
/**
 * 使用OkHttpClient作为底层客户端
 * @return
 */private ClientHttpRequestFactory getClientHttpRequestFactory(){
    OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .connectTimeout(5, TimeUnit.SECONDS)
            .writeTimeout(5, TimeUnit.SECONDS)
            .readTimeout(5, TimeUnit.SECONDS)
            .build();    return new OkHttp3ClientHttpRequestFactory(okHttpClient);
}
@RestControllerpublic class TestController { 
    /**
     * 不带参的get请求
     * @return
     */
    @RequestMapping(value = "testGet", method = RequestMethod.GET)    public ResponseBean testGet(){
        ResponseBean result = new ResponseBean();
        result.setCode("200");
        result.setMsg("请求成功,方法:testGet");        return result;
    }
}
public class ResponseBean { 
    private String code; 
    private String msg; 
    public String getCode() {        return code;
    } 
    public void setCode(String code) {        this.code = code;
    } 
    public String getMsg() {        return msg;
    } 
    public void setMsg(String msg) {        this.msg = msg;
    } 
    @Override
    public String toString() {        return "ResponseBean{" +                "code='" + code + ''' +                ", msg='" + msg + ''' +                '}';
    }
}
@Autowiredprivate RestTemplate restTemplate; 
/**
 * 单元测试(不带参的get请求)
 */@Testpublic void testGet(){    //请求地址
    String url = "http://localhost:8080/testGet"; 
    //发起请求,直接返回对象
    ResponseBean responseBean = restTemplate.getForObject(url, ResponseBean.class);
    System.out.println(responseBean.toString());
}
@RestControllerpublic class TestController { 
    /**
     * 带参的get请求(restful风格)
     * @return
     */
    @RequestMapping(value = "testGetByRestFul/{id}/{name}", method = RequestMethod.GET)    public ResponseBean testGetByRestFul(@PathVariable(value = "id") String id, @PathVariable(value = "name") String name){
        ResponseBean result = new ResponseBean();
        result.setCode("200");
        result.setMsg("请求成功,方法:testGetByRestFul,请求参数id:" +  id + "请求参数name:" + name);        return result;
    }
}
@Autowiredprivate RestTemplate restTemplate; 
 
 /**
 * 单元测试(带参的get请求)
 */@Testpublic void testGetByRestFul(){    //请求地址
    String url = "http://localhost:8080/testGetByRestFul/{1}/{2}"; 
    //发起请求,直接返回对象(restful风格)
    ResponseBean responseBean = restTemplate.getForObject(url, ResponseBean.class, "001", "张三");
    System.out.println(responseBean.toString());
}
@RestControllerpublic class TestController { 
    /**
     * 带参的get请求(使用占位符号传参)
     * @return
     */
    @RequestMapping(value = "testGetByParam", method = RequestMethod.GET)    public ResponseBean testGetByParam(@RequestParam("userName") String userName,
                                             @RequestParam("userPwd") String userPwd){
        ResponseBean result = new ResponseBean();
        result.setCode("200");
        result.setMsg("请求成功,方法:testGetByParam,请求参数userName:" +  userName + ",userPwd:" + userPwd);        return result;
    }
}
@Autowiredprivate RestTemplate restTemplate; 
 /**
 * 单元测试(带参的get请求)
 */@Testpublic void testGetByParam(){    //请求地址
    String url = "http://localhost:8080/testGetByParam?userName={userName}&userPwd={userPwd}"; 
    //请求参数
    Map<String, String> uriVariables = new HashMap<>();
    uriVariables.put("userName", "唐三藏");
    uriVariables.put("userPwd", "123456"); 
    //发起请求,直接返回对象(带参数请求)
    ResponseBean responseBean = restTemplate.getForObject(url, ResponseBean.class, uriVariables);
    System.out.println(responseBean.toString());
}
 /**
 * 单元测试
 */@Testpublic void testAllGet(){    //请求地址
    String url = "http://localhost:8080/testGet"; 
    //发起请求,返回全部信息
    ResponseEntity<ResponseBean> response = restTemplate.getForEntity(url, ResponseBean.class); 
    // 获取响应体
    System.out.println("HTTP 响应div:" + response.getBody().toString()); 
    // 以下是getForEntity比getForObject多出来的内容
    HttpStatus statusCode = response.getStatusCode();    int statusCodeValue = response.getStatusCodeValue();
    HttpHeaders headers = response.getHeaders();
 
    System.out.println("HTTP 响应状态:" + statusCode);
    System.out.println("HTTP 响应状态码:" + statusCodeValue);
    System.out.println("HTTP Headers信息:" + headers);
}
@RestControllerpublic class TestController { 
    /**
     * 模拟表单请求,post方法测试
     * @return
     */
    @RequestMapping(value = "testPostByForm", method = RequestMethod.POST)    public ResponseBean testPostByForm(@RequestParam("userName") String userName,
                                        @RequestParam("userPwd") String userPwd){
        ResponseBean result = new ResponseBean();
        result.setCode("200");
        result.setMsg("请求成功,方法:testPostByForm,请求参数userName:" + userName + ",userPwd:" + userPwd);        return result;
    }
}
@Autowiredprivate RestTemplate restTemplate; 
/**
 * 模拟表单提交,post请求
 */@Testpublic void testPostByForm(){    //请求地址
    String url = "http://localhost:8080/testPostByForm"; 
    // 请求头设置,x-www-form-urlencoded格式的数据
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); 
    //提交参数设置
    MultiValueMap<String, String> map = new LinkedMultiValueMap<>();    map.add("userName", "唐三藏");    map.add("userPwd", "123456"); 
    // 组装请求体
    HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers); 
    //发起请求
    ResponseBean responseBean = restTemplate.postForObject(url, request, ResponseBean.class);
    System.out.println(responseBean.toString());
}
@RestControllerpublic class TestController { 
    /**
     * 模拟表单请求,post方法测试
     * @param request
     * @return
     */
    @RequestMapping(value = "testPostByFormAndObj", method = RequestMethod.POST)    public ResponseBean testPostByForm(RequestBean request){
        ResponseBean result = new ResponseBean();
        result.setCode("200");
        result.setMsg("请求成功,方法:testPostByFormAndObj,请求参数:" + JSON.toJSONString(request));        return result;
    }
}
public class RequestBean {
 
 
    private String userName; 
 
    private String userPwd; 
 
    public String getUserName() {        return userName;
    } 
    public void setUserName(String userName) {        this.userName = userName;
    } 
    public String getUserPwd() {        return userPwd;
    } 
    public void setUserPwd(String userPwd) {        this.userPwd = userPwd;
    }
}
@Autowiredprivate RestTemplate restTemplate; 
/**
 * 模拟表单提交,post请求
 */@Testpublic void testPostByForm(){    //请求地址
    String url = "http://localhost:8080/testPostByFormAndObj"; 
    // 请求头设置,x-www-form-urlencoded格式的数据
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); 
    //提交参数设置
    MultiValueMap<String, String> map = new LinkedMultiValueMap<>();    map.add("userName", "唐三藏");    map.add("userPwd", "123456"); 
    // 组装请求体
    HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers); 
    //发起请求
    ResponseBean responseBean = restTemplate.postForObject(url, request, ResponseBean.class);
    System.out.println(responseBean.toString());
}
@RestControllerpublic class TestController { 
    /**
     * 模拟JSON请求,post方法测试
     * @param request
     * @return
     */
    @RequestMapping(value = "testPostByJson", method = RequestMethod.POST)    public ResponseBean testPostByJson(@RequestBody RequestBean request){
        ResponseBean result = new ResponseBean();
        result.setCode("200");
        result.setMsg("请求成功,方法:testPostByJson,请求参数:" + JSON.toJSONString(request));        return result;
    }
}
@Autowiredprivate RestTemplate restTemplate; 
/**
 * 模拟JSON提交,post请求
 */@Testpublic void testPostByJson(){    //请求地址
    String url = "http://localhost:8080/testPostByJson"; 
    //入参
    RequestBean request = new RequestBean();
    request.setUserName("唐三藏");
    request.setUserPwd("123456789"); 
   
    //发送post请求,并打印结果,以String类型接收响应结果JSON字符串
    ResponseBean responseBean = restTemplate.postForObject(url, request, ResponseBean.class);
    System.out.println(responseBean.toString());
}
@Controllerpublic class LoginController { 
    /**
     * 重定向
     * @param request
     * @return
     */
    @RequestMapping(value = "testPostByLocation", method = RequestMethod.POST)    public String testPostByLocation(@RequestBody RequestBean request){        return "redirect:index.html";
    }
}
@Autowiredprivate RestTemplate restTemplate; 
/**
 * 重定向,post请求
 */@Testpublic void testPostByLocation(){    //请求地址
    String url = "http://localhost:8080/testPostByLocation"; 
    //入参
    RequestBean request = new RequestBean();
    request.setUserName("唐三藏");
    request.setUserPwd("123456789"); 
    //用于提交完成数据之后的页面跳转,返回跳转url
    URI uri = restTemplate.postForLocation(url, request);
    System.out.println(uri.toString());
}
http://localhost:8080/index.html
@RestControllerpublic class TestController { 
    /**
     * 模拟JSON请求,put方法测试
     * @param request
     * @return
     */
    @RequestMapping(value = "testPutByJson", method = RequestMethod.PUT)    public void testPutByJson(@RequestBody RequestBean request){
        System.out.println("请求成功,方法:testPutByJson,请求参数:" + JSON.toJSONString(request));
    }
}
@Autowiredprivate RestTemplate restTemplate; 
/**
 * 模拟JSON提交,put请求
 */@Testpublic void testPutByJson(){    //请求地址
    String url = "http://localhost:8080/testPutByJson"; 
    //入参
    RequestBean request = new RequestBean();
    request.setUserName("唐三藏");
    request.setUserPwd("123456789"); 
    //模拟JSON提交,put请求
    restTemplate.put(url, request);
}
@RestControllerpublic class TestController { 
    /**
     * 模拟JSON请求,delete方法测试
     * @return
     */
    @RequestMapping(value = "testDeleteByJson", method = RequestMethod.DELETE)    public void testDeleteByJson(){
        System.out.println("请求成功,方法:testDeleteByJson");
    }
}
@Autowiredprivate RestTemplate restTemplate; 
/**
 * 模拟JSON提交,delete请求
 */@Testpublic void testDeleteByJson(){    //请求地址
    String url = "http://localhost:8080/testDeleteByJson"; 
    //模拟JSON提交,delete请求
    restTemplate.delete(url);
}
@Test
    public void rtExchangeTest() throws JSONException {
        RestTemplate restTemplate = new RestTemplate();
        String url = "http://xxx.top/notice/list";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        JSONObject jsonObj = new JSONObject();
        jsonObj.put("start",1);
        jsonObj.put("page",5);
 
        HttpEntity<String> entity = new HttpEntity<>(jsonObj.toString(), headers);
        ResponseEntity<JSONObject> exchange = restTemplate.exchange(url,
                                          HttpMethod.GET, entity, JSONObject.class);
        System.out.println(exchange.getBody());
    }
@Override
    @Nullable
    public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables)
            throws RestClientException {
 
        RequestCallback requestCallback = httpEntityCallback(request, responseType);
        HttpMessageConverterExtractor<T> responseExtractor =                new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);        return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
    }

restTemplate.postForEntity等方法虽然表面上接收的request是@Nullable Object request类型,但是你追踪下去会发现,这个request是用HttpEntity来解析,所以就直接使用HttpEntity.

//文件: RestTemplate.java//行数: 899
 package org.springframework.web.client; 
public HttpEntityRequestCallback(@Nullable Object requestBody, @Nullable Type responseType) {            super(responseType);            if (requestBody instanceof HttpEntity) {                this.requestEntity = (HttpEntity<?>) requestBody;
            }            else if (requestBody != null) {                this.requestEntity = new HttpEntity<>(requestBody);
            }            else {                this.requestEntity = HttpEntity.EMPTY;
            }
        }

我们知道,调用reseful接口传递的数据内容是json格式的字符串,返回的响应也是json格式的字符串。然而restTemplate.postForObject方法的请求参数RequestBean和返回参数ResponseBean却都是java类。是RestTemplate通过HttpMessageConverter自动帮我们做了转换的操作。

默认情况下RestTemplate自动帮我们注册了一组HttpMessageConverter用来处理一些不同的contentType的请求。
如StringHttpMessageConverter来处理text/plain;MappingJackson2HttpMessageConverter来处理application/json;MappingJackson2XmlHttpMessageConverter来处理application/xml。
你可以在org.springframework.http.converter包下找到所有spring帮我们实现好的转换器。
如果现有的转换器不能满足你的需求,你还可以实现org.springframework.http.converter.HttpMessageConverter接口自己写一个。详情参考官方api。