实现一个简单的Tomcat
实现一个简单的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("\n")[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\n")
.append("Content-Type: text/html\n")
.append("\r\n")
.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<ServletMapping> 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<String, String> urlServletMap = new HashMap<String, String>();
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...\n监听端口:" + 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<MyServlet> myServletClass = (Class<MyServlet>) 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
实现一个简单的Tomcat的更多相关文章
- 自己模拟的一个简单的tomcat
servlet容器的职责 总的来说,一个全功能的servlet容器会为servlet的每个HTTP请求做下面的一些工作: 1,当第一次调用servlet的时候,加载该servlet类并调用servle ...
- 模拟一个简单的tomcat
目录 简单处理 每个请求一个线程 模拟tomcat 参考 简单处理 // 客户端和服务器的通信,说到底就是两个数据的传输, // 客户端发送inputStream给服务器,服务器回复 // outpu ...
- IntelliJ IDEA 15 部署Tomcat及创建一个简单的Web工程
一.部署Tomcat 二.创建一个简单的Web工程 2.1创建一个新工程 创建一个新工程 设置JDK及选择Web Application (创建的是Web工程) 点击Next,选择工作空间,起个工程名 ...
- Web开发之tomcat配置及使用(环境变量设置及测试,一个简单的web应用实例)
Tomcat的配置及测试: 第一步:下载tomcat,然后解压到任意盘符 第二步:配置系统环境变量 tomcat解压到的D盘 (路径为: D:\tomcat), 配置环境变量: 启动tomcat需要两 ...
- how tomcat works 札记(两)----------一个简单的servlet集装箱
app1 (看着眼前这章建议读者,看how tomcat works 札记(一个)----------一个简单的webserver http://blog.csdn.net/dlf123321/art ...
- Tomcat剖析(二):一个简单的Servlet服务器
Tomcat剖析(二):一个简单的Servlet服务器 1. Tomcat剖析(一):一个简单的Web服务器 2. Tomcat剖析(二):一个简单的Servlet服务器 3. Tomcat剖析(三) ...
- Tomcat剖析(一):一个简单的Web服务器
Tomcat剖析(一):一个简单的Web服务器 1. Tomcat剖析(一):一个简单的Web服务器 2. Tomcat剖析(二):一个简单的Servlet服务器 3. Tomcat剖析(三):连接器 ...
- how tomcat works 读书笔记(二)----------一个简单的servlet容器
app1 (建议读者在看本章之前,先看how tomcat works 读书笔记(一)----------一个简单的web服务器 http://blog.csdn.net/dlf123321/arti ...
- tomcat原理解析(一):一个简单的实现
tomcat原理解析(一):一个简单的实现 https://blog.csdn.net/qiangcai/article/details/60583330 2017年03月07日 09:54:27 逆 ...
随机推荐
- 正则表达式字符&使用
正则详细解说:https://juejin.im/post/5965943ff265da6c30653879 一.正则表达式中的字符含意 \ 做为转义,即通常在"\"后面的字符不按 ...
- 关于lock和synchronized的选择
这里不介绍具体用法,介绍lock和synchronized的不同从而做出选择 1.lock是一个接口,而synchronized是java中的一个关键字,synchronized是内置的语言实现. 2 ...
- sql server 游标和with as使用
) --声明变量,需要读取的数据 DECLARE cur CURSOR --去掉STATIC关键字即可 FOR WITH Emp AS (SELECT acc.* FROM GXSpreadDB.db ...
- LNMP环境搭建wordpress博客及伪静态
WordPress是使用PHP语言开发的博客平台,是一款开源的软件,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站.也可以把 WordPress当作一个内容管理系统(CMS)来使用 ...
- 3-JavaSe-1-stream-1-流库特征
1.parallelStream可以让流库以并行方式来执行过滤和计数. String content=new String(Files.readAllBytes(Paths.get("D:\ ...
- WinServer-SMTP服务
摘要 SMTP服务是用来发送邮件的,常用于代码中发送邮件,不能接收.本章介绍SMTP服务的安装,配置. 搭建F5负载均衡集群注意事项: 1.集群不能与exchang在同网段,否则发不出邮件. 2.AP ...
- 关于ubuntu软件图标的问题
原因是这样的,有一次我更新我的IDEA之后,程序图标就不见了. 怎么说呢,就是以下显示的这样. 在Frequent中显示正常, 在All中却没有!!! 是的,它就是在一边有一边没有... 奇了怪了. ...
- 协议形式化安全分析 Scyther 并非所有协议可以照抄就搬
1.Scyther 形式化分析工具可以对协议进行形式化描述,验证协议的机密性和可认证性是否存在安全威胁.在攻击时支持会话轮数无限次执行,同时支持在强安全模型和Delov-Yao模型.在对要形式化分析的 ...
- python中set(集合),深浅拷贝以及一些补充知识点
1.set集合 特点:无序,不重复,元素必须可哈希(不可变) 作用:去重复 本身是可变的数据类型.有增删改查操作.{集合的增删改查操作应用较少,这里不做详细介绍了(这里的增有一个方法update注意这 ...
- (一)AppScan的安装及破解
IBM AppScan是一款目前最好用的Web 应用安全测试工具,Rational AppScan 可自动化 Web 应用的安全漏洞评估工作,能扫描和检测所有常见的 Web 应用安全漏洞,例如 SQL ...