众所周知,Netty是一款高性能的I/O框架,那怎么在它之上构建Web服务呢,今天网上搜了一篇文章,学习了一下:
Java Servlets have been vastly used in companies for more than 10 years now. Recently another project from JBoss named Netty has gained on popularity to serve data. From Netty website: "Netty has succeeded to find a way to achieve ease of development, performance, stability, and flexibility without a compromise.".
But at the moment to serve data or to handle requests, you need to choose for the implementation either for a Servlet or for Netty.
As main developer of XINS, an open-source web services framework, I‘ve developed a few years ago a basic Servlet container to be able to run unit tests and to run WAR if you wanted to with java -jar my-api.war or xins run-my-api.
For the release of XINS 3.0, I‘ve decided to put the Servlet container on top of Netty.
Netty takes cares of the IO and the HTTP handling and my Servlet container takes care of the handling of the HTTP request to the Servlet itself.
How to do it
First you need to handle HTTP data with a Netty ChannelPipeline using apipeline factory:
public class DefaultNettyServletPipelineFactory implements ChannelPipelineFactory { ... public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = pipeline(); pipeline.addLast("decoder", new HttpRequestDecoder()); pipeline.addLast("encoder", new HttpResponseEncoder()); pipeline.addLast("deflater", new HttpContentCompressor()); pipeline.addLast("handler", servletHandler); // will convert http request to servlet request return pipeline; }
Then you will need a NettyServletHandler that converts Netty HttpRequest to a Servlet request:
public class NettyServletHandler extends SimpleChannelUpstreamHandler { ... @Override public void messageReceived(ChannelHandlerContext context, MessageEvent event) throws Exception { HttpRequest request = (HttpRequest) event.getMessage(); // Then get URL, method, headers, ... and pass the values to the Servlet container. }
You will also need a method to start the server:
public void startServer(int port, String pipelineFactory) throws Exception { ServerBootstrap server = new ServerBootstrap( new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); if (pipelineFactory == null) { // If the user doesn‘t have a specific pipeline use the default one pipelineFactory = "org.xins.common.servlet.container.DefaultNettyServletPipelineFactory"; } DefaultNettyServletPipelineFactory pipelineFactoryClass = (DefaultNettyServletPipelineFactory) Class.forName(pipelineFactory).newInstance(); pipelineFactoryClass.setServletHandler(this); server.setPipelineFactory(pipelineFactoryClass); server.bind(new InetSocketAddress(port)); }
And voilà! Your server code has the best of both worlds: it uses a standard API and it runs on Netty.