简单封装 HTTP 请求
2017-2-19 更新到第二版:
源码地址:http://git.oschina.net/sp42/ajaxjs/tree/master/ajaxjs-base/src/com/ajaxjs/net?dir=1&filepath=ajaxjs-base%2Fsrc%2Fcom%2Fajaxjs%2Fnet
和文件操作一样,其内部使用了链式风格的调用方式。
GET/HEAD 请求
GET 请求用法参见下面的测试用例,包括普通 GET 请求、获取 302 重定向调转地址、获取资源文件体积大小、是否 404以及下载二进制文件等功能。
System.out.println(Client.GET("https://www.baidu.com/"));// 获取资源文件体积大小
long size = Client.getFileSize("http://c.csdnimg.cn/jifen/images/xunzhang/xunzhang/bokezhuanjiamiddle.png");
assertEquals(size, 4102L);
// 获取 302 重定向跳转地址
System.out.println(Client.get302redirect("https://baidu.com"));
// 封装 head 请求检测是否 404
assertTrue(!Client.is404("http://c.csdnimg.cn/jifen/images/xunzhang/xunzhang/bokezhuanjiamiddle.png"));
// B 站强制 Gzip 返回,無論请求是否带有 GZIP 字段
System.out.println(Client.GET_Gzip("http://www.bilibili.com/video/av5178498/"));
POST 请求
String url = "http://localhost:8080/pachong/post.jsp";
String result = Client.POST(url, new HashMap<String, Object>() {private static final long serialVersionUID = 1L;{put("foo", "bar");}
});
System.out.println("Feedback:" + result);
2016-7-12 : 新增 GZip 请求和 Gzip 响应判断。
请求判断
if(request.isEnableGzip()) // 是否启动 GZip 请求connection.addRequestProperty("Accept-Encoding", "gzip, deflate");
一般情况下,请求头加入了上面的 Accept-Encoding 字段,服务器才会对内容进行 GZip 压缩,否则就不压缩,原文输出。但有些网站是不管有没有这种请求都一概返回 GZIP 的。如果有 GZIP,服务器会告诉我们的,在响应头中加入 Content-Encoding 的字段。响应判断:
// 是否启动 GZip 请求// 有些网站强制加入 Content-Encoding:gzip,而不管之前的是否有 GZip 的请求boolean isGzip = request.isEnableGzip() || "gzip".equals(connection.getHeaderField("Content-Encoding"));
如果不对 Gzip 的内容进行 GZipInputStream 处理会一段乱码。
测试用例:
@Testpublic void testGZipGet() {Request request = new Request();request.setUrl("http://u.3gtv.net");request.setEnableGzip(true);RequestClient rc = new RequestClient(request);try {rc.connect();} catch (ConnectException e) {System.out.println("请求出错" + request.getUrl());}String html = request.getFeedback();System.out.println(html);assertNotNull(html);}// B 站强制 Gzip 返回,無論请求是否带有 GZIP@Testpublic void testForce_GZipGet() {String url = "http://www.bilibili.com/video/av5178498/";String html = Get.GET(url);System.out.println(html);assertNotNull(html);}
-------------------------------------------------------------------------------------------------------------
简单封装 Java 类库里面的 HttpURLConnection 来完成日常的 HTTP 请求,如 GET、HEAD、POST 等的请求。
GET 请求用法参见下面的测试用例,包括普通 GET 请求、获取 302 重定向调转地址、获取资源文件体积大小、是否 404以及下载二进制文件等功能。
import static org.junit.Assert.*;
import org.junit.Test;import java.io.IOException;import com.ajaxjs.net.http.Get;
import com.ajaxjs.util.FileUtil;public class TestGet {@Testpublic void testSimpleGET() {String url = "https://baidu.com";String html = Get.simpleGET(url);System.out.println(html);assertNotNull(html);}@Testpublic void testGet() {String url = "https://baidu.com";String html = Get.GET(url);System.out.println(html);assertNotNull(html);}@Testpublic void testGet302redirect() {String url = "http://baidu.com";String location = Get.get302redirect(url);System.out.println(location);assertNotNull(location);}@Testpublic void testIs404() {String url = "http://c.csdnimg.cn/jifen/images/xunzhang/xunzhang/bokezhuanjiamiddle.png";assertTrue(!Get.is404(url));assertTrue(Get.is404("http://www.qq.com/54543"));}@Testpublic void testGetFileSize() {String url = "http://c.csdnimg.cn/jifen/images/xunzhang/xunzhang/bokezhuanjiamiddle.png";long size = Get.getFileSize(url);assertEquals(size, 4102L);}@Testpublic void testDownload2disk() throws IOException {String url = "http://c.csdnimg.cn/jifen/images/xunzhang/xunzhang/bokezhuanjiamiddle.png";Get.download2disk(url, "c:/temp/dd.png");String saveTo = "c:/temp/js.js";Get.download2disk("http://bdimg.share.baidu.com/static/api/js/base/tangram.js?v=37768233.js", saveTo);assertNotNull(FileUtil.readFileAsText(saveTo));}}
Get.simpleGET 和 Get.GET 用法一致,传入 url 参数,返回该网址的文本内容。具体不同可能要看看源码。simpleGET 是原始 API 版, 一句话完事的:new URL(url).openStream(),然后把字符流转为 text 即可。Get.GET 也是字符流转为 text,只是前期处理上不是调 API,为自己实现逻辑,遵循了 bean 方式的调用。这种方式在咱们这个 HTTP 库里面的是通用方式。首先 Request 类是一个 Java bean,定义了请求地址 HTTP Url、请求方法 HTTP Mehtod,还有若干常见的 HTTP 头,都做成了 getter/setter,使用者按照 Request 类的方法调用即可。其次 GET 请求和 POST 请求本身就差别不少,因此划分为 Get/Post 两个类。但实际发出请求的是 RequestClient 类。这个类是不管哪种请求的,都是围绕后期 HTTP 响应作处理,主要是流的处理,以及一些诸如 404、超时异常的处理。下面是 RequestClient 源码:
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.UnknownHostException;import com.ajaxjs.util.FileUtil;
import com.ajaxjs.util.StringUtil;import sun.misc.BASE64Encoder;/*** 发起 HTTP 请求* @author frank**/
public class RequestClient {/*** 请求目标地址*/private URL url;/*** API 链接对象*/private HttpURLConnection connection;/*** 携带请求信息的 Bean*/private Request request;/*** 创建 HTTP 请求* * @param request* 请求信息对象*/public RequestClient(Request request) {this.request = request;try {url = new URL(request.getUrl());connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod(request.getMethod());} catch (IOException e) {System.err.println("初始化连接出错!" + request.getUrl());e.printStackTrace();}}/*** 内部初始化*/private void init() {connection.addRequestProperty("User-Agent", request.getUserAgent());connection.addRequestProperty("Referer", request.getUrl() == null ? url.getHost() : request.getUrl());connection.setConnectTimeout(request.getTimeout() * 1000);// 设置超时// connection.setReadTimeout(30000);if (request.getCookies() != null) {String cookieStr = StringUtil.HashJoin(request.getCookies(), ";");connection.setRequestProperty("Cookie", cookieStr);}if (request.getBasicAuthorization() != null) { // HTTP 用户认证String username = request.getBasicAuthorization()[0], password = request.getBasicAuthorization()[1];String encoding = new BASE64Encoder().encode((username + ":" + password).getBytes());connection.setRequestProperty("Authorization", "Basic " + encoding);}}/*** 发起请求* * @return true 表示为发起请求成功* @throws ConnectException*/public boolean connect() throws ConnectException {init();// 写入数据(POST ONLY, GET 不需要)if (request.getWriteData() != null && !request.getMethod().equalsIgnoreCase("GET")) {// 写入 POST 数据try (OutputStream os = connection.getOutputStream()) {os.write(request.getWriteData());os.flush();} catch (IOException e) {e.printStackTrace();return false;}}// 接受响应try (InputStream is = connection.getInputStream();) {if (connection.getResponseCode() >= 400) {// 如果返回的结果是400以上,那么就说明出问题了ConnectException e = null;if (connection.getResponseCode() < 500) {e = new ConnectException(connection.getResponseCode() + ":客户端请求参数错误!");} else {e = new ConnectException(connection.getResponseCode() + ":抱歉!我们服务端出错了!");}String msg = FileUtil.readText(is);e.setFeedback(msg);if (request.isTextResponse())request.setFeedback(msg);throw e;}if (request.getCallback() != null) {request.getCallback().onDataLoad(is);}if (request.isTextResponse())request.setFeedback(FileUtil.readText(is));} catch (UnknownHostException e) {throw new ConnectException("未知地址!" + request.getUrl());} catch (FileNotFoundException e) {throw new ConnectException("404 地址!" + request.getUrl());} catch (SocketTimeoutException e) {throw new ConnectException("请求地址超时!" + request.getUrl());} catch (IOException e) {try {System.out.println(connection.getResponseCode());} catch (IOException e1) {e1.printStackTrace();}throw new ConnectException("请求地址 IO 异常!" + request.getUrl());}return true;} public URL getUrl() {return url;}public void setUrl(URL url) {this.url = url;}public Request getRequest() {return request;}public void setRequest(Request request) {this.request = request;}public HttpURLConnection getConnection() {return connection;}public void setConnection(HttpURLConnection connection) {this.connection = connection;}}
其他源码就不张贴了,有兴趣的可以到这里看全部源码。
POST 例子不多,先放一个:
String url = "http://localhost:8080/pachong/post.jsp";
Request request = Post.POST(url, new HashMap<String, Object>() {private static final long serialVersionUID = 1L;{put("foo", "bar");}
});
System.out.println("Feedback:" + request.getFeedback());
assertNotNull(request);
assertTrue(request.isDone());
代码比较简单,应该没有什么晦涩的地方。请大家多给给意见。
简单封装 HTTP 请求相关推荐
- 小程序简单封装 request 请求
我在这里做了详细的介绍 : 小程序简单封装 request 请求 转载于:https://www.cnblogs.com/biangz/p/9984340.html
- 小程序基础开发(三):授权,获取用户信息,注册,登录,简单封装request请求
一,授权 1,首先在app.js里检测用户是否授权 // 查看是否授权wx.getSetting({success: function (res) {if (res.authSetting['scop ...
- PHP对接抖音小店接口的简单封装以及请求
简单分享一下PHP对接抖音小店的方法 首先需要配置一些公共的参数 踩到不少坑,需要有一起开发的互相学习. protected $app_key = "app_key"; // ...
- 模仿Retrofit封装一个使用更简单的网络请求框架
本文已授权微信公众号:郭霖 在微信公众号平台原创首发.会用Retrofit了?你也能自己动手写一个! 前言 想封装一套网络请求,不想直接上来就用别人写好的,或者说对项目可以更好的掌控,所以自己模仿着 ...
- Xamarin.Android之封装个简单的网络请求类
http://doc.okbase.net/catcher1994/archive/220195.html Catcher8 2016/4/23 0:28:50 阅读(72) 评论(0) 一.前言 回 ...
- 【跨域问题】Vue简单封装axios—解决post请求后端接收不到参数问题
原因分析: 1. 传参数据没有序列化? 解决办法: [推荐] [推荐阅读] vue+axios+qs序列化 "三步解析"[含demo实例]- 代码篇 2. 服务端接受数据格式参数配 ...
- Android APP更新下载工具类——简单封装DownloadManager
几乎所有APP都包含了检查更新功能,更新下载功能的实现方式常用的有两种:1.使用App网络框架的文件下载请求:2.使用自带的DownloadManager类:本文介绍第二种,简单封装一下Downloa ...
- App 组件化/模块化之路——如何封装网络请求框架
App 组件化/模块化之路--如何封装网络请求框架 在 App 开发中网络请求是每个开发者必备的开发库,也出现了许多优秀开源的网络请求库.例如 okhttp retrofit android-asyn ...
- Python接口自动化实战 ( 第一阶段) - 封装接口请求类和异常处理
1.封装http接口请求 已经实现了一个简单的接口请求,接下来就要考虑封装这个请求,在后面的用例中,只需要传递参数(URL ,Params,cookie,heade,method 等)每次去调用这个请 ...
最新文章
- 【Python进阶】带你使用Matplotlib进行可视化
- oracle 修改sgamaxsize_oracle初始化内存配置参数(sga,pga,sharepool)
- maven 报错一站式解决方案
- oracle rac 高并发性能_高并发业务下 JVM 涉及的垃圾回收与性能问题分析与定位...
- IIC 差异电平传输 和 IIC 地址
- BZOJ1305 [CQOI2009]dance跳舞 【网络流】
- Loopback for Mac(创建虚拟音频设备与音频编辑工具)
- YYLabel的若干个疑问持续更新
- python word转pdf linux_在Linux系统中把Pdf转化成word文档的软件
- 用免费新浪云sea搭建个人云服务器
- 列出叶节点 (二叉树的建立和BFS)
- 网吧无盘系统服务器安装,网吧网络无盘系统的安装方法
- dnf剑魂buff等级上限_DNF:国服鬼剑85版本以来的变迁,剑魂最惨,阿修罗起伏不大...
- SQL的update语句
- 继承(extends)
- 【ZZULIOJ】1011: 圆柱体表面积
- 【Practical】最小二乘与正规方程
- 【OpenCV】ChArUco标定板角点的检测Detection of ChArUco Corners
- Excel(Office)哪一版最好用?
- 互联网日报 | 8月7日 星期六 | 华为上半年销售收入3204亿元;微博宣布下线“明星势力榜”;小米平板5系列8月10日发布...
热门文章
- jQuery插件simplePagination的使用-踩坑记_03
- 云场景实践研究第74期:科沃斯
- 【GO语言】合理配置GOMAXPROCS提升一倍以上的性能
- 2.3. 实体(Core Data 应用程序实践指南)
- 微软职位内部推荐-Senior Software Engineer_Azure
- C#设置Cookies
- mysql版本 时间_【MySQL】MySQL版本时间线和MySQL各版本的区别
- 出问题 初始化ucosiii_STM32 ucosii 双堆栈初始化问题
- shell脚本——实现简单的功能
- A 01 如何理解会计中的借和贷