使用Netty实现HttpServer

package netty;

import static io.netty.handler.codec.http.HttpHeaderNames.CONNECTION;
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Values.KEEP_ALIVE;

import com.alibaba.fastjson.JSON;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.HttpServerExpectContinueHandler;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslHandler;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import lombok.Cleanup;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;

/**
 * Test
 *
 * @author xfyou
 */
public class Test {

  @SneakyThrows
  public static void main(String[] args) {
    HttpServer server = new HttpServer(8080);
    server.start();
  }

  @RequiredArgsConstructor
  private static class HttpServer {

    private final Integer port;

    @SneakyThrows
    public void start() {
      EventLoopGroup bossGroup = new NioEventLoopGroup(1);
      EventLoopGroup workerGroup = new NioEventLoopGroup(20);
      try {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup, workerGroup)
            .option(ChannelOption.SO_BACKLOG, 128)
            .childOption(ChannelOption.SO_KEEPALIVE, true)
            .channel(NioServerSocketChannel.class)
            .childHandler(new ChannelInitializerImpl());
        ChannelFuture future = serverBootstrap.bind(port).sync();
        System.out.println("Server started...");
        future.channel().closeFuture().sync();
      } finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
      }
    }

  }

  private static final class ChannelInitializerImpl extends ChannelInitializer<Channel> {

    private final SslContext sslContext;

    @SneakyThrows
    public ChannelInitializerImpl() {
      sslContext = createSslContext();
    }

    @SneakyThrows
    private SslContext createSslContext() {
      String keyStoreFilePath = "/root/.ssl/test.pkcs12";
      String keyStorePassword = "passwd";
      KeyStore keyStore = KeyStore.getInstance("PKCS12");
      @Cleanup InputStream inputStream = new FileInputStream(keyStoreFilePath);
      keyStore.load(inputStream, keyStorePassword.toCharArray());
      KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
      keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
      return SslContextBuilder.forServer(keyManagerFactory).build();
    }

    @Override
    protected void initChannel(Channel ch) {
      ChannelPipeline cp = ch.pipeline();
      // support SSL/TLS
      cp.addLast(new SslHandler(sslContext.newEngine(ch.alloc())));
      // decode and encode
      cp.addLast(new HttpServerCodec());
      // handle message-body of POST
      cp.addLast(new HttpObjectAggregator(Integer.MAX_VALUE));
      cp.addLast(new HttpServerExpectContinueHandler());
      cp.addLast(new SimpleChannelInboundHandler<FullHttpRequest>() {
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) {
          System.out.println(msg.content().toString(StandardCharsets.UTF_8));
          System.out.println(ch);
          String res = "I am OK";
          FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(JSON.toJSONString(res).getBytes(StandardCharsets.UTF_8)));
          response.headers().set(CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
          response.headers().set(CONTENT_LENGTH, response.content().readableBytes());
          if (HttpUtil.isKeepAlive(msg)) {
            response.headers().set(CONNECTION, KEEP_ALIVE);
            ctx.write(response);
          } else {
            ctx.write(response).addListener(ChannelFutureListener.CLOSE);
          }
          ctx.flush();
        }
      });
    }
  }

}

猜你喜欢

转载自www.cnblogs.com/frankyou/p/12144087.html