学习HttpClient,从两个小例子开始

前言

HTTP(Hyper-Text Transfer Protocol,超文本传输协议)在如今的互联网也许是最重要的协议,我们每天做的很多事情都与之有关,比如,网上购物、刷博客、看新闻等。偶尔你的上级还会安排任务给你让你去对接API接口(RESTFUL),你接到任务后,啪啪的敲了一行又一行代码,一遍敲着一遍心里骂着:这是谁设计的这样脑残接口,一点都不好用,对接起来非常麻烦,最终,你怀着极其复杂的心情把api对接完了。有一天你的上级叫你去开发一个API接口,你情绪高涨,把接口开发完了,结果......。在程序中使用RESTFUL API,与传统的webservice相比,耦合度更低,任何能使用http的地方都能使用RESTFUL API,你能在java、python中调用,甚至能在网页中使用ajax来调用。

HttpClient是Apache HttpComponents的一个组件,提供了用来发送HTTP请求和接受HTTP响应的组件库,它并不是一个浏览器,但是他实现了浏览器HTTP相关的功能。你能使用HttpClient来构建你所需要的应用,例如:网页爬虫、调用RESTFUL接口等。JDK提供的HttpURLConnection也支持HTTP特性,不过使用起来比较麻烦,为了能写入请求体和读取请求体,你不得不分别获取底层的InputStream和Outputstream,在流的角度上来进行操作。HttpClient使得这种操作非常简单,而且非常灵活易于扩展。为了增强趣味性,本文就HttpClient的一些较简单的实战,从两个例子开始来说明HttpClient API的使用。

环境准备

  • 本文使用的是JDK8,请确保安装了JDK8或者更高版本的JDK。
  • 为了能使用HttpClient,需要在maven中添加如下的依赖:
<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpclient</artifactId>
  <version>4.5.6</version>
</dependency>
  • 在示例一中使用了jackson来解析JSON,需要加入如下的依赖包:
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.9.6</version>
</dependency>
  • 在示例二中使用了jsoup来解析html文档,需要加入如下的依赖包:
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>1.11.3</version>
</dependency>
  • 如果想要有日志输出则还需要添加log4j的日志依赖包,本文使用的是log4j2:
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.11.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.11.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-jcl</artifactId>
    <version>2.11.0</version>
</dependency>

例子1:从阿里云API接口获取天气预报信息

在java程序中调用第三方厂商提供的API接口是很常见的需求,假设要写一个程序,根据传入的城市名称来展示该城市当天的天气信息。当然要自己动手去测量天气信息,这应该不是一件简单的事情,但是我们可以借助其他的接口来查询天气信息。阿里云上的全国天气预报查询接口就挺好用的,而且还是免费的(不过限制只能调用一万次)。你首先需要购买该api接口,购买完成后,会得到一个appCode,有了这个appCode,你可以在上面在线调试该接口。博主自己已经购买了,各位可以使用博主的这个appCode。

public class WeatherQuery {

  static String appCode = "4073983cf899411a8792dec11dc88e43";

  static String url = "http://jisutqybmf.market.alicloudapi.com/weather/query";

  public static void main(String[] args) throws Exception {
    if (args.length != 1) {
      System.err.println("Usage: <city name>");
      System.exit(-1);
    }
    String charset = "utf-8";
    String encodedCityName = URLEncoder.encode(args[0], charset);
    CloseableHttpClient client = HttpClients.createDefault();
    try {
      HttpGet httpget = new HttpGet(url + "?city=" + encodedCityName);
      // add Authorized Header
      httpget.addHeader(new BasicHeader("Authorization", "APPCODE " + appCode));
      System.out.println("Executing request: " + httpget.getRequestLine());
      CloseableHttpResponse response = client.execute(httpget);
      try {
        System.out.println("-----------------------------------------");
        System.out.println(response.getStatusLine());
        String content = EntityUtils.toString(response.getEntity(), charset);
        System.out.println("Response: " + content);
        Map<String, ?> map = parseJson(content);
        Map<String, ?> weatherData = (Map<String, ?>) map.get("result");
        System.out.printf("%s  %s%n", weatherData.get("date"), weatherData.get("week"));
        System.out.printf("%s  %s  %s~%s℃    %s%s", weatherData.get("city"),  weatherData.get("weather"),
            weatherData.get("templow"), weatherData.get("temphigh"),
            weatherData.get("winddirect"), weatherData.get("windpower"));
      } finally {
        response.close();
      }
    } finally {
      client.close();
    }
  }

  static Map<String, ?> parseJson(String content) throws Exception {
    ObjectMapper objectMapper = new ObjectMapper();
    return objectMapper.readValue(content, Map.class);
  }
}

首先创建了一个HttpClient的实例,用来执行请求操作,创建了HttpGet的实例表示要发送的是GET请求,并在请求头中加入了app认证信息:httpget.addHeader(new BasicHeader("Authorization", "APPCODE " + appCode))response.getEntity()获取响应体信息,调用EntityUtils.toString工具类,将该响应体转换成字符串,接下来用Jackson解析返回的响应的JSON信息,用printf将获取到的天气信息输出到控制台。注意:要在try finally中关闭HttpClient和Response,以完成资源的释放。

执行命令来测试:% WeatherQuery 广州,产生了如下的输出:

2018-07-19  星期四
广州  多云  27~33℃    西南风1级

例子2:获取博客园精华文章

对爬取到的html进行解析是爬虫程序很关键的一环,接下来,看一下简单的html内容分析的例子:爬墙博客园首页的精华文章信息。和例一类似,首先需要创建一个HttpClient的思路,然后创建一个GET请求,执行请求获取响应体信息。为了能提取出精华文章信息,调用Jsoup.parse方法,该方法返回Document对象,调用该对象上的select,并传入CSS选择器相关的方法,选择出我们要提取的内容。

Document doc = Jsoup.parse(content);
Elements postItems = doc.select("#post_list .post_item");
System.out.printf("%-9s\t%-24s\t%s%n", "推荐数", "作者", "标题");
System.out.println("-----------------------------------------------------");
for (Element postItem : postItems) {
  String diggit = postItem.select(".diggit").text();
  String title = postItem.select(".post_item_body .titlelnk").text();
  String author = postItem.select(".post_item_foot .lightblue").text();
  System.out.printf("%-6s\t%-24s\t%s%n", diggit, author, title);
}

运行该程序得到的结果如下(省略掉了部分结果):

推荐数         作者                          标题
-----------------------------------------------------
334     小曾看世界                       通俗易懂,什么是.NET?什么是.NET Framework?什么是.NET Core?
109     陈树义                         藏在正则表达式里的陷阱
16      程序诗人                        你所不知道的日志异步落库

总结

本文通过两个简单的例子来说明了HttpClient的用法,当然这只是HttpClient的冰山一角,本文也不旨在全面较深入的介绍HttpClient,其更加高级的用法将在陆续的文章中进行介绍。来,总结下HttpClient的基本流程:

  1. 创建一个HttpClient的实例;
  2. HttpGet、HttpPost或者其他类似的请求对象,并设置请求头、请求体信息;
  3. 执行请求并返回Response的实例;
  4. 处理响应消息。

相关资源

原文地址:https://www.cnblogs.com/zhangfengxian/p/learning-httpclient-from-two-examples.html

时间: 2024-08-25 11:29:20

学习HttpClient,从两个小例子开始的相关文章

用两个小例子来解释单例模式中的“双重锁定”

学习单例模式时,好多人都不太理解双重锁定.学完后突然想到一个很有趣的例子. 单例模式结构图: 代码: Singleton类 class Singleton { private static Singleton instance; private static readonly object syncRoot = new object(); //程序运行时创建一个静态只读的进程辅助对象 private Singleton() { } //用private修饰构造方法,防止外界利用new创建此类实例

关于oracle触发器的两个小例子

今天接到一个任务,需要修改触发器,因为好久都没有看过关于oracle触发器的东东了,所以这里通过两个简单的小例子复习下触发器,以备忘. 1. 案例一 需求:建立触发器,判断员工工资,如果小于0,则改为0:如果大于10000,则改为10000 建表: create table emp1( e_id number primary key not null, e_no number, e_name varchar2(20), e_sal number ) select * from emp1; cre

两个小例子

public class Cal { //交换两个变量的值 //排序 public void sort(int []a){ for (int i = 0; i < a.length-1; i++) { for (int j = 0; j < a.length-1-i; j++) { if(a[j]>a[j+1]){ int t=a[j]; a[j]=a[j+1]; a[j+1]=t; } } } //调用另一个方法 print(a); //可以提高复用性 } //输出数组中的所有元素 p

数值处理的两个小例子

2的N次方 注意:这里在处理的时候并没有用循环来处理,而是用移位的做法.    n<<4  就是 n*2^4    ,所以在本例中只需要写 1<<time  (time是要求的精度). 1 #include <stdio.h> 2 #include <stdlib.h> 3 int main(){ 4 int time; 5 printf("要求出2的多少次方:"); 6 scanf("%d",&time) ;

java 学习第3课,小例子

package temperature.convert; import java.util.Scanner; public class Converter { public static void main(String[] args) { // TODO 自动生成的方法存根 int flag; //进行功能选择 int centigrade; //用于输入摄氏温度 int fahrenheit; //用于输入华氏温度 double centigrade1; //用于保存计算后的摄氏温度 dou

关于Finereport移动端报表二次开发的两个小例子

例1:刷新页面 1. 问题描述 A超链至B填报,B提交数据后返回A时,A自动刷新显示新的数据. 2. 解决方案 1. contentPane.setAppearRefresh();  //在A的加载结束后事件中添加js 3. 示例 3.1 打开报表 %FR_HOME%\WebReport\WEB-INF\reportlets\doc\Advanced\mobile-client\ DetailedDrillA.cpt %FR_HOME%\WebReport\WEB-INF\reportlets\

多态的两个小例子

class A { public String show(B obj){ return ("A and D"); } public String show(A obj) { return ("A and A"); } } class B extends A { public String show(B obj) { return ("B and B"); } public String show(A obj) { return ("B

freemarker入门小例子

我用freemarker做了两个小例子,主要的东西是:两个Test文件,一个Animal实体类,一个ftl模板---freemarker的模板,我使用maven做的java工程案例.主要结构内容如下图: 注意:需要导入freemarker的jar包: 1.首先我们先来了解一下freemarker的概念: freeMarker概述: FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写: FreeMarker被设计用来生成HTML Web页面,特别是基于MVC

python2.7练习小例子(二十四)

    24):1.题目:利用递归方法求5!.     程序分析:递归公式:fn=fn_1*4! #!/usr/bin/python # -*- coding: UTF-8 -*- def fact(j): sum = 0 if j == 0: sum = 1 else: sum = j * fact(j - 1) return sum print fact(5)     以上实例输出结果为: 120     python3 参考方案: def Factorial(n):     if n ==