Tomcat入门理解-手写 Tomcat

作为java开发者,都知道Tomcat是一个家户喻晓的Web服务器。手写一个Tomcat对我们理解Tomcat的工作原理,还有servlet的执行流程有很大的帮助,下面是我手写一个简要版Tomcat的总结和收获!

首先,需要了解浏览器与Web服务器是如何处理请求的

1. 浏览器与服务器

在这里插入图片描述

​  当我们打开浏览器,在浏览器的地址栏中输入URL地址访问服务器上的资源的过程中,浏览器和服务器都做了神马操作呢,我们是怎么在浏览器里面看到1.

浏览器和服务器做了以下几个操作:

1、浏览器根据主机名去操作系统的Hosts文件中查找主机名对应的IP地址。

2、浏览器如果在操作系统的Hosts文件中没有找到对应的IP地址,就去互联网上的DNS服务器上查找这台主机对应的IP地址。

3、浏览器查找到"访问地址"这台主机对应的IP地址后,就使用IP地址连接到Web服务器。

4、浏览器连接到web服务器后,就使用http协议向服务器发送请求,发送请求的过程中,浏览器会向Web服务器以Stream(流)的形式传输数据,告诉Web服务器要访问服务器里面的哪个Web应用下的Web资源

5、浏览器做完上面4步工作后,就开始等待,等待Web服务器把自己想要访问的资源给它

6.服务器接收到浏览器传输的数据后,开始解析接收到的数据,服务器解析里面的内容时知道客户端浏览器的请求,然后服务器响应请求,讲请求的内容传输给浏览器。

​ 7.浏览器拿到服务器传输给它的数据之后,就可以把数据展现给用户看了

了解了浏览器与服务器的加护过程,我们重点要注意的是tomcat是如何解析和响应请求的

2 tomcat是如何解析和响应请求的

  1. 首先接受用户发送url访问地址,也就是我们浏览器地址栏的地址,

  2. 然后web.xml或者web.properties里面配置好访问路径和对应要交给处理的servlet的全类名,然后项目初始化的时候,加载web.xml配置文件,将其中的url和className提取出来,将其封装到ServletMapping中,这是一个键值对,键是url,值是className。

  3. 接着就这就去找我们自己定义的servlet,我们自己写的servlet都会继承HttpServlet,然后就会执行父类的service在这个方法中,判断是执行doGet()还是doPost,而接收这些http协议的是HttpRequest,这个对象获取到用户的url和执行方法,然后再通过HttpResponse响应结果

明白了tomcat的详细流程,我们可以总结出Tomcat的工作流程

3.Tomcat的大致流程

1.加载配置文件,初始化ServletMapping

2.等待用户请求

3.获取到Socket对象,将socket.getInputStream()封装成request 将socket.getOutputStream()封装成response

4.实现动态调用doGet/doPost方法,并且能够自定义返回结果

代码如下

下面是我的项目结构:

在这里插入图片描述

主程序

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import com.kkb.http.TzRequest;
import com.kkb.http.TzResponse;
import com.kkb.http.TzServlet;
//主要思路:
//1.加载配置文件,初始化ServletMapping
//2.等待用户请求,用一个死循环等待用户请求
//3.获取到Socket对象,将socket.getInputStream()封装成request
//	                                          将socket.getOutputStream()封装成response
//4.实现动态调用doGet/doPost方法,并且能够自定义返回结果

public class TzTomcat {
	private int port=2080;//指定端口号
	private ServerSocket server;
	
	private Map<String, TzServlet> servletMapping=new HashMap<String,TzServlet>();
	
	private Properties webxml=new Properties();
	
	//1.加载配置文件,初始化ServletMapping
	private void init() {
		//加载web.xml文件,同时初始化ServletMapping对象
		try {
			String WEB_INF=this.getClass().getResource("/").getPath();
			FileInputStream fis=new FileInputStream(WEB_INF+"web.properties");
			webxml.load(fis);
			
			for (Object k : webxml.keySet()) {
				String key=k.toString();
				
				if(key.endsWith(".url")) {
					//投机取巧,取到servletName
					String servletName=key.replaceAll("\\.url$","");
					
					String url=webxml.getProperty(key);
					
					String className=webxml.getProperty(servletName+".class");
					
					TzServlet obj=(TzServlet)Class.forName(className).newInstance();
					
					servletMapping.put(url, obj);

				}
			}
			
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
		
	}

	
	private void process(Socket client) throws Exception {
		//3.获取到Socket对象,将socket.getInputStream()封装成request
	    // 将socket.getOutputStream()封装成response
		
		InputStream is=client.getInputStream();
		OutputStream out=client.getOutputStream();
		
		
		TzRequest request=new TzRequest(is);
		TzResponse response=new TzResponse(out);
		
		
 //4.实现动态调用doGet/doPost方法,并且能够自定义返回结果
		
		//想办法拿到用户所请求的url
		
		String url=request.getUrl();
		if(servletMapping.containsKey(url)) {
		
			servletMapping.get(url).service(request, response);
		}else {
			response.write("404 - Not Found");
		}
			
		out.flush();
		out.close();
		//为什么要关闭client?因为HTTP请求都是采用短连接
		client.close();
	}

	
	
	//启动Tomcat
		public void start() {
			//1.加载配置文件,初始化ServletMapping
			init();
			
			try {
				server=new ServerSocket(this.port);
				
				System.out.println("Tuzi Tomcat 已启动,监听的端口是:"+this.port);
				
				//得到一个客户端
				//Socket socket=server.accept();
				
				//2.等待用户请求,用一个死循环等待用户请求
				while(true) {
					Socket client=server.accept();
					
					process(client);
					

				}
				//System.out.println(socket);
				
				
			} catch (Exception e) {
				
				e.printStackTrace();
			}
		}
	
	
	
	public static void main(String[] args) {
		new TzTomcat().start();
		
	}
}

第一个测试Servlet

package com.kkb.servlet;

import com.kkb.http.TzRequest;
import com.kkb.http.TzResponse;
import com.kkb.http.TzServlet;

public class FirstServlet extends TzServlet {

	@Override
	public void doGet(TzRequest request, TzResponse response) throws Exception {
		this.doPost(request, response);
		
	}

	@Override
	public void doPost(TzRequest request, TzResponse response) throws Exception {
		response.write("Welcome to tuzi Tomcat!<br/><br/>");
		response.write("This is tuzi01 Servlet");
	}

}

访问测试结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值