Java实现一个简单的tomcat

博主突发奇想自制Tomcat,定义了入口类监听请求,自定义注解,还定义了请求、响应输入流等类,实现了Servlet接口及请求转发。服务器端接收参数正常,浏览器端能正常得到响应,但请求参数未处理,也无细致校验,源码在github。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天突发奇想——能不能自己实现一个tomcat?
到底能不能呢?
分析开始:

首先:能想到的技术包括——Java、反射、注解、入口类、Servlet接口、Servlet接口实现类、Http类...
	 具体思路如下
  • 1.定义Tomcat入口类,监听请求
  • 2.自定义WebServlet注解,实现urlPattern属性
  • 3.定义HttpRequestServlet,请求输入流
  • 4.定义HttpResponceServlet,响应输入流
  • 5.定义Servlet接口,提供service静态方法
  • 6.定义HttpServlet,实现Servlet接口,通过url判断实现请求转发 get|post
  • 7.定义TestServlet&Test02Servlet测试类

1 ) 定义Tomcat入口类,监听请求

/**
 * create by Mr.Huang
 * 666
 * 666
 * CREATE-TIME 2019年5月29日 17:41:55
 *
 * 基于HTTP1.1
 * 需求分析:根据Tomcat&Servlet执行原理 做一个简单版本的Tomcat服务器&Servlet类
 *
 *  - 1.定义Tomcat入口类,监听请求
 *  - 2.自定义WebServlet注解,实现urlPattern属性
 *  - 3.定义HttpRequestServlet,请求输入流
 *  - 4.定义HttpResponceServlet,响应输入流
 *  - 5.定义Servlet接口,提供service静态方法
 *  - 6.定义HttpServlet,实现Servlet接口,通过url判断实现请求转发  get|post
 *  - 7.定义TestServlet&Test02Servlet测试类
 */
public class Tomcat {

    private List<String> list = new ArrayList<>();//存储类的全限定名
    private Map<String,Servlet> servletMap = new HashMap();//存储Servlet类

    /**
     * Tomcat入口
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        // 链式编程
        new Tomcat().init().listen();
    }

    /**
     * 监听一次性请求
     * 如果要进行多次连接  while 循环即可
     * @throws IOException
     */
    public void listen() throws Exception {
        //ServerSocket监听8888端口
        ServerSocket serverSocket = new ServerSocket(8888);
        //连接
        Socket accept = serverSocket.accept();
        //获取输入输出流
        InputStream inputStream = accept.getInputStream();
        OutputStream outputStream = accept.getOutputStream();
        //将输入输出流传入HttpRequestServlet&&HttpResponceServlet 对象
        HttpRequestServlet httpRequestServlet = new HttpRequestServlet(inputStream);
        HttpResponceServlet httpResponceServlet = new HttpResponceServlet(outputStream);
        //获取请求Url
        String url = httpRequestServlet.getUrl();
        //从容器中取出对应的Servlet
        Servlet servlet = servletMap.get(url);
        //调用service方法
        servlet.service(httpRequestServlet,httpResponceServlet);
        //释放资源
        inputStream.close();
        accept.close();
        serverSocket.close();
    }


    /**
     * 初始化
     * @return 返回Tomcat本身实现链式编程
     * @throws Exception
     */
    public Tomcat init() throws Exception {
        //获取src的路径
        String resource = Tomcat.class.getResource("/").getPath();
        //处理文件
        file(resource,list);
        //遍历获取Servlet并存入容器
        for (String s:list) {
            Class<?> servletClass = Class.forName(s);
            WebServlet webServlet = servletClass.getAnnotation(WebServlet.class);
            servletMap.put(webServlet.urlPattern(), (Servlet) servletClass.newInstance());
        }
        return this;
    }
    public void file(String url,List<String> list) throws Exception {
        //得到文件流的数组
        File[] files = new File(url).listFiles();
        //递归遍历
        for (File f: files) {
            if(f.isDirectory()){
                //如果是文件夹递归继续遍历
                file(f.getPath(),list);
            }else{
                //对路径进行处理
                String replace = f.getAbsolutePath().replace("C:\\Black\\Demo\\workSpace\\out\\production\\my-tomcat\\", "");
                String replace1 = replace.replace(".class", "");
                String replace2 = replace1.replace("\\", ".");
                //判断是否为Servlet
                if(isServlet(replace2)){
                    //存入容器
                    list.add(replace2);
                }
            }
        }
    }

    /**
     * 判断是否为有WebServlet注解的Servlet
     * @param s
     * @return
     * @throws Exception
     */
    public boolean isServlet(String s) throws Exception {
        //反射获取对应类
        Class<?> aClass = Class.forName(s);
        //判断aClass是否为assignableFrom的子类
        boolean assignableFrom = Servlet.class.isAssignableFrom(aClass);
        if(assignableFrom){
            //判断是有WebServlet注解
            WebServlet webServlet = aClass.getAnnotation(WebServlet.class);
            if (webServlet != null) {
                return true;
            }
        }
        return false;
    }

}

2 ) 自定义WebServlet注解,实现urlPattern属性

/**
 * create by Mr.huang
 * 666
 * 666
 * 自定义WebServlet注解
 */
//作用在类上
@Target(ElementType.TYPE)
//一直存在
@Retention(RetentionPolicy.RUNTIME)
public @interface WebServlet {
    String urlPattern();
}

3 ) 定义HttpRequestServlet,请求输入流

/**
 * create by Mr.huang
 * 666
 * 666
 * 暂时没有对请求参数做处理
 */
public class HttpRequestServlet {
    private String method;
    private String url;
    private String servletName;
    private Map parameter = new HashMap();

    public String getMethod() {
        return method;
    }

    public String getUrl() {
        return url;
    }

    public String getServletName() {
        return servletName;
    }

    public String getParameter(String s) {
        return "1";
    }

    public void setParameter(Map parameter) {
        this.parameter = parameter;
    }

    public HttpRequestServlet(InputStream inputStream) throws IOException {
        String s = new BufferedReader(new InputStreamReader(inputStream)).readLine();
        System.out.println(s);
        String[] s1 = s.split(" ");
        this.method = s1[0];
        System.out.println(this.method);
        this.url = s1[1];
        this.servletName = s1[1];
        System.out.println(this.servletName);
    }

}

4 ) 定义HttpResponceServlet,响应输入流

/**
 * create by Mr.huang
 * 666
 * 666
 */

public class HttpResponceServlet {
    private OutputStream outputStream;

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

    public void write(String s) throws IOException {
        StringBuilder sb = new StringBuilder();
        sb.append("HTTP/1.1 200 OK\n")
                .append("Content-Type: text/html;charset=utf-8\n")
                .append("\n");

        sb.append(s);
        outputStream.write(sb.toString().getBytes());
    }
}

5 ) 定义Servlet接口,提供service静态方法

/**
 * create by Mr.huang
 * 666
 * 666
 */
public interface Servlet {
    void service(HttpRequestServlet req,HttpResponceServlet resp) throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, Exception;
}

6 ) 定义HttpServlet,实现Servlet接口,通过url判断实现请求转发 get|post

/**
 * create by Mr.huang
 * 666
 * 666
 */

public class HttpServlet implements Servlet {
    @Override
    public void service(HttpRequestServlet req, HttpResponceServlet resp) throws Exception{
        /**
         * 分析请求头
         * 获得请求方式 get | post
         * 请求转发到对应的方法中
         */
        if("GET".equals(req.getMethod())){
            doGet(req,resp);
        }else{
            doPost(req,resp);
        }
    }
    public void doGet(HttpRequestServlet req, HttpResponceServlet resp){

    }
    public void doPost(HttpRequestServlet req, HttpResponceServlet resp){

    }
}


测试——可以简单实现HTTP请求 如 127.0.0.1:8888/test02

服务器端接收参数正常
在这里插入图片描述
浏览器端可以正常得到响应
在这里插入图片描述



1.请求参数这块没有做处理
2.没有做细致的校验
3.源码在我的 github



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值