RestTemplate发送HTTP、HTTPS请求

article/2025/10/1 0:23:03

        前面我们介绍了如何使用Apache的HttpClient发送HTTP请求,这里我们介绍Spring的Rest客户端(即:RestTemplate)
如何发送HTTP、HTTPS请求。注:
HttpClient如何发送HTTPS请求,有机会的话也会再给出示例。

声明:本人一些内容摘录自其他朋友的博客,链接在本文末给出!


基础知识

         微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就必须使用HTTP客户端。我们可以使用JDK原生的URLConnectionApache的Http ClientNetty的异步HTTP Client,最方便、最优雅的Feign, Spring的RestTemplate等。

  • RestTemplate简述
            RestTemplate是Spring提供的用于访问Rest服务(Rest风格、Rest架构)的客户端。
             RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。

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

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

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

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


软硬件环境: Windows10、Eclipse、JDK1.8、SpringBoot

准备工作:引入相关依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

HTTP之GET请求(示例)

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;import com.google.gson.Gson;/*** 单元测试** @author JustryDeng* @DATE 2018年9月7日 下午6:37:05*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class AbcHttpsTestApplicationTests {/*** RestTemplate 发送  HTTP GET请求 --- 测试* @throws UnsupportedEncodingException ** @date 2018年7月13日 下午4:18:50*/@Testpublic void doHttpGetTest() throws UnsupportedEncodingException {// -------------------------------> 获取Rest客户端实例RestTemplate restTemplate = new RestTemplate();// -------------------------------> 解决(响应数据可能)中文乱码 的问题List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();converterList.remove(1); // 移除原来的转换器// 设置字符编码为utf-8HttpMessageConverter<?> converter = new StringHttpMessageConverter(StandardCharsets.UTF_8);converterList.add(1, converter); // 添加新的转换器(注:convert顺序错误会导致失败)restTemplate.setMessageConverters(converterList);// -------------------------------> (选择性设置)请求头信息// HttpHeaders实现了MultiValueMap接口HttpHeaders httpHeaders = new HttpHeaders();// 给请求header中添加一些数据httpHeaders.add("JustryDeng", "这是一个大帅哥!");// -------------------------------> 注:GET请求 创建HttpEntity时,请求体传入null即可// 请求体的类型任选即可;只要保证 请求体 的类型与HttpEntity类的泛型保持一致即可String httpBody = null;HttpEntity<String> httpEntity = new HttpEntity<String>(httpBody, httpHeaders);// -------------------------------> URIStringBuffer paramsURL = new StringBuffer("http://127.0.0.1:9527/restTemplate/doHttpGet");// 字符数据最好encoding一下;这样一来,某些特殊字符才能传过去(如:flag的参数值就是“&”,不encoding的话,传不过去)paramsURL.append("?flag=" + URLEncoder.encode("&", "utf-8"));URI uri = URI.create(paramsURL.toString());//  -------------------------------> 执行请求并返回结果// 此处的泛型  对应 响应体数据   类型;即:这里指定响应体的数据装配为StringResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, httpEntity, String.class);// -------------------------------> 响应信息//响应码,如:401、302、404、500、200等System.err.println(response.getStatusCodeValue());Gson gson = new Gson();// 响应头System.err.println(gson.toJson(response.getHeaders()));// 响应体if(response.hasBody()) {System.err.println(response.getBody());}}}

被http请求的对应的方法逻辑为:

注:我们也可以使用@RequestHeader()来获取到请求头中的数据信息,如:

结果(效果)展示

1.进行HTTP请求的方法获得响应后输出结果为:

2.被HTTP请求的方法被请求后的输出结果为:

HTTP之POST请求(示例)

/*** RestTemplate 发送  HTTP POST请求 --- 测试* @throws UnsupportedEncodingException ** @date 2018年9月8日 下午2:12:50*/
@Test
public void doHttpPostTest() throws UnsupportedEncodingException {// -------------------------------> 获取Rest客户端实例RestTemplate restTemplate = new RestTemplate();// -------------------------------> 解决(响应数据可能)中文乱码 的问题List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();converterList.remove(1); // 移除原来的转换器// 设置字符编码为utf-8HttpMessageConverter<?> converter = new StringHttpMessageConverter(StandardCharsets.UTF_8);converterList.add(1, converter); // 添加新的转换器(注:convert顺序错误会导致失败)restTemplate.setMessageConverters(converterList);// -------------------------------> (选择性设置)请求头信息// HttpHeaders实现了MultiValueMap接口HttpHeaders httpHeaders = new HttpHeaders();// 设置contentTypehttpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);// 给请求header中添加一些数据httpHeaders.add("JustryDeng", "这是一个大帅哥!");// ------------------------------->将请求头、请求体数据,放入HttpEntity中// 请求体的类型任选即可;只要保证 请求体 的类型与HttpEntity类的泛型保持一致即可// 这里手写了一个json串作为请求体 数据 (实际开发时,可使用fastjson、gson等工具将数据转化为json串)String httpBody = "{\"motto\":\"唉呀妈呀!脑瓜疼!\"}";HttpEntity<String> httpEntity = new HttpEntity<String>(httpBody, httpHeaders);// -------------------------------> URIStringBuffer paramsURL = new StringBuffer("http://127.0.0.1:9527/restTemplate/doHttpPost");// 字符数据最好encoding一下;这样一来,某些特殊字符才能传过去(如:flag的参数值就是“&”,不encoding的话,传不过去)paramsURL.append("?flag=" + URLEncoder.encode("&", "utf-8"));URI uri = URI.create(paramsURL.toString());//  -------------------------------> 执行请求并返回结果// 此处的泛型  对应 响应体数据   类型;即:这里指定响应体的数据装配为StringResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, String.class);// -------------------------------> 响应信息//响应码,如:401、302、404、500、200等System.err.println(response.getStatusCodeValue());Gson gson = new Gson();// 响应头System.err.println(gson.toJson(response.getHeaders()));// 响应体if(response.hasBody()) {System.err.println(response.getBody());}}

被http请求的对应的方法逻辑为:

注:我们也可以使用@RequestHeader()来获取到请求头中的数据信息,如:

结果(效果)展示

进行HTTP请求的方法获得响应后输出结果为:

被HTTP请求的方法被请求后的输出结果为:


HTTPS请求的准备工作

HTTPS请求 = 超文本传输协议HTTP + 安全套接字层SSL

先给出等下需要用到的一个SimpleClientHttpRequestFactory的实现类

/*** 声明:此代码摘录自https://blog.csdn.net/wltsysterm/article/details/80977455* 声明:关于Socket的相关知识,本人会在后面的闲暇时间进行学习整理,请持续关注博客更新** @author JustryDeng* @DATE 2018年9月8日 下午4:34:02*/
public class HttpsClientRequestFactory extends SimpleClientHttpRequestFactory {@Overrideprotected void prepareConnection(HttpURLConnection connection, String httpMethod) {try {if (!(connection instanceof HttpsURLConnection)) {throw new RuntimeException("An instance of HttpsURLConnection is expected");}HttpsURLConnection httpsConnection = (HttpsURLConnection) connection;TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {@Overridepublic java.security.cert.X509Certificate[] getAcceptedIssuers() {return null;}@Overridepublic void checkClientTrusted(X509Certificate[] certs, String authType) {}@Overridepublic void checkServerTrusted(X509Certificate[] certs, String authType) {}}};SSLContext sslContext = SSLContext.getInstance("TLS");sslContext.init(null, trustAllCerts, new java.security.SecureRandom());httpsConnection.setSSLSocketFactory(new MyCustomSSLSocketFactory(sslContext.getSocketFactory()));httpsConnection.setHostnameVerifier(new HostnameVerifier() {@Overridepublic boolean verify(String s, SSLSession sslSession) {return true;}});super.prepareConnection(httpsConnection, httpMethod);} catch (Exception e) {e.printStackTrace();}}/*** We need to invoke sslSocket.setEnabledProtocols(new String[] {"SSLv3"});* see http://www.oracle.com/technetwork/java/javase/documentation/cve-2014-3566-2342133.html (Java 8 section)*/// SSLSocketFactory用于创建 SSLSocketsprivate static class MyCustomSSLSocketFactory extends SSLSocketFactory {private final SSLSocketFactory delegate;public MyCustomSSLSocketFactory(SSLSocketFactory delegate) {this.delegate = delegate;}// 返回默认启用的密码套件。除非一个列表启用,对SSL连接的握手会使用这些密码套件。// 这些默认的服务的最低质量要求保密保护和服务器身份验证@Overridepublic String[] getDefaultCipherSuites() {return delegate.getDefaultCipherSuites();}// 返回的密码套件可用于SSL连接启用的名字@Overridepublic String[] getSupportedCipherSuites() {return delegate.getSupportedCipherSuites();}@Overridepublic Socket createSocket(final Socket socket, final String host, final int port, final boolean autoClose) throws IOException {final Socket underlyingSocket = delegate.createSocket(socket, host, port, autoClose);return overrideProtocol(underlyingSocket);}@Overridepublic Socket createSocket(final String host, final int port) throws IOException {final Socket underlyingSocket = delegate.createSocket(host, port);return overrideProtocol(underlyingSocket);}@Overridepublic Socket createSocket(final String host, final int port, final InetAddress localAddress, final int localPort) throwsIOException {final Socket underlyingSocket = delegate.createSocket(host, port, localAddress, localPort);return overrideProtocol(underlyingSocket);}@Overridepublic Socket createSocket(final InetAddress host, final int port) throws IOException {final Socket underlyingSocket = delegate.createSocket(host, port);return overrideProtocol(underlyingSocket);}@Overridepublic Socket createSocket(final InetAddress host, final int port, final InetAddress localAddress, final int localPort) throwsIOException {final Socket underlyingSocket = delegate.createSocket(host, port, localAddress, localPort);return overrideProtocol(underlyingSocket);}private Socket overrideProtocol(final Socket socket) {if (!(socket instanceof SSLSocket)) {throw new RuntimeException("An instance of SSLSocket is expected");}((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1"});return socket;}}
}

HTTPS之GET请求

说明:RestTemplate发送HTTPS与发送HTTP的代码,除了在创建RestTemplate时不一样以及协议不一样
         (一个URL是http开头,一个是https开头)外,其余的都一样

HTTP获取RestTemplate实例

HTTPS获取RestTemplate实例

给出具体HTTPS发送GET请求代码示例(HTTPS发送POST请求类比即可)

注:HTTPS与HTTP的使用不同之处,在途中已经圈出了。

注:上图中请求的https://tcc.taobao.com/cc/json/mobile_tel_segment.htm是阿里提供的一个简单查询手机信息的地址。

运行该主函数,控制台打印出的结果为:

注:如果用HTTP协议开头的URL去访问HTTPS开头的URL的话(这两个URL除了协议不同其它都相同),是访问不了的;除
       非服务端有相应的设置。

注:发送HTTPS的逻辑代码是可以拿来发送HTTP的。但是根据我们写得HttpsClientRequestFactory类中的代码可知,会
       打印出异常(异常抛出后被catch了):

如果用HTTPS访问HTTP时不想抛出异常,那么把对应的这个逻辑去掉即可。

提示:“发送HTTPS的逻辑代码是可以拿来发送HTTP的”这句话的意思是:拿来做发HTTPS请求的逻辑,可以复用来作发
            HTTP请求的逻辑。并不是说说一个API能被HTTPS协议的URL访问,就一定能被HTTP协议的URL访问。

HTTPS之POST请求

注:关于HTTPS这里只给出了一个GET示例,使用HTTPS进行POST请求与HTTP进行POST请求几乎是一样的,
     只是创建的RestTemplate实例和协议不一样而已,其余的都一样
;类比GET即可,这里就不再给出示例了


提示:在进行请求时,最好使用资源池管理Socket;如果每次请求都创建Socket的话,
           那么一定要记得请求完毕后释放Socket,可通过将Socket定义为一个Field,使用
           完毕后,进行释放。对于HPPT/HTTPS请求,本人这里其实并不推荐RestTemplate,
           推荐使用HttpClientOkHttp


^_^ 参考链接、摘录内容出处
     
  https://www.cnblogs.com/duanxz/p/3510622.html
        https://blog.csdn.net/wltsysterm/article/details/80977455
        https://blog.csdn.net/zhoumengshun/article/details/79100053

^_^ 如有不当之处,欢迎指正

^_^ 本次示例测试代码项目托管链接
       
 https://github.com/JustryDeng/PublicRepository

^_^ 本文已经被收录进《程序员成长笔记(五)》,笔者JustryDeng


http://chatgpt.dhexx.cn/article/QEM2kb7E.shtml

相关文章

HttpEntity的用法

关于HttpEntity的用法 HttpEntity表示http的request和resposne实体&#xff0c;它由消息头和消息体组成。 从HttpEntity中可以获取http请求头和回应头&#xff0c;也可以获取http请求体和回应体信息。HttpEntity的使用&#xff0c;与RequestBody 、ResponseBody类似。 HttpEnti…

关于HttpEntity的用法

关于HttpEntity的用法 HttpEntity表示http的request和resposne实体&#xff0c;它由消息头和消息体组成。从HttpEntity中可以获取http请求头和回应头&#xff0c;也可以获取http请求体和回应体信息。 HttpEntity的使用&#xff0c;与RequestBody 、ResponseBody类似。HttpEntit…

查询MySQL数据库中表结构的几种方法

mySQL: 方法一、二、三&#xff1a;是在本数据库中查询。 /** 方法一 **/ show columns from activity_station; /** 方法二 **/ desc activity_station; describe activity_station;/** 方法三 **/ show create table activity_station;方法四是在统计数据库中查询。 informa…

mysql 表结构查询的SQL语句

1、查看表结构 desc student;2、查看表的DDL语句 show create table student;3、查看列的结构信息 select column_name,data_type,column_comment,column_key,extra,character_maximum_length,is_nullable,column_default from information_schema.columns where table_sch…

mysql查看表结构 desc 表名;

查看表结构 语法&#xff1a;desc 表名;

MySQL之表结构

1.添加、删除字段 查看表结构 desc blog;show columns from blog;新增字段 alter table 表名 add 字段名 字段数据类型;alter table blog add age tinyint;删除字段 alter table 表名 drop 字段名;alter table blog drop age;重新添加age alter table blog add age tinyin…

mysql查看表结构和编码

show full columns from XXXXX

查看修改MySQL表结构命令

查看修改MySQL表结构命令 简述 小编经常会遇到一些数据库编码不对得问题&#xff0c;好TM头疼&#xff0c;这里做一个记录&#xff0c;供大家参考。 修改数据库字符集&#xff1a; ALTER DATABASE db_name DEFAULT CHARACTER SET character_name [COLLATE …]; 把表默认的字…

Mysql数据库常用表结构操作语句

目录 一、准备工作二、常用表结构操作语句1.在数据库表中新增 字段、约束1.1 新增字段1.2 新增约束 2.在数据库表中修改 表、字段2.1 修改表的名字2.2 修改字段名、数据类型、默认值、注释、自增属性 3.在数据库表中删除表、字段3.1 删除表3.2删除字段、字段约束 3.在数据库表中…

mysql 查询所有表结构_mysql数据库查看表结构

Mysql技术知识点 Mysql技术知识点,首先来讲一下Mysql语句精进安装数据库,然后导入tigerfive.sql。 sql见文档结尾部分MySQL示例数据库模式由以下表组成: customers: 存储客户的数据。 products: 存储汽车的数据。 productLines: 存储产品类别数据。 orde... 文章 好程序员 2…

linux mysql 结构_linux查看mysql数据表结构

展开全部 一、简单描述表结构&#xff0c;字段类型 desc tabl_name; 显示32313133353236313431303231363533e78988e69d8331333365636133表结构&#xff0c;字段类型&#xff0c;主键&#xff0c;是否为空等属性&#xff0c;但不显示外键。 例如&#xff1a;desc table_name 二、…

mysql查看表结构修改记录表_MySQL 表结构查看以及表结构修改

使用MySql数据库时&#xff0c;如果对表字典不够熟悉&#xff0c;我们就需要查看表结构。如果数据库是在远程linux上部署&#xff0c;很多时候我们只能通过mysql的命令来查看表结构。同样&#xff0c;如果我们想要修改表结构&#xff0c;添加、删除、修改列时&#xff0c;也只能…

mysql查看表描述_MySQL 查看表结构简单命令

一、简单描述表结构,字段类型 desc tabl_name; 显示表结构,字段类型,主键,是否为空等属性,但不显示外键。 例如:desc table_name 二、查询表中列的注释信息 select * from information_schema.columns where table_schema = db #表所在数据库 and table_name = tablename…

mysql查看表结构的几种方式

在我第N次忘记如何查看表结构后&#xff0c;在网上查了一下后&#xff0c;看到有好几种查看表结构的方式&#xff0c;总结一下。 以student&#xff08;sid,sname,birthday,sex&#xff09;的查看为例。 【方式一】&#xff1a;desc student; 语法&#xff1a;desc 表名;-----…

【Jon】连接Mysql数据库出现1046错误

问题&#xff1a;今天博主在使用Navicat12连接Mysql数据库的时候出现1046-UDAL-No database selected错误。 解决办法&#xff1a;直接换了一个版本的Navicat&#xff0c;就解决了问题。Nice^^

MYSQL 1064 错误

用MySQL执行批量插入数据&#xff0c;格式如下&#xff1a; declare i integer ; -- 定义变量begin i : 0000;loop /* 插入数据 */ insert into 表名 (字段1,字段2,... ) values (字段1值,字段2值,...); /* 参数递增 */ i : i 1;/* 停止条件 */ exit when i > 000111; …

【报错问题解决】MySQL创建表报错 ERROR 1046 (3D000): No database selected

【报错问题解决】MySQL创建表报错 ERROR 1046 : No database selected 问题概述原因解决方法 关于数据库和表的创建请参考文章 【手把手】MySQL创建数据库和表 问题概述 数据库已经创建 创建表的时候报错&#xff1a;ERROR 1046 (3D000): No database selected 原因 创建…

Mysql Workbench 插入数据提示错误:1046(ErrorCode:1046.No database select...)

Mysql Workbench 插入数据提示错误&#xff1a;1046&#xff08;ErrorCode&#xff1a;1046.No database select…&#xff09; 问题描述&#xff1a;初学者在使用Mysql Workbench向数据库添加数据过程中出现错误&#xff08;ErrorCode&#xff1a;1046.No database select…&…

已解决:Navicat 1046 - UDAL - No database selected

解决方法&#xff1a; 1、在常规选项中填入正确的数据库信息&#xff0c;测试连接通过。 2、在数据库选项中&#xff0c;勾选"使用自定义数据库列表">>添加数据库到列表>>输入数据库名>>确定。 3、搞定。

MySQL错误ERROR 1046 (3D000): No database selected解决办法

No database selected可以理解为没有选择种数据库 先在查看数据库种包括的database有哪些&#xff0c;选择自己要操作的数据 记住database后面一定加s 选择自己要操作那一个数据库(这样选择之后mysql>就和上面的不是同一个意思) 这样之后就可以操作数据库&#xff0c;所以…