美文网首页
手写一个tomcat

手写一个tomcat

作者: 兮兮码字的地方 | 来源:发表于2020-03-28 18:06 被阅读0次

tomcat是十分常用的轻量级的web服务容器,其原理其实不复杂,本质就是在jdk的socket,输入输出流,反射,线程池等技术基础上封装出的一套方便开发与客户端交互的服务器。但更常用于http协议的web项目开发。

下面我们实现一个自己的简易的tomcat服务。

1,服务总类

程序的入口,负责创建一个ServerSocket 服务端,监听客户端请求并创建Socket 客户端响应,为提升并发能力,创建连接池来分发任务。

package com.lly;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class MyWebServer {

    public static void startServer(int port) throws Exception{

        @SuppressWarnings("resource")

ServerSocket serverSocket = new ServerSocket(port);

        System.out.println("创建服务成功");

        Socket socket = null;

        int count =0;

ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(32);

while (true) {

socket = serverSocket.accept();

System.out.println("收到客户端请求次数:"+(++count));

newFixedThreadPool.execute(new MyRunnable(socket));

}

    }

    public static void main(String[] args) {

        try {

        System.out.println("start WebServer");

            startServer(8080);

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}

2,处理每个服务的Runnable 线程类

接收服务总类分配过来的socket对象,并获取到输入输出流来创建request和response对象,通过request得到请求的相关信息,分配给相应的servlet来处理业务请求。

package com.lly;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.Socket;

/**

* Handles requests received by the socket server

*/

public class MyRunnable implements Runnable {

Socket socket = null;

public MyRunnable() {

super();

}

public MyRunnable(Socket socket) {

super();

this.socket = socket;

}

@Override

public void run() {

String name = Thread.currentThread().getName();

System.out.println("当前线程:" + name);

InputStream inputStream = null;

OutputStream outputStream = null;

try {

inputStream = socket.getInputStream();

outputStream = socket.getOutputStream();

MyRequest request;

request = new MyRequest(inputStream);

MyResponse response = new MyResponse(outputStream);

String clazz = new MyMapping().getMapping().get(request.getRequestUrl());

if (clazz != null) {

Class<MyAbstractHttpServlet> myServletClass =  (Class<MyAbstractHttpServlet>)Class.forName(clazz);

MyAbstractHttpServlet myServlet;

myServlet = myServletClass.newInstance();

myServlet.service(request, response);

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

3,Request 类

负责根据输入流解析请求数据。

package com.lly;

import java.io.IOException;

import java.io.InputStream;

public class MyRequest {

    private String requestMethod="";

    private String requestUrl="";

    public MyRequest(InputStream inputStream) throws Exception{

        byte[] buffer = new byte[1024];

        String[] params = extracted(inputStream, buffer);

        if(params!=null && params.length>=2) {

        this.requestMethod = params[0];

        this.requestUrl = params[1];

        }

    }

private String[] extracted(InputStream inputStream, byte[] buffer) throws IOException {

String[] params = null;

try {

int len;

String str = "";

if((len = inputStream.read(buffer,0,1024))>0){

str += new String(buffer,0,len);

}

String data =  str.split("\n")[0];

params = data.split(" ");

} catch (Exception e) {

System.out.println(e.toString());

}

return params;

}

    public String getRequestMethod() {

        return requestMethod;

    }

    public String getRequestUrl() {

        return requestUrl;

    }

}

4,Response类

负责按照servlet服务类给的返回数据来给客户端响应数据。

package com.lly;

import java.io.OutputStream;

public class MyResponse {

private OutputStream outputStream;

public MyResponse(OutputStream outputStream) {

this.outputStream = outputStream;

}

public void write(String str) throws Exception {

StringBuilder builder = new StringBuilder();

builder.append("HTTP/1.1 200 OK\n").

append("Content-Type:text/html\n").

append("\r\n").

append("<html>").

append("<body>").

append("<h1>" + str + "</h1>").

append("</body>").

append("</html>");

this.outputStream.write(builder.toString().getBytes());

this.outputStream.flush();

this.outputStream.close();

System.out.println("响应success...");

}

}

5,AbstractHttpServlet 

定义一套Servlet的规范,包含doGet和doPost两个抽象方法和一个service方法。

package com.lly;

public abstract class MyAbstractHttpServlet {

    public static final String METHOD_GET = "GET";

    public static final String METHOD_POST = "POST";

    public abstract void doGet(MyRequest request,MyResponse response) throws  Exception;

    public abstract void doPost(MyRequest request,MyResponse response) throws  Exception;

    /**

    * @param request

    * @param response

    */

    public void service(MyRequest request,MyResponse response) throws Exception{

        if(METHOD_GET.equals(request.getRequestMethod())){

            doGet(request,response);

        }else if(METHOD_POST.equals(request.getRequestMethod())){

            doPost(request,response);

        }

    }

}

6,Servlet 类

接收request,response对象,并调用相应的业务类处理后用response响应客户端。

package com.lly;

public class MyServlet extends MyAbstractHttpServlet {

@Override

public void doGet(MyRequest request, MyResponse response) throws Exception {

        response.write("<a href=\"https://user.qzone.qq.com/172496791?source=friendlist\">click me</a>");

}

@Override

public void doPost(MyRequest request, MyResponse response) throws Exception {

    doGet(request, response);

}

}

7,Mapping 类

负责映射服务端请求地址和servlet类的关系

package com.lly;

import java.util.HashMap;

public class MyMapping {

public static HashMap<String,String> mapping = new HashMap<String,String>();

    static {

        mapping.put("/myTomcat","com.lly.MyServlet");

    }

    public HashMap<String,String> getMapping(){

        return mapping;

    }

}

简单总结一下,tomcat负责创建socket服务端监听客户端的请求,为每个请求分配一个线程,并发的解析请求数据并传递给相应的servlet类处理。

servlet中可调用复杂的业务逻辑并通过response响应数据给客户端。

相关文章

  • 手写tomcat

    手写tomcat+servlet https://my.oschina.net/960823/blog/28778...

  • 手写Tomcat

    需求分析 根据Tomcat的基本功能分析,基本需求包括: 监听端口,接受外部请求 多线程并发处理多个请求 解析HT...

  • 手写一个tomcat

    tomcat是十分常用的轻量级的web服务容器,其原理其实不复杂,本质就是在jdk的socket,输入输出流,反射...

  • 手写一个简易版的tomcat

    @[TOC] 手写一个简易版的tomcat 前言 使用tomcat的时候当浏览器输入url之后,开始发送http请...

  • 基于netty手写Tomcat

    netty 简介 Netty一个基于NIO的客户、服务器端的编程框架 1.环境准备 maven依赖

  • 使用bio手写tomcat

    业务功能 浏览器发送请求给服务器,服务器根据请求的分给不同的Servlet的doGet或doPost的方法,并把响...

  • 使用netty手写tomcat

    区别 和使用BIO整体思路是一样的,区别是io的处理上 核心代码

  • 手写一个简化版Tomcat

    Tomcat作为Web服务器深受市场欢迎,有必要对其进行深入的研究。在工作中,我们经常会把写好的代码打包放在Tom...

  • 手写一个简化版Tomcat

    Tomcat作为Web服务器深受市场欢迎,有必要对其进行深入的研究。在工作中,我们经常会把写好的代码打包放在Tom...

  • 1.手写一个简易Tomcat

    GitHub代码 具体代码详见GitHub

网友评论

      本文标题:手写一个tomcat

      本文链接:https://www.haomeiwen.com/subject/ccdsuhtx.html