1. HttpServer

HttpServer作为http服务器的server端:

public final class HttpServer {    private static final String IP = "127.0.0.1";    private static final int PORT = 9000;    private static final int BIZ_THREAD_SIZE = 100;    private static final Logger logger = LoggerFactory.getLogger(HttpServer.class);    public static void main(String[] args) throws Exception {        System.out.println("启动Server...");        HttpServer.start();    }    public static void start() throws Exception {        initServerConfig();        // new NioEventLoopGroup()默认线程数为CPU核心数的两倍(Runtime.getRuntime().availableProcessors() * 2),所以这里不用额外指定。        EventLoopGroup bossGroup = new NioEventLoopGroup();        // 这里worker不能使用默认,如果并发大的话需要增加线程数量        EventLoopGroup workerGroup = new NioEventLoopGroup(BIZ_THREAD_SIZE);        try {            ServerBootstrap bootstrap = new ServerBootstrap();            bootstrap.group(bossGroup, workerGroup)                    .channel(NioServerSocketChannel.class)                    // ChannelOption.SO_BACKLOG对应的是tcp/ip协议listen函数中的backlog参数。函数listen(int socketfd, int backlog)用来初始化服务端可连接队列。                    // 服务端处理客户端连接请求是顺序处理的,所以同一时间只能处理一个客户端连接,多个客户端来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理,backlog参数指定了队列的大小。                    .option(ChannelOption.SO_BACKLOG, 1024)                    .handler(new LoggingHandler(LogLevel.INFO))                    .childOption(ChannelOption.SO_KEEPALIVE, true) // 子channel配置,保持长连接                    .childHandler(new HttpServerInitializer());            // sync追踪代码可以得到:this.await(),实现阻塞            ChannelFuture channelFuture = bootstrap.bind(IP, PORT).sync();            // 启动失败则关闭线程组            if (!channelFuture.isSuccess()) {                shutdown(bossGroup, workerGroup);                throw new RuntimeException(channelFuture.cause());            }            channelFuture.channel().closeFuture().sync();            logger.info("bootstrap channel closed...");        } finally {            shutdown(bossGroup, workerGroup);        }    }    // 添加路径映射和过滤器映射    private static void initServerConfig() {        ServerContext.setFilter(ServerContext.MAPPING_ALL,  Filter.class);        ServerContext.setFilter("/template", TemplateFilter.class);        ServerContext.setAction(ServerContext.MAPPING_ALL, DefaultIndexAction.class);        ServerContext.setAction("/template", TemplateAction.class);        ServerContext.setAction("/files", FileAction.class);        ServerContext.setROOT("root");        ServerContext.setPORT(8090);    }    private static void shutdown(EventLoopGroup bossGroup, EventLoopGroup workerGroup) {        bossGroup.shutdownGracefully();        workerGroup.shutdownGracefully();    }}

HttpServerInitializer设置http编解码器,以及请求aggregator等:

public class HttpServerInitializer extends ChannelInitializer<SocketChannel> {    @Override    public void initChannel(SocketChannel socketChannel) {        ChannelPipeline pipeline = socketChannel.pipeline();        pipeline                //或者使用HttpRequestDecoder & HttpResponseEncoder                .addLast(new HttpServerCodec())                //把Http Aggregator放入管道里。Http Aggregator会把多个消息转换为一个单一的FullHttpRequest或是FullHttpResponse                .addLast(new Http Aggregator(1024 * 1024))                //压缩Http消息//                            .addLast(new HttpChunkContentCompressor())                //大文件支持,文件上传时使用//                            .addLast(new ChunkedWriteHandler())                .addLast(new HttpServerExpectContinueHandler())                .addLast(new HttpServerDispatcherHandler());    }}

入栈处理器,用于转发http请求,类似于DispatcherServlet:

public class HttpServerDispatcherHandler extends ChannelInboundHandlerAdapter {    @Override    public void channelRead(ChannelHandlerContext ctx,   msg) {        if (!(msg instanceof FullHttpRequest)) {            return;        }        FullHttpRequest fullHttpRequest = (FullHttpRequest) msg;        final Request customerRequest = Request.build(ctx, fullHttpRequest);        final Response customerResponse = Response.build(ctx, customerRequest);        if (customerRequest.getRequestUrl().equals(HttpHelper.FAVICON_ICO)) {            return;        }        // 过滤器放行之后,执行action,实际处理业务逻辑        boolean passFilter = doFilter(customerRequest, customerResponse);        if (passFilter) {            doAction(customerRequest, customerResponse);        }        //如果发送请求未被触发,则触发之,否则跳过。        if(false == customerResponse.isSent()) {            customerResponse.response();        }    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {        cause.printStackTrace();        ctx.close();    }    @Override    public void channelReadComplete(ChannelHandlerContext ctx) {        ctx.flush();    }    /**     * 过滤器     * @param request     * @param response     * @return     */    private boolean doFilter(Request request, Response response) {        //全局过滤器        Filter filter = ServerContext.getFilter(ServerContext.MAPPING_ALL);        if(null != filter) {            if(false == filter.doFilter(request, response)) {                return false;            }        }        //自定义过滤器        filter = ServerContext.getFilter(request.getRequestUrl());        if(null != filter) {            if(false == filter.doFilter(request, response)) {                return false;            }        }        return true;    }    /**     * 请求处理器     * 相当于servlet     * @param request     * @param response     */    private void doAction(Request request, Response response) {        Action action = ServerContext.getAction(request.getRequestUrl());        if (null == action) {            //查找匹配所有路径的Action            action = ServerContext.getAction(ServerContext.MAPPING_ALL);            if(null == action) {                // 非Action方法,调用静态文件读取                action = Singleton.get(FileAction.class);            }        }        action.doAction(request, response);    }}

过滤器

public interface Filter {        /**     * 执行过滤     * @param request 请求对象     * @param response 响应对象     * @return 如果返回true,则继续执行下一步内容,否则中断     */    boolean doFilter(Request request, Response response);}

过滤器示例:

public class TemplateFilter implements Filter {    @Override    public boolean doFilter(Request request, Response response) {        System.out.println("welcome in template filter...");        return true;    }}

action

action用于实际处理业务,顶层接口:

public interface Action {    void doAction(Request request, Response response);}

抽象Adapter:

public abstract class AbstractAction implements Action {    @Override    public void doAction(Request request, Response response) {        String method = request.getMethod();        if (HttpHelper.METHOD_GET.equals(method)) {            doGet(request, response);        } else if (HttpHelper.METHOD_POST.equals(method)) {            doPost(request, response);        } else if (HttpHelper.METHOD_PUT.equals(method)) {            doPut(request, response);        } else if (HttpHelper.METHOD_DELETE.equals(method)) {            doDelete(request, response);        } else if (HttpHelper.METHOD_HEAD.equals(method)) {            doHead(request, response);        } else if (HttpHelper.METHOD_OPTIONS.equals(method)) {            doOptions(request, response);        } else if (HttpHelper.METHOD_TRACE.equals(method)) {            doTrace(request, response);        }    }    protected void doGet(Request request, Response response) {}    protected void doPost(Request request, Response response) {}    protected void doPut(Request request, Response response) {}    protected void doDelete(Request request, Response response) {}    protected void doOptions(Request request, Response response) {}    protected void doHead(Request request, Response response) {}    protected void doTrace(Request request, Response response) {}}

action示例:

public class TemplateAction extends AbstractAction {    @Override    protected void doGet(Request request, Response response) {        response.setContentType(HttpHelper.CONTENT_TYPE_JSON);        response.setContent("welcome in template action, do get...");    }    @Override    protected void doPost(Request request, Response response) {        response.setContent("welcome in template action, do post...");    }}

。。。

收藏 打印