美文网首页
基于Tomcat思想的简单web服务器(2)

基于Tomcat思想的简单web服务器(2)

作者: 初省 | 来源:发表于2019-05-07 21:02 被阅读0次

现在我们把原来的BIO改成基于netty的NIO

因为netty中自带了HTTPRequest,所以我们就不在需要之前的HTTPRequest
Response也需要做一定的修改,因为netty封装了OutputString,我们需要使用netty通过socket连接建立的管道

HTTPResponse

public class HTTPResponse {

    private ChannelHandlerContext ctx;

    public HTTPResponse(ChannelHandlerContext ctx) {
        this.ctx = ctx;
    }

    // 使用netty的管道来返回数据
    public void write(String message) throws IOException {
        DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(message.getBytes()));
        response.headers().set("Content-Type", "text/html; charset=UTF-8");
        ctx.writeAndFlush(response);
        ctx.channel().close();
    }

}

ServletMapping,ServletMappingConfig没有任何改动

Servlet将原来的HTTPRequest类改成netty封装的HttpRequest类

Servlet

public abstract class Servlet {

    public abstract void doGet(HttpRequest httpRequest, HTTPResponse httpResponse) throws IOException;

    public abstract void doPost(HttpRequest httpRequest, HTTPResponse httpResponse) throws IOException;

    public void service(HttpRequest httpRequest, HTTPResponse httpResponse) throws IOException {
        if ("GET".equals(httpRequest.getMethod().name())) {
            doGet(httpRequest, httpResponse);
        } else if ("POST".equals(httpRequest.getMethod().name())) {
            doPost(httpRequest, httpResponse);
        }
    }

}

HelloServlet 也是一样

public class HelloServlet extends Servlet {

    @Override
    public void doGet(HttpRequest httpRequest, HTTPResponse httpResponse) throws IOException {
        httpResponse.write("hello Get");
    }

    @Override
    public void doPost(HttpRequest httpRequest, HTTPResponse httpResponse) throws IOException {
        httpResponse.write("hello Post");
    }

}

主类只需要启动netty就可以了,之前的分发,我们新建一个的类,因为对于数据的读取,我们放在Hander事件处理器中了,无法从WebServer中分发

public class WebServer {

    private static Logger logger = LoggerFactory.getLogger(WebServer.class);

    private int port;

    private ServerSocket serverSocket;

    public WebServer(int port) throws IOException {
        this.port = port;
    }

    private void start() throws IOException {
        logger.info("服务器启动");
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new HttpRequestDecoder());
                        ch.pipeline().addLast(new HttpResponseEncoder());
                        ch.pipeline().addLast(new ServerHandler());
                    }
                });
        try {
            ChannelFuture f = bootstrap.bind(port).sync();
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws IOException {
        new WebServer(8888).start();
    }

}

事件处理器,定义了读取数据之后的业务逻辑

public class ServerHandler extends SimpleChannelInboundHandler<HttpRequest> {

    private static Logger logger = LoggerFactory.getLogger(ServerHandler.class);

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        logger.info("有客户端连接:" + ctx.channel().remoteAddress().toString());
        super.channelActive(ctx);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpRequest httpRequest) throws Exception {
        HTTPResponse httpResponse = new HTTPResponse(ctx);
        Dispatcher.dispatcher(httpRequest, httpResponse);
    }

}

Dispatcher 能够将request分发到正确的Servlet中

public class Dispatcher {

    private static HashMap<String, ServletMapping> hashMap;

    static {
        hashMap = new HashMap<>();
        for (ServletMapping i : ServletMappingConfig.list) {
            hashMap.put(i.getUri(), i);
        }
    }


    public static void dispatcher(HttpRequest httpRequest, HTTPResponse httpResponse) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        String clazz = hashMap.get(httpRequest.getUri()).getClazz();
        Class<Servlet> servletClass = (Class<Servlet>) Class.forName(clazz);
        Servlet servlet = servletClass.newInstance();
        servlet.service(httpRequest, httpResponse);
    }

}

这样我们就完成了一个基于NIO的web服务器,并且简化了之前的代码

相关文章

网友评论

      本文标题:基于Tomcat思想的简单web服务器(2)

      本文链接:https://www.haomeiwen.com/subject/lffuoqtx.html