网站首页 > 精选教程 正文
最近面试的时候,竟然有面试官提出这样的要求:请用Java实现一个HTTP请求!当然不能怂! 雄起!!!
今天将介绍一种在 Java 中执行 HTTP 请求的方法 -- 通过使用 Java 内置的 HttpUrlConnection 类实现。
从 JDK 11 开始,Java 为执行 HTTP 请求提供了一个新的 API,它是用来替代 HttpUrlConnection 的,即HttpClient API。
HttpUrlConnection
HttpUrlConnection 类允许我们执行基本的 HTTP 请求,而无需使用任何额外的库。我们需要的所有类都是 java.net 包的一部分。
使用这种方法的缺点是,代码可能比其他的HTTP库更繁琐,而且它不提供更高级的功能,如添加头文件或认证的专用方法。
创建一个请求
我们可以使用 URL 类的 openConnection() 方法创建一个 HttpUrlConnection 实例。注意,这个方法只是创建一个连接对象,但还没有建立连接。
HttpUrlConnection 类通过将 requestMethod 属性设置为get, post, head, options, put, delete, trace其中一个值。
让我们使用GET方法创建一个与给定URL的连接:
URL url = new URL("https://www.javanorth.cn");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
添加请求参数
如果我们想向一个请求添加参数,我们必须将 doOutput 属性设置为 true,然后向 HttpUrlConnection 实例的OutputStream 写一个类似 param1=value&m2=value 的字符串。
Map<String, String> parameters = new HashMap<>();
parameters.put("param1", "val");
con.setDoOutput(true);
DataOutputStream out = new DataOutputStream(con.getOutputStream());
out.writeBytes(ParameterStringBuilder.getParamsString(parameters));
out.flush();
out.close();
为了方便参数Map的转换,我们编写了一个名为ParameterStringBuilder的实用类,其中包含一个静态方法getParamsString(),可以将Map转换为所需格式的字符串。
public class ParameterStringBuilder {
public static String getParamsString(Map<String, String> params)
throws UnsupportedEncodingException{
StringBuilder result = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
result.append("&");
}
String resultString = result.toString();
return resultString.length() > 0 ? resultString.substring(0, resultString.length() - 1) : resultString;
}
}
设置请求头信息
通过使用 setRequestProperty() 方法可以实现在请求中添加头信息。
con.setRequestProperty("Content-Type", "application/json");
要从一个连接中读取一个头的值,我们可以使用 getHeaderField() 方法。
String contentType = con.getHeaderField("Content-Type");
配置超时
HttpUrlConnection 类允许设置连接和读取超时。这些值定义了等待与服务器的连接建立或数据可被读取的时间间隔。
为了设置超时值,我们可以使用 setConnectTimeout()和 setReadTimeout()方法。
con.setConnectTimeout(5000);
con.setReadTimeout(5000);
在这个例子中,我们把两个超时值都设为5秒。
处理Cookie
java.net 包包含了便于处理 cookie 的类,如 CookieManager 和 HttpCookie。
首先,为了从响应中读取 cookie,我们可以检索 Set-Cookie 头的值,并将其解析为一个 HttpCookie 对象的列表。
String cookiesHeader = con.getHeaderField("Set-Cookie");
List<HttpCookie> cookies = HttpCookie.parse(cookiesHeader);
接下来,我们将把cookie添加到cookieStore。
cookies.forEach(cookie -> cookieManager.getCookieStore().add(null, cookie));
让我们检查一下是否有一个叫做 username 的 cookie,如果没有,我们将把它添加到cookieStore,其值为 "javanorth"。
Optional<HttpCookie> usernameCookie = cookies.stream().findAny().filter(cookie -> cookie.getName().equals("username"));
if (usernameCookie == null) {
cookieManager.getCookieStore().add(null, new HttpCookie("username", "javanorth"));
}
最后,为了在请求中加入 cookie,我们需要在关闭和重新打开连接后设置 Cookie 头。
con.disconnect();
con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("Cookie", StringUtils.join(cookieManager.getCookieStore().getCookies(), ";"));
处理重定向
我们可以通过使用参数为 true 或 false 的 setInstanceFollowRedirects() 方法,为一个特定的连接启用或禁用自动跟踪重定向。
con.setInstanceFollowRedirects(false);
也可以启用或禁用所有连接的自动重定向。
HttpUrlConnection.setFollowRedirects(false);
默认情况下,该行为是启用的。
当一个请求返回状态代码 301 或 302,表示重定向时,我们可以检索位置头并创建一个新的请求到新的URL。
if (status == HttpURLConnection.HTTP_MOVED_TEMP || status == HttpURLConnection.HTTP_MOVED_PERM) {
String location = con.getHeaderField("Location");
URL newUrl = new URL(location);
con = (HttpURLConnection) newUrl.openConnection();
}
读取响应
读取请求的响应可以通过解析 HttpUrlConnection 实例的 InputStream 来完成。
为了执行请求,我们可以使用 getResponseCode()、connect()、getInputStream() 或 getOutputStream() 方法。
int status = con.getResponseCode();
最后,让我们读一下请求的响应,并把它放在一个内容字符串中。
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer content = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
in.close();
要关闭连接,我们可以使用 disconnect() 方法。
con.disconnect();
在失败的请求中读取响应
如果请求失败了,我们从 HttpUrlConnection 实例的 InputStream 读取是读取不到数据的。我们可以从 HttpUrlConnection.getErrorStream() 提供的流读取。
我们可以通过比较 HTTP 状态码来决定使用哪个 InputStream。
int status = con.getResponseCode();
Reader streamReader = null;
if (status > 299) {
streamReader = new InputStreamReader(con.getErrorStream());
} else {
streamReader = new InputStreamReader(con.getInputStream());
}
最后,我们可以用与上一节相同的方式读取 streamReader。
总结
在这篇文章中,我们展示了如何使用 HttpUrlConnection 类来执行HTTP请求。
猜你喜欢
- 2024-11-05 关于 URL,说几个你不知道的点 url各部分含义
- 2024-11-05 避免自己写的 url 被diss!建议看看这篇RESTful API简明教程!
- 2024-11-05 IntelliJ IDEA 15款 神级超级牛逼插件推荐
- 2024-11-05 学习SpringMVC——如何获取请求参数
- 2024-11-05 java验证码生成(一) java生成验证码并验证
- 2024-11-05 Nice,终于有人把SpringMVC讲明白了,太简单了...
- 2024-11-05 Java代理IP设置指南:让你的网络请求更灵活
- 2024-11-05 请说说RPC的一个请求的流程是怎么样的?
- 2024-11-05 Javaweb 演示session的URL重写 java sessionid
- 2024-11-05 springboot2.2.X手册:构建全局唯一的短链接数据中心
你 发表评论:
欢迎- 04-11Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- 04-11Java中你知道几种从字符串中找指定的字符的数量
- 04-11探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- 04-11Python字符串详解与示例(python字符串的常见操作)
- 04-11java正则-取出指定字符串之间的内容
- 04-11String s1 = new String("abc");这句话创建了几个字符串对象?
- 04-11java判断字符串中是否包含某个字符
- 04-11关于java开发中正确的发牌逻辑编写规范
- 最近发表
-
- Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- Java中你知道几种从字符串中找指定的字符的数量
- 探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- Python字符串详解与示例(python字符串的常见操作)
- java正则-取出指定字符串之间的内容
- String s1 = new String("abc");这句话创建了几个字符串对象?
- java判断字符串中是否包含某个字符
- 关于java开发中正确的发牌逻辑编写规范
- windows、linux如何后台运行jar(并且显示进程名)
- 腾讯大佬私人收藏,GitHub上最受欢迎的100个JAVA库,值得学习
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)