手写tomcat

github地址

一。浏览器发送请求http://localhost:8080 返回hello world到浏览器 或者跳转到一个页面

跳转页面其实也是往浏览器返回页面内容(先读取页面的内容)

@Data
public class MyTomcat {
    private int port = 8080;

    public MyTomcat(int port) {
        this.port = port;
    }

    private void start() throws Exception {
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("my taomcat start on :" + port);
        while (true){
            Socket socket = serverSocket.accept();
            socket.getOutputStream().write("hello world".getBytes());
            socket.close();
        }
    }

    public static void main(String[] args) throws Exception {
        MyTomcat myTomcat = new MyTomcat();
        myTomcat.start();
    }
}
private void start() throws Exception {
    initServlet();
    ServerSocket serverSocket = new ServerSocket(port);
    System.out.println("my taomcat start on :" + port);
    while (true) {
        Socket socket = serverSocket.accept();

        //读取请求头信息
        MyRequest myRequest = new MyRequest(socket.getInputStream());

        //响应
        MyResponse myResponse = new MyResponse(socket.getOutputStream());


        ServletCollectAndDispatch servletCollectAndDispatch = new ServletCollectAndDispatch(myRequest, myResponse);
        servletCollectAndDispatch.dispatch(myRequest, myResponse);

        socket.close();
    }
}

二。tomcat获取浏览器请求信息 和响应信息给浏览器 抽取出MyRequest和MyResponse

1.MyRequest对象



import lombok.Data;
import java.io.InputStream;

/**
 * 解析请求头信息,实际解析的是socket.getInputStream()
 */
@Data
public class MyRequest {
    private String method;
    private String uri;
    private InputStream inputStream;

    /**
     * 读取浏览器请求头信息
     *
     * @param inputStream 输入流
     * @throws Exception 异常
     */
    public MyRequest(InputStream inputStream) throws Exception {
        this.inputStream = inputStream;
        int count = 0;
        while (count == 0) {
            count = inputStream.available();
        }
        byte[] bytes = new byte[inputStream.available()];
        inputStream.read(bytes);
        System.out.println(new String(bytes));
        this.extractRequestContent(new String(bytes));

    }

    /**
     * 解析请求头嘻嘻
     *
     * <p>
     * GET / HTTP/1.1
     * Accept: text/html, application/xhtml+xml, image/jxr,
     * Accept-Language: zh-Hans-CN,zh-Hans;q=0.5
     * User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
     * Accept-Encoding: gzip, deflate
     * Host: localhost:8080
     * Connection: Keep-Alive
     * </p>
     *
     * @param content 请求内容
     */
    private void extractRequestContent(String content) {
        if (content.equals("")) {
            System.out.println("empty");
        } else {
            //第一行 根据换行符
            String firstLine = content.split("\\n")[0];
            String[] split = firstLine.split("\\s");
            String method = split[0];
            String uri = split[1];
            String protocol = split[2];
            System.out.println(method);
            System.out.println(uri);
            System.out.println(protocol);
            this.method = method;
            this.uri = uri;
        }
    }
}

2.response对象


import lombok.Data;
import java.io.IOException;
import java.io.OutputStream;

/**
 * 用来向浏览器发送数据,发送对象socket.getOutputStream())
 */
@Data
public class MyResponse {
    private OutputStream outputStream;


    public MyResponse(OutputStream outputStream) {
        this.outputStream = outputStream;
    }

    /**
     * 展示html页面
     *
     * @param path
     */
    public void writeHtml(String path) {

    }

    /**
     * 传送数据
     *
     * @param content 数据内容
     * @throws IOException 异常
     */
    public void writeContent(String content) throws IOException {
        outputStream.write(content.getBytes());
    }
}

三。不同的请求路径去不同的类

1.搜索所有的servlet资源集合(MyServlet1 MyServlet2),装进Map(url,类名)
2.根据myrequest的uri去map获取对应的类,然后执行方法(即分发请求)


package com.test;

import com.test.config.ServletConfig;
import com.test.config.ServletConfigMapping;
import com.test.servlet.MyServletBasic;
import lombok.Data;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Data
public class ServletCollectAndDispatch {
    private MyRequest myRequest;
    private MyResponse myResponse;

    public ServletCollectAndDispatch(MyRequest myRequest, MyResponse myResponse) {
        this.myRequest = myRequest;
        this.myResponse = myResponse;
        try {
            initServlet();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //用来存放所有servlet
    private static Map<String, Class<MyServletBasic>> servletMap = new HashMap();

    /**
     * 初始化servlet
     * 获取所有servlet集合并放入map
     *
     * @throws Exception 类找不到异常
     */
    public void initServlet() throws Exception {
        List<ServletConfig> servletConfigList = ServletConfigMapping.getServletConfigList();
        for (ServletConfig servletConfig : servletConfigList) {
            servletMap.put(servletConfig.getUrlMapping(), (Class<MyServletBasic>) Class.forName(servletConfig.getClazz()));
        }

    }

    /**
     * 分发请求
     *
     * @param myRequest  请求对象
     * @param myResponse 响应对象
     */
    public void dispatch(MyRequest myRequest, MyResponse myResponse) throws Exception {
        if (myRequest.getUri().equals("/")) {
            myResponse.writeContent("uri is empty,please fill uri");
        } else if (servletMap.get(myRequest.getUri()) == null) {
            myResponse.writeContent("can't find service uri");
        } else {
            Class<MyServletBasic> servletClass = servletMap.get(myRequest.getUri());
            MyServletBasic myServletBasic = servletClass.newInstance();
            myServletBasic.service(myRequest, myResponse);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飘然生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值