HttpClient、HttpURLConnection协议访问网络
一:HttpClient简介
HttpClient是什么?
HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包。
尽管java.net软件包提供了用于通过HTTP访问资源的基本功能,但它并未提供许多应用程序所需的全部灵活性或功能。HttpClient试图通过提供高效,最新且功能丰富的程序包来实现此空白,以实现最新HTTP标准和建议的客户端。
- httpclient官方网址:http://hc.apache.org/httpcomponents-client-5.0.x/quickstart.html
主要功能介绍
- 实现了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
- 支持自动转向
- 支持 HTTPS 协议
- 支持代理服务器等
使用前的准备工作
创建一个maven项目并且导入依赖
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.12</version>
</dependency>
使用 HttpClient 需要以下 6 个步骤:
-
创建 HttpClient 的实例,下面要使用这个实例执行get/post请求
CloseableHttpClient httpClient = HttpClients.createDefault();
-
创建http协议的get实例
HttpGet httpGet = new HttpGet("https://www.baidu.com");
-
使用httpclient实例执行get请求
CloseableHttpResponse response = httpClient.execute(httpGet);
-
解析 response,获取返回实体
HttpEntity entity = response.getEntity();
-
获取网页内容
EntityUtils.toString(entity, "utf-8");
-
释放连接。无论执行方法是否成功,都必须释放连接
response.close(); httpClient.close();
public static void main(String[] args) {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("https://www.tuicool.com");
httpGet.setHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0");
try {
CloseableHttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
String string = EntityUtils.toString(entity, "GB2312");
System.out.println("网页内容:"+string);
response.close();
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
获取网页源码可能遇到的问题:
- 乱码 :jb51.net
- 被网站拦截:tuicool.com
二:HttpURLConnection简介
HttpURLConnection是什么?
HttpURLConnection是java的标准指定网站发送GET请求、post请求的一个类。HttpURLConnection继承自URLConnection,可用于向指定网站发送GET请求、post请求,HttpURLConnection在使用上相对简单,并且易于扩展,推荐使用。
关于HttpClient和HttpURLConnection故事
大多数的Android应用程序都会使用HTTP协议来发送和接收网络数据,而Android中主要提供了两种方式来进行HTTP操作:HttpURLConnection和HttpClient,这两种方式都支持HTTPS协议、以流的形式进行上传和下载、配置超时时间、IPv6、以及连接池等功能。
尽管网上很多人很推崇HttpClient,但Google官方对HttpClient并不感冒,在Android5.1后废止了HttpClient的Api。DefaultHttpClient和它的兄弟AndroidHttpClient都是HttpClient具体的实现类,它们都拥有众多的API,而且实现比较稳定,bug数量也很少,但同时也由于HttpClient的API数量过多,使得我们很难在不破坏兼容性的情况下对它进行升级和扩展。而HttpURLConnection是一种多用途、轻量极的HTTP客户端,使用它来进行HTTP操作可以适用于大多数的应用程序,虽然HttpURLConnection的API提供的比较简单,但是同时这也使得我们可以更加容易地去使用和扩展它。
在Android 2.2版本之前,HttpClient拥有较少的bug,因此使用它是最好的选择。而在Android 2.3版本及以后,HttpURLConnection则是最佳的选择。HttpURLConnection的API简单、体积较小,因而非常适用于Android项目,压缩和缓存机制可以有效地减少网络访问的流量,在提升速度和省电方面也起到了较大的作用,对于新的Android应用程序应该更加偏向于使用HttpURLConnection。
转自博客:https://blog.csdn.net/u011150924/article/details/52763443
更推荐使用HttpURLConnection原因:
HttpURLConnection相较于HttpClient的API更简单、体积更小,而且更容易升级拓展。
Get基本用法
-
创建一个URL对象,传入url地址
URL url = new URL(HTTP_ADDRESS);
-
调用URL对象的openConnection()方法 来获取HttpURLConnection对象的实例
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
-
配置一些发送请求的基本参数,可以是get/post或者其他的
urlConnection.setRequestMethod("GET"); urlConnection.setConnectTimeout(8 * 1000);
-
调用getInputstream()方法获得服务器返回的输入流
InputStream inputStream = urlConnection.getInputStream();
-
将流数据转化为字符串
String res = InputStreamUtils.parseIsToString(inputStream);
-
最后调用disconnect()方法将HTTP连接断掉。
urlConnection.disconnect();
代码如下:
/** 访问网络,获取网络源码方法 */
private void getHttpText() {
//创建一个URL对象,传入url地址
URL url = new URL(HTTP_ADDRESS);
//调用URL对象的openConnection()方法 来获取HttpURLConnection对象的实例
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//配置一些发送请求的基本参数
urlConnection.setRequestMethod("GET");
urlConnection.setConnectTimeout(8 * 1000);//超时时长的限制,因为发送请求不能无限制的等待,超过这个时间就算没有请求成功
//获取请求到的数据,得到的是一个流类型的数据
InputStream inputStream = urlConnection.getInputStream();
//将流数据转化为字符串
final String res = InputStreamUtils.parseIsToString(inputStream);
huc_tv.setText(res);
//断开连接
urlConnection.isconnect();
}
-
将流转化为字符串的工具类
public class InputStreamUtils { public static String parseIsToString(InputStream inputStream) throws IOException { StringBuilder builder = new StringBuilder(); String line; BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); while((line = bufferedReader.readLine())!=null){ builder.append(line); } String string = builder.toString(); return string; } }
Post基本用法
-
创建一个URL对象,传入url地址
URL url = new URL(HTTP_ADDRESS);
-
调用URL对象的openConnection()方法 来获取HttpURLConnection对象的实例
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
-
配置一些发送请求的基本参数
urlConnection.setRequestMethod("POST"); // 指定使用POST请求方式 urlConnection.setConnectTimeout(8 * 1000);//超时时间 urlConnection.setDoInput(true); // 向连接中写入数据 urlConnection.setDoOutput(true); // 从连接中读取数据 urlConnection.setUseCaches(false); // 禁止缓存 urlConnection.setInstanceFollowRedirects(true); //自动执行HTTP重定向 urlConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); // 设置内容类型
-
调用getOutputstream()方法获得服务器返回的输出流
DataOutputStream out = new DataOutputStream(urlConnection.getOutputStream()); // 获取输出流
-
连接要提交的数据
String param = "chat=" + URLEncoder.encode(string, "utf-8");
-
将要传递的数据写入数据输出流
out.writeBytes(param);
-
最后关闭连接和流
out.flush(); //输出缓存 out.close(); //关闭数据输出流 urlConnection.disconnect(); //断开连接
代码如下:
URL url = new URL(HTTP_ADRESS);
//调用URL对象的openConnection()方法 来获取HttpURLConnection对象的实例
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST"); // 指定使用POST请求方式
urlConnection.setDoInput(true); // 向连接中写入数据
urlConnection.setDoOutput(true); // 从连接中读取数据
urlConnection.setUseCaches(false); // 禁止缓存
urlConnection.setInstanceFollowRedirects(true); //自动执行HTTP重定向
urlConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); // 设置内容类型
DataOutputStream out = new DataOutputStream(urlConnection.getOutputStream()); // 获取输出流
String param = "chat=" + URLEncoder.encode(string, "utf-8"); //连接要提交的数据
Log.i(TAG, "param的内容: " + param);
out.writeBytes(param);//将要传递的数据写入数据输出流
out.flush(); //输出缓存
out.close(); //关闭数据输出流
urlConnection.disconnect(); //断开连接
Get和Post的区别
-
get参数通过url传递,post放在request body中。
-
get请求在url中传递的参数长度受浏览器限制的,而post没有。
-
get比post更不安全,因为参数直接暴露在url中,所以不能用来传递敏感信息。
在android中使用可能遇到的问题:
-
显示报错:NetworkOnMainThreadException,(网络操作在主线程上发生的一个异常)
所以说,网络操作不能够写在主线程上
那么为什么?
因为网络操作是一个耗时的操作,所以不能写在主线程上,因为它会阻塞主线程的执行,会让软件变卡
-
报错: Only the original thread that created a view hierarchy can touch its views.(原始的界面才能创建一个视图或者更改或使用它)
所以说,子线程是不能够更新界面信息的
解决办法: 用runOnUiThread,实现异步的效果,可以解决这个问题,把修改视图的代码写在它里面