zoukankan      html  css  js  c++  java
  • Netty从零搭建Http服务器 终于在JNDI,RMI的驱使下,开始了网络这一块,作为Tomcat内核的netty成为开门红。

    Netty从零搭建Http服务器

    终于在JNDI,RMI的驱使下,开始了网络这一块,作为Tomcat内核的netty成为开门红。

    • 本地服务目录如下

    image-20211222143655884

    • 本地静态资源如下

    image-20211222143731433

    1.搭建maven工程.pom依赖如下

    <!--  JSON解析  -->
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.2.2</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
    </dependency>
    <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
    <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>4.1.72.Final</version>
    </dependency>
    

    2.服务启动类

    package cn.http;
    
    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.nio.NioServerSocketChannel;
    
    /**
     * @author 王居三木超
     * @version 1.0
     * @date 2021/12/22 11:02
     * @description TODO
     **/
    public class HttpServer {
    
        //定义线程池
        private static NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        private static NioEventLoopGroup workerGroup = new NioEventLoopGroup();
    
        public static void main(String[] args) throws InterruptedException {
            //服务端引导器
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            try {
                //设置EventLoop
                serverBootstrap.group(bossGroup, workerGroup)
                    //设置channel
                        .channel(NioServerSocketChannel.class)
                    //设置处理器
                        .childHandler(new ServerInitializer());
                //绑定端口
                ChannelFuture channelFuture = serverBootstrap.bind(8273).sync();
                //设置优雅关闭
                channelFuture.channel().closeFuture().sync();
            } finally {
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        }
    }
    

    3.处理器编写

    package cn.http;
    
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.ChannelPipeline;
    import io.netty.channel.socket.nio.NioSocketChannel;
    import io.netty.handler.codec.http.HttpServerCodec;
    
    /**
     * @author 王居三木超
     * @version 1.0
     * @date 2021/12/22 11:08
     * @description TODO
     **/
    public class ServerInitializer extends ChannelInitializer<NioSocketChannel> {
        @Override
        protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
            ChannelPipeline pipeline = nioSocketChannel.pipeline();
            //设置http编-解码器
            pipeline.addLast("MyHttpServerCodec", new HttpServerCodec());
            //设置ChannelInboundHandler
            pipeline.addLast("ServerHandler", new ServerHandler());
        }
    }
    

    4.ChannelInboundHandler

    package cn.http;
    
    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.Unpooled;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.SimpleChannelInboundHandler;
    import io.netty.handler.codec.http.*;
    import io.netty.util.CharsetUtil;
    import org.springframework.core.io.FileSystemResource;
    
    import java.io.IOException;
    
    /**
     * @author 王居三木超
     * @version 1.0
     * @date 2021/12/22 11:10
     * @description TODO
     **/
    public class ServerHandler extends SimpleChannelInboundHandler<HttpObject> {
    
        //icon路径
        private String favicon = "/favicon.ico";
        //获取resource路径下的static本地位置
        private String localPath = getClass().getResource("/static/").getFile();
        private byte[] bytes;
    
        private enum FileEndType {
            //Local file of request path
            HTML("html", 0),
            CSS("css", 1),
            JS("js", 2),
            ICO("ico", 3);
            public String type;
            public Integer code;
    
            FileEndType(String type, Integer code) {
                this.type = type;
                this.code = code;
            }
        }
    
        @Override
        protected void channelRead0(ChannelHandlerContext channelHandlerContext, HttpObject request) throws IOException {
            //判断是否为请求
            if (request instanceof HttpRequest) {
                //获取访问路径
                String uri = ((HttpRequest) request).uri();
                //如果为favicon.ico进行拦截
                if (favicon.equals(uri)) {
                    return;
                }
                //拼接访问地址到本地的位置
                String path = localPath + uri;
                //获取文件
                FileSystemResource localFile = new FileSystemResource(path);
                //文件不存在,返回404页面
                if (!localFile.exists()) {
                    path = localPath + "404.html";
                    localFile = new FileSystemResource(path);
                    bytes = new byte[(int) localFile.getFile().length()];
                    localFile.getInputStream().read(bytes);
                    try {                    
                        throw new ExceptionError(ExceptionError.error());
                    } catch (ExceptionError exceptionError) {
                        //自定义返回体方法
                        channelHandlerContext.writeAndFlush(responseContent(exceptionError.getMessage()));
                    }
                }
                //文件存在,正常返回资源
                bytes = new byte[(int) localFile.getFile().length()];
                localFile.getInputStream().read(bytes);
                //判断访问文件类型,进行返回
                if (path.endsWith(FileEndType.HTML.type)) {
                    channelHandlerContext.writeAndFlush(responseHtml(bytes));
                } else if (path.endsWith(FileEndType.CSS.type)) {
                    channelHandlerContext.writeAndFlush(responseCss(bytes));
                } else if (path.endsWith(FileEndType.JS.type)) {
                    channelHandlerContext.writeAndFlush(responseJs(bytes));
                }
            }
        }
    
        //自定义信息返回体
        private HttpResponse responseContent(String mes) {
            //返回体内容ByteBuf
            ByteBuf content = Unpooled.copiedBuffer(mes, CharsetUtil.UTF_8);
            //生成response
            HttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1
                    , HttpResponseStatus.OK, content);
            //设置返回体头步CONTENT_TYPE信息
            response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
            //设置返回体头步CONTENT_LENGTH信息
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
            return response;
        }
        //自定义资源返回体
        private HttpResponse response(byte[] bytes, String contentType, HttpResponseStatus status) {
            ByteBuf content = Unpooled.copiedBuffer(bytes);
            HttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1
                    , status, content);
            response.headers().set(HttpHeaderNames.CONTENT_TYPE, contentType);
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
            return response;
        }
    
        private HttpResponse responseHtml(byte[] bytes) {
            return response(bytes, "text/html", HttpResponseStatus.OK);
        }
    
        private HttpResponse responseHtml(byte[] bytes, HttpResponseStatus status) {
            return response(bytes, "text/html", status);
        }
    
        private HttpResponse responseJs(byte[] bytes) {
            return response(bytes, "text/javascript", HttpResponseStatus.OK);
        }
    
        private HttpResponse responseJs(byte[] bytes, HttpResponseStatus status) {
            return response(bytes, "text/javascript", status);
        }
    
        private HttpResponse responseCss(byte[] bytes) {
            return response(bytes, "text/css", HttpResponseStatus.OK);
        }
    
        private HttpResponse responseCss(byte[] bytes, HttpResponseStatus status) {
            return response(bytes, "text/css", status);
        }
    }
    

    5.异常类如下

    package cn.http;
    
    import cn.hutool.json.JSONObject;
    
    /**
     * @author 王居三木超
     * @version 1.0
     * @date 2021/12/22 13:06
     * @description TODO
     **/
    public class ExceptionError extends Exception {
    
    
        private String message;
    
        public ExceptionError(String message) {
            super(message);
            this.message = message;
        }
    
        @Override
        public String getMessage() {
            return message;
        }
    
        public static String error() {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("version", "1.1");
            jsonObject.put("author", "wjsmc");
            jsonObject.put("localwebsite", "http://www.openpool.cn/");
            return jsonObject.toString();
        }
    }
    

    6.测试访问

  • 相关阅读:
    opengl像素格式管理
    opengl的体系结构
    符号文件——Windows 应用程序调试必备
    [Study Note] Patterns in Practice 20100404
    “在我的机器上可以运行”症状自查(Windows编程)
    [Study Note] Patterns in Practice 20100402
    [Study Note] Patterns in Practice 20100406
    [Study Note] Design and Testability 20100410
    [Study Note] Patterns in Practice 20100403
    [Study Note] Design and Testability 20100411
  • 原文地址:https://www.cnblogs.com/hmcjsc/p/15719504.html
Copyright © 2011-2022 走看看