├── 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 |
4 |
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 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
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 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
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 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
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 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
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 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
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 |
1096 |
1097 |
1098 |
1099 |
1100 |
1101 |
1102 |
1103 |
1104 |
1105 | No facets are configured
1106 |
1107 |
1108 |
1109 |
1110 |
1111 |
1112 |
1113 |
1114 |
1115 |
1116 |
1117 |
1118 |
1119 |
1120 |
1121 |
1122 |
1123 |
1124 |
1125 |
1126 |
1127 |
1128 | 1.8
1129 |
1130 |
1131 |
1132 |
1133 |
1134 |
1135 |
1136 |
1137 |
1138 |
1139 |
1140 | httpclientpool
1141 |
1142 |
1143 |
1144 |
1145 |
1146 |
1147 |
1148 |
1149 |
1150 |
1151 |
1152 |
1153 | 1.8
1154 |
1155 |
1156 |
1157 |
1158 |
1159 |
1160 |
1161 |
1162 |
1163 |
1164 |
1165 |
1166 |
1167 |
1168 |
1169 |
1170 |
1171 |
1172 |
1173 |
1174 |
1175 |
1176 |
1177 |
1178 |
1179 |
1180 |
1181 |
1182 |
1183 |
1184 |
1185 |
1186 |
1187 |
1188 |
1189 |
--------------------------------------------------------------------------------