ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

B站马士兵老师的JSP+Servlet+Tomcat应用开发中手写tomcat的内容理解

2021-05-01 14:02:19  阅读:219  来源: 互联网

标签:outputStream String tomcat request Tomcat public JSP response 请求


这篇文章用于理解老师手写的tomcat的具体实现

引言 (可忽略)

学完java基础找了直接来看了这个视频,前面看的挺好,看到老师手写这个tomcat的时候蒙了,先花了两天时间重新学了IO流的知识(推荐B站尚硅谷java基础)回顾了网络的知识,今天把代码跟着敲完细读代码,一步步调试把过程中的变量拿出来看才看懂了整个结构,后附有代码

先附视频https://www.bilibili.com/video/BV1z5411A7DL?p=11

01ServeLet之Tomcat

定义:服务端上一直运行的常服务
tomcat组成:
————首先是和客户端连接的用于request 和response的两个对象,
这两个对象统称server,
通过这两个对象访问多个applet(也就是ServeLet),
在applet中实现接口类来做具体的事,
接口类是一套规范里面有很多需要处理数据用的方法,
server会根据信息要求applet实现各个请求,
所以他们合起来叫servelet

tomcat

跟着视频自己写了Tomcat
基于TCP协议。Socket套接字
首先主要就是ServerSocket创建好后获取相应的Socket对象,以及Soket对象的输入输出流
这个输入输出流我们把他具体化为两个请求
Request和响应Response的类,

先讲响应 response

response这个类的对象由Socket的输出流为构造参数创建,类中有类成员变量OutputStream,
也就是说OutputStream就是Socket的输出流,他的写操作会直接进行传输,
于是response这个类有write()方法(字节流字符流的IO都是read()和write()方法),
write()方法中根据传入的String参数改变了响应体中的标签内容以外,就是标准的HTTP响应格式书写的

再讲请求request 请求是指处理别人的请求

request类对象也是由Socket的输入流为构造参数创建,
类中有类成员变量InputStream,这个对象除了了构造函数和读写函数没有方法
主要功能在构造方法中,整个类就是为了接收到InputStream中需要的信息并且分析然后给出服务器特定的参数———
事例是通过自身的类成员提供了两个信息

 //请求方法  GET/POST  
    private String requestMethod;  
//请求地址资源定位  URL  
    private String requestUrl;   

这两个信息中
1-请求方法用于传递给所有ServerLet的抽象父亲HttpServerLet,作用下文会讲到
2-URL用于给MAP来根据URL(获取到的是整个tomcat工程的路径)获取到相应的ServeLet类,

这里有疑点就是Socket如何获取到这个路径的?

接下来是map类

前面讲到request带给我们两个信息的第二个是URL,
map类中只有一个成员变量里就是一个HashMap,并且具体的键值对信息由static申明好
这样就可以在服务器获得请求时给出相应的ServLet(会调用response())来响应
当然map中还有get方法,方便被调用获取键值

ServeLet

ServeLet可以有很多个,就是根据请求中的URL被map挑选到的用来根据需要返回特定信息的方法类;
所有ServeLet都继承了一个接口HttpServeLet,(下文会讲到,实际用了抽象类)
并且ServeLet要重写两个继承方法用于实现 在获得GET 和POST两种请求时的响应
案例中就单纯的调用了response的写方法来发送了回应,
response来自于接口重写方法中的参数

HttpServeLet

就是上文讲到的所有ServeLet的继承的接口,但事实上老师用了抽象类,
因为抽象类里面能定义非抽象的能被完整继承的方法Server()提供给ServeLet们使用,
这个方法用于判断POST 和GET请求,参数为request和response
将request中的GetrequestUrl()方法的返回值与类中静态常量"POST""GET"对比得出
并且直接执行对应的抽象方法(子类调用的时候就会执行自己重写好的方法)

具体实现

首先创建好ServerSocket对象,通过ServerSocket对象获得Socket对象。
再通过Socket对象分别获得OutputStream 和 InputStream
再拿来分别用来创建Request对象和Response对象
这时通过Request对象的GetRequestUrl来获取到请求中的URL,
再通过map获得请求的ServerLet对象对应类名
通过类名用反射来创建对象,
通过对象来调用Service方法(继承自父类,)
参数就是上面创建好的请求和响应对象
就这么多了,没看懂结合代码再看十遍

代码 注释不全但是保留了关键用于理解的输出

MyRequest代码

package com.hajizu;

import java.io.InputStream;

/**
 * 通过参数为输入流的构造方法获得输入流中的请求方法
 */
public class MyRequest {
    //请求方法  GET/POST
    private String requestMethod;
    //请求地址资源定位  URL
    private String requestUrl;
//    //协议版本  HTML1.1
//    private String protocolType;

    public MyRequest(InputStream i)throws Exception{
        byte[] bys = new byte[1024];
        int len=0;
        String str=null;
        if((len=i.read(bys))!=-1)
        {
            str = new String(bys,0,len);
        }
        String[] s = str.split("\n")[0].split(" ");
//        GET /mytomcat HTTP/1.1
//        Host: localhost:52777
//        Connection: keep-alive
//        Cache-Control: max-age=0
//        sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"
//        sec-ch-ua-mobile: ?0
//        Upgrade-Insecure-Requests: 1
//        User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36
//        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,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
        this.requestMethod=s[0];
        this.requestUrl=s[1];
    }

    public String getRequestMethod() {
        return requestMethod;
    }

    public void setRequestMethod(String requestMethod) {
        this.requestMethod = requestMethod;
    }

    public String getRequestUrl() {
        return requestUrl;
    }

    public void setRequestUrl(String requestUrl) {
        this.requestUrl = requestUrl;
    }

//    public String getProtocolType() {
//        return protocolType;
//    }
//
//    public void setProtocolType(String protocolType) {
//        this.protocolType = protocolType;
//    }
}

MyResponse代码

package com.hajizu;

import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

/**
 *自动输出一个write函数参数和固定HTML报文构成的字符串;
 */
public class MyResponse {
    private OutputStream outputStream;

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

    public void write(String str)throws Exception
    {
        StringBuilder sb = new StringBuilder();
        sb.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(sb.toString().getBytes());
        this.outputStream.flush();
        this.outputStream.close();

    }

    public OutputStream getOutputStream() {
        return outputStream;
    }

    public void setOutputStream(OutputStream outputStream) {
        this.outputStream = outputStream;
    }


}

MyMapping代码

package com.hajizu;

import java.util.HashMap;


/**
 * 用于通过a,b页面标签连接具体的servelet
 */
public class MyMapping {
    public static HashMap<String,String> mapping =new HashMap<>();
    static{
        mapping.put("/mytomcat","com.hajizu.Myservlet");
    }

    public static HashMap<String, String> getMapping() {
        return mapping;
    }
}

ServeLet代码

package com.hajizu;

/**
 * applet具体类 也就是具体做的事
 */
public class Myservlet extends MyHttpServlet{
    @Override
    public void doGet(MyRequest request, MyResponse response) throws Exception {
        response.write("xxkelaDSB");
    }

    @Override
    public void doPost(MyRequest request, MyResponse response) throws Exception {
        response.write("hds");
    }
}

HttpServeLet代码

package com.hajizu;

/**
 * applet具体类 也就是具体做的事
 */
package com.hajizu;

/**
 * 抽象方法,类似接口,用于给予servlet类service方法,并且service自己定义get和post的执行内容
 */
public abstract class MyHttpServlet {
    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;

    public void service (MyRequest request,MyResponse response)throws Exception{
        if(METHOD_GET.equals(request.getRequestMethod())){
            doGet(request,response);
        }
        if(METHOD_POST.equals(request.getRequestMethod())){
            doPost(request,response);
        }

    }
}


标签:outputStream,String,tomcat,request,Tomcat,public,JSP,response,请求
来源: https://blog.csdn.net/weixin_43723581/article/details/116329722

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有