zoukankan      html  css  js  c++  java
  • Netty练手项目-简单Http服务器

      简单的设计思路就是,启动一个可以截断并处理Http请求的服务器代码。使用netty提供的boss线程与worker线程的模型,并使用netty的http解码器。自行编写了http url处理的部分。在接口层面,使用json作为格式。

      初始化扫描会指定扫描controller.container下的类,使用了自定义Annotation并且单例的方式加载,未考虑太多细节就为了好玩。

       接下来使用postman尝试调用接口。

      一个简单的netty搭建的web服务就完成了。

    package server;
    
    import handler.HttpServerHandler;
    import initScan.InitialProcess;
    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.ChannelOption;
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioServerSocketChannel;
    import io.netty.handler.codec.http.HttpServerCodec;
    
    /**
     * Created by MacBook on 2019/7/14.
     */
    public class ServerStarter {
    
        private EventLoopGroup boss ;
    
        private EventLoopGroup worker ;
    
        private int port;
    
        private static int DEFAULT_PORT = 8080;
    
        public ServerStarter(){
            boss = new NioEventLoopGroup();
            worker = new NioEventLoopGroup();
            port = DEFAULT_PORT;
        }
    
        public ServerStarter(int port){
            this();
            if(port < 0 || port > 65535){
                throw new IllegalArgumentException("port:"+port+" is illegal");
            }
            this.port = port;
        }
    
        public void startup() throws InterruptedException{
    
            if(boss.isShutdown() || worker.isShutdown()){
                throw new IllegalStateException("server was closed");
            }
    
            // 初始化容器
            InitialProcess initialProcess = new InitialProcess();
            initialProcess.init();
    
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            System.out.println("=====http server start ");
            serverBootstrap.channel(NioServerSocketChannel.class)
                    .group(boss,worker)
                    .childOption(ChannelOption.SO_KEEPALIVE,true)
                    .option(ChannelOption.SO_BACKLOG,1024)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast("http-decode",new HttpServerCodec());
                            socketChannel.pipeline().addLast(new HttpServerHandler());
                        }
                    });
    
            ChannelFuture future = serverBootstrap.bind(port).sync();
    
            System.out.println("server port listen:"+port);
    
            future.channel().closeFuture().sync();
    
            shutDownGracefully();
        }
    
        /**
         * 关闭管道
         */
        public void shutDownGracefully(){
            this.boss.shutdownGracefully();
            this.worker.shutdownGracefully();
        }
    
    }

      这是服务器启动的核心代码,首先初始化两个Nio线程组,把它们绑定到ServerBootstrap里,并添加Handler。

    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.parser.Feature;
    import com.alibaba.fastjson.serializer.SerializeConfig;
    import com.alibaba.fastjson.serializer.SerializerFeature;
    import controller.Properties;
    import io.netty.channel.ChannelFutureListener;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.ChannelInboundHandlerAdapter;
    import io.netty.handler.codec.http.*;
    import response.BaseResponse;
    
    import java.lang.reflect.Method;
    
    /**
     * Created by MacBook on 2019/7/14.
     */
    public class HttpServerHandler extends ChannelInboundHandlerAdapter{
    
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            if(msg instanceof HttpRequest){
                HttpRequest request = (HttpRequest)msg;
    //            boolean keepAlive = HttpUtil.isKeepAlive(request);
    
                System.out.println("http request method :"+request.method());
                System.out.println("http request uri : "+request.uri());
    
                Object controller = Properties.urlController.get(request.uri());
                Method m = Properties.urlMethod.get(request.uri());
                if(controller == null){
                    FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND);
                    ctx.writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);
    
                }else {
                    FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
    
                    httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json");
                    Object result = m.invoke(controller);
    
                    httpResponse.content().writeBytes(JSON.toJSONString(result,SerializerFeature.WriteMapNullValue).getBytes());
    
                    ctx.writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);
                }
    
            }
        }
    }

      这是处理器的代码,在经过第一个Http解码器之后,进来的对象msg已经被转化为HttpRequest了。

  • 相关阅读:
    JQ_浏览器窗口改变触发
    5. 通过PHP反序列化进行远程代码执行
    2. 文件包含(150)
    1. md5 collision(50)
    4.xpath注入详解
    2.HTTP头注入
    1.5 xss漏洞修复
    1.4 DVWA亲测XSS漏洞
    1.如何绕过WAF(Web应用防火墙)
    1.3 xss原理分析与剖析(4)
  • 原文地址:https://www.cnblogs.com/chentingk/p/11373114.html
Copyright © 2011-2022 走看看