ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

从源码研究实现Java发送get和post请求

2021-04-14 13:57:48  阅读:236  来源: 互联网

标签:Java 请求 get 对象 client httpPost 源码 response String


一、get和post的一些基础知识

get请求:

  1. 原理:get请求本质上是去数据库里面查资源;

  2. 表现形式:请求数据会依附在url只有,以?分割,参数与参数之间以&符号相连,请求参数最多只能是1024个字节;

  3. 提交形式:请求和header一起发出;

  4. 安全性:安全性低,参数明文传输。

post请求:

  1. 原理:post请求本质是向数据库提交数据,增删改操作;

  2. 表现形式:提交的数据放在http的body体内,http协议对post请求的参数大小没有限制,但是不排除各大浏览器自己会做限制;

  3. 提交形式:请求header先发出,收到服务器返回的response header后,body再发出;

  4. 安全性:相对get请求,post请求的请求参数放在body体内相对安全一些,涉及用户登录密码和金钱相关的数据要特别注意加密处理。

二、http协议和https协议

二者的区别:

  1. http协议:超文本传输协议,且信息是明文传输;若攻击者截取客户端和服务器之间的传输报文,就可以获取用户信息,不安全;
  2. https协议:是具有安全性的ssl加密传输协议,为客户端和服务器之间的通信加密,确保数据传输安全。
  3. http结构:http–tcp–ip;https结构:http–ssl–tcp–ip;
  4. http协议连接简单,是无状态的;https是有ssl+http协议构建的加密传输、身份认证的网络协议;
  5. http协议的端口是80;https协议的端口是443;
  6. http证书申请免费,https证书需要到ca申请,需要交费。

三、Java-HTTPclient官方网站

2.1 官网地址:

http://hc.apache.org/httpcomponents-client-4.5.x/quickstart.html

2.2 eclipse中maven工程在pom.xml中配置HTTPclient依赖

<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
		<dependency>
		    <groupId>org.apache.httpcomponents</groupId>
		    <artifactId>httpclient</artifactId>
		    <version>4.5.6</version>
		</dependency>

四、java发送get请求

  • A. 定义一个HTTPClients类的对象client,用来执行发送请求操作。类似于是一个浏览器的driver,client执行完发送请求的操作后,服务端返回的cookie(和session)信息会存储在client中;
    • A.1 取cookie过程需要在定义client时调用另一个类方法,即方法:HttpClients.custom()方法,它的返回值类型是HttpClientBuilder,最后通过研究这个源码类使用以下两行代码得到CookieStore对象存储服务器返回的session值,这个值存放在cookie中;
CookieStore cookieStore = new BasicCookieStore();
client = HttpClients.custom().setDefaultCookieStore(cookieStore).build();

如果想要输出cookie信息,则需要注意两点:
1、输出cookie信息的操作要在执行请求后,即服务器返回结果后,在关闭response和client对象之前;
2、通过cookieStore.getCookies()方法得到的是一个List对象,数组的输出通过for循环即可得到结果。

  • B. 定义一个HTTPGet类的对象httpGet,用来携带需要发送的信息,例如请求url、请求头header信息、请求超时等信息;
    • B.1 请求url:初始化时,调用HttpGet类的构造方法时传参实现。get请求url是接口地址和请求参数拼接组成,代码中第5行;
    • B.2 请求头header信息:通过拿到的httpGet对象,向上转型到HttpMessage源码类,调用HttpMessage源码类中的setHeader(final String name, final String value)方法,该方法已经在子类中被覆写,子类是:AbstractHttpMessage;
    • B.3 请求超时 通过HttpGet对象向上转型调用父类HttpRequestBase源码类中的setConfig(final RequestConfig config)方法添加到httpGet对象中,其中setConfig()方法中传参是RequestConfig类型,通过研究RequestConfig这个源码类就可设置成功超时时间,调用的是setConnectionRequestTimeout(final int connectionRequestTimeout)方法;
  • C. 准备好发送请求的数据后,使用client.execute(httpGet)发送请求,得到对象response,是CloseableHttpResponse类型,我们想要是String或者Json类型结构的数据,还没达到目标;
  • D. 判断response.getStatusLine().getStatusCode()是否返回的时200,当是200时证明服务器返回正常,我们再通过response.getEntity()方法得到一个HttpEntity类型的返回对象entity;
  • E. 最后通过EntityUtils工具类中的EntityUtils.toString(entity, “utf-8”)方法把上一步得到的entity对象转化成String类型,返回结果;
  • F. 最最后,我们要恢复环境执行response.close()和client.close()。

简单封装后的发送get请求整个过程代码如下:

public static void sendGet(String url, String param) throws Exception {
		String result = null;
		CloseableHttpClient client = null;
		CloseableHttpResponse response = null;
		String finUrl = url + "?" + param;
		try {
			client = HttpClients.createDefault();
			HttpGet httpGet = new HttpGet(finUrl);
			
			//设置请求头
			httpGet.setHeader("Content-Type", "application/json; charset=utf-8");
			httpGet.setHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36");
			
			//设置请求超时 
			Builder builder = RequestConfig.custom();
    		builder.setConnectionRequestTimeout(3000);
			RequestConfig config = builder.build();
			httpGet.setConfig(config);
			httpGet.setConfig(RequestConfig.custom().setConnectionRequestTimeout(3000).build());
			
			response = client.execute(httpGet);
			int code = response.getStatusLine().getStatusCode();
   
			if (code == HttpStatus.SC_OK) {
				HttpEntity entity = response.getEntity();
				result = EntityUtils.toString(entity, "utf-8");
			}else {
				result = "服务器状态码为:" + code + " ,请检查接口地址和请求参数。";
			}	
		}finally {
			response.close();
			client.close();
		}
		return result;
	}

五、java发送post请求

  • A. 定义一个HTTPClients类的对象client,用来执行发送请求操作。类似于是一个浏览器的driver,client执行完发送请求的操作后,服务端返回的cookie(和session)信息会存储在client中;
  • B. 定义一个HTTPGet类的对象httpPost,用来携带需要发送的信息,例如请求url、请求头header信息、请求超时等信息;
  • C. 准备请求参数,post请求参数存放在请求body体内,如果使用官网方法,需要传参为NameValuePair类型的数据,即官网示例如下:
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("username", "vip"));
nvps.add(new BasicNameValuePair("password", "secret"));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));

因为我们正常提供的测试case,在param字段中一般存String类型,所以找传String类型的请求参数,放到httpPost对象中(通过httpPost.setEntity()方法),携带发送请求。经过研究发现httpPost.setEntity()方法的入参是HttpEntity源码类的对象,但是HttpEntity是个接口,只能通过实例化子类来得到父类对象,找到StringEntity源码类,发现使用这个源码类中的其中一个构造方法,可以传String类型的参数,new子类通过向上转型,从而得到HttpEntity的对象,到此我们把sendPost方法中的String param字段添加到了httpPost对象内;

  • D. 准备好发送请求的数据后,使用client.execute(httpPost)发送请求,得到对象response,是CloseableHttpResponse类型,我们想要是String或者Json类型结构的数据,还没达到目标;
  • E. 判断response.getStatusLine().getStatusCode()是否返回的时200,当是200时证明服务器返回正常,我们再通过response.getEntity()方法得到一个HttpEntity类型的返回对象entity;
  • F. 最后通过EntityUtils工具类中的EntityUtils.toString(entity, “utf-8”)方法把上一步得到的entity对象转化成String类型,返回结果;
  • G. 最最后,我们要恢复环境执行response.close()和client.close()。

简单封装后的发送post请求整个过程代码如下:

public static String sendPost(String url, String param) throws Exception {
		String result = null;
		CloseableHttpClient client = null;
		CloseableHttpResponse response = null;
		try {
			client = HttpClients.createDefault();
			HttpPost httpPost = new HttpPost(url);
			//设置请求头
			httpPost.setHeader("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148");
			httpPost.setHeader("Content-Type", "application/json");
			
			//设置请求超时 
			Builder builder = RequestConfig.custom();
			builder.setConnectionRequestTimeout(3000);
			RequestConfig config = builder.build();
			httpPost.setConfig(config);
			httpPost.setConfig(RequestConfig.custom().setConnectionRequestTimeout(3000).build());
			
			//设置post请求参数
//			List<NameValuePair> nvps = new ArrayList<NameValuePair>();
//			BasicNameValuePair bnvp = new BasicNameValuePair(null, null);
			// 直接添加NameValuePair类型的数据 遇到一级value下又有多级数据时也是直接写入吗?例如:"h_ids": {"idfa": "0CB4E1A5-1782-4F31-8B30-0218453BBCBE"}
//			nvps.add(new BasicNameValuePair("name", "zhaoliu"));
//			httpPost.setEntity(new UrlEncodedFormEntity(nvps));
			
                   //入参是HttpEntity类型,HTTPEntity是个接口,需要通过子类实例化得到父类对象,找HTTPEntity的实现类,StringEntity
//			httpPost.setEntity(HTTPEntity httpEntity);
			httpPost.setEntity(new StringEntity(param, "utf-8"));
			
			// 执行发送请求操作
			response = client.execute(httpPost);
			int code = response.getStatusLine().getStatusCode();
			
			if (code == HttpStatus.SC_OK) {
				HttpEntity entity = response.getEntity();
				result = EntityUtils.toString(entity, "utf-8");
			}else {
				result = "服务器状态码为:" + code + " ,请检查接口地址和请求参数。";
			}
		}finally {
			response.close();
			client.close();
		}
		return result;
	}

六、总结

6.1 不管发送post请求还是get请求,都需要先定义CloseableHttpClient的对象client。client对象可以生成一个CookieStore的对象管理和存储header的cookie和服务器返回的session信息,即cookie和session信息是在client对象这里操作的;

6.2 得到HttpGet或者HttpPost对象后,我们要设置的请求超时、请求header数据都是在这一步生成和操作的;

6.3 get请求的参数通过拼接即可实现,但post请求的请求参数是在body体内的,要通过httpPost.setEntity(new StringEntity(param, “utf-8”))代码绑定到HttpPost的对象上;

6.4 以上三步准备好之后,通过client.excute(httpPost) / client.excute(httpGet)拿到CloseableHttpResponse类型的一个返回值,我们初步拿到了服务器的返回结果;

6.5 对服务器返回结果做处理,通过response.getEntity()方法把返回结果转化成HttpEntity类型,最后通过EntityUtils工具类中的toString()方法把服务器返回的结果转化成我们常见的String类型;

6.6 最后就是善后工作,关闭response对象,关闭client对象。

赶快自己去实验一下吧!
中间的一些源码转换没有详细记录,哪里看不太懂欢迎和我交流!

标签:Java,请求,get,对象,client,httpPost,源码,response,String
来源: https://blog.csdn.net/weixin_44332139/article/details/115696174

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有