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 // dbcp数据库连接池需要依赖
2.新建java工程TestNettyServer
2.1导入netty的例子
HttpServer.java
- package org.jboss.netty.example.http.snoop;
- import java.net.InetSocketAddress;
- import java.util.concurrent.Executors;
- import org.jboss.netty.bootstrap.ServerBootstrap;
- import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
- public class HttpServer {
- public static void main(String[] args) {
- // Configure the server.
- ServerBootstrap bootstrap = new ServerBootstrap(
- new NioServerSocketChannelFactory(
- Executors.newCachedThreadPool(),
- Executors.newCachedThreadPool()));
- // Set up the event pipeline factory.
- bootstrap.setPipelineFactory(new HttpServerPipelineFactory());
- // Bind and start to accept incoming connections.
- bootstrap.bind(new InetSocketAddress(8081));
- }
- }
HttpServerPipelineFactory.java
- package org.jboss.netty.example.http.snoop;
- import static org.jboss.netty.channel.Channels.*;
- import org.jboss.netty.channel.ChannelPipeline;
- import org.jboss.netty.channel.ChannelPipelineFactory;
- import org.jboss.netty.handler.codec.http.HttpContentCompressor;
- import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
- import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
- public class HttpServerPipelineFactory implements ChannelPipelineFactory {
- public ChannelPipeline getPipeline() throws Exception {
- // Create a default pipeline implementation.
- ChannelPipeline pipeline = pipeline();
- // Uncomment the following line if you want HTTPS
- //SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
- //engine.setUseClientMode(false);
- //pipeline.addLast("ssl", new SslHandler(engine));
- pipeline.addLast("decoder", new HttpRequestDecoder());
- // Uncomment the following line if you don't want to handle HttpChunks.
- //pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));
- pipeline.addLast("encoder", new HttpResponseEncoder());
- // Remove the following line if you don't want automatic content compression.
- pipeline.addLast("deflater", new HttpContentCompressor());
- pipeline.addLast("handler", new HttpRequestHandler());
- return pipeline;
- }
- }
HttpRequestHandler.java
- package org.jboss.netty.example.http.snoop;
- import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
- import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
- import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
- import static org.jboss.netty.handler.codec.http.HttpVersion.*;
- import java.util.List;
- import java.util.Map;
- import java.util.Map.Entry;
- import java.util.Set;
- import org.jboss.netty.buffer.ChannelBuffer;
- import org.jboss.netty.buffer.ChannelBuffers;
- import org.jboss.netty.channel.ChannelFuture;
- import org.jboss.netty.channel.ChannelFutureListener;
- import org.jboss.netty.channel.ChannelHandlerContext;
- import org.jboss.netty.channel.ExceptionEvent;
- import org.jboss.netty.channel.MessageEvent;
- import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
- import org.jboss.netty.handler.codec.http.Cookie;
- import org.jboss.netty.handler.codec.http.CookieDecoder;
- import org.jboss.netty.handler.codec.http.CookieEncoder;
- import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
- import org.jboss.netty.handler.codec.http.HttpChunk;
- import org.jboss.netty.handler.codec.http.HttpChunkTrailer;
- import org.jboss.netty.handler.codec.http.HttpRequest;
- import org.jboss.netty.handler.codec.http.HttpResponse;
- import org.jboss.netty.handler.codec.http.QueryStringDecoder;
- import org.jboss.netty.util.CharsetUtil;
- /**
- * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
- * @author Andy Taylor (andy.taylor@jboss.org)
- * @author <a href="http://gleamynode.net/">Trustin Lee</a>
- *
- * @version $Rev: 2368 $, $Date: 2010-10-18 17:19:03 +0900 (Mon, 18 Oct 2010) $
- */
- public class HttpRequestHandler extends SimpleChannelUpstreamHandler {
- private HttpRequest request;
- private boolean readingChunks;
- /** Buffer that stores the response content */
- private final StringBuilder buf = new StringBuilder();
- @Override
- public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
- if (!readingChunks) {
- HttpRequest request = this.request = (HttpRequest) e.getMessage();
- if (is100ContinueExpected(request)) {
- send100Continue(e);
- }
- buf.setLength(0);
- buf.append("WELCOME TO THE WILD WILD WEB SERVER\r\n");
- buf.append("===================================\r\n");
- buf.append("VERSION: " + request.getProtocolVersion() + "\r\n");
- buf.append("HOSTNAME: " + getHost(request, "unknown") + "\r\n");
- buf.append("REQUEST_URI: " + request.getUri() + "\r\n\r\n");
- for (Map.Entry<String, String> h: request.getHeaders()) {
- buf.append("HEADER: " + h.getKey() + " = " + h.getValue() + "\r\n");
- }
- buf.append("\r\n");
- QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.getUri());
- Map<String, List<String>> params = queryStringDecoder.getParameters();
- if (!params.isEmpty()) {
- for (Entry<String, List<String>> p: params.entrySet()) {
- String key = p.getKey();
- List<String> vals = p.getValue();
- for (String val : vals) {
- buf.append("PARAM: " + key + " = " + val + "\r\n");
- }
- }
- buf.append("\r\n");
- }
- if (request.isChunked()) {
- readingChunks = true;
- } else {
- ChannelBuffer content = request.getContent();
- if (content.readable()) {
- buf.append("CONTENT: " + content.toString(CharsetUtil.UTF_8) + "\r\n");
- }
- writeResponse(e);
- }
- } else {
- HttpChunk chunk = (HttpChunk) e.getMessage();
- if (chunk.isLast()) {
- readingChunks = false;
- buf.append("END OF CONTENT\r\n");
- HttpChunkTrailer trailer = (HttpChunkTrailer) chunk;
- if (!trailer.getHeaderNames().isEmpty()) {
- buf.append("\r\n");
- for (String name: trailer.getHeaderNames()) {
- for (String value: trailer.getHeaders(name)) {
- buf.append("TRAILING HEADER: " + name + " = " + value + "\r\n");
- }
- }
- buf.append("\r\n");
- }
- writeResponse(e);
- } else {
- buf.append("CHUNK: " + chunk.getContent().toString(CharsetUtil.UTF_8) + "\r\n");
- }
- }
- }
- private void writeResponse(MessageEvent e) {
- // Decide whether to close the connection or not.
- boolean keepAlive = isKeepAlive(request);
- // Build the response object.
- HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
- response.setContent(ChannelBuffers.copiedBuffer(buf.toString(), CharsetUtil.UTF_8));
- response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");
- if (keepAlive) {
- // Add 'Content-Length' header only for a keep-alive connection.
- response.setHeader(CONTENT_LENGTH, response.getContent().readableBytes());
- }
- // Encode the cookie.
- String cookieString = request.getHeader(COOKIE);
- if (cookieString != null) {
- CookieDecoder cookieDecoder = new CookieDecoder();
- Set<Cookie> cookies = cookieDecoder.decode(cookieString);
- if(!cookies.isEmpty()) {
- // Reset the cookies if necessary.
- CookieEncoder cookieEncoder = new CookieEncoder(true);
- for (Cookie cookie : cookies) {
- cookieEncoder.addCookie(cookie);
- }
- response.addHeader(SET_COOKIE, cookieEncoder.encode());
- }
- }
- // Write the response.
- ChannelFuture future = e.getChannel().write(response);
- // Close the non-keep-alive connection after the write operation is done.
- if (!keepAlive) {
- future.addListener(ChannelFutureListener.CLOSE);
- }
- }
- private void send100Continue(MessageEvent e) {
- HttpResponse response = new DefaultHttpResponse(HTTP_1_1, CONTINUE);
- e.getChannel().write(response);
- }
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
- throws Exception {
- e.getCause().printStackTrace();
- e.getChannel().close();
- }
- }
DatabaseUtil.java
- package org.jboss.netty.example.http.snoop;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Statement;
- import org.apache.commons.dbcp.BasicDataSource;
- /**
- * 连接和使用数据库资源的工具类
- *
- * @author yifangyou
- * @version gtm 2010-09-27
- */
- public class DatabaseUtil {
- /**
- * 数据源
- */
- private BasicDataSource dataSource;
- /**
- * 数据库连接
- */
- public Connection conn;
- /**
- * 获取数据源
- * @return 数据源
- */
- public BasicDataSource getDataSource() {
- return dataSource;
- }
- /**
- * 设置数据源
- * @param dataSource 数据源
- */
- public void setDataSource(BasicDataSource dataSource) {
- this.dataSource = dataSource;
- }
- /**
- * 获取数据库连接
- * @return conn
- */
- public Connection getConnection() {
- try {
- conn = dataSource.getConnection();
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- return conn;
- }
- /**
- * 关闭数据库连接
- * @param conn
- */
- public void closeConnection(Connection conn) {
- if (null != conn) {
- try {
- conn.close();
- conn = null;
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- /**
- * 获取执行SQL的工具
- * @param conn 数据库连接
- * @param sql SQL语句
- * @return prepStmt
- */
- public PreparedStatement getPrepStatement(Connection conn, String sql) {
- PreparedStatement prepStmt = null;
- try {
- prepStmt = conn.prepareStatement(sql);
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return prepStmt;
- }
- /**
- * 关闭数据库资源
- * @param prepStmt
- */
- public void closePrepStatement(PreparedStatement prepStmt) {
- if (null != prepStmt) {
- try {
- prepStmt.close();
- prepStmt = null;
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- }
2.2 导入jar包
在工程下添加lib目录
把jar包拷进去
点击工程的右键“propertis”->Java Build Path->Libraries->Add JARS
3.分析如何注入
Netty的运行过程是
因此我们需要
Spring注入入口在HttpServer里的main函数
把HttpRequestHandler注入到HttpServerPipelineFactory,
把HttpServerPipelineFactory注入到HttpServer
另外我们在HttpRequestHandler需要用到mysql连接池,因此还要把mysql连接池注入到HttpRequestHandler
本文转自yifangyou 51CTO博客,原文链接:http://blog.51cto.com/yifangyou/622607,如需转载请自行联系原作者