netty之Tomcat

netty之Tomcat

创建一个Tomcat,使用原生api

手写一个简单的Tomcat服务器,需要的东西有:request和response,分别处理请求和响应,当用户发送http请求时,request负责接收发送过来的请求体,然后进行解析,调用对应的servlet进行业务处理,然后通过response响应给客户端。

  1. 首先需要定义一个servlet负责处理get请求或post 请求。
  2. 用户通过创建servlet继承我们提供的servlet来自定义自己的方法,执行自己的业务逻辑
  3. 还需要创建request类,负责接收请求,并对接收到的数据进行解析,找到要执行的方法
  4. response负责处理响应给客户端的数据
  5. 这里通过web.properties的方式进行配置,因此还需要读取配置文件进行解析获取到方法的映射也就是将方法名和路径关联起来
  6. 如此就可以实现一个简单的Tomcat服务器。

开始

创建servlet抽象类

package com.lany.mytomcat;

/**
 * @author liuyanyan
 * @date 2021/12/14 15:21
 */
public abstract class GPServlet {
    public void service(GPRequest request,GPResponse response) throws Exception {
        if("GET".equalsIgnoreCase(request.getMethod())){
            doGet(request,response);
        }else{
            doPost(request,response);
        }
    }

    protected abstract void doPost(GPRequest request, GPResponse response) throws Exception;

    protected abstract void doGet(GPRequest request, GPResponse response) throws Exception;

}

用户自定义自己的servlet

package com.lany.mytomcat;

/**
 * @author liuyanyan
 * @date 2021/12/14 15:24
 */
public class FirstServlet extends GPServlet {

    @Override
    protected void doPost(GPRequest request, GPResponse response) throws Exception {
        response.write("This is First Servlet");
    }

    @Override
    protected void doGet(GPRequest request, GPResponse response) throws Exception {
        this.doPost(request, response);
    }
}

配置web.properties

servlet.one.url=/firstServlet.do
servlet.one.className=com.lany.mytomcat.FirstServlet

servlet.two.url=/secondServlet.do
servlet.two.className=com.lany.mytomcat.SecondServlet

创建GPRequest类

request对象就是通过读取Http请求头的信息进行解析,后台服务器获得到的数据就是一段字符串

GET /firstServlet.do HTTP/1.1
Host: localhost:8080
Connection: keep-alive
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="96", "Microsoft Edge";v="96"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36 Edg/96.0.1054.53
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6

在request中通过解析获取到请求的方法和请求的路径

package com.lany.mytomcat;

import java.io.InputStream;

/**
 * @author liuyanyan
 * @date 2021/12/14 15:22
 */
public class GPRequest {
    private String method;
    private String url;

    public GPRequest(InputStream in) {
        try {
            // 获取http内容
            String content = "";
            byte[] buff = new byte[1024];
            int len = 0;
            if ((len = in.read(buff)) > 0) {
                content = new String(buff, 0, len);
            }
            System.out.println(content);

            String line = content.split("\\n")[0];
            String[] arr = line.split("\\s");

            this.method = arr[0];
            this.url = arr[1].split("\\?")[0];
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public String getUrl() {
        return url;
    }

    public String getMethod() {
        return method;
    }
}

创建GPResponse 类

response按照HTTP规范输出格式化的字符串

package com.lany.mytomcat;

import java.io.OutputStream;

/**
 * @author liuyanyan
 * @date 2021/12/14 15:22
 */
public class GPResponse {
    private OutputStream out;

    public GPResponse(OutputStream out) {
        this.out = out;
    }

    public void write(String s) throws Exception {
        StringBuilder sb = new StringBuilder();
        sb.append("Http/1.1 200 OK\n")
                .append("Content-Type: text/html;\n")
                .append("\r\n")
                .append(s);
        out.write(sb.toString().getBytes());
    }
}

创建GPTomcat类

package com.lany.mytomcat;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @author liuyanyan
 * @date 2021/12/14 15:53
 */
public class GPTomcat {
    private int port = 8080;
    private ServerSocket server;
    private Map<String, GPServlet> servletMapping = new HashMap<>();
    private Properties webxml = new Properties();

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

    private void init() {
        try {
            String WEB_INF = this.getClass().getResource("/").getPath();
            FileInputStream fis = new FileInputStream(WEB_INF + "web.properties");
            webxml.load(fis);
            for (Object k : webxml.keySet()) {
                String key = k.toString();
                // System.out.println("key:" + key);
                if (key.endsWith(".url")) {
                    String servletName = key.replaceAll("\\.url$", "");
                    // System.out.println("servletName: " + servletName);
                    String url = webxml.getProperty(key);
                    System.out.println("url: " + url);
                    String className = webxml.getProperty(servletName + ".className");
                    System.out.println("className:" + className);
                    // 单实例,多线程
                    GPServlet obj = (GPServlet) Class.forName(className).newInstance();
                    servletMapping.put(url, obj);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void start() {
        init();
        try {
            server = new ServerSocket(this.port);
            System.out.println("GPTomcat 已启动,监听端口是:" + this.port);
            while (true) {
                Socket client = server.accept();
                process(client);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void process(Socket client) throws Exception {
        InputStream is = client.getInputStream();
        OutputStream os = client.getOutputStream();

        GPRequest request = new GPRequest(is);
        GPResponse response = new GPResponse(os);

        String url = request.getUrl();

        if (servletMapping.containsKey(url)) {
            servletMapping.get(url).service(request, response);
        } else {
            response.write("404 - Not Found");
        }

        os.flush();
        os.close();

        is.close();
        client.close();
    }


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值