├── httpclientpool ├── .idea │ ├── .name │ ├── dictionaries │ │ └── fjs.xml │ ├── copyright │ │ └── profiles_settings.xml │ ├── scopes │ │ └── scope_settings.xml │ ├── encodings.xml │ ├── vcs.xml │ ├── modules.xml │ ├── libraries │ │ └── Maven__io_netty_netty_all_4_0_20_Final.xml │ ├── misc.xml │ ├── compiler.xml │ └── workspace.xml ├── target │ └── classes │ │ └── fjs │ │ ├── Example │ │ ├── Fjs.class │ │ ├── Fjs$1.class │ │ └── Fjs$2.class │ │ ├── client │ │ ├── Client.class │ │ ├── NettyClient.class │ │ ├── AbstractClient.class │ │ ├── NettyClient$1.class │ │ ├── NettyClient$2.class │ │ ├── NettyClient$1$1.class │ │ └── Client$ClientStatus.class │ │ ├── future │ │ ├── Future.class │ │ ├── AbstractFuture.class │ │ ├── AbstractFuture$1.class │ │ ├── AbstractFuture$2.class │ │ ├── AbstractFuture$3.class │ │ ├── AbstractFuture$4.class │ │ ├── Future$EventType.class │ │ ├── Future$Listener.class │ │ └── Future$FutureStatus.class │ │ ├── http │ │ ├── Request.class │ │ ├── Response.class │ │ ├── RequestFuture.class │ │ └── Request$RequestMethod.class │ │ ├── clientpool │ │ ├── ClientPool.class │ │ ├── NettyClientPool.class │ │ ├── AbstractClientPool$1.class │ │ └── AbstractClientPool.class │ │ ├── lifecycle │ │ └── Lifecycle.class │ │ └── netty │ │ └── http │ │ ├── HandlerInitializer$1.class │ │ ├── HandlerInitializer.class │ │ └── HandlerInitializer$ReadHandler.class ├── src │ └── main │ │ └── java │ │ └── fjs │ │ ├── lifecycle │ │ └── Lifecycle.java │ │ ├── http │ │ ├── Response.java │ │ ├── Request.java │ │ └── RequestFuture.java │ │ ├── clientpool │ │ ├── NettyClientPool.java │ │ ├── ClientPool.java │ │ └── AbstractClientPool.java │ │ ├── client │ │ ├── Client.java │ │ ├── AbstractClient.java │ │ └── NettyClient.java │ │ ├── future │ │ ├── Future.java │ │ └── AbstractFuture.java │ │ ├── Example │ │ └── Fjs.java │ │ └── netty │ │ └── http │ │ └── HandlerInitializer.java ├── pom.xml └── httpclientpool.iml └── Readme.md /httpclientpool/.idea/.name: -------------------------------------------------------------------------------- 1 | httpclientpool -------------------------------------------------------------------------------- /httpclientpool/.idea/dictionaries/fjs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /httpclientpool/.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | 基于netty开发的支持并发的http客户端。。。 2 | 后台将会维护一个tcp的长连接池。。。。 3 | 4 | 5 | 用法就看 我的博客吧: http://blog.csdn.net/fjslovejhl/article/details/33340755 -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/Example/Fjs.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/Example/Fjs.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/Example/Fjs$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/Example/Fjs$1.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/Example/Fjs$2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/Example/Fjs$2.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/client/Client.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/client/Client.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/future/Future.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/future/Future.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/http/Request.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/http/Request.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/http/Response.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/http/Response.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/client/NettyClient.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/client/NettyClient.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/http/RequestFuture.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/http/RequestFuture.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/client/AbstractClient.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/client/AbstractClient.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/client/NettyClient$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/client/NettyClient$1.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/client/NettyClient$2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/client/NettyClient$2.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/clientpool/ClientPool.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/clientpool/ClientPool.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/future/AbstractFuture.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/future/AbstractFuture.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/lifecycle/Lifecycle.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/lifecycle/Lifecycle.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/client/NettyClient$1$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/client/NettyClient$1$1.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/future/AbstractFuture$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/future/AbstractFuture$1.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/future/AbstractFuture$2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/future/AbstractFuture$2.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/future/AbstractFuture$3.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/future/AbstractFuture$3.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/future/AbstractFuture$4.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/future/AbstractFuture$4.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/future/Future$EventType.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/future/Future$EventType.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/future/Future$Listener.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/future/Future$Listener.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/client/Client$ClientStatus.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/client/Client$ClientStatus.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/clientpool/NettyClientPool.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/clientpool/NettyClientPool.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/future/Future$FutureStatus.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/future/Future$FutureStatus.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/http/Request$RequestMethod.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/http/Request$RequestMethod.class -------------------------------------------------------------------------------- /httpclientpool/.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/clientpool/AbstractClientPool$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/clientpool/AbstractClientPool$1.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/clientpool/AbstractClientPool.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/clientpool/AbstractClientPool.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/netty/http/HandlerInitializer$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/netty/http/HandlerInitializer$1.class -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/netty/http/HandlerInitializer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/netty/http/HandlerInitializer.class -------------------------------------------------------------------------------- /httpclientpool/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /httpclientpool/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /httpclientpool/target/classes/fjs/netty/http/HandlerInitializer$ReadHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2225377fjs/HttpClientPool/HEAD/httpclientpool/target/classes/fjs/netty/http/HandlerInitializer$ReadHandler.class -------------------------------------------------------------------------------- /httpclientpool/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /httpclientpool/src/main/java/fjs/lifecycle/Lifecycle.java: -------------------------------------------------------------------------------- 1 | package fjs.lifecycle; 2 | 3 | /** 4 | * Created by fjs on 14-6-20. 5 | * 用于管理组件的生命周期 6 | */ 7 | public interface Lifecycle { 8 | /** 9 | * 启动组件 10 | */ 11 | public void start(); 12 | 13 | /** 14 | * 停止组件 15 | */ 16 | public void stop(); 17 | } 18 | -------------------------------------------------------------------------------- /httpclientpool/.idea/libraries/Maven__io_netty_netty_all_4_0_20_Final.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /httpclientpool/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | httpclientpool 8 | httpclientpool 9 | 1.0-SNAPSHOT 10 | 11 | 12 | io.netty 13 | netty-all 14 | 4.0.20.Final 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /httpclientpool/src/main/java/fjs/http/Response.java: -------------------------------------------------------------------------------- 1 | package fjs.http; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.handler.codec.http.DefaultHttpResponse; 5 | 6 | /** 7 | * Created by fjs on 14-6-20. 8 | */ 9 | public class Response { 10 | private DefaultHttpResponse response; 11 | private ByteBuf body; 12 | 13 | public Response(DefaultHttpResponse response, ByteBuf body) { 14 | this.response = response; 15 | this.body = body; 16 | } 17 | 18 | 19 | public ByteBuf getBody() { 20 | return body; 21 | } 22 | 23 | public void setBody(ByteBuf body) { 24 | this.body = body; 25 | } 26 | 27 | public DefaultHttpResponse getResponse() { 28 | return response; 29 | } 30 | 31 | public void setResponse(DefaultHttpResponse response) { 32 | this.response = response; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /httpclientpool/httpclientpool.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /httpclientpool/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Abstraction issues 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /httpclientpool/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /httpclientpool/src/main/java/fjs/clientpool/NettyClientPool.java: -------------------------------------------------------------------------------- 1 | package fjs.clientpool; 2 | 3 | import fjs.client.Client; 4 | import fjs.client.NettyClient; 5 | import io.netty.channel.nio.NioEventLoopGroup; 6 | 7 | import java.util.concurrent.TimeUnit; 8 | 9 | /** 10 | * Created by fjs on 14-6-20. 11 | */ 12 | public class NettyClientPool extends AbstractClientPool { 13 | private NioEventLoopGroup nioEventLoopGroup; 14 | 15 | 16 | public NettyClientPool(int size, String remoteHost) { 17 | super(size, remoteHost); 18 | this.nioEventLoopGroup = new NioEventLoopGroup(2); 19 | } 20 | /** 21 | * 用于构建具体的client 22 | * 23 | * @return 24 | */ 25 | @Override 26 | public Client newClient() { 27 | NettyClient client = new NettyClient(this); 28 | client.setGroup(this.nioEventLoopGroup); 29 | return client; 30 | } 31 | 32 | /** 33 | * 延迟执行一个task,单位微秒 34 | * 35 | * @param task 36 | * @param time 37 | */ 38 | @Override 39 | public void schuild(Runnable task, int time) { 40 | this.nioEventLoopGroup.schedule(task, time, TimeUnit.MILLISECONDS); 41 | } 42 | 43 | public NioEventLoopGroup getNioEventLoopGroup() { 44 | return nioEventLoopGroup; 45 | } 46 | 47 | /** 48 | * 停止组件 49 | */ 50 | @Override 51 | public void stop() { 52 | super.stop(); 53 | this.nioEventLoopGroup.shutdownGracefully(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /httpclientpool/src/main/java/fjs/clientpool/ClientPool.java: -------------------------------------------------------------------------------- 1 | package fjs.clientpool; 2 | 3 | import fjs.client.Client; 4 | import fjs.http.Request; 5 | import fjs.http.RequestFuture; 6 | import fjs.lifecycle.Lifecycle; 7 | 8 | /** 9 | * Created by fjs on 14-6-20. 10 | */ 11 | public interface ClientPool extends Lifecycle{ 12 | /** 13 | * 获取当前连接的远端的地址 14 | * @return 15 | */ 16 | public String getRemoteHost(); 17 | 18 | /** 19 | * 获取当前pool的规模,其实也就是有多少个client 20 | * @return 21 | */ 22 | public int getSize(); 23 | 24 | /** 25 | * 发送一个http请求,并返回一个RequestFuture 26 | * @param request 27 | * @return 28 | */ 29 | public RequestFuture request(Request request); 30 | 31 | /** 32 | * 向当前的pool添加client 33 | * @param client 34 | */ 35 | public void addClient(Client client); 36 | 37 | 38 | /** 39 | * 移除一个client 40 | * @param client 41 | */ 42 | public void removeClient(Client client); 43 | /** 44 | * 带有超时控制的请求 45 | * @param request 46 | * @param time 单位为微秒 47 | * @return 48 | */ 49 | RequestFuture requestWithTimeOut(Request request, int time); 50 | 51 | /** 52 | * 当有client退出的时候的处理,相当于提供给client的回调 53 | * @param client 54 | */ 55 | public void clientExit(Client client); 56 | 57 | /** 58 | * 延迟执行一个task,单位微秒 59 | * @param task 60 | * @param time 61 | */ 62 | public void schuild(Runnable task, int time); 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /httpclientpool/src/main/java/fjs/client/Client.java: -------------------------------------------------------------------------------- 1 | package fjs.client; 2 | 3 | import fjs.clientpool.ClientPool; 4 | import fjs.http.Request; 5 | import fjs.http.RequestFuture; 6 | import fjs.lifecycle.Lifecycle; 7 | 8 | /** 9 | * Created by fjs on 14-6-20. 10 | */ 11 | public interface Client extends Lifecycle{ 12 | public static enum ClientStatus { 13 | Startting, Ready, Working, Stopped 14 | } 15 | 16 | /** 17 | * 获取所属的pool 18 | * @return 19 | */ 20 | public ClientPool getClientPool(); 21 | 22 | /** 23 | * 获取远程地址 24 | * @return 25 | */ 26 | public String getRemoteHost(); 27 | 28 | 29 | /** 30 | * 处理请求 31 | * @param request 32 | * @return 33 | */ 34 | public void request(Request request); 35 | 36 | /** 37 | * 取消正在运行的request 38 | */ 39 | public void cancel(); 40 | 41 | /** 42 | * 设置正在运行的request 43 | * @param request 44 | */ 45 | public void setRequest(Request request); 46 | 47 | /** 48 | * 返回正在运行的request 49 | * @return 50 | */ 51 | public Request getRequest(); 52 | 53 | /** 54 | * 用于返回当前client的状态 55 | * @return 56 | */ 57 | public ClientStatus getStatus(); 58 | 59 | 60 | /** 61 | *  用于设置当前client的状态 62 | * @param status 63 | */ 64 | public void setStatus(ClientStatus status); 65 | 66 | 67 | /** 68 | * 当当前client可以用的时候调用的方法,将这个client加入到pool啥的 69 | */ 70 | public void ready(); 71 | 72 | } 73 | -------------------------------------------------------------------------------- /httpclientpool/src/main/java/fjs/http/Request.java: -------------------------------------------------------------------------------- 1 | package fjs.http; 2 | 3 | import fjs.future.Future; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.buffer.Unpooled; 6 | 7 | import java.util.HashMap; 8 | 9 | /** 10 | * Created by fjs on 14-6-20. 11 | */ 12 | public class Request { 13 | public static enum RequestMethod { 14 | GET, POST 15 | } 16 | 17 | private Future future; 18 | private String path; 19 | private HashMap headers = new HashMap(); 20 | private RequestMethod method; 21 | private ByteBuf body; 22 | 23 | public Request(String path, RequestMethod method) { 24 | this.path = path; 25 | this.method = method; 26 | this.body = Unpooled.buffer(); 27 | } 28 | 29 | 30 | public Future getFuture() { 31 | return future; 32 | } 33 | 34 | public void setFuture(Future future) { 35 | this.future = future; 36 | } 37 | 38 | 39 | public String getPath() { 40 | return path; 41 | } 42 | 43 | public void setPath(String path) { 44 | this.path = path; 45 | } 46 | 47 | public RequestMethod getMethod() { 48 | return method; 49 | } 50 | 51 | public void setMethod(RequestMethod method) { 52 | this.method = method; 53 | } 54 | 55 | public ByteBuf getBody() { 56 | return body; 57 | } 58 | 59 | public void setBody(ByteBuf body) { 60 | this.body = body; 61 | } 62 | 63 | public void addHeader(String name, String value) { 64 | this.headers.put(name, value); 65 | } 66 | 67 | public HashMap getHeaders() { 68 | return headers; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /httpclientpool/src/main/java/fjs/future/Future.java: -------------------------------------------------------------------------------- 1 | package fjs.future; 2 | 3 | /** 4 | * Created by fjs on 14-6-20. 5 | * 提交请求之后返回的,用于注册回调,获取执行结果啥的 6 | */ 7 | public interface Future { 8 | /** 9 | * 定义的事件类型,Complete表示处理完成,Exception就是处理的时候出现了异常 10 | */ 11 | static enum EventType{ 12 | Complete, Exception 13 | } 14 | 15 | /** 16 | * 当前Future的类型 17 | */ 18 | static enum FutureStatus { 19 | Pendding, Running, Canceled, Error, Timeout, Success 20 | } 21 | static public interface Listener { 22 | /** 23 | * 当处理完成了之后要调用的方法 24 | * @param arg : 处理完之后的结果 25 | */ 26 | public void complete(Object arg); 27 | 28 | /** 29 | * 当处理的时候有问题发生调用的方法 30 | * @param t 31 | */ 32 | public void exception(Throwable t); 33 | } 34 | 35 | /** 36 | * 获取当前future的状态 37 | * @return 38 | */ 39 | public FutureStatus getStatus(); 40 | 41 | /** 42 | * 设置当前future的状态 43 | * @param status 44 | */ 45 | public void setStatus(FutureStatus status); 46 | 47 | 48 | /** 49 | * 取消当前任务的执行 50 | */ 51 | public void cancel(); 52 | 53 | 54 | 55 | /** 56 | * 添加回调,用于处理结果或者异常啥的 57 | * @param listener 58 | */ 59 | public void addListener(Listener listener); 60 | 61 | /** 62 | * 当有进展的时候将会调用这个方法 63 | * @param type : 类型,有可能是处理完了,也有可能是有异常 64 | * @param arg : 传递的参数 65 | */ 66 | public void fireEvent(EventType type, Object arg); 67 | 68 | 69 | /** 70 | * 当处理成功之后会调用的方法 71 | * @param arg 72 | */ 73 | public void success(Object arg); 74 | 75 | /** 76 | * 当超时的时候会调用的方法 77 | */ 78 | public void timeOut(); 79 | 80 | 81 | /** 82 | * 当执行过程中出现异常调用的方法 83 | * @param t 84 | */ 85 | public void exception(Throwable t); 86 | 87 | } 88 | -------------------------------------------------------------------------------- /httpclientpool/src/main/java/fjs/Example/Fjs.java: -------------------------------------------------------------------------------- 1 | package fjs.Example; 2 | 3 | import fjs.clientpool.ClientPool; 4 | import fjs.clientpool.NettyClientPool; 5 | import fjs.future.Future; 6 | import fjs.http.Request; 7 | import fjs.http.Response; 8 | 9 | import java.nio.charset.Charset; 10 | 11 | /** 12 | * Created by fjs on 14-6-22. 13 | */ 14 | public class Fjs { 15 | public static void doGet() { 16 | final ClientPool pool = new NettyClientPool(2, "www.baidu.com"); 17 | pool.start(); 18 | Request request = new Request("/", Request.RequestMethod.GET); 19 | pool.request(request).addListener(new Future.Listener() { 20 | @Override 21 | public void complete(Object arg) { 22 | Response res = (Response)arg; 23 | System.out.println(res.getBody().toString(Charset.forName("utf-8"))); 24 | pool.stop(); 25 | } 26 | 27 | @Override 28 | public void exception(Throwable t) { 29 | 30 | } 31 | }); 32 | } 33 | 34 | public static void doPost() { 35 | final ClientPool pool = new NettyClientPool(2, "www.baidu.com"); 36 | pool.start(); 37 | Request request = new Request("/", Request.RequestMethod.POST); 38 | request.getBody().writeBytes("aa".getBytes(Charset.forName("utf-8"))); 39 | pool.request(request).addListener(new Future.Listener() { 40 | @Override 41 | public void complete(Object arg) { 42 | Response res = (Response)arg; 43 | System.out.println(res.getBody().toString(Charset.forName("utf-8"))); 44 | pool.stop(); 45 | } 46 | 47 | @Override 48 | public void exception(Throwable t) { 49 | 50 | } 51 | }); 52 | } 53 | 54 | public static void doGetSync() throws Throwable { 55 | final ClientPool pool = new NettyClientPool(2, "www.baidu.com"); 56 | pool.start(); 57 | Request request = new Request("/", Request.RequestMethod.POST); 58 | request.getBody().writeBytes("aa".getBytes(Charset.forName("utf-8"))); 59 | Response response = pool.requestWithTimeOut(request, 2000).sync(); 60 | pool.stop(); 61 | System.out.println(response.getBody().toString(Charset.forName("utf-8"))); 62 | } 63 | 64 | public static void main(String args[]) throws Throwable { 65 | //Fjs.doGet(); 66 | //Fjs.doPost(); 67 | Fjs.doGetSync(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /httpclientpool/src/main/java/fjs/client/AbstractClient.java: -------------------------------------------------------------------------------- 1 | package fjs.client; 2 | 3 | import fjs.clientpool.ClientPool; 4 | import fjs.http.Request; 5 | 6 | import java.util.logging.Logger; 7 | 8 | /** 9 | * Created by fjs on 14-6-20. 10 | */ 11 | public abstract class AbstractClient implements Client{ 12 | private String remoteHost; 13 | private ClientPool pool; 14 | private volatile Request request; 15 | private volatile ClientStatus status; 16 | 17 | public AbstractClient(ClientPool pool) { 18 | this.pool = pool; 19 | this.remoteHost = pool.getRemoteHost(); 20 | this.status = ClientStatus.Startting; 21 | } 22 | 23 | 24 | @Override 25 | public void setRequest(Request request) { 26 | this.request = request; 27 | } 28 | 29 | @Override 30 | public Request getRequest() { 31 | return this.request; 32 | } 33 | 34 | /** 35 | * 获取所属的pool 36 | * 37 | * @return 38 | */ 39 | @Override 40 | public ClientPool getClientPool() { 41 | return this.pool; 42 | } 43 | 44 | /** 45 | * 获取远程地址 46 | * 47 | * @return 48 | */ 49 | @Override 50 | public String getRemoteHost() { 51 | return this.remoteHost; 52 | } 53 | 54 | /** 55 | * 取消正在运行的request 56 | */ 57 | @Override 58 | public void cancel() { 59 | if (this.request != null) { 60 | 61 | } 62 | } 63 | 64 | 65 | 66 | 67 | /** 68 | * 停止组件,这里主要是通知pool有client退出了 69 | */ 70 | @Override 71 | public void stop() { 72 | this.getClientPool().clientExit(this); 73 | } 74 | 75 | 76 | /** 77 | * 用于返回当前client的状态 78 | * 79 | * @return 80 | */ 81 | @Override 82 | public ClientStatus getStatus() { 83 | return this.status; 84 | } 85 | 86 | /** 87 | *  用于设置当前client的状态 88 | * 89 | * @param status 90 | */ 91 | @Override 92 | public void setStatus(ClientStatus status) { 93 | this.status = status; 94 | } 95 | 96 | /** 97 | * 当当前client可以用的时候调用的方法,将这个client加入到pool啥的 98 | */ 99 | @Override 100 | public synchronized void ready() { 101 | if (this.status.equals(ClientStatus.Working) || status.equals(ClientStatus.Startting)) { 102 | this.setStatus(ClientStatus.Ready); 103 | this.getClientPool().addClient(this); 104 | this.setRequest(null); 105 | } else { 106 | Logger.getGlobal().warning("client准备好了,但是client的状态不对啊"); 107 | this.start(); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /httpclientpool/src/main/java/fjs/http/RequestFuture.java: -------------------------------------------------------------------------------- 1 | package fjs.http; 2 | 3 | import fjs.client.Client; 4 | import fjs.future.AbstractFuture; 5 | import fjs.future.Future; 6 | import oracle.jrockit.jfr.events.RequestableEventEnvironment; 7 | 8 | /** 9 | * Created by fjs on 14-6-20. 10 | */ 11 | public class RequestFuture extends AbstractFuture{ 12 | 13 | 14 | 15 | private Request request; 16 | private Client client; 17 | private volatile Response response; 18 | private volatile Throwable t; 19 | 20 | 21 | 22 | public RequestFuture(Request request) { 23 | this.request = request; 24 | } 25 | 26 | 27 | /** 28 | * 设置当前的response,相当于做一层记录 29 | * @param response 30 | */ 31 | public void setResponse(Response response) { 32 | this.response = response; 33 | } 34 | 35 | 36 | /** 37 | * 添加回调,用于处理结果或者异常啥的 38 | * 39 | * @param listener 40 | */ 41 | @Override 42 | public void addListener(Listener listener) { 43 | if (this.getStatus().equals(FutureStatus.Success)) { 44 | for (Listener lis : this.getListeners()) { 45 | lis.complete(this.response); 46 | } 47 | } else { 48 | super.addListener(listener); 49 | } 50 | } 51 | 52 | /** 53 | * 取消当前任务的执行 54 | */ 55 | @Override 56 | public synchronized void cancel() { 57 | if (this.getStatus().equals(FutureStatus.Pendding) || this.getStatus().equals(FutureStatus.Running)) { 58 | super.cancel(); 59 | if (this.getStatus().equals(FutureStatus.Running)) { 60 | this.client.cancel(); 61 | } 62 | } 63 | } 64 | public void setClient(Client client) { 65 | this.client = client; 66 | } 67 | 68 | 69 | /** 70 | * 当处理成功之后会调用的方法 71 | * 72 | * @param arg 73 | */ 74 | @Override 75 | public synchronized void success(Object arg) { 76 | super.success(arg); 77 | this.setResponse((Response)arg); 78 | this.notifyAll(); 79 | } 80 | 81 | /** 82 | * 当超时的时候会调用的方法 83 | */ 84 | @Override 85 | public synchronized void timeOut() { 86 | super.timeOut(); 87 | this.t = new Exception("超时了"); 88 | this.notifyAll(); 89 | } 90 | 91 | /** 92 | * 当执行过程中出现异常调用的方法 93 | * 94 | * @param t 95 | */ 96 | @Override 97 | public synchronized void exception(Throwable t) { 98 | super.exception(t); 99 | this.t = t; 100 | this.notifyAll(); 101 | } 102 | 103 | public synchronized Response sync() throws Throwable{ 104 | while (true) { 105 | if (this.response != null) { 106 | return response; 107 | } 108 | if (this.t != null) { 109 | throw t; 110 | } 111 | try { 112 | this.wait(); 113 | } catch (InterruptedException e) { 114 | continue; 115 | } 116 | } 117 | } 118 | 119 | 120 | } 121 | -------------------------------------------------------------------------------- /httpclientpool/src/main/java/fjs/netty/http/HandlerInitializer.java: -------------------------------------------------------------------------------- 1 | package fjs.netty.http; 2 | 3 | import fjs.client.Client; 4 | import fjs.client.NettyClient; 5 | import fjs.future.Future; 6 | import fjs.http.Response; 7 | import io.netty.buffer.ByteBuf; 8 | import io.netty.buffer.Unpooled; 9 | import io.netty.channel.ChannelHandlerContext; 10 | import io.netty.channel.ChannelInboundHandler; 11 | import io.netty.channel.ChannelInboundHandlerAdapter; 12 | import io.netty.channel.socket.nio.NioSocketChannel; 13 | import io.netty.handler.codec.http.*; 14 | 15 | import java.util.logging.Logger; 16 | 17 | /** 18 | * Created by fjs on 14-6-21. 19 | */ 20 | public class HandlerInitializer implements ChannelInboundHandler{ 21 | 22 | private class ReadHandler extends ChannelInboundHandlerAdapter{ 23 | private DefaultHttpResponse response; 24 | private ByteBuf body; 25 | 26 | @Override 27 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 28 | if (msg instanceof HttpResponse) { 29 | this.response = (DefaultHttpResponse)msg; 30 | } 31 | 32 | if (msg instanceof HttpContent) { 33 | HttpContent content = (HttpContent)msg; 34 | if (this.body == null) { 35 | this.body = Unpooled.buffer(); 36 | } 37 | this.body.writeBytes(content.content()); 38 | 39 | if (msg instanceof LastHttpContent) { 40 | Response nr = new Response(this.response, this.body); 41 | this.body = null; 42 | if (client.getRequest().getFuture().getStatus().equals(Future.FutureStatus.Running)) { 43 | client.getRequest().getFuture().success(nr); 44 | } else { 45 | Logger.getLogger("main").warning("请求执行付完毕,但是请求状态不对"); 46 | } 47 | client.ready(); 48 | } 49 | } 50 | } 51 | } 52 | 53 | 54 | private NettyClient client; 55 | 56 | public HandlerInitializer(NettyClient client) { 57 | this.client = client; 58 | } 59 | 60 | @Override 61 | public void channelRegistered(ChannelHandlerContext channelHandlerContext) throws Exception { 62 | channelHandlerContext.fireChannelRegistered(); 63 | } 64 | 65 | @Override 66 | public void channelUnregistered(ChannelHandlerContext channelHandlerContext) throws Exception { 67 | channelHandlerContext.fireChannelUnregistered(); 68 | } 69 | 70 | @Override 71 | public void channelActive(ChannelHandlerContext channelHandlerContext) throws Exception { 72 | NioSocketChannel channel = this.client.getChannel(); 73 | channel.pipeline().remove(this); 74 | channel.pipeline().addFirst(new HttpClientCodec()); //为当前的channel添加 75 | channel.pipeline().addLast(new ReadHandler()); 76 | channel.pipeline().addLast(this); 77 | client.ready(); 78 | } 79 | 80 | @Override 81 | public void channelInactive(ChannelHandlerContext channelHandlerContext) throws Exception { 82 | client.disconnected(); 83 | } 84 | 85 | @Override 86 | public void channelRead(ChannelHandlerContext channelHandlerContext, Object o) throws Exception { 87 | channelHandlerContext.fireChannelRead(o); 88 | } 89 | 90 | @Override 91 | public void channelReadComplete(ChannelHandlerContext channelHandlerContext) throws Exception { 92 | channelHandlerContext.fireChannelReadComplete(); 93 | } 94 | 95 | @Override 96 | public void userEventTriggered(ChannelHandlerContext channelHandlerContext, Object o) throws Exception { 97 | channelHandlerContext.fireUserEventTriggered(o); 98 | } 99 | 100 | @Override 101 | public void channelWritabilityChanged(ChannelHandlerContext channelHandlerContext) throws Exception { 102 | channelHandlerContext.fireChannelWritabilityChanged(); 103 | } 104 | 105 | @Override 106 | public void handlerAdded(ChannelHandlerContext channelHandlerContext) throws Exception { 107 | 108 | } 109 | 110 | @Override 111 | public void handlerRemoved(ChannelHandlerContext channelHandlerContext) throws Exception { 112 | 113 | } 114 | 115 | @Override 116 | public void exceptionCaught(ChannelHandlerContext channelHandlerContext, Throwable throwable) throws Exception { 117 | client.exception(throwable); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /httpclientpool/src/main/java/fjs/clientpool/AbstractClientPool.java: -------------------------------------------------------------------------------- 1 | package fjs.clientpool; 2 | 3 | import fjs.client.Client; 4 | import fjs.future.Future; 5 | import fjs.http.Request; 6 | import fjs.http.RequestFuture; 7 | 8 | import java.util.concurrent.LinkedBlockingQueue; 9 | import java.util.concurrent.TimeUnit; 10 | import java.util.logging.Logger; 11 | 12 | /** 13 | * Created by fjs on 14-6-20. 14 | */ 15 | public abstract class AbstractClientPool implements ClientPool{ 16 | private int size; 17 | private String remoteHost; 18 | private LinkedBlockingQueue clients; 19 | 20 | public AbstractClientPool(int size, String remoteHost) { 21 | this.size = size; 22 | this.remoteHost = remoteHost; 23 | this.clients = new LinkedBlockingQueue(this.size); 24 | } 25 | 26 | 27 | /** 28 | * 获取当前连接的远端的地址 29 | * 30 | * @return 31 | */ 32 | @Override 33 | public String getRemoteHost() { 34 | return this.remoteHost; 35 | } 36 | 37 | /** 38 | * 获取当前pool的规模,其实也就是有多少个client 39 | * 40 | * @return 41 | */ 42 | @Override 43 | public int getSize() { 44 | return this.size; 45 | } 46 | 47 | /** 48 | * 当有client退出的时候的处理,相当于提供给client的回调 49 | * 50 | * @param client 51 | */ 52 | @Override 53 | public void clientExit(Client client) { 54 | Logger.getLogger("main").warning("有client退出了"); 55 | this.clients.remove(client); 56 | } 57 | 58 | /** 59 | * 发送一个http请求,并返回一个RequestFuture 60 | * 61 | * @param request 62 | * @return 63 | */ 64 | @Override 65 | public RequestFuture request(Request request) { 66 | 67 | Client client = null; 68 | while (true || client == null) { 69 | try { 70 | client = this.clients.poll(1000, TimeUnit.DAYS); 71 | break; 72 | } catch (InterruptedException e) { 73 | continue; 74 | } 75 | 76 | } 77 | 78 | RequestFuture future = new RequestFuture(request); 79 | request.setFuture(future); 80 | future.setClient(client); 81 | client.setRequest(request); 82 | future.setStatus(Future.FutureStatus.Running); 83 | client.request(request); 84 | 85 | return future; 86 | } 87 | 88 | /** 89 | * 带有超时控制的请求 90 | * 91 | * @param request 92 | * @param time 93 | * @return 94 | */ 95 | @Override 96 | public RequestFuture requestWithTimeOut(Request request, int time) { 97 | long before = System.currentTimeMillis(); 98 | final RequestFuture future = new RequestFuture(request); 99 | Client client = null; 100 | while (true) { 101 | try { 102 | client = this.clients.poll(time, TimeUnit.MILLISECONDS); 103 | break; 104 | } catch (InterruptedException e) { 105 | continue; 106 | } 107 | 108 | } 109 | if (client == null) { //超时了居然都还没有拿到client来处理 110 | future.timeOut(); 111 | return future; 112 | } 113 | long after = System.currentTimeMillis(); 114 | 115 | future.setClient(client); 116 | client.setRequest(request); 117 | request.setFuture(future); 118 | future.setStatus(Future.FutureStatus.Running); 119 | 120 | time = (int) (time - (after - before)); 121 | this.schuild(new Runnable() { 122 | @Override 123 | public void run() { 124 | future.timeOut(); 125 | } 126 | }, time); 127 | client.request(request); 128 | return future; 129 | 130 | 131 | } 132 | 133 | /** 134 | * 用于构建具体的client 135 | * @return 136 | */ 137 | public abstract Client newClient(); 138 | 139 | 140 | /** 141 | * 启动组件 142 | */ 143 | @Override 144 | public void start() { 145 | for (int i = 0; i < this.size; i++) { 146 | this.newClient().start(); //在client确实启动好了之后会加入到pool里面 147 | } 148 | } 149 | 150 | /** 151 | * 停止组件 152 | */ 153 | @Override 154 | public void stop() { 155 | while (this.clients.size() > 0) { 156 | Client client = this.clients.peek(); 157 | client.stop(); 158 | } 159 | } 160 | 161 | 162 | /** 163 | * 向当前的pool添加client 164 | * 165 | * @param client 166 | */ 167 | @Override 168 | public void addClient(Client client) { 169 | try { 170 | this.clients.put(client); 171 | } catch (InterruptedException e) { 172 | e.printStackTrace(); 173 | } 174 | } 175 | 176 | 177 | /** 178 | * 移除一个client 179 | * 180 | * @param client 181 | */ 182 | @Override 183 | public void removeClient(Client client) { 184 | this.clients.remove(client); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /httpclientpool/src/main/java/fjs/future/AbstractFuture.java: -------------------------------------------------------------------------------- 1 | package fjs.future; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.Executor; 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | import java.util.concurrent.ThreadFactory; 9 | import java.util.concurrent.locks.ReentrantLock; 10 | import java.util.logging.Logger; 11 | 12 | /** 13 | * Created by fjs on 14-6-20. 14 | */ 15 | public abstract class AbstractFuture implements Future { 16 | 17 | //因为这里添加listener与调用listener在不同的线程,所以用这个来保证内存的可见性 18 | private ReentrantLock tlock = new ReentrantLock(); 19 | private List listeners = new ArrayList(2); 20 | 21 | //最开始的时候future的状态肯定是pendding 22 | private volatile FutureStatus status = FutureStatus.Pendding; 23 | 24 | //他主要是用来隔离用户的回调,尽量不要在netty的线程中执行用户的回调 25 | private static ExecutorService service = Executors.newFixedThreadPool(1, new ThreadFactory() { 26 | @Override 27 | public Thread newThread(Runnable r) { 28 | Thread t = new Thread(r); 29 | t.setDaemon(true); 30 | return t; 31 | } 32 | }); 33 | 34 | /** 35 | * 添加回调,用于处理结果或者异常啥的 36 | * 37 | * @param listener 38 | */ 39 | @Override 40 | public void addListener(Listener listener) { 41 | if (this.status.equals(FutureStatus.Timeout)) { 42 | listener.exception(new Exception("timout")); 43 | } else if (this.status.equals(FutureStatus.Error)) { 44 | listener.exception(new Exception("已经出了异常")); 45 | } else if (this.status.equals(FutureStatus.Success)) { 46 | listener.complete(null); 47 | } else if (this.status.equals(FutureStatus.Canceled)) { 48 | listener.exception(new Exception("已经取消了")); 49 | } else { 50 | this.tlock.lock(); 51 | try { 52 | this.listeners.add(listener); 53 | } finally { 54 | this.tlock.unlock(); 55 | } 56 | } 57 | } 58 | 59 | /** 60 | * 当有进展的时候将会调用这个方法 61 | * 62 | * @param type : 类型,有可能是处理完了,也有可能是有异常 63 | * @param arg : 传递的参数 64 | */ 65 | @Override 66 | public void fireEvent(EventType type, Object arg) { 67 | 68 | if (type.equals(EventType.Complete)) { 69 | this.status = FutureStatus.Success; 70 | this.tlock.lock(); 71 | try { 72 | for (Listener lis : this.listeners) { 73 | lis.complete(arg); 74 | } 75 | } finally { 76 | this.tlock.unlock(); 77 | } 78 | } else if (type.equals(EventType.Exception)) { 79 | this.status = FutureStatus.Error; 80 | this.tlock.lock(); 81 | try { 82 | for (Listener lis : this.listeners) { 83 | lis.exception((Throwable) arg); 84 | } 85 | } finally { 86 | this.tlock.unlock(); 87 | } 88 | } 89 | } 90 | 91 | /** 92 | * 取消当前任务的执行 93 | */ 94 | @Override 95 | public void cancel() { 96 | this.status = FutureStatus.Canceled; 97 | } 98 | 99 | 100 | public synchronized List getListeners() { 101 | return listeners; 102 | } 103 | 104 | /** 105 | * 获取当前future的状态 106 | * 107 | * @return 108 | */ 109 | @Override 110 | public synchronized FutureStatus getStatus() { 111 | return this.status; 112 | } 113 | 114 | /** 115 | * 设置当前future的状态 116 | * 117 | * @param status 118 | */ 119 | @Override 120 | public synchronized void setStatus(FutureStatus status) { 121 | this.status = status; 122 | } 123 | 124 | 125 | /** 126 | * 当超时的时候会调用的方法 127 | */ 128 | @Override 129 | public synchronized void timeOut() { 130 | if (getStatus().equals(FutureStatus.Pendding) || getStatus().equals(FutureStatus.Running)) { 131 | if (this.getStatus().equals(FutureStatus.Running)) { 132 | this.cancel(); 133 | } 134 | this.setStatus(FutureStatus.Timeout); 135 | service.execute(new Runnable() { 136 | @Override 137 | public void run() { 138 | AbstractFuture.this.fireEvent(EventType.Exception, new Exception("超时了")); 139 | } 140 | }); 141 | } 142 | } 143 | 144 | /** 145 | * 当执行过程中出现异常调用的方法 146 | * 147 | * @param t 148 | */ 149 | @Override 150 | public synchronized void exception(final Throwable t) { 151 | 152 | if (this.status.equals(FutureStatus.Running)) { 153 | this.setStatus(FutureStatus.Error); 154 | service.execute(new Runnable() { 155 | @Override 156 | public void run() { 157 | AbstractFuture.this.fireEvent(EventType.Exception, t); 158 | } 159 | }); 160 | } 161 | } 162 | 163 | /** 164 | * 当处理成功之后会调用的方法 165 | * 166 | * @param arg 167 | */ 168 | @Override 169 | public synchronized void success(final Object arg) { 170 | if (this.getStatus().equals(FutureStatus.Running)) { 171 | this.setStatus(FutureStatus.Success); 172 | service.execute(new Runnable() { 173 | @Override 174 | public void run() { 175 | AbstractFuture.this.fireEvent(EventType.Complete, arg); 176 | } 177 | }); 178 | } else { 179 | Logger.getGlobal().warning("执行完了,但是状态不对啊"); 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /httpclientpool/src/main/java/fjs/client/NettyClient.java: -------------------------------------------------------------------------------- 1 | package fjs.client; 2 | 3 | import fjs.clientpool.ClientPool; 4 | import fjs.clientpool.NettyClientPool; 5 | import fjs.future.Future; 6 | import fjs.http.Request; 7 | import fjs.http.Response; 8 | import fjs.netty.http.HandlerInitializer; 9 | import io.netty.channel.ChannelFuture; 10 | import io.netty.channel.ChannelFutureListener; 11 | import io.netty.channel.nio.NioEventLoopGroup; 12 | import io.netty.channel.socket.nio.NioSocketChannel; 13 | import io.netty.handler.codec.http.*; 14 | 15 | import java.lang.Thread; 16 | import java.net.InetSocketAddress; 17 | import java.net.URI; 18 | import java.net.URISyntaxException; 19 | import java.nio.charset.Charset; 20 | import java.util.Map; 21 | import java.util.concurrent.atomic.AtomicInteger; 22 | import java.util.logging.Logger; 23 | 24 | 25 | /** 26 | * Created by fjs on 14-6-20. 27 | */ 28 | public class NettyClient extends AbstractClient{ 29 | private NioEventLoopGroup group; 30 | private volatile NioSocketChannel channel; 31 | 32 | public NettyClient(ClientPool pool) { 33 | super(pool); 34 | } 35 | 36 | private AtomicInteger connectNumber = new AtomicInteger(0); 37 | 38 | 39 | /** 40 | * 处理请求 41 | * 42 | * @param request 43 | * @return 44 | */ 45 | @Override 46 | public void request(Request request) { 47 | if (this.getStatus().equals(ClientStatus.Ready)) { 48 | this.setStatus(ClientStatus.Working); 49 | } else { 50 | Logger.getGlobal().warning("client状态不对啊"); 51 | return; 52 | } 53 | QueryStringEncoder encoder = new QueryStringEncoder("http://" + this.getRemoteHost() + request.getPath()); 54 | URI uriGet = null; 55 | try { 56 | uriGet = new URI(encoder.toString()); 57 | //System.out.println(uriGet); 58 | } catch (URISyntaxException e) { 59 | System.out.println("我擦,,,,"); 60 | } 61 | 62 | FullHttpRequest nr = null; 63 | 64 | if (request.getMethod().equals(Request.RequestMethod.GET)) { 65 | nr = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uriGet.getRawPath()); 66 | } else if (request.getMethod().equals(Request.RequestMethod.POST)) { 67 | nr = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, uriGet.getRawPath()); 68 | nr.content().writeBytes(request.getBody()); 69 | nr.headers().add("content-length", nr.content().readableBytes()); 70 | } 71 | 72 | 73 | for (Map.Entry header : request.getHeaders().entrySet()) { 74 | nr.headers().add(header.getKey(), header.getValue()); 75 | } 76 | 77 | nr.headers().add("Host", this.getRemoteHost()); 78 | nr.headers().add("Connection", "keep-alive"); 79 | this.channel.pipeline().write(nr); 80 | this.channel.pipeline().flush(); 81 | } 82 | 83 | /** 84 | * 取消正在运行的request 85 | */ 86 | @Override 87 | public void cancel() { 88 | if (this.getStatus().equals(ClientStatus.Working)) { 89 | Logger.getGlobal().warning("正在工作的request被取消了"); 90 | this.channel.close(); 91 | this.start(); 92 | } 93 | } 94 | 95 | /** 96 | * 当前的链接除了异常 97 | * @param t 98 | * @return 99 | */ 100 | public synchronized void exception(Throwable t) { 101 | if (this.getStatus().equals(ClientStatus.Stopped)) { 102 | return; 103 | } 104 | Logger.getGlobal().warning("链接出现了异常,将会进行重链接"); 105 | if (this.getStatus().equals(ClientStatus.Ready)) { 106 | this.getClientPool().removeClient(this); 107 | } else if (this.getStatus().equals(ClientStatus.Working)) { 108 | Logger.getGlobal().severe("request执行时出现异常, request is :" + this.getRequest()); 109 | this.getRequest().getFuture().exception(t); 110 | } 111 | this.start(); //重启 112 | } 113 | 114 | /** 115 | * 当链接断开了之后调用的方法 116 | */ 117 | public synchronized void disconnected() { 118 | if (this.getStatus().equals(ClientStatus.Stopped)) { 119 | return; 120 | } 121 | Logger.getGlobal().warning("链接断开了,将会尝试重新链接"); 122 | if (this.getStatus().equals(ClientStatus.Ready)) { 123 | this.getClientPool().removeClient(this); 124 | } else if (this.getStatus().equals(ClientStatus.Working)) { 125 | Logger.getGlobal().severe("request执行时出现异常, request is :" + this.getRequest()); 126 | this.getRequest().getFuture().exception(new Exception("链接断开了")); 127 | } 128 | this.start(); //重启 129 | } 130 | 131 | /** 132 | * 这里主要是创建channel,然后将其注册到group上面去,另外要看连接是否成功 133 | * 如果连接失败的话要调度重新建立链接,另外还要控制重连接的数量,如果超过十次还不成功那就算了吧 134 | * 启动组件 135 | */ 136 | @Override 137 | public void start() { 138 | this.setStatus(ClientStatus.Startting); 139 | if (this.channel != null) { 140 | this.channel.close(); 141 | this.channel = null; 142 | } 143 | this.channel = new NioSocketChannel(); 144 | this.channel.pipeline().addFirst(new HandlerInitializer(this)); 145 | this.group.register(this.channel); 146 | this.channel.connect(new InetSocketAddress(this.getRemoteHost(), 80)).addListener(new ChannelFutureListener() { 147 | @Override 148 | public void operationComplete(ChannelFuture channelFuture) throws Exception { 149 | if (channelFuture.channel().isActive()) { 150 | connectNumber.set(0); //链接上了之后就可以刷新成0 151 | Logger.getGlobal().info("连接建立成功, host : " + getRemoteHost()); 152 | } else { 153 | int number = connectNumber.incrementAndGet(); 154 | if (number > 10) { 155 | Logger.getGlobal().severe("我擦,尝试这么多次,还是没有连接上,算了吧"); 156 | getClientPool().stop(); 157 | return; 158 | } 159 | Logger.getGlobal().warning("连接超时,即将尝试重新连接"); 160 | NettyClient.this.getClientPool().schuild(new Runnable() { 161 | @Override 162 | public void run() { 163 | NettyClient.this.start(); 164 | } 165 | }, 2000); 166 | } 167 | } 168 | }); 169 | } 170 | 171 | /* 172 | * 停止组件 173 | */ 174 | @Override 175 | public void stop() { 176 | super.stop(); 177 | this.setStatus(ClientStatus.Stopped); 178 | this.channel.close(); 179 | } 180 | 181 | public NioSocketChannel getChannel() { 182 | return channel; 183 | } 184 | 185 | public void setGroup(NioEventLoopGroup group) { 186 | this.group = group; 187 | } 188 | 189 | public static void main(String args[]) { 190 | final NettyClientPool pool = new NettyClientPool(2, "127.0.0.1"); 191 | pool.start(); 192 | 193 | for (int i = 0; i < 100000000; i++) { 194 | Request request = new Request("/", Request.RequestMethod.POST); 195 | request.getBody().writeBytes("樊劲松".getBytes(Charset.forName("utf-8"))); 196 | pool.requestWithTimeOut(request, 2000).addListener(new Future.Listener() { 197 | @Override 198 | public void complete(Object arg) { 199 | Response response = (Response) arg; 200 | System.out.println(response.getBody().toString(Charset.forName("utf-8"))); 201 | //System.out.println("ok"); 202 | } 203 | 204 | @Override 205 | public void exception(Throwable t) { 206 | System.out.println(t); 207 | } 208 | }); 209 | try { 210 | Thread.currentThread().sleep(100); 211 | } catch (InterruptedException e) { 212 | e.printStackTrace(); 213 | } 214 | } 215 | /* 216 | Future future = pool.request(new Request()); 217 | future.addListener(new Future.Listener() { 218 | @Override 219 | public void complete(Object arg) { 220 | //pool.stop(); 221 | pool.request(new Request()); 222 | } 223 | 224 | @Override 225 | public void exception(Throwable t) { 226 | System.out.println("haha error : " + t); 227 | //pool.stop(); 228 | } 229 | });*/ 230 | } 231 | 232 | 233 | 234 | } 235 | -------------------------------------------------------------------------------- /httpclientpool/.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 120 | 121 | 122 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 159 | 160 | 163 | 164 | 167 | 168 | 171 | 172 | 173 | 174 | 177 | 178 | 181 | 182 | 185 | 186 | 189 | 190 | 193 | 194 | 195 | 196 | 199 | 200 | 203 | 204 | 205 | 206 | 209 | 210 | 213 | 214 | 215 | 216 | 219 | 220 | 223 | 224 | 227 | 228 | 229 | 230 | 233 | 234 | 237 | 238 | 241 | 242 | 245 | 246 | 247 | 248 | 251 | 252 | 255 | 256 | 259 | 260 | 263 | 264 | 267 | 268 | 271 | 272 | 275 | 276 | 277 | 278 | 281 | 282 | 285 | 286 | 289 | 290 | 293 | 294 | 297 | 298 | 301 | 302 | 303 | 304 | 307 | 308 | 311 | 312 | 315 | 316 | 319 | 320 | 323 | 324 | 327 | 328 | 331 | 332 | 333 | 334 | 337 | 338 | 341 | 342 | 345 | 346 | 349 | 350 | 353 | 354 | 357 | 358 | 361 | 362 | 363 | 364 | 367 | 368 | 371 | 372 | 375 | 376 | 379 | 380 | 383 | 384 | 387 | 388 | 391 | 392 | 393 | 394 | 397 | 398 | 401 | 402 | 405 | 406 | 409 | 410 | 413 | 414 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 465 | 466 | 481 | 482 | 497 | 498 | 513 | 514 | 515 | 519 | 520 | 521 | 540 | 541 | 548 | 549 | 550 | 561 | 562 | 563 | 581 | 588 | 589 | 602 | 603 | 604 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 642 | 643 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | localhost 681 | 5050 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 1403251677892 692 | 1403251677892 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 729 | 732 | 733 | 734 | 736 | 737 | 740 | 741 | 742 | 743 | 744 | 745 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 915 | 916 | 917 | 918 | 919 | 920 | 921 | 922 | 923 | 924 | 925 | 926 | 927 | 928 | 929 | 930 | 931 | 932 | 933 | 934 | 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | 950 | 951 | 952 | 953 | 954 | 955 | 956 | 957 | 958 | 959 | 960 | 961 | 962 | 963 | 964 | 965 | 966 | 967 | 968 | 969 | 970 | 971 | 972 | 973 | 974 | 975 | 976 | 977 | 978 | 979 | 980 | 981 | 982 | 983 | 984 | 985 | 986 | 987 | 988 | 989 | 990 | 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | 999 | 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | 1024 | 1025 | 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 1048 | 1049 | 1050 | 1051 | 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 1058 | 1059 | 1060 | 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | 1077 | 1078 | 1079 | 1080 | 1081 | 1082 | 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | 1091 | 1092 | 1093 | 1094 | 1095 | 1100 | 1101 | 1102 | 1103 | 1104 | 1105 | No facets are configured 1106 | 1107 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1123 | 1124 | 1125 | 1126 | 1127 | 1128 | 1.8 1129 | 1130 | 1135 | 1136 | 1137 | 1138 | 1139 | 1140 | httpclientpool 1141 | 1142 | 1148 | 1149 | 1150 | 1151 | 1152 | 1153 | 1.8 1154 | 1155 | 1160 | 1161 | 1162 | 1163 | 1164 | 1165 | 1166 | 1171 | 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | 1182 | 1183 | 1184 | 1185 | 1186 | 1187 | 1188 | 1189 | --------------------------------------------------------------------------------