web服务器——tomcat

web服务器基本概念

在这里插入图片描述
请求不能像自己的代码一样,控制什么时候运行。因为不知道什么时候客户端发送请求。 所以webserver处一定要开启长服务。而这个服务就是tomcat。这里面可以嵌入n个applet小程序(购物车模块、订单模块…不同模块接收不同请求进行分别处理。处理逻辑放到webserver里。所以webserver相当于是一个容器,代码来实现、当成安装程序。安装到物理服务器中,启动就能对外提供服务)

web服务器实现——自定义tomcat

在这里插入图片描述

  1. 定义MyRequest类:请求对象。里面有请求方法(get/post)和请求地址url。构造函数传参inputstream,从inputstream中获得请求方法和地址。
  2. 定义MyResponse类:响应对象。就只有outputstream。有一个write方法,写入响应行、响应头和响应体。
  3. 定义MyMapping类:请求和处理相应请求的逻辑类(MyServlet)的映射关系。【就是看使用图中哪个applet进行处理】用hashmap存储。value是要要映射到的类,也就是包名+类名(MyServlet)。有一个getMapping方法,返回hashmap。
  4. 定义MyHttpServlet类:抽象类(图中接口)对servie和applet中格式进行转换。两个抽象方法doGet和doPost。一个service方法,根据传入的请求方式来判断调用doGet还是doPost方法。
  5. 定义MyServlet类:继承MyHttpServlet抽象类。实现doGet和doPost方法。分别通过参数myResponse的write方法,写入对应的内容。
  6. 定义MyServer类:定义startServer方法,服务端的接收程序,接收socket请求。里面定义请求对象和响应对象。获得MyMapping的Class对象,通过newInstance创建MyServlet实例,然后调用service方法,从而调用doGet或者doPost方法。
  7. 测试main方法:调用startServer方法,传入post。
  8. 到浏览器中,输入localhost:10086/mytomcat,可以看到doGet方法中写入的内容。

localhost:10086/ 显示不出内容,如下:
在MyServer中String clazz = new MyMapping().getMapping().get(myRequest.getRequestUrl());设置断点。然后浏览器中输入localhost:10086,会发现如下:
在这里插入图片描述
也就是getMapping()会获得/mytomcat -> MyServletget()。然后get(“/“)获得的是null,clazz是null。

所以只有当输入localhost:10086/mytomcat,点进get()中,会发现getRequestUrl()中,会发现:
在这里插入图片描述
clazz为"MyServlet"

通过Class.forName方法来获取对象, 传入一个类的完全限定名即可。

通过反射获取MyServlet类的Class对象myServletClass。
在这里插入图片描述

然后根据myServletClass创建对象。
在这里插入图片描述
然后调用service方法,发现是请求方法是Get,所以调用doGet方法,输出get mytomcat
在这里插入图片描述

具体代码:

MyRequest.java
import java.io.InputStream;
/**
 * @Author : LiuYan
 * @create 2021/4/19 22:36
 * 请求对象
 * 需要解析请求
 */
public class MyRequest {
    // 请求方法 GET/POST
    private String requestMethod;
    // 请求地址 统一资源定位符
    private String requestUrl;

public MyRequest(InputStream inputStream) throws Exception {
    // 缓冲区
    byte[] buffer = new byte[1024];
    // 读取数据长度
    int len = 0;
    // 定义请求变量
    String str = null;
    if ((len = inputStream.read(buffer)) > 0) {
        str = new String(buffer, 0, len);
    }
    // GET 请求地址 http/1.1
    String data = str.split("\n")[0];
    String[] params = data.split(" ");
    this.requestMethod = params[0];
    this.requestUrl = params[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;
}

}

MyResponse.java
import java.io.IOException;
import java.io.OutputStream;
/**
 * @Author : LiuYan
 * @create 2021/4/19 22:45
 * 响应对象
 * 不需要解析,但是需要write方法,然后把内容返回给客户端浏览器
 */
public class MyResponse {
    private OutputStream outputStream;

public MyResponse(OutputStream outputStream) {
    this.outputStream = outputStream;
}
// 响应行 响应头 响应体
public void write(String str) throws IOException {
    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("</html>")
            .append("</body>");
    this.outputStream.write(builder.toString().getBytes());
    this.outputStream.flush();
    this.outputStream.close();
}

}

MyMapping.java
import java.util.HashMap;
/**
 * @Author : LiuYan
 * @create 2021/4/19 22:51
 * 映射关系
 * 请求和对应处理的逻辑类的映射关系
 */
public class MyMapping {
    public static HashMap mapping = new HashMap<>();
    static {
        mapping.put("/mytomcat","MyServlet");
    }
    public HashMap getMapping() {
        return mapping;
    }
}

MyHttpServlet.java
import java.io.IOException;
/**
 * @Author : LiuYan
 * @create 2021/4/19 22:53
 */
public abstract class MyHttpServlet {
    // 定义常量
    public static final String METHOD_GET = "GET";
    public static final String METHOD_POST = "POST";
    // 具体实现
    public abstract void doGet(MyRequest myRequest, MyResponse myResponse) throws IOException;
    public abstract void doPost(MyRequest myRequest, MyResponse myResponse) throws IOException;

//实现转换功能 根据请求方式来判断调用doGet还是doPost
public void service(MyRequest myRequest, MyResponse myResponse) throws IOException {
    if (METHOD_GET.equals(myRequest.getRequestMethod())) {
        doGet(myRequest, myResponse);
    } else if (METHOD_POST.equals(myRequest.getRequestMethod())) {
        doPost(myRequest, myResponse);
    }
}

}

MyServlet.java
import java.io.IOException;
/**
 * @Author : LiuYan
 * @create 2021/4/19 22:59
 */
public class MyServlet extends MyHttpServlet{

@Override
public void doGet(MyRequest myRequest, MyResponse myResponse) throws IOException {
    myResponse.write("get mytomcat");
}

@Override
public void doPost(MyRequest myRequest, MyResponse myResponse) throws IOException {
    myResponse.write("post tomcat");
}

}

MyServer.java
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
 * @Author : LiuYan
 * @create 2021/4/19 23:02
 */
public class MyServer {
    /**
     * 定义服务端的接收程序,接收socket请求
     * @param post
     */
    public static void startServer(int post) throws Exception {
        //定义服务端套接字
        ServerSocket serverSocket = new ServerSocket(post);
        // 定义客户端套接字 每个请求是不同套接字
        Socket socket = null;
        // 不停接收请求
        while (true) {
            socket = serverSocket.accept();
            // 获取输入和输出流
            InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();
            // 定义请求对象
            MyRequest myRequest = new MyRequest(inputStream);
            // 定义响应对象
            MyResponse myResponse = new MyResponse(outputStream);

        String clazz = new MyMapping().getMapping().get(myRequest.getRequestUrl());
        if (clazz != null) {
            Class<MyServlet> myServletClass = (Class<MyServlet>) Class.forName(clazz);
            //根据myServletClass创建对象
            MyServlet myServlet = myServletClass.newInstance();
            myServlet.service(myRequest, myResponse);
        }
    }
}

public static void main(String[] args) throws Exception {
    startServer(10086);
}

}