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. 【编程技巧】NSDate,NSDateFormatter,NSTimeInterval

    //获取日期 todaysDate=[NSDate date]; //显示日期和时间 dateFormat = [[NSDateFormatter alloc] init];//NSDate没有自己的 ...

  2. Nodejs+Grunt配置SASS项目自动编译

    Nodejs+Grunt配置SASS项目自动编译 早前听说Nodejs和Grunt很强大,特别是用来构建自动化的前端开发,更是强大无比.但一直碍于自己掌握的技术有限,不敢深入,也未曾深入下去.最近在开 ...

  3. CCF系列之I’m stuck!(201312-5)

    试题名称: I’m stuck! 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 给定一个R行C列的地图,地图的每一个方格可能是'#', '+', '-', '|', '.', ...

  4. php中session_start()函数的作用

    php中session_start()函数的作用 用$_SESION之前必须要session_start()----其中之一的功能,$_SESSION是服务器端的cookie,相当一个大数组(浏览器关 ...

  5. [one day one question] nodejs require 缓存,无法检测文件变化

    问题描述: nodejs require 缓存,无法检测文件变化,当文件require引入后,当文件发生变动后即使再次使用require,返回的依然是第一次引入的文件内容,这怎么破? 解决方案: de ...

  6. Linuxc - 标准输入流、标准输出流、标准错误流

    输入流stdin默认是键盘,输出流stdout默认是显示器,错误流stderr #include <stdio.h> int main() { printf("请输入选择的数字: ...

  7. Python使用requests模块访问HTTPS网站报错`certificate verify failed`

    使用requests模块访问HTTPS网站报错: SNIMissingWarning: An HTTPS request has been made, but the SNI (Subject Nam ...

  8. JavaScript var的作用域和提升

    在ES6标准之前,var 作为唯一的声明变量关键字,本篇将着重介绍var的作用域和变量提升. 1. var Hoisting(变量提升) va rHoisting:使用var在函数或全局内任何地方声明 ...

  9. linux_Nginx日志

    错误信息日志配置: 日志文件默认:/application/nginx/logs/erroe.log error_log logs/error.log error; # 不写默认就有,默认error, ...

  10. dump、libeay32.dll、gsoap、webserver多线程调用gsoap产生崩溃

    问题:调用webserver接口出现dump文件,dump文件指向libeay32.dll有问题,产生崩溃的原因是gsoap多线程问题,多线程调用时需要程序启动的地方调用如下函数进行多线程初始化: i ...