手写tomcat-基于netty

1 篇文章 0 订阅

模仿《netty4 核心核心原理》一书中的例子,通过netty 实现简单tomcat功能。
通过启动启动类,在浏览器输入对应的地址,实现访问:
在这里插入图片描述

具体代码如下:

  1. tomcat servlet类
public abstract class MServletNetty {
    public void service(MRequestNetty request, MRsponseNetty response)throws Exception{
        if("GET".equalsIgnoreCase(request.getMethod())){
            doGet(request,response);
        }else {
            doPost(request,response);
        }
    }

    public abstract void doGet(MRequestNetty request,MRsponseNetty response) throws Exception;
    public abstract void doPost(MRequestNetty request,MRsponseNetty response) throws Exception;
}

2,tomcat servlet实现类=对应controller

public class FirstServletNetty extends MServletNetty {
    @Override
    public void doGet(MRequestNetty request, MRsponseNetty response) throws Exception {
        this.doPost(request,response);
    }

    @Override
    public void doPost(MRequestNetty request, MRsponseNetty response) throws Exception {
        response.write("firstServletNetty");
    }
}

3,tomcat servlet实现类2=对应controller

public class SecondServletNetty extends MServletNetty {
    @Override
    public void doGet(MRequestNetty request, MRsponseNetty response) throws Exception {
        this.doPost(request,response);
    }

    @Override
    public void doPost(MRequestNetty request, MRsponseNetty response) throws Exception {
        response.write("SecondServletNetty");
    }
}

4,请求体类

public class MRequestNetty {

    private ChannelHandlerContext ctx;
    private HttpRequest request;

    public MRequestNetty(ChannelHandlerContext ctx, HttpRequest request) {
        this.ctx = ctx;
        this.request = request;
    }

    public String getUrl(){
      return   request.uri();
    }

    public String getMethod(){
        return request.method().name();
    }
}```

5,响应体类

public class MRsponseNetty {

    private ChannelHandlerContext ctx;
    private HttpRequest request;

    public MRsponseNetty(ChannelHandlerContext ctx, HttpRequest request) {
        this.ctx = ctx;
        this.request = request;
    }

  public void write(String out)throws Exception{
        try {
            if(out == null || out.length()==0){
                return;
            }
            DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(out.getBytes(StandardCharsets.UTF_8)));
            response.headers().set("Content-Type", "text/html;");
            ctx.write(response);

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            ctx.flush();
            ctx.close();
        }
  }
}

6,tomcat 核心类-启动类

public class MTomcatNetty {
    private int port = 8080;
    private ServerSocket serverSocket;
    private Map<String, MServletNetty> servletMapping = new HashMap<>();
    private Properties webXml = new Properties();

    private void init(){
        try {
//            模拟加载配置文件
            String path = this.getClass().getResource("/").getPath();
            FileInputStream fileInputStream = new FileInputStream(path + "configNetty.properties");
            webXml.load(fileInputStream);
            for (Object o : webXml.keySet()) {
                String key = o.toString();
                if(key.endsWith(".url")){
                    String servletName = key.replaceAll("\\.url$", "");
                    String url = webXml.getProperty(key);
                    String className = webXml.getProperty(servletName + ".className");
                    MServletNetty servlet = (MServletNetty) Class.forName(className).newInstance();
                    servletMapping.put(url, servlet);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public void start(){
        init();
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workGroup = new NioEventLoopGroup();
        try{
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel socketChannel) throws Exception {
                    socketChannel.pipeline().addLast(new HttpResponseEncoder());
                    socketChannel.pipeline().addLast(new HttpRequestDecoder());
                    socketChannel.pipeline().addLast(new MtomcatHandler());
                }
            }).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);
            ChannelFuture channelFuture = serverBootstrap.bind(this.port).sync();
            System.out.println("Mtomcat 已启动,监听的端口是:"+port);
            channelFuture.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }

    }

    public static void main(String[] args) {
        new MTomcatNetty().start();
    }

    public class MtomcatHandler extends ChannelInboundHandlerAdapter {

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg)throws Exception{
            if (msg instanceof HttpRequest) {
                System.out.println("channel Read");
                HttpRequest req = (HttpRequest) msg;
                MRequestNetty request = new MRequestNetty(ctx,req);
                MRsponseNetty response = new MRsponseNetty(ctx,req);

                String url = request.getUrl();
                if(servletMapping.containsKey(url)){
                    servletMapping.get(url).service(request,response);
                }else {
                    response.write("404-not found");
                }
            }
        }
    }
}

7 配置文件:

servlet.one.url=/firstServlet.do
servlet.one.className=com.test.zlb.NettyBase.FirstServletNetty

servlet.two.url=/secondServlet.do
servlet.two.className=com.test.zlb.NettyBase.SecondServletNetty

8,项目结构:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值