RestTemplate 使用详解

2023-05-16

一、简介

常见的http客户端请求工具:

  1. JDK 自带 HttpURLConnection
  2. Apache HttpClient
  3. OKHttp

以上 工具虽然常用,但对于 RESTful 操作相对不是太友好。所以,从 Spring3.0开始支持的一个 HTTP 请求工具RestTemplate,提供了常见的 REST请求方案的模板。
RestTemplate只是提供了 Http请求模板,其底层默认是使用HttpURLConnection作为真正的请求工具。它可以通过构造方法替换底层的执行引擎,常见的引擎又HttpClientNettyOkHttp

二、简单的请求

1、GET请求

1. 直接拼接参数

  String params = "http://localhost:10011/user/params?name=诸葛亮&age=100";
  String result = template.getForObject(HOST  + params, String.class);
  LOGGER.info("请求返回结果:{}", result);

2. 占位符参数

  // 1、可以直接在方法中指定参数, 此种方式还可以使用下标的形式。
  // 请求路径还可以为:name={0}&age={1}
 String url = "http://localhost:10011/user/params?name={name}&age={age}";
 String result = template.getForObject(url , String.class, "李四", 20);
 LOGGER.info("请求返回结果:{}", result);

// 2、 通过 Map 传递参数,此种方式必须使用占位符,并且 map 中的 key 值,要与请求
// 路径中的 占位符一致
Map<String, Object> map = new HashMap<>();
map.put("name", "王五");
map.put("age", 30);
ResponseEntity<String> forEntity = template.getForEntity(HOST + url , String.class, map);

2、POST请求

接口实例
如下的接口实例中两个方法的唯一区别为 一个参数中加了注解@RequestBody,一个没有加,两者在 POST请求中传值方式不同。

    // 接口 1
    @RequestMapping("/obj")
    @ResponseBody
    public User getObj(User user){
        return user;
    }
    // 接口 2
    @RequestMapping("/body")
    @ResponseBody
    public User getBody(@RequestBody User user){
        return user;
    }

1、带有 @RequestBody 注解的请求

此种情况下,请求参数可以为 设置User 对象,也可以说使用Map

   String url = "http://localhost:10011/user/body";
   
   User user = new User().setName("张三")
            .setAge(40);
    String result = template.postForObject(url, user, String.class);
    LOGGER.info("请求返回结果:{}", result);

    Map<String, Object> map = new HashMap<>();
    map.put("name", "王五");
    map.put("age", 30);

    ResponseEntity<String> forEntity = template.postForEntity(url, map, String.class);

    LOGGER.info("请求返回结果:{}", forEntity.getBody());

2、不带@RequestBody 注解的请求

此种情况下,传的参数需要使用MultiValueMap

  MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
  map.add("name", "王五");
  map.add("age", 30);
  ResponseEntity<String> forEntity = template.postForEntity(url, map, String.class);

   LOGGER.info("请求返回结果:{}", forEntity.getBody());

三、带请求头的请求

1、GET 请求

GET请求中的getForObjectgetForEntity 方法不支持传递头信息,需要使用 通用方法exchange,如下所示:

  String url = "http://localhost:10011/user/params?name={name}&age={age}";
   // 定义头信息
   HttpHeaders headers = new HttpHeaders();
   headers.add("token", UUID.randomUUID().toString());
   // 请求参数
   Map<String, Object> map = new HashMap<>();
   map.put("name", "王五");
   map.put("age", 30);

   // 使用 HttpEntity 对 头信息进行封装
   HttpEntity<Map<String, Object>> entity = new HttpEntity<>(headers);
   // 请求方法 exchange
   ResponseEntity<String> response = template.exchange(url, HttpMethod.GET, entity, String.class, map);
   LOGGER.info("请求返回结果:{}", response.getBody());

2、POST请求

POST 请求添加头信息比较简单,只需要使用 HttpEntity 对请求对象进行一次封装即可。

   // 定义头信息
   HttpHeaders headers = new HttpHeaders();
   headers.add("token", UUID.randomUUID().toString());
   User user = new User().setName("张三")
            .setAge(40);
    // 使用 HttpEntity 把请求对象user 和 header 进行组装
   HttpEntity<User> userHttpEntity = new HttpEntity<>(user, headers);
    // 把请求参数改为 httpEntity 对象即可
   String result = template.postForObject(url, userHttpEntity, String.class);
   LOGGER.info("请求返回结果:{}", result);

四、form 表单请求

form表单的提交只需要需要把头信息ContentType 设置为MediaType.APPLICATION_FORM_URLENCODED ,同时参数需要使用 MultiValueMap 封装。如下所示:

     String url = "http://localhost:10011/user/obj";
      
     HttpHeaders headers = new HttpHeaders();
     headers.add("token", UUID.randomUUID().toString());
     // 设置请求类型
     headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
     // 组装参数
     MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
     multiValueMap.add("name", "王五");
     multiValueMap.add("age", 30);
     // 发送请求
     HttpEntity< MultiValueMap<String, Object>> request = new HttpEntity<>(multiValueMap, headers);
     ResponseEntity<String> exchange = template.exchange(url, HttpMethod.POST, request, String.class);
     LOGGER.info("请求返回结果:{}", exchange.getBody());

五、上传下载

1、上传

  String url = "http://localhost:10011/user/upload";
  HttpHeaders headers = new HttpHeaders();

  // 模拟读取文件
  File file = new File("F:/run.bat");
  //从File句柄创建一个新的FileSystemResource
  FileSystemResource resource = new FileSystemResource(file);

  MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
  multiValueMap.add("name", "update.bat");
  multiValueMap.add("file", resource);

  HttpEntity< MultiValueMap<String, Object>> request = new HttpEntity<>(multiValueMap, headers);
  ResponseEntity<String> exchange = template.exchange(url, HttpMethod.POST, request, String.class);
  LOGGER.info("请求返回结果:{}", exchange.getBody());

2、下载

1. 小文件下载
小文件下载比较简单,只需要把请求响应类型设置为byte[] 即可,如下所示:

   String url = "http://localhost:10011/user/downLoad";
   // 请求下载
   ResponseEntity<byte[]> entity = template.getForEntity(url, byte[].class);
   // 写文件
   byte[] body = entity.getBody();
   Files.write(Paths.get("D:/download.jpg"), body);

这种下载方法实际上是将下载文件一次性加载到客户端本地内存,然后从内存将文件写入磁盘。这种方式对于小文件的下载还比较适合,如果文件比较大或者文件下载并发量比较大,容易造成内存的大量占用,从而降低应用的运行效率。

2. 大文件下载

这种下载方式的区别在于

  • 设置了请求头APPLICATION_OCTET_STREAM,表示以流的形式进行数据加载
  • RequestCallback 结合File.copy保证了接收到一部分文件内容,就向磁盘写入一部分内容。而不是全部加载到内存,最后再写入磁盘文件。
   String url = "http://localhost:10011/user/downLoad";

   String targetPath = "D:/download.jpg";

   // 定义请求头的接收类型
   RequestCallback requestCallback = request -> request.getHeaders()
           .setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
   //对响应进行流式处理而不是将其全部加载到内存中
   template.execute(url, HttpMethod.GET, requestCallback, clientHttpResponse -> {
       Files.copy(clientHttpResponse.getBody(), Paths.get(targetPath));
       return null;
   });

六、更换底层请求执行引擎

Spring中已经提供了大部分的执行引擎,比如 HttpClientOkHttp3 等,要想使用这些底层引擎只需要加入响应的依赖,然后再初始化类似,在构造方法中指定响应的执行引擎即可。

// 1、使用 HttpClient 引擎。
RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
// 2、使用OkHttp3 引擎
RestTemplate restTemplate = new RestTemplate(new OkHttp3ClientHttpRequestFactory());

七、拦截器

当所有的请求需要设置公共信息时,就可以使用拦截器,为每个请求设置。设置方法如下:

  RestTemplate template = new RestTemplate();
  // 此处设置了一个公共请求头 AUTHORIZATION
  ClientHttpRequestInterceptor interceptor = new ClientHttpRequestInterceptor() {
       @Override
       public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
           HttpHeaders headers = request.getHeaders();
           headers.set(HttpHeaders.AUTHORIZATION, "636213dc4ac6e9220a0f5107");
           return execution.execute(request, body);
       }
   };
   template.setInterceptors(Arrays.asList(interceptor));
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RestTemplate 使用详解 的相关文章

随机推荐

  • 配置VNC环境在windows主机访问阿里云linux服务器

    配置VNC环境在windows主机访问阿里云linux服务器 虽然作为服务器使用更多的是使用字符终端连接服务器 xff0c 进行操作 xff0c 因为图形界面很消耗性能和资源 xff0c 但有的时候使用图形界面进行操作更为便捷 xff0c
  • pythondataframe输出小结

    在使用dataframe时遇到datafram在列太多的情况下总是自动换行显示的情况 xff0c 导致数据阅读困难 xff0c 效果如下 xff1a coding utf 8 import numpy as np import pandas
  • 聊聊 Redis 为什么构建自己的简单动态字符串 SDS

    我们知道 xff0c Redis 支持字符串 哈希 列表 集合和有序集合五种基本类型 那么我们如何把图片 音频 视频或者压缩文件等二进制数据保存到 Redis 中呢 xff1f 之前在使用 Memcached 缓存这类数据时是把它们转换成
  • 聊聊 Redis 高可用之持久化AOF和RDB分析

    Redis 持久化概述 Redis 是内存数据库 xff0c 数据都是存储在内存中 xff0c 为了避免进程退出导致数据的永久丢失 xff0c 需要定期将 Redis 中的数据以某种形式把内存中的数据保存到磁盘中 xff1b 当 Redis
  • mysqldump: Got error: 1044: Access denied for user XXXX when doing LOCK TABLES

    一 报错信息 在使用mysqldump 执行远程备份数据库的时候报如下错误 xff1a mysqldump Got error span class token number 1044 span Access denied span cla
  • jmap -heap [pid]运行报:Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException(不允许的操作)

    一 运行环境 操作系统 xff1a Ubuntu 5 4 0 6 Java版本 xff1a JDK8 二 执行命令 jmap heap span class token punctuation span pid号 span class to
  • chkconfig: command not found

    问题描述 在 ubuntu1 16 04 10 执行 chkconfig 命令报 chkconfig command not found 说明此服务上没有安装 chkconfig 执行如下命令进行安装 span class token fu
  • Docker 基础篇 之 安装

    一 Docker安装 查看 CentOS 内核版本 Docker 要求 CentOS 系统的内核版本高于3 10 执行如下命令查询 内核版本 span class token function uname span r span class
  • Java 基础 之 Valid 验证

    一 64 Valid 简介 Bean Validation 内置的校验器 校验器说明 64 Null被注解的元素必须为 null 64 NotNull被注解的元素必须不为 null 64 AssertTrue被注解的元素必须为 true 6
  • HttpURLConnection链接详解

    HttpURLConnection链接详解 一 简介 简单来说 xff0c HttpURLConnection 是 Java 提供的发起 HTTP 请求的基础类库 xff0c 提供了 HTTP 请求的基本功能 xff0c 不过封装的比较少
  • Apache HttpClient 详解

    1 简介 HttpClient 是 Apache Jakarta Common 下的子项目 xff0c 用来提供高效的 最新的 功能丰富的支持 HTTP 协议的客户端编程工具包 xff0c 并且它支持 HTTP 协议最新的版本和建议 Htt
  • OKHttp使用详解

    1 简介 OkHttp 是一个默认高效的 HTTP 客户端 xff1a HTTP 2 支持允许对同一主机的所有请求共享一个套接字 连接池减少了请求延迟 xff08 如果 HTTP 2 不可用 xff09 透明 GZIP 缩小了下载大小 响应
  • python二维码生成与扫码

    1 import qrcode img 61 qrcode make 34 hello world 34 img get image show img save 39 hello png 39 2 import qrcode qr 61 q
  • C语言可变参数(从stdarg.h到应用)

    1 什么是可变参数函数 在C语言编程中有时会遇到一些参数可变的函数 xff0c 例如printf scanf xff0c 其函数原型为 xff1a span class token keyword int span span class t
  • OkHttp 缓存实战

    1 简介 在实际业务中可能某些查询数据 xff0c 不经常变化 xff0c 为了节省流量 提高响应速度和增强用户体验等 xff0c 把变化频率小的数据缓存到本地 xff0c 以实现复用 OkHttp 的缓存功能使用起来也比较简单和灵活 xf
  • Feign 详解

    1 Feign 是什么 Feign是一个http请求调用的轻量级框架 xff0c 可以以Java接口注解的方式调用Http请求 Feign通过处理注解 xff0c 将请求模板化 xff0c 当实际调用的时候 xff0c 传入参数 xff0c
  • @Transactional 注解失效情况及解决办法

    一 64 Transactional 注解在了非 public 方法上 如下所示 64 Transactional修饰在了非public方法上 span class token annotation punctuation 64 Servi
  • @Transactional 事务加了 锁 为什么还有并发问题?

    一 原因分析 Spring 中通过在方法上添加注解 64 Transactional 可以很好的处理事务问题 Spring对此的处理原理是对 加了 64 Transactional 注解的方法 添加 AOP切面来时先事务管理的 而 sync
  • 聊聊微服务之什么是微服务及其好处

    一 什么是微服务 微服务就是一些协同工作的小而自治的服务 很小 xff0c 专注于做好一件事 在单一模块系统中 xff0c 随着新功能的增加 xff0c 代码库会越来越大 时间久了代码库会变得非常庞大 xff0c 以至于在什么地方修改都很困
  • RestTemplate 使用详解

    一 简介 常见的http客户端请求工具 xff1a JDK 自带 HttpURLConnectionApache HttpClientOKHttp 以上 工具虽然常用 xff0c 但对于 RESTful 操作相对不是太友好 所以 xff0c