Java利用httpasyncclient进行异步HTTP请求

前段时间有个需求在springmvc mapping的url跳转前完成一个统计的业务。显然需要进行异步的处理,不然出错或者异常会影响到后面的网页跳转。异步的方式也就是非阻塞式的,当异步调用成功与否程序会接着往下执行,不必等到输入输出处理完毕才返回。

主要用到httpasyncclient-4.0.1.jar,httpclient-4.3.2.jar,httpcore-4.3.2.jar,httpcore-nio-4.3.2.jar,commons-logging-1.1.3.jar。

java.util.concurrent中主要包括三类工具,Executor Freamework,并发集合(Concurrent Collection),以及同步器(Synchronizer)。下面的例子是利用java.util.concurrent.Future只请求一个 url异步请求。Future接口表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get 方法来获取结果,如有必要,计算完成前可以阻塞此方法。取消则由 cancel 方法来执行。还提供了其他方法,以确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明 Future<?> 形式类型、并返回 null 作为底层任务的结果。

import java.util.concurrent.Future;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
/**
 * This example demonstrates a basic asynchronous HTTP request / response
 * exchange. Response content is buffered in memory for simplicity.
 */
public class AsyncClientHttpExchange {
 public static void main(final String[] args) throws Exception {
  CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault();// 默认的配置
  try {
   httpclient.start();
   HttpGet request = new HttpGet("http://www.apache.org/");
   Future<HttpResponse> future = httpclient.execute(request, null);
   HttpResponse response = future.get();// 获取结果
   System.out.println("Response: " + response.getStatusLine());
   System.out.println("Shutting down");
  } finally {
   httpclient.close();
  }
  System.out.println("Done");
 }
}

同步器(Synchronizer)是一些使线程能够等待另一个线程的对象,允许它们协作,最常用的同步器是CountDownLatch和
Semaphore。较不常用的是CyclicBarrier和Exchanger。Semaphore类是一个计数信号量。从概念上讲,信号量维护了一
个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release()
添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。
CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。用给定的计数 初始化
CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await
方法会一直受阻塞。之后,会释放所有等待的线程,await
的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,可使用
CyclicBarrier。倒计数索存器(CountDownLatch)是一次性的障碍。它的唯一构造器带有一个int类型的参数,这个参数是指允许
所有的等待线程处理之前,必须在锁存器上调用countDown()方法的次数。这一点非常有用。下面是异步请求一组url的例子,利用callback
借口完成独立的操作。

import java.util.concurrent.CountDownLatch;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
/**
 * This example demonstrates a fully asynchronous execution of multiple HTTP
 * exchanges where the result of an individual operation is reported using a
 * callback interface.
 */
public class AsyncClientHttpExchangeFutureCallback {
 public static void main(final String[] args) throws Exception {
  RequestConfig requestConfig = RequestConfig.custom()
    .setSocketTimeout(3000).setConnectTimeout(3000).build();
  CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom()
    .setDefaultRequestConfig(requestConfig).build();
  try {
   httpclient.start();
   final HttpGet[] requests = new HttpGet[] {
     new HttpGet("http://www.apache.org/"),
     new HttpGet("https://www.verisign.com/"),
     new HttpGet("http://www.google.com/"),
     new HttpGet("http://www.baidu.com/") };
   final CountDownLatch latch = new CountDownLatch(requests.length);
   for (final HttpGet request : requests) {
    httpclient.execute(request, new FutureCallback<HttpResponse>() {
     //无论完成还是失败都调用countDown()
     @Override
     public void completed(final HttpResponse response) {
      latch.countDown();
      System.out.println(request.getRequestLine() + "->"
        + response.getStatusLine());
     }
     @Override
     public void failed(final Exception ex) {
      latch.countDown();
      System.out.println(request.getRequestLine() + "->" + ex);
     }
     @Override
     public void cancelled() {
      latch.countDown();
      System.out.println(request.getRequestLine()
        + " cancelled");
     }
    });
   }
   latch.await();
   System.out.println("Shutting down");
  } finally {
   httpclient.close();
  }
  System.out.println("Done");
 }
}

参考文档:http://hc.apache.org/httpcomponents-asyncclient-dev/examples.html

时间: 2024-11-10 21:41:00

Java利用httpasyncclient进行异步HTTP请求的相关文章

springMVC项目异步处理请求的错误Async support must be enabled on a servlet and for all filters involved in async

从github上down下来一个项目,springMVC-chat.作者全是用的注解,也就是零配置. 这可苦了我,经过千辛万苦,最终集成到现在的项目中有一点样子了,结果报出来下面的错误.红色部分.解决方法为,在web.xml中也就是springMVC的总配置文件中加上一句话: <async-supported>true</async-supported> 这句话的位置一定要放正确,否则,一切都是徒劳.至于配置spring异步支持(其实是配置servlet异步支持)的放置位置见下图.

利用java servlet实现简单的web请求过滤和跳转

今日有两个微信web项目合并了,但是还有些链接指向废弃的项目,另外不想在服务器上运行两份相同web项目(1.影响性能.2.维护升级容易出错),因此决定写一个简单链接跳转的项目,spring的filter过滤器可以实现,但想想spring干这个有点大材小用,想到java的servlet可以支持通配符,因此用servlet写了一个简单的跳转程序,总共花了不到一小时的时间.废话少说上代码: 1 /** 2 * Servlet implementation class Default 3 */ 4 @W

【转载】 java利用snmp4j包来读取snmp协议数据(Manager端)

https://www.cnblogs.com/xdp-gacl/p/4187089.html http://doc.okbase.net/yuanfy008/archive/265663.html java利用snmp4j包来读取snmp协议数据(Manager端) 1 snmp简单介绍 java利用snmp4j包来读取snmp协议数据,很简单的一个流程,就是利用java来读取运行snmp协议的数据,例如服务器.PC机或者路由器等运行了snmp协议的设备. snmp协议是什么呢? 简单网络管理

(转) Java多线程同步与异步

Java线程 同步与异步 线程池1)多线程并发时,多个线程同时请求同一个资源,必然导致此资源的数据不安全,A线程修改了B线 程的处理的数据,而B线程又修改了A线程处理的数理.显然这是由于全局资源造成的,有时为了解 决此问题,优先考虑使用局部变量,退而求其次使用同步代码块,出于这样的安全考虑就必须牺牲 系统处理性能,加在多线程并发时资源挣夺最激烈的地方,这就实现了线程的同步机制 同步:A线程要请求某个资源,但是此资源正在被B线程使用中,因为同步机制存在,A线程请求 不到,怎么办,A线程只能等待下去

Java利用Callable、Future进行并行计算求和

内容:在Java中利用Callable进行带返回结果的线程计算,利用Future表示异步计算的结果,分别计算不同范围的Long求和,类似的思想还能够借鉴到需要大量计算的地方. public class Sums { public static class Sum implements Callable<Long> { private final Long from; private final Long to; public Sum(long from, long to) { this.fro

Android中的异步网络请求

本篇文章我们来一起写一个最基本的Android异步网络请求框架,借此来了解下Android中网络请求的相关姿势.由于个人水平有限,文中难免存在疏忽和谬误,希望大家可以指出,谢谢大家:) 1. 同步网络请求 以HTTP的GET请求为例,我们来介绍一下Android中一个基本的同步请求框架的实现.直接贴代码: public class HttpUtils { public static byte[] get(String urlString) { HttpURLConnection urlConne

block传值以及利用block封装一个网络请求类

1.block在俩个UIViewController间传值 最近刚学了几招block 的高级用法,其实就是利用block语法在俩个UIViewController之间传值,在这里分享给初学者,同时也方便我自己理解.我们知道UINavigationController类管理UIViewController的时候,利用的是"栈"的思想,在这里不做过多解释,切入正题,假设我们现在有俩个UIViewController,viewC1和viewC2,viewC1比viewC2先进入到UINavi

基于netty的异步http请求

package com.pt.utils; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.N

Java 利用 Socket 实现服务器客户端聊天

Socket是网络编程中最基本的通信接口,常用的网络辅助类,比如URL等之类,其底层还是基于Socket来实现的. 而Socket,形象来说,就是连接通信的两端,比如这样 S<==>S,中间的通道就是网络了,而简单地利用Socket,我们就可以来实现一个简单的聊天功能 具体效果看下图: 这只是在本地中试用的效果,如果加上UI界面,其实就可以做成一个聊天的小应用了. 1. Server 端主要是利用ServerSocket的accept方法来等待客户端的连接,如果客户一直没有连接,则会在这里等待