netty的性能非常高,能达到8000rps以上,见
1.准备好需要的jar包
点击(此处)折叠或打开
- spring.jar //spring包
- netty-3.2.4.Final.jar // netty库
- commons-dbcp.jar // dbcp数据库连接池
- mysql-connector-java-5.1.6.jar // dbcp数据库连接池需要依赖
- commons-logging.jar //spring.jar需要依赖
- commons-pool.jar
2.新建java工程TestNettyServer
2.1导入netty的例子
HttpServer.java
1.package org.jboss.netty.example.http.snoop;
2.
3.import java.net.InetSocketAddress;
4.import java.util.concurrent.Executors;
5.import org.jboss.netty.bootstrap.ServerBootstrap;
6.import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
7.
8.public class HttpServer {
9. public static void main(String[] args) {
10. // Configure the server.
11. ServerBootstrap bootstrap = new ServerBootstrap(
12. new NioServerSocketChannelFactory(
13. Executors.newCachedThreadPool(),
14. Executors.newCachedThreadPool()));
15. // Set up the event pipeline factory.
16. bootstrap.setPipelineFactory(new HttpServerPipelineFactory());
17.
18. // Bind and start to accept incoming connections.
19. bootstrap.bind(new InetSocketAddress(8081));
20. }
21.}
1.package org.jboss.netty.example.http.snoop;
2.
3. import static org.jboss.netty.channel.Channels.*;
4.
5. import org.jboss.netty.channel.ChannelPipeline;
6. import org.jboss.netty.channel.ChannelPipelineFactory;
7. import org.jboss.netty.handler.codec.http.HttpContentCompressor;
8. import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
9. import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
10.
11. public class HttpServerPipelineFactory implements ChannelPipelineFactory {
12. public ChannelPipeline getPipeline() throws Exception {
13. // Create a default pipeline implementation.
14. ChannelPipeline pipeline = pipeline();
15.
16. // Uncomment the following line if you want HTTPS
17. //SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
18. //engine.setUseClientMode(false);
19. //pipeline.addLast("ssl", new SslHandler(engine));
20.
21. pipeline.addLast("decoder", new HttpRequestDecoder());
22. // Uncomment the following line if you don't want to handle HttpChunks.
23. //pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));
24. pipeline.addLast("encoder", new HttpResponseEncoder());
25. // Remove the following line if you don't want automatic content compression.
26. pipeline.addLast("deflater", new HttpContentCompressor());
27. pipeline.addLast("handler", new HttpRequestHandler());
28. return pipeline;
29. }
30. }
1.package org.jboss.netty.example.http.snoop;
2.
3. import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
4. import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
5. import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
6. import static org.jboss.netty.handler.codec.http.HttpVersion.*;
7.
8. import java.util.List;
9. import java.util.Map;
10. import java.util.Map.Entry;
11. import java.util.Set;
12.
13. import org.jboss.netty.buffer.ChannelBuffer;
14. import org.jboss.netty.buffer.ChannelBuffers;
15. import org.jboss.netty.channel.ChannelFuture;
16. import org.jboss.netty.channel.ChannelFutureListener;
17. import org.jboss.netty.channel.ChannelHandlerContext;
18. import org.jboss.netty.channel.ExceptionEvent;
19. import org.jboss.netty.channel.MessageEvent;
20. import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
21. import org.jboss.netty.handler.codec.http.Cookie;
22. import org.jboss.netty.handler.codec.http.CookieDecoder;
23. import org.jboss.netty.handler.codec.http.CookieEncoder;
24. import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
25. import org.jboss.netty.handler.codec.http.HttpChunk;
26. import org.jboss.netty.handler.codec.http.HttpChunkTrailer;
27. import org.jboss.netty.handler.codec.http.HttpRequest;
28. import org.jboss.netty.handler.codec.http.HttpResponse;
29. import org.jboss.netty.handler.codec.http.QueryStringDecoder;
30. import org.jboss.netty.util.CharsetUtil;
31.
32. /**
33. * @author <a href="http://www.jboss.org/netty/">The Netty Project
34. * @author Andy Taylor (andy.taylor@jboss.org)
35. * @author <a href="http://gleamynode.net/">Trustin Lee
36. *
37. * @version $Rev: 2368 $, $Date: 2010-10-18 17:19:03 +0900 (Mon, 18 Oct 2010) $
38. */
39. public class HttpRequestHandler extends SimpleChannelUpstreamHandler {
40.
41. private HttpRequest request;
42. private boolean readingChunks;
43. /** Buffer that stores the response content */
44. private final StringBuilder buf = new StringBuilder();
45.
46. @Override
47. public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
48. if (!readingChunks) {
49. HttpRequest request = this.request = (HttpRequest) e.getMessage();
50.
51. if (is100ContinueExpected(request)) {
52. send100Continue(e);
53. }
54.
55. buf.setLength(0);
56. buf.append("WELCOME TO THE WILD WILD WEB SERVER\r\n");
57. buf.append("===================================\r\n");
58.
59. buf.append("VERSION: " + request.getProtocolVersion() + "\r\n");
60. buf.append("HOSTNAME: " + getHost(request, "unknown") + "\r\n");
61. buf.append("REQUEST_URI: " + request.getUri() + "\r\n\r\n");
62.
63. for (Map.Entry<String, String> h: request.getHeaders()) {
64. buf.append("HEADER: " + h.getKey() + " = " + h.getValue() + "\r\n");
65. }
66. buf.append("\r\n");
67.
68. QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.getUri());
69. Map<String, List<String>> params = queryStringDecoder.getParameters();
70. if (!params.isEmpty()) {
71. for (Entry<String, List<String>> p: params.entrySet()) {
72. String key = p.getKey();
73. List<String> vals = p.getValue();
74. for (String val : vals) {
75. buf.append("PARAM: " + key + " = " + val + "\r\n");
76. }
77. }
78. buf.append("\r\n");
79. }
80.
81. if (request.isChunked()) {
82. readingChunks = true;
83. } else {
84. ChannelBuffer content = request.getContent();
85. if (content.readable()) {
86. buf.append("CONTENT: " + content.toString(CharsetUtil.UTF_8) + "\r\n");
87. }
88. writeResponse(e);
89. }
90. } else {
91. HttpChunk chunk = (HttpChunk) e.getMessage();
92. if (chunk.isLast()) {
93. readingChunks = false;
94. buf.append("END OF CONTENT\r\n");
95.
96. HttpChunkTrailer trailer = (HttpChunkTrailer) chunk;
97. if (!trailer.getHeaderNames().isEmpty()) {
98. buf.append("\r\n");
99. for (String name: trailer.getHeaderNames()) {
100. for (String value: trailer.getHeaders(name)) {
101. buf.append("TRAILING HEADER: " + name + " = " + value + "\r\n");
102. }
103. }
104. buf.append("\r\n");
105. }
106.
107. writeResponse(e);
108. } else {
109. buf.append("CHUNK: " + chunk.getContent().toString(CharsetUtil.UTF_8) + "\r\n");
110. }
111. }
112. }
113.
114. private void writeResponse(MessageEvent e) {
115. // Decide whether to close the connection or not.
116. boolean keepAlive = isKeepAlive(request);
117.
118. // Build the response object.
119. HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
120. response.setContent(ChannelBuffers.copiedBuffer(buf.toString(), CharsetUtil.UTF_8));
121. response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");
122.
123. if (keepAlive) {
124. // Add 'Content-Length' header only for a keep-alive connection.
125. response.setHeader(CONTENT_LENGTH, response.getContent().readableBytes());
126. }
127.
128. // Encode the cookie.
129. String cookieString = request.getHeader(COOKIE);
130. if (cookieString != null) {
131. CookieDecoder cookieDecoder = new CookieDecoder();
132. Set<Cookie> cookies = cookieDecoder.decode(cookieString);
133. if(!cookies.isEmpty()) {
134. // Reset the cookies if necessary.
135. CookieEncoder cookieEncoder = new CookieEncoder(true);
136. for (Cookie cookie : cookies) {
137. cookieEncoder.addCookie(cookie);
138. }
139. response.addHeader(SET_COOKIE, cookieEncoder.encode());
140. }
141. }
142.
143. // Write the response.
144. ChannelFuture future = e.getChannel().write(response);
145.
146. // Close the non-keep-alive connection after the write operation is done.
147. if (!keepAlive) {
148. future.addListener(ChannelFutureListener.CLOSE);
149. }
150. }
151.
152. private void send100Continue(MessageEvent e) {
153. HttpResponse response = new DefaultHttpResponse(HTTP_1_1, CONTINUE);
154. e.getChannel().write(response);
155. }
156.
157. @Override
158. public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
159. throws Exception {
160. e.getCause().printStackTrace();
161. e.getChannel().close();
162. }
163. }
1.package org.jboss.netty.example.http.snoop;
2.
3.import java.sql.Connection;
4.import java.sql.PreparedStatement;
5.import java.sql.ResultSet;
6.import java.sql.SQLException;
7.import java.sql.Statement;
8.
9.import org.apache.commons.dbcp.BasicDataSource;
10.
11./**
12. * 连接和使用数据库资源的工具类
13. *
14. * @author yifangyou
15. * @version gtm 2010-09-27
16. */
17.public class DatabaseUtil {
18.
19. /**
20. * 数据源
21. */
22. private BasicDataSource dataSource;
23.
24. /**
25. * 数据库连接
26. */
27. public Connection conn;
28.
29. /**
30. * 获取数据源
31. * @return 数据源
32. */
33. public BasicDataSource getDataSource() {
34. return dataSource;
35. }
36.
37. /**
38. * 设置数据源
39. * @param dataSource 数据源
40. */
41. public void setDataSource(BasicDataSource dataSource) {
42. this.dataSource = dataSource;
43. }
44.
45.
46. /**
47. * 获取数据库连接
48. * @return conn
49. */
50. public Connection getConnection() {
51. try {
52. conn = dataSource.getConnection();
53. } catch (Exception e) {
54. e.printStackTrace();
55. return null;
56. }
57. return conn;
58. }
59.
60. /**
61. * 关闭数据库连接
62. * @param conn
63. */
64. public void closeConnection(Connection conn) {
65. if (null != conn) {
66. try {
67. conn.close();
68. conn = null;
69. } catch (SQLException e) {
70. e.printStackTrace();
71. }
72. }
73. }
74.
75.
76.
77. /**
78. * 获取执行SQL的工具
79. * @param conn 数据库连接
80. * @param sql SQL语句
81. * @return prepStmt
82. */
83. public PreparedStatement getPrepStatement(Connection conn, String sql) {
84. PreparedStatement prepStmt = null;
85. try {
86. prepStmt = conn.prepareStatement(sql);
87. } catch (SQLException e) {
88. e.printStackTrace();
89. }
90. return prepStmt;
91. }
92.
93.
94. /**
95. * 关闭数据库资源
96. * @param prepStmt
97. */
98. public void closePrepStatement(PreparedStatement prepStmt) {
99. if (null != prepStmt) {
100. try {
101. prepStmt.close();
102. prepStmt = null;
103. } catch (SQLException e) {
104. e.printStackTrace();
105. }
106. }
107. }
108.
109.}
点击工程的右键“propertis”->Java Build Path->Libraries->Add JARS
3.分析如何注入
Netty的运行过程是
Netty的运行过程是
因此我们需要
Spring注入入口在HttpServer里的main函数
把HttpRequestHandler注入到HttpServerPipelineFactory,
把HttpServerPipelineFactory注入到HttpServer
另外我们在HttpRequestHandler需要用到mysql连接池,因此还要把mysql连接池注入到HttpRequestHandler
Spring注入入口在HttpServer里的main函数
把HttpRequestHandler注入到HttpServerPipelineFactory,
把HttpServerPipelineFactory注入到HttpServer
另外我们在HttpRequestHandler需要用到mysql连接池,因此还要把mysql连接池注入到HttpRequestHandler