基于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.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.EventExecutorGroup; import java.net.URI;
import java.util.Map; /**
* @author panteng
* @description
* @date 17-3-20.
*/
public class NonBlockHttpClient {
public static EventLoopGroup workerGroup = new NioEventLoopGroup(1);
public static Bootstrap b = new Bootstrap();
public static final EventExecutorGroup executor = new DefaultEventExecutorGroup(2);
static {
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000);
}
public static Object lock = new Object();
/**
* 异步GET请求
*
* @param url
* @param head
* @param handler
* @return
*/
public static Boolean get(String url, Map<String, String> head, final HttpHandler handler) {
try {
URI uri = new URI(url);
String domain = uri.getHost();
Integer port = uri.getPort() < 0 ? 80 : uri.getPort();
DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uri.toASCIIString());
if (head == null) {
request.headers().add("Host", domain);
request.headers().add("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:44.0) Gecko/20100101 Firefox/44.0");
request.headers().add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
request.headers().add("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");
request.headers().add("Connection", "keep-alive");
request.headers().add("Cache-Control", "max-age=0");
} else {
for (Map.Entry entry : head.entrySet()) {
request.headers().add((String) entry.getKey(), entry.getValue());
}
}
ChannelInitializer channelInitializer = new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
// 客户端接收到的是httpResponse响应,所以要使用HttpResponseDecoder进行解码
socketChannel.pipeline().addLast(new HttpResponseDecoder());
// 客户端发送的是httprequest,所以要使用HttpRequestEncoder进行编码
socketChannel.pipeline().addLast(new HttpRequestEncoder());
socketChannel.pipeline().addLast(executor, new GeneralHandler(handler));
}
};
ChannelFuture f;
synchronized (lock) {
b.handler(channelInitializer);
f = b.connect(domain, port).sync();
}
f.channel().writeAndFlush(request);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static void close() {
try {
executor.shutdownGracefully();
workerGroup.shutdownGracefully();
} catch (Exception e) {
e.printStackTrace();
}
}
}
核心类1
package com.pt.utils; import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpResponse; import java.util.HashMap;
import java.util.Map; /**
* @author panteng
* @description
* @date 17-3-20.
*/
public class GeneralHandler extends ChannelInboundHandlerAdapter {
com.pt.utils.HttpHandler httpHandler;
Integer respLength = Integer.MAX_VALUE; // 响应报文长度
Map<String, String> head = new HashMap<String, String>();
String respContent = ""; public GeneralHandler(com.pt.utils.HttpHandler handler) {
this.httpHandler = handler;
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof HttpResponse) {
HttpResponse response = (HttpResponse) msg;
for (Map.Entry entry : response.headers().entries()) {
head.put((String) entry.getKey(), (String) entry.getValue());
}
if (response.headers().get("Content-Length") != null) {
respLength = Integer.parseInt(response.headers().get("Content-Length"));
}
} if (msg instanceof HttpContent) {
HttpContent content = (HttpContent) msg;
ByteBuf buf = content.content();
respContent += buf.toString(httpHandler.getCharset());
((HttpContent) msg).release();
if (respContent.getBytes().length >= respLength || !buf.isReadable()) {
ctx.channel().close();
httpHandler.handler(head, respContent);
}
}
}
}
核心类2
package com.pt.utils; import java.nio.charset.Charset;
import java.util.Map; /**
* @author panteng
* @description http响应的异步回调
* @date 17-3-20.
*/
public interface HttpHandler {
public void handler(Map<String, String> headMap, String body);
public Charset getCharset();
}
用户自定义处理接口
使用用例:
package com.pt.utils.test; import com.pt.utils.HttpHandler; import java.nio.charset.Charset;
import java.util.Map; /**
* @author panteng
* @description
* @date 17-3-20.
*/
public class MyHandler implements HttpHandler {
boolean isFinish = false;
String id; public MyHandler(String id) {
this.id = id;
} public void handler(Map<String, String> headMap, String body) {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(id + "自己处理:" + body);
this.setIsFinish(true);
} public Charset getCharset() {
return Charset.forName("UTF-8");
} public boolean isFinish() {
return isFinish;
} public void setIsFinish(boolean isFinish) {
this.isFinish = isFinish;
} public String getId() {
return id;
} public void setId(String id) {
this.id = id;
}
}
用户定义处理的实现
package com.pt.utils.test; import com.pt.utils.NonBlockHttpClient; /**
* @author panteng
* @description
* @date 17-3-22.
*/
public class NonBlockHttpClientTest {
public static void main(String[] arges) {
MyHandler myHandler = new MyHandler("A");
MyHandler myHandler1 = new MyHandler("B");
MyHandler myHandler2 = new MyHandler("C");
MyHandler myHandler3 = new MyHandler("D");
NonBlockHttpClient
.get(url1,
null, myHandler);
NonBlockHttpClient
.get(url2,
null, myHandler1);
NonBlockHttpClient
.get(url3,
null, myHandler2);
NonBlockHttpClient
.get(url4,
null, myHandler3);
System.out.println("做别的事情");
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
while (!(myHandler.isFinish() && myHandler1.isFinish() && myHandler2.isFinish() && myHandler3.isFinish())) {
try {
Thread.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
}
NonBlockHttpClient.close();
System.out.println("退出主函数... ...");
}
}
基于netty的异步http请求的更多相关文章
- suging闲谈-netty 的异步非阻塞IO线程与业务线程分离
前言 surging 对外沉寂了一段时间了,但是作者并没有闲着,而是针对于客户的需要添加了不少功能,也给我带来了不少外快收益, 就比如协议转化,consul 的watcher 机制,JAVA版本,sk ...
- 基于Netty和SpringBoot实现一个轻量级RPC框架-Client端请求响应同步化处理
前提 前置文章: <基于Netty和SpringBoot实现一个轻量级RPC框架-协议篇> <基于Netty和SpringBoot实现一个轻量级RPC框架-Server篇> & ...
- 在Silverlight中的DispatcherTimer的Tick中使用基于事件的异步请求
需求:在silverlight用户界面上使用计时器定时刷新数据. 在 Silverlight 中的 DispatcherTimer 的 Tick 事件 中使用异步请求数据时,会出现多次请求的问题,以下 ...
- 基于Netty打造RPC服务器设计经验谈
自从在园子里,发表了两篇如何基于Netty构建RPC服务器的文章:谈谈如何使用Netty开发实现高性能的RPC服务器.Netty实现高性能RPC服务器优化篇之消息序列化 之后,收到了很多同行.园友们热 ...
- 基于Netty的私有协议栈的开发
基于Netty的私有协议栈的开发 书是人类进步的阶梯,每读一本书都使自己得以提升,以前看书都是看了就看了,当时感觉受益匪浅,时间一长就又还回到书本了!所以说,好记性不如烂笔头,以后每次看完一本书都写一 ...
- 《Java 编写基于 Netty 的 RPC 框架》
一 简单概念 RPC: ( Remote Procedure Call),远程调用过程,是通过网络调用远程计算机的进程中某个方法,从而获取到想要的数据,过程如同调用本地的方法一样. 阻塞IO :当阻塞 ...
- java编写基于netty的RPC框架
一 简单概念 RPC:(Remote Procedure Call),远程调用过程,是通过网络调用远程计算机的进程中某个方法,从而获取到想要的数据,过程如同调用本地的方法一样. 阻塞IO:当阻塞I/O ...
- 基于Netty和SpringBoot实现一个轻量级RPC框架-Client篇
前提 前置文章: <基于Netty和SpringBoot实现一个轻量级RPC框架-协议篇> <基于Netty和SpringBoot实现一个轻量级RPC框架-Server篇> 前 ...
- 这样基于Netty重构RPC框架你不可能知道
原创申明:本文由公众号[猿灯塔]原创,转载请说明出处标注 今天是猿灯塔“365天原创计划”第5天. 今天呢!灯塔君跟大家讲: 基于Netty重构RPC框架 一.CyclicBarrier方法说明 1. ...
随机推荐
- java打开后台程序
try{ String cmds="java -version"; Process p = Runtime.getRuntime().exec(cmds); int exitVal ...
- 集成 SOLR 到 TOMCAT 中(傻瓜教程)
按照如下配置,整个 Solr 是绿色版的,可以将 Tomcat 目录复制到任何一个地方运行 1.下载 solr 4.3 版本 2.下载 Tomcat 7 ( 6 也可以),另外可以根据系统下载 32 ...
- 在Windows 7 (SP1)上安装Visual Studio 2015
背景说明:最近重装了Windows 7 系统,那就顺手装个Visual Studio 2015吧,没想到一案装就报错(具体没截图了).只有Windows8 或是Windows 10才能装 2015?答 ...
- AJAX与后台交互传参的两种方式
工作中的简单总结备忘,防遗失. 第一种:直接传入json数据(后台一个一个入参对接) 1- js请求: var data = {}; data = {"infoId":infoId ...
- Java你不知道的那些事儿—Java隐藏特性
转载自:http://www.cnblogs.com/lanxuezaipiao/p/3460373.html 每 种语言都很强大,不管你是像我一样的初学者还是有过N年项目经验的大神,总会有你不知道的 ...
- NOIP2010~2017部分真题总结
NOIP2010~2017部分真题总结 2010 (吐槽)md这个时候的联赛还只有4题吗? 引水入城 只要发现对于有合法解的地图,每个蓄水厂贡献一段区间这个结论就很好做了 那么\(O(n^3)\)对每 ...
- 从B 树、B+ 树、B* 树谈到R 树(转)
作者:July.weedge.Frankie.编程艺术室出品. 说明:本文从B树开始谈起,然后论述B+树.B*树,最后谈到R 树.其中B树.B+树及B*树部分由weedge完成,R 树部分由Fra ...
- 检查arg是方法还是函数?
from types import MethodType,FunctionType def check(arg): """ 检查arg是方法还是函数? :param ar ...
- jQuery实现复选框全选、全不选、反选问题解析
今天打算用jQuery实现一下复选框的全选.全不选和反选问题,刚开始用的是attr("checked",true/false)方法,发现只能在最开始实现一次全选,可以实现全不选,无 ...
- window.onload和$(document).ready()比较
浏览器在页面加载完毕后,JS通常使用window.onload方法为DOM元素添加事件,而jQuery使用的是$(document).ready()方法.两者功能相似,但也有细微差异,下面简要对比一下 ...