4 种 Springboot RestTemplate 服务里发送 HTTP 请求用法
本文分享自华为云社区《Springboot RestTemplate 服务里发送HTTP请求及几种用法的介绍》,作者:gentle_zhou。
在微服务如此流行的当下,专门为某项功能开发模块作为另一项功能的构建块就变得异常重要。假设我们的服务 A 是调用某个 API 接口,服务 B 则专门用来校验用户是否有权限,那么知道如何在服务 A 发送 http 请求去调用服务 B 的接口就很必要。
如果刚好我们的项目是用 Java 开发的,那么 RestTemplate 就是我们需要的可以提供便捷访问远程 Http 服务方法的类。我们先去官网看下 RestTemplate 类是在哪个包下:
可以看到是在 spring 框架网页客户端下,官网对它的介绍:
"Synchronous client to perform HTTP requests, exposing a simple, template method API over underlying HTTP client libraries such as the JDK HttpURLConnection, Apache HttpComponents, and others.
The RestTemplate offers templates for common scenarios by HTTP method, in addition to the generalized exchange and execute methods that support of less frequent cases."
翻译过来就是同步客户端来执行 HTTP 请求,暴露一个简单的模板方法 API 给底层的 HTTP 客户端库比如 JDK HttpURLConnection、Apache HttpComponents。
RestTemplate 通过 HTTP 方法为常见的场景提供了模板,除此之外,还提供了通用的交换和执行方法来支持不太常见的情况。
【如何创建?】
因为 RestTemplate 是 Spring 的封装;我们先去 pom.xml 文件里引入 springboot starter web 依赖,内含 spring-web-X.X.X.RELEASE.jar 包:
再去官网看看构建的介绍:
我们可以用官网给的这三种方式来创建 RestTemplate。一般来说我们用第一种方式就可以了:
在这个创建过程,RestTemplate 默认使用 HttpMessageConverter 实例将 HTTP 消息转换成 POJO(Plain Ordinary Java Object,即普通的没有使用 Entity Beans 的 Java 对象)或则从 POJO 转换成 HTTP 消息。
RestTemplate 与 REST 资源交互的方法涵盖了 HTTP 请求方法,包括 get, post, put, delete。
【Get 请求】
在 RestTemplate 里,有两种方式可以发送 Get 请求:
1.getForEntity(),发送 HTTP GET 请求,返回 ResponseEntity 包含相应体所映射成的对象。官方对该函数的解释如下:
首先是需要三个参数:url(要调用的服务的地址),返回值的类型和包含 uri 模板值的 map 以及 最后会返回 ResponseEntity<T>(是 Spring 对 HTTP 请求相应的封装,包含了几个重要的元素比如响应码,内容类型,内容长度和响应消息体)。
当然该函数的参数也可以是"url,返回值的类型,扩展模板的变量" / "url,返回值的类型"。
举个例子,我下面用的参数就是"url,返回值的类型,扩展模板的变量":
getBody()可以得到 ResponseEntity<T>里面的响应消息体。
2.getForObject(),发送 HTTP GET 请求,返回映射的对象。官方对该函数的解释如下:
该方法也是需要三个参数:url,返回值的类型和包含 uri 模板值的 map 以及 最后会返回 T。
当然该函数的参数也可以是"url,返回值的类型,扩展模板的变量" / "url,返回值的类型"。
最后返回的 T 实际上是对上一种方法返回的值 ResponseEntity<T>的进一步封装,返回的是响应消息体里面的内容。
【Post 请求】
在 RestTemplate 里,有三种方式可以发送 Post 请求:
1.postForEntity(),发送 HTTP POST 请求,返回 ResponseEntity 包含相应体所映射成的对象。官方对该函数的解释如下:
首先是需要三个参数:url,需要 POST 上去的对象(可以是 null) 和扩展模板的变量 以及 最后会返回 ResponseEntity<T>。
当然该函数的参数也可以是"url,需要 POST 上去的对象(可以是 null),响应消息的类型,包含 uri 模板值的 map" / "url,需要 POST 上去的对象(可以是 null),响应消息的类型"。
2.postForObject(),发送 HTTP POST 请求,返回映射的对象。官方对该函数的解释如下:
首先是需要三个参数:url,需要 POST 上去的对象(可以是 null) 和扩展模板的变量 以及 最后会返回 ResponseEntity<T>。
当然该函数的参数也可以是"url,需要 POST 上去的对象(可以是 null),响应消息的类型,包含 uri 模板值的 map" / "url,需要 POST 上去的对象(可以是 null),响应消息的类型"。
3.postForLocation(),发送 HTTP POST 请求,返回的是 URI(提交 POST 之后,新资源的 URI 链接)。官方对该函数的解释如下:
首先是需要三个参数:url,需要 POST 上去的对象(可以是 null) 和扩展模板的变量 以及 最后会返回 URL(提交 POST 之后,新资源的 URI 链接)。
当然该函数的参数也可以是"url,需要 POST 上去的对象(可以是 null),响应消息的类型,包含 uri 模板值的 map" / "url,需要 POST 上去的对象(可以是 null)"。
【Put 请求】
put 和 post 作用类似,只是后一个请求会把前一个请求覆盖,所以会被用来更改资源,POST 则是用来增加资源。
在 RestTemplate 里,有 1 种方式可以发送 Put 请求:
1.put(),发送 HTTP PUT 请求,是 void 函数不返回内容。官方对该函数的解释如下:
首先是需要三个参数:url,需要 PUT 上去的对象(可以是 null) 和扩展模板的变量,最后不会返回什么。做的事就是更改需要 PUT 上去的对象至 URL 指定的资源。
当然该函数的参数也可以是"url,需要 PUT 上去的对象(可以是 null),包含 uri 模板值的 map" / "url,需要 PUT 上去的对象(可以是 null)"。
【Delete 请求】
在 RestTemplate 里,有 1 种方式可以发送 Delete 请求:
1.delete(),发送 HTTP DELETE 请求,是 void 函数不返回内容。官方对该函数的解释如下:
首先是需要 2 个参数:url 和扩展模板的变量,最后不会返回什么。做的事就是直接删除 URL 指定的资源。
当然该函数的参数也可以是"url,包含 uri 模板值的 map" / "url"。
【Exchange 方法和 Execute 方法】
1.exchange(),在 URL 上执行特定的 HTTP 方法,返回从响应体中映射得到的包含对象的 ResponseEntity。
该方法可以指定请求的 HTTP 类型。对指定的 URI 模板执行 HTTP 方法,把指定的请求实体写入请求,并返回 ResponseEntity 响应。
官方对该函数的解释如下:
首先是需要 5 个参数:url,指定的 HTTP 方法(比如 POST, GET),需要写入请求的实体(头部和主体 或 头部 或 主体,也可以是 null) ,响应消息的类型和扩展模板的变量 以及 最后会返回 ResponseEntity<T>。
当然该函数的参数也可以是"url,指定的 HTTP 方法(比如 POST, GET),需要写入请求的实体(头部和主体 或 头部 或 主体,也可以是 null) ,响应消息的类型,包含 uri 模板值的 map" / "URI 格式的 url,指定的 HTTP 方法(比如 POST, GET),需要写入请求的实体(头部和主体 或 头部 或 主体,也可以是 null) ,响应消息的类型" / "url,指定的 HTTP 方法(比如 POST, GET),需要写入请求的实体(头部和主体 或 头部 或 主体,也可以是 null) ,响应消息的类型-ParameterizedTypeReference<T>,扩展模板的变量" / "url,指定的 HTTP 方法(比如 POST, GET),需要写入请求的实体(头部和主体 或 头部 或 主体,也可以是 null) ,响应消息的类型-ParameterizedTypeReference<T>,包含 uri 模板值的 map" / "URI 格式的 url,指定的 HTTP 方法(比如 POST, GET),需要写入请求的实体(头部和主体 或 头部 或 主体,也可以是 null) ,响应消息的类型-ParameterizedTypeReference<T>" / "需要写入请求的实体(头部和主体 或 头部 或 主体,不可以是 null), 响应消息的类型" / "需要写入请求的实体(头部和主体 或 头部 或 主体,不可以是 null), 响应消息的类型-ParameterizedTypeReference<T>"。
2.execute(),在 URL 上执行特定的 HTTP 方法,返回一个从相应体映射得到的对象。
该方法可以对指定的 URI 模板执行请求的 HTTP 方法,用 RequestCallback 准备请求,并用 ResponseExtractor 读取响应,最后返回一个 arbitrary 对象(这里有个困惑,不知道怎么翻译才准确;根据英文定义,“An arbitrary object has those properties common to the individual objects in its range”即一个对象具有其范围内各个对象所共有性质的属性;物以类聚的感觉)。
官方对该函数的解释如下:
首先是需要 5 个参数:url,指定的 HTTP 方法(比如 POST, GET),功能性的接口 RequestCallback(准备请求的对象;可以是 null),从响应消息里提取返回值的对象(可以是 null)和扩展模板的变量 以及 最后会返回 T。
当然该函数的参数也可以是"url,指定的 HTTP 方法(比如 POST, GET),功能性的接口 RequestCallback(准备请求的对象;可以是 null),从响应消息里提取返回值的对象(可以是 null)和包含 uri 模板值的 map" / "URI 格式的 url,指定的 HTTP 方法(比如 POST, GET),功能性的接口 RequestCallback(准备请求的对象;可以是 null),从响应消息里提取返回值的对象(可以是 null)"。
【需要注意的地方】
1.url 里面要把 http/https 写上,不然会报错;浏览器地址会帮我们自动补全,这里 url 变量可不会了
2.解决中文乱码的问题:.setContentType(MediaType.APPLICATION_JSON_UTF8),针对 HttpHeaders
3.getForEntity() 返回的是 HttpEntity<String>,如果我们需要的是里面的内容,我们需要 HttpEntity<String>.getBody()来获取里面的字符串 或则 直接就用 getForObject()
4.URL 是 URI 的一个子集。 在《HTTP 权威指南》一书中,对于 URI 的定义是:统一资源标识符;对于 URL 的定义是:统一资源定位符。 二者的区别在于,URI 表示请求服务器的路径,定义这么一个资源。 而 URL 同时说明要如何访问这个资源(http://)
5.一个 arbitrary 对象(这里有个困惑,不知道怎么翻译才准确;根据英文定义,“An arbitrary object has those properties common to the individual objects in its range”即一个对象具有其范围内各个对象所共有性质的属性;物以类聚的感觉。)。
【参考资料】
2.https://www.jianshu.com/p/91158fb8860b
3.https://www.baeldung.com/rest-template
4.https://howtodoinjava.com/spring-boot2/resttemplate/spring-restful-client-resttemplate-example/
版权声明: 本文为 InfoQ 作者【华为云开发者社区】的原创文章。
原文链接:【http://xie.infoq.cn/article/ca3c70e6ffd58e24a6b7a9599】。文章转载请联系作者。
评论