资讯专栏INFORMATION COLUMN

实现一个简单的Tomcat

Zoom / 3203人阅读

摘要:实现一个简单的作用我们的应用会运行在中,那么显然请求必定是先到达的,对于请求实际上会进行如下的处理提供服务的启动,必然是服务,支持协议。进行请求的分发一个可以为多个应用提供服务,那么就需要把下发到不同的应用。下面我们就自己来实现这三步。

实现一个简单的Tomcat 1. Tomcat作用

我们的web应用会运行在Tomcat中,那么显然请求必定是先到达Tomcat的,Tomcat对于请求实际上会进行如下的处理:

提供Socket服务:Tomcat的启动,必然是Socket服务,支持http协议。

进行请求的分发:一个Tomcat可以为多个web应用提供服务,那么就需要把url下发到不同的web应用。

需要将请求和响应封装成request和response:我们在写后端代码的时候都是直接使用request和response的,这是因为Tomcat已经做好了。

下面我们就自己来实现这三步。

2. 实现代码

项目结构:

  src
    └─mytomcat
            BookServlet.java
            CarServlet.java
            MyRequest.java
            MyResponse.java
            MyServlet.java
            MyTomcat.java
            ServletMapping.java
            ServletMappingConfig.java
2.1 封装http请求和响应
package mytomcat;

import java.io.IOException;
import java.io.InputStream;

/**
 * 封装http请求
 */
public class MyRequest {
    
    private String url;
    private String method;
    
    public MyRequest(InputStream inputStream) throws IOException {
        
        String httpRequest = "";
        byte[] httpRequestBytes = new byte[1024];
        int length = 0;
        if((length = inputStream.read(httpRequestBytes)) > 0) {
            httpRequest = new String(httpRequestBytes, 0, length);
        }
        
        String httpHead = httpRequest.split("
")[0];
        url = httpHead.split("s")[1];
        method = httpHead.split("s")[0];
        
        System.out.println(this.toString());
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }
    
    @Override
        public String toString() {
            return "MyRequest -- url:" + url + ",method:" + method;
        }

}
package mytomcat;

import java.io.IOException;
import java.io.OutputStream;

/**
 * 封装http响应
 */
public class MyResponse {
    
    private OutputStream outputStream;
    
    public MyResponse (OutputStream outputStream) {
        this.outputStream = outputStream;
    }
    
    public void write(String content) throws IOException {
        StringBuffer httpResponse = new StringBuffer();
        httpResponse.append("HTTP/1.1 200 OK
")
                    .append("Content-Type: text/html
")
                    .append("
")
                    .append(content);
        
        outputStream.write(httpResponse.toString().getBytes());
        outputStream.close();
    }

}
2.2 实现不同的Servlet
package mytomcat;
/**
 * Servlet抽象类
 */
public abstract class MyServlet {
    
    public abstract void doGet(MyRequest myRequest, MyResponse myResponse);
    
    public abstract void doPost(MyRequest myRequest, MyResponse myResponse);
    
    public void service(MyRequest myRequest, MyResponse myResponse) {
        if(myRequest.getMethod().equalsIgnoreCase("POST")) {
            doPost(myRequest, myResponse);
        }else if(myRequest.getMethod().equalsIgnoreCase("GET")) {
            doGet(myRequest, myResponse);
        }
    }
}
package mytomcat;

import java.io.IOException;

/**
 * 处理操作"书"的http请求
 */
public class BookServlet extends MyServlet {

    @Override
    public void doGet(MyRequest myRequest, MyResponse myResponse) {
        try {
            myResponse.write("[get] book...");
        }catch(IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void doPost(MyRequest myRequest, MyResponse myResponse) {
        try {
            myResponse.write("[post] book...");
        }catch(IOException e) {
            e.printStackTrace();
        }
    }

}
package mytomcat;

import java.io.IOException;

/**
 * 处理操作"车"的http请求
 */
public class CarServlet extends MyServlet {

    @Override
    public void doGet(MyRequest myRequest, MyResponse myResponse) {
        try {
            myResponse.write("[get] car...");
        }catch(IOException e) {
            e.printStackTrace();
        }
        
    }

    @Override
    public void doPost(MyRequest myRequest, MyResponse myResponse) {
        try {
            myResponse.write("[post] car...");
        }catch(IOException e) {
            e.printStackTrace();
        }
    }

}
2.3 定义Servlet映射POJO类
package mytomcat;

public class ServletMapping {
    
    private String servletName;
    private String url;
    private String className;
    
    public ServletMapping(String servletName, String url, String className) {
        super();
        this.servletName = servletName;
        this.url = url;
        this.className = className;
    }

    public String getServletName() {
        return servletName;
    }

    public void setServletName(String servletName) {
        this.servletName = servletName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }
    
}
2.4 配置Servlet映射关系
package mytomcat;

import java.util.ArrayList;
import java.util.List;

/**
 * 配置请求url和处理的servlet的对应关系
 */
public class ServletMappingConfig {
    
    public static List servletMappingList = new ArrayList<>();;
    
    static {
        servletMappingList.add(new ServletMapping("Book", "/book", "mytomcat.BookServlet"));
        servletMappingList.add(new ServletMapping("Car", "/car", "mytomcat.CarServlet"));
    }

}
2.5 主类
package mytomcat;

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;

public class MyTomcat {
    private int port;
    //保存请求url和处理请求servlet的对应关系
    private Map urlServletMap = new HashMap();
    
    public MyTomcat(int port) {
        this.port = port;
    }
    
    public void start() {
        initServletMapping();
        
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(port);
            System.out.println("MyTomcat is start...
监听端口:" + port);
            
            while(true) {
                System.out.println("等待请求...");
                Socket socket = serverSocket.accept();
                InputStream inputStream = socket.getInputStream();
                OutputStream outputStream = socket.getOutputStream();
                
                MyRequest myRequest = new MyRequest(inputStream);
                MyResponse myResponse = new MyResponse(outputStream);
                
                //请求分发
                disPatch(myRequest, myResponse);
                socket.close();
            }
        }catch(IOException e) {
            e.printStackTrace();
        }finally {
            if(serverSocket != null) {
                try {
                    serverSocket.close();
                }catch(IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    //初始化url和处理的servlet的对应关系
    private void initServletMapping() {
        for(ServletMapping servletMapping: ServletMappingConfig.servletMappingList) {
            urlServletMap.put(servletMapping.getUrl(), servletMapping.getClassName());
        }
    }
    
    //分发处理请求
    private void disPatch(MyRequest myRequest, MyResponse myResponse) {
        String className = urlServletMap.get(myRequest.getUrl());
        
        //反射
        try {
            Class myServletClass = (Class) Class.forName(className);
            MyServlet myServlet = myServletClass.newInstance();
            
            myServlet.service(myRequest, myResponse);
        }catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        MyTomcat myTomcat = new MyTomcat(8080);
        myTomcat.start();
    }
}
3. 测试

运行MyTomcat主类,然后在浏览器输入http://localhost:8080/car,可以看到返回[get] car...,大功告成。

源码地址:

https://github.com/WangJun-SCU/mytomcat

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72060.html

相关文章

  • 实现简单Tomcat | Tomcat原理学习(1)

    摘要:项目结构项目结构如下实现细节创建对象首先创建自定义的请求类,其中定义与两个属性,表示请求的以及请求的方式。其构造函数需要传入一个输入流,该输入流通过客户端的套接字对象得到。创建服务端套接字,并绑定某个端口。 缘起 用了那么久tomcat,突然觉得自己对它或许并没有想象中的那么熟悉,所以趁着放假我研究了一下这只小猫咪,实现了自己的小tomcat,写出这篇文章同大家一起分享! 照例附上gi...

    Corwien 评论0 收藏0
  • Nginx+Tomcat关于Session管理

    摘要:前言对的管理一直有了解,但是一直没有实际操作一遍,本文从最简单的安装启动开始,通过实例的方式循序渐进的介绍了几种管理的方式。 前言 Nginx+Tomcat对Session的管理一直有了解,但是一直没有实际操作一遍,本文从最简单的安装启动开始,通过实例的方式循序渐进的介绍了几种管理session的方式。 nginx安装配置 1.安装nginx [root@localhost ~]# y...

    superw 评论0 收藏0
  • 使用 Docker 搭建简易 Java Web 环境 (二)

    摘要:创建一个环境最近公司正在使用开发网站应用,所以有必要了解下如何使用创建对应的环境。还好,提供了文档的形式来组合多个容器来搭建开发环境。下一步我们将使用来构建更加复杂的开发环境。 showImg(https://segmentfault.com/img/remote/1460000011106825); 从《从最简单的入手学习 Docker (一)》一文中,可以简单的了解 Docker ...

    Tamic 评论0 收藏0
  • Java Python 和Nodejs在web开发方面简单比较

    摘要:在做数据分析和人工智能方面也有很多可以直接使用的算法库。各方面都能找到优秀的组件。但开发起来复杂一些,更适合有一定规模的团队采用。 对语言之间优势这个问题,可以写几本书来具体阐述. 我尝试简单地说一点。不见得对,也不可能完整,仅供参考。 互联网兴起,静态页面不能满足复杂的交互需求. 出现了动态技术.史前时期动态Web 开发多采用CGI 技术来实现. CGI 将脚本作为单独的进程运行, ...

    Riddler 评论0 收藏0

发表评论

0条评论

Zoom

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<