概述
由来
在Java的世界中,Http客户端之前一直是Apache家的HttpClient占据主导,但是由于此包较为庞大,API又比较难用,因此并不使用很多场景。而新兴的OkHttp、Jodd-http固然好用,但是面对一些场景时,学习成本还是有一些的。很多时候,我们想追求轻量级的Http客户端,并且追求简单易用。而JDK自带的HttpUrlConnection可以满足大部分需求。Hutool针对此类做了一层封装,使Http请求变得无比简单。
介绍
Hutool-http针对JDK的HttpUrlConnection做一层封装,简化了HTTPS请求、文件上传、Cookie记忆等操作,使Http请求变得无比简单。
Hutool-http的核心集中在两个类:
- HttpRequest
- HttpResponse
Hutool-http优点
- 根据URL自动判断是请求HTTP还是HTTPS,不需要单独写多余的代码。
- 表单数据中有File对象时自动转为
multipart/form-data
表单,不必单做做操作。 - 默认情况下Cookie自动记录,比如可以实现模拟登录,即第一次访问登录URL后后续请求就是登录状态。
- 自动识别304跳转并二次请求
- 自动识别页面编码,即根据header信息或者页面中的相关标签信息自动识别编码,最大可能避免乱码。
- 自动识别并解压Gzip格式返回内容
使用
最简单的使用莫过于用HttpUtil工具类快速请求某个页面:
一行代码即可搞定,当然Post请求也很简单://GET请求
String content = HttpUtil.get(url);
Post请求只需使用Map预先制定form表单项即可。//POST请求
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("city", "北京");
String result1 = HttpUtil.post(url, paramMap);
更多
根据Hutool的“便捷性与灵活性并存”原则,HttpUtil的存在体现了便捷性,那HttpRequest对象的使用则体现了灵活性,使用此对象可以自定义更多的属性给请求,以适应Http请求中的不同场景(例如自定义header、自定义cookie、自定义代理等等)。相关类的使用请见下几个章节。Http客户端工具类-HttpUtil
概述
HttpUtil是应对简单场景下Http请求的工具类封装,此工具封装了HttpRequest对象常用操作,可以保证在一个方法之内完成Http请求。
此模块基于JDK的HttpUrlConnection封装完成,完整支持https、代理和文件上传。
使用
请求普通页面
针对最为常用的GET和POST请求,HttpUtil封装了两个方法,
HttpUtil.get
HttpUtil.post
这两个方法用于请求普通页面,然后返回页面内容的字符串,同时提供一些重载方法用于指定请求参数(指定参数支持File对象,可实现文件上传,当然仅仅针对POST请求)。
GET请求栗子:
// 最简单的HTTP请求,可以自动通过header等信息判断编码,不区分HTTP和HTTPS
String result1= HttpUtil.get("https://www.baidu.com");
// 当无法识别页面编码的时候,可以自定义请求页面的编码
String result2= HttpUtil.get("https://www.baidu.com", CharsetUtil.CHARSET_UTF_8);
//可以单独传入http参数,这样参数会自动做URL编码,拼接在URL中
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("city", "北京");
String result3= HttpUtil.get("https://www.baidu.com", paramMap);
POST请求例子:
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("city", "北京");
String result= HttpUtil.post("https://www.baidu.com", paramMap);
文件上传
HashMap<String, Object> paramMap = new HashMap<>();
//文件上传只需将参数中的键指定(默认file),值设为文件对象即可,对于使用者来说,文件上传与普通表单提交并无区别
paramMap.put("file", FileUtil.file("D:\\face.jpg"));
String result= HttpUtil.post("https://www.baidu.com", paramMap);
下载文件
因为Hutool-http机制问题,请求页面返回结果是一次性解析为byte[]的,如果请求URL返回结果太大(比如文件下载),那内存会爆掉,因此针对文件下载HttpUtil单独做了封装。文件下载在面对大文件时采用流的方式读写,内存中只是保留一定量的缓存,然后分块写入硬盘,因此大文件情况下不会对内存有压力。
String fileUrl = "http://mirrors.sohu.com/centos/7.3.1611/isos/x86_64/CentOS-7-x86_64-DVD-1611.iso";
//将文件下载后保存在E盘,返回结果为下载文件大小
long size = HttpUtil.downloadFile(fileUrl, FileUtil.file("e:/"));
System.out.println("Download size: " + size);
当然,如果我们想感知下载进度,还可以使用另一个重载方法回调感知下载进度:
//带进度显示的文件下载
HttpUtil.downloadFile(fileUrl, FileUtil.file("e:/"), new StreamProgress(){
@Override
public void start() {
Console.log("开始下载。。。。");
}
@Override
public void progress(long progressSize) {
Console.log("已下载:{}", FileUtil.readableFileSize(progressSize));
}
@Override
public void finish() {
Console.log("下载完成!");
}
});
StreamProgress接口实现后可以感知下载过程中的各个阶段。
当然,工具类提供了一个更加抽象的方法:HttpUtil.download
,此方法会请求URL,将返回内容写入到指定的OutputStream中。使用这个方法,可以更加灵活的将HTTP内容转换写出,以适应更多场景。
更多有用的工具方法
HttpUtil.encodeParams
对URL参数做编码,只编码键和值,提供的值可以是url附带参数,但是不能只是urlHttpUtil.toParams
和HttpUtil.decodeParams
两个方法是将Map参数转为URL参数字符串和将URL参数字符串转为Map对象HttpUtil.urlWithForm
是将URL字符串和Map参数拼接为GET请求所用的完整字符串使用HttpUtil.getMimeType
根据文件扩展名快速获取其MimeType(参数也可以是完整文件路径)更多请求参数
如果想设置头信息、超时、代理等信息,请见下一章节《Http客户端-HttpRequest》。Http请求-HttpRequest
介绍
本质上,HttpUtil中的get和post工具方法都是HttpRequest对象的封装,因此如果想更加灵活操作Http请求,可以使用HttpRequest。
使用
普通表单
我们以POST请求为例:
//链式构建请求
String result2 = HttpRequest.post(url)
.header(Header.USER_AGENT, "Hutool http")//头信息,多个头信息多次调用此方法即可
.form(paramMap)//表单内容
.timeout(20000)//超时,毫秒
.execute().body();
Console.log(result2);
通过链式构建请求,我们可以很方便的指定Http头信息和表单信息,最后调用execute方法即可执行请求,返回HttpResponse对象。HttpResponse包含了服务器响应的一些信息,包括响应的内容和响应的头信息。通过调用body方法即可获取响应内容。
Restful请求
String json = ...;
String result2 = HttpRequest.post(url)
.body(json)
.execute().body();
其它自定义项
同样,我们通过HttpRequest可以很方便的做以下操作:
- 指定请求头
- 自定义Cookie(cookie方法)
- 指定是否keepAlive(keepAlive方法)
- 指定表单内容(form方法)
- 指定请求内容,比如rest请求指定JSON请求体(body方法)
- 超时设置(timeout方法)
- 指定代理(setProxy方法)
- 指定SSL协议(setSSLProtocol)
- 简单验证(basicAuth方法)
Http响应-HttpResponse
介绍
HttpResponse是HttpRequest执行execute()方法后返回的一个对象,我们可以通过此对象获取服务端返回的:
- Http状态码(getStatus方法)
- 返回内容编码(contentEncoding方法)
- 是否Gzip内容(isGzip方法)
- 返回内容(body、bodyBytes、bodyStream方法)
- 响应头信息(header方法)
使用
此对象的使用非常简单,最常用的便是body方法,会返回字符串Http响应内容。如果想获取byte[]则调用bodyBytes即可。获取响应状态码
HttpResponse res = HttpRequest.post(url)..execute();
Console.log(res.getStatus());
获取响应头信息
HttpResponse res = HttpRequest.post(url)..execute();
//预定义的头信息
Console.log(res.header(Header.CONTENT_ENCODING));
//自定义头信息
Console.log(res.header("Content-Disposition"));
常用Http状态码-HttpStatus
介绍
针对Http响应,Hutool封装了一个类用于保存Http状态码
此类用于保存一些状态码的别名,例如:
/**
* HTTP Status-Code 200: OK.
*/
public static final int HTTP_OK = 200;
UA工具类-UserAgentUtil
由来
User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、浏览器及版本、浏览器渲染引擎等。
Hutool在4.2.1之后支持User-Agent的解析。
使用
以桌面浏览器为例,假设你已经获取了用户的UA:
String uaStr = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1";
获取UA信息
我们可以借助UserAgentUtil.parse
方法解析:
UserAgent ua = UserAgentUtil.parse(uaStr);
ua.getBrowser().toString();//Chrome
ua.getVersion();//14.0.835.163
ua.getEngine().toString();//Webkit
ua.getEngineVersion();//535.1
ua.getOs().toString();//Windows 7
ua.getPlatform().toString();//Windows
判断终端是否为移动终端
ua.isMobile();
常见问题
Received fatal alert: handshake_failure 错误
用户错误如图,场景为使用Hutool-http请求https服务器,原因是JDK中的JCE安全机制导致的问题解决方法如下:
- 方法1:如果你使用的是JDK8,请升级到JDK8的最新版本(例如jdk1.8.0_181)。
- 方法2:尝试添加以下代码:
System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");