1. 概述

在这篇快速教程中,我们将使用Java内置类HttpUrlConnection来实现一个Http请求。

2. HttpUrlConnection

HttpUrlConnection类允许我们不用添加其他任何类库就能实现基本的Http请求。所有需要的类都包含在 java.net包内。缺点是,相比于其他http类库,该方法有点笨重,而且也没有提供一些高级特性的API,比如添加请求头,添加认证等。不过这些都不要紧。你完全可以将这个实现封装一下,添加一些高级特性也不是很复杂。

如果你只是想快速地进行些Http请求而不想添加一些类库的话,本文的这些代码就足够了。

另外,如果你对java的http请求基本实现不很了解,本文给出的代码也会有些帮助。

3. 创建请求

HttpUrlConnection类的创建是通过URL 类的openConnection()方法。这个方法只是创建一个连接对象,并不建立连接。

通过设置requestMethod属性,HttpUrlConnection类可以创建各种请求类型——包括GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE。

比如创建一个GET请求:

URL url = new URL("www.baidu.com");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");

4. 添加请求参数

如果我们想要添加请求参数,我们需要设置doOutput 为true,然后将请求参数拼接成字符串,格式param1=value&param2=value,以流的形式写入到HttpUrlConnection 实例的OutputStream中。示例代码如下:

 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();

为方便转换字符串参数,我写了个工具类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;
}
}        

5. 添加请求头

通过setRequestProperty() 方法可以添加请求头:

 con.setRequestProperty("Content-Type", "application/json");

通过getHeaderField()方法可以读取响应头:

 String contentType = con.getHeaderField("Content-Type");

6. 配置超时时间

类允许我们设置连接超时时间和读取超时时间。这些值决定了连接建立的最大等待时间间隔或读取到达数据的最大等待时间间隔。

设置超时时间,我们可以调用方法setConnectTimeout() 和方法setReadTimeout()

 con.setConnectTimeout(5000);
con.setReadTimeout(5000);

这个例子中我们将超时时间设为5秒。

7.  处理Cookies

java.net 包包含的类CookieManager,HttpCookie等能很便捷地处理Cookies.

首先,从响应中读取cookies,我们先获取相应头里的Set-Cookie值,然后解析成HttpCookie对象的List.

 String cookiesHeader = con.getHeaderField("Set-Cookie");
List<HttpCookie> cookies = HttpCookie.parse(cookiesHeader);

接下来,我们将cookies存储起来:

 cookies.forEach(cookie -> cookieManager.getCookieStore().add(null, cookie));

我们检查cookies中是否包含一个username属性,如果不包含,我们把一个叫zhangsan的username添加进去:

 Optional<HttpCookie> usernameCookie = cookies.stream()
  .findAny().filter(cookie -> cookie.getName().equals("username"));
if (usernameCookie == null) {
    cookieManager.getCookieStore().add(null, new HttpCookie("username", "john"));
}

最后,将cookies添加到请求中去,我们需要在关闭连接和重新打开连接后,添加Cookie请求头 :

 con.disconnect();
con = (HttpURLConnection) url.openConnection(); con.setRequestProperty("Cookie",
StringUtils.join(cookieManager.getCookieStore().getCookies(), ";"));

8. 处理重定向

我们可以通过调用方法setInstanceFollowRedirects(),设置为true或者false,来控制是否允许一个特定连接自动跟随重定向:

 con.setInstanceFollowRedirects(false);

也可以全局设置所有的连接是否允许自动跟随重定向:

 HttpUrlConnection.setFollowRedirects(false);

默认是允许自动跟随重定向的。

请求返回状态码301,302表示重定向,我们可以获取响应头的Location属性并用新的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();
}

9. 读取响应

通过读取HttpUrlConnection实例的InputStream流来读取响应。

读取响应常用方法有getResponseCode(), connect(), getInputStream() or getOutputStream() 。

比如,读取响应状态码:

 int status = con.getResponseCode();

比如,读取响应头:

 String contentType = con.getHeaderField("Content-Type");

比如,读取响应文本:

 BufferedReader in = new BufferedReader(
  new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer content = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    content.append(inputLine);
}
in.close();

关闭连接:

 con.disconnect();

结论

在这篇文章中,我们展示了如何通过HttpUrlConnection类来时间Http请求。以下代码可以直接拷贝使用。由于太简单,就不传github了。

 package com.shlugood.utils;

 import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map; public class HttpUtil { private static String POST = "POST";
private static String GET = "GET";
private static String CONTENT_TYPE_URLENCODED = "application/x-www-form-urlencoded";
private static String CONTENT_TYPE_JSON = "application/json"; private static String httpRequest(String method, String contentType, String urlStr, HashMap<String,String> paras)
throws IOException {
URL url = new URL(urlStr);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(5000);
con.setReadTimeout(5000);
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); if(paras != null && !paras.isEmpty()){
con.setDoOutput(true);
DataOutputStream out = new DataOutputStream(con.getOutputStream());
out.writeBytes(ParameterStringBuilder.getParamsString(paras));
out.flush();
out.close();
} BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer content = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
in.close();
con.disconnect();
return content.toString();
} private static 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;
}
} public static String httpGetRequest(String url){
try {
return httpRequest(GET, CONTENT_TYPE_URLENCODED, url, null);
} catch (IOException e) {
e.printStackTrace();
}
return "";
} public static String httpPostRequest(String url, HashMap<String,String> paras){
try {
return httpRequest(POST, CONTENT_TYPE_URLENCODED, url, paras);
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
}

Java中简单Http请求的更多相关文章

  1. JAVA中简单的for循环竟有这么多坑,你踩过吗

    JAVA中简单的for循环竟有这么多坑,你踩过吗 实际的业务项目开发中,大家应该对从给定的list中剔除不满足条件的元素这个操作不陌生吧? 很多同学可以立刻想出很多种实现的方式,但你想到的这些实现方式 ...

  2. java中简单的反射

    1.为什么会用到反射机制? 最近需要写定时服务,如果一个一个去写定时服务的话,后期维护是很烦人的,通过反射机制,我们就可以将定时服务的信息通过数据配置来实现,这样我们后期就可以将整个模块交给运维人员去 ...

  3. java中简单内存计算

    今天面试遇到一个问题,假设一个类中只声明一个int类型,那么这个对象多大,这里先写出解决方案,首先引入内存计算工具lucene-core, <dependency> <groupId ...

  4. Java中前台JSP请求Servlet实例(http+Servlet)

    1.前台jsp代码 himily.jsp,定义了用户名和密码两个输入框,使用post方式提交:/order-web/HimilyServlet其中order-web为站点名称,HimilyServle ...

  5. java中的http请求的封装(GET、POST、form表单形式)

    目前JAVA实现HTTP请求的方法用的最多的有两种:一种是通过HTTPClient这种第三方的开源框架去实现.HTTPClient对HTTP的封装性比较不错,通过它基本上能够满足我们大部分的需求,Ht ...

  6. 简述Java中Http/Https请求监听方法

    一.工欲善其事必先利其器 做Web开发的人总免不了与Http/Https请求打交道,很多时候我们都希望能够直观的的看到我们发送的请求参数和服务器返回的响应信息,这个时候就需要借助于某些工具啦.本文将采 ...

  7. java中发送http请求的方法

    package org.jeecgframework.test.demo; import java.io.BufferedReader; import java.io.FileOutputStream ...

  8. Java中简单的操作(if语句、常用操作符、switch语句、变量赋值等)

    ---------------------if语句介绍--------------------------------------------------- class IfDemo { public ...

  9. [Freemarker] 在Java中简单实现对Freemarker的引用

    Demo目录结构 ├─src │ ├─main │ │ ├─java │ │ │ └─demo │ │ │ └─freemarker │ │ │ ├─main │ │ │ │ Test.java │ ...

随机推荐

  1. Asp.net Core 跨域配置

    一般情况WebApi都是跨域请求,没有设置跨域一般会报以下错误 No 'Access-Control-Allow-Origin' header is present on the requested ...

  2. RPC架构简单理解

    RPC(Remote Promote Call) 一种进程间通信方式.允许像调用本地服务一样调用远程服务. RPC框架的主要目标就是让远程服务调用更简单.透明.RPC框架负责屏蔽底层的传输方式(TCP ...

  3. Postgresql中string转换成timestamp类型

    Mybatis+Postgresql TO_DATE(#{startTime}, 'YYYY-MM-DD') AND op_date <![CDATA[>= ]]>  TO_TIME ...

  4. 数据结构 链式哈希表(Hash Table)的接口定义与实现分析(完整代码)

    链式哈希表的接口定义 关于哈希表与链式哈希表的描述可以参阅:http://www.cnblogs.com/idreamo/p/7990860.html 链式哈希表的操作与属性有:初始化.销毁.插入元素 ...

  5. MySQL 取得小时分钟部分

    MySQL 取得小时分钟部分 SELECT `CpParkID` , DATE_FORMAT( `UPDATE_TIME` , '%H:%i' )FROM `cp_park`WHERE HOUR( ` ...

  6. jq dom操作

    下面介绍我在网络上找的JQUERY的父,子,兄弟节点查找方法 jQuery.parent(expr) 找父亲节点,可以传入expr进行过滤,比如$("span").parent() ...

  7. CSS深入理解学习笔记之relative

    1.relative和absolute的相煎关系 限制作用:①限制left/top/right/bottom定位:②限制z-index层级:③限制在overflow下的嚣张气焰. relative和f ...

  8. javascript 类数组对象

    原文:https://segmentfault.com/a/1190000000415572 定义: 拥有length属性,其他属性(索引)为非负整数(对象中的所有会被当做字符串来处理,这里你可以当做 ...

  9. 使用copy命令合并二进制文件

    CMD下的copy命令可以将一份或多份文件复制到另一个位置. 也具备连接文件的功能. 使用如下命令格式可以将多个二进制文件合并为一个二进制文件: copy  /b  file1+file2+...+f ...

  10. JAVA中实现让程序等待一段时间的方法

    JAVA中想让代码等待一段时间再继续执行,可以通过让当前线程睡眠一段时间的方式. 方法一:通过线程的sleep方法. Thread.currentThread().sleep(1000); 在需要程序 ...