qidao123.com技术社区-IT企服评测·应用市场
标题:
手写tomcat:根本功能实现(3)
[打印本页]
作者:
傲渊山岳
时间:
前天 00:18
标题:
手写tomcat:根本功能实现(3)
TomcatRoute类
TomcatRoute类是Servlet容器,是Tomcat中最核心的部分,其自己是一个HashMap,其功能为:将路径和对象写入Servlet容器中。
package com.qcby.config;
import com.qcby.Util.SearchClassUtil;
import com.qcby.servlet.Httpservlet;
import com.qcby.zj.YbyServlet;
import java.util.HashMap;
import java.util.List;
import java.util.List;
import java.util.Map;
public class TomcatRoute {
public static HashMap<String, Httpservlet> Route = new HashMap<>();
static {
List<String> classesPath = SearchClassUtil.searchClass();
for (String path : classesPath) {
try {
//加载类
Class clazz = Class.forName(path);
//获取注解
YbyServlet webServlet = (YbyServlet) clazz.getDeclaredAnnotation(YbyServlet.class);
// 对象
Object servlet = clazz.getDeclaredConstructor().newInstance();
Route.put(webServlet.url(), (Httpservlet) servlet);
// Httpservlet servlet = (Httpservlet) clazz.newInstance();
// servletMap.put(webServlet.url(),servlet);
System.out.println(Route);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
复制代码
静态代码块
1. 确保初始化时机
静态代码块在
类加载时自动执行
,且
仅执行一次
。这确保了路由表在程序启动时就被初始化,后续无需手动调用初始化方法。
对比其他初始化方式
:
构造函数
:每次创建对象时都会执行,而路由表只需初始化一次。
普通静态方法
:需要手动调用,可能被忘记或重复调用。
静态代码块
:自动触发,保证全局唯一性。
2. 全局唯一性
静态代码块属于类,而非某个实例。无论创建多少个TomcatRoute对象,路由表只会初始化一次。
功能
自动扫描
:通过 SearchClassUtil.searchClass() 扫描项目中的所有类。
注解辨认
:使用 @YbyServlet 注解标记需要注册的 Servlet。
路由映射
:将注解中的 url() 值作为路径,对应的 Servlet 实例作为值,存入静态的 Route 映射表。
类加载时初始化
:利用静态代码块在类加载时执行初始化逻辑,确保路由表在程序启动时就已准备好。
public static HashMap<String, Httpservlet> Route = new HashMap<>();
1. 多态性的应用
Httpservlet是所有具体 Servlet 的
抽象父类
(或接口),通过父类范例引用子类实例,可以实现
统一调用
。
2. 解耦路由逻辑与具体实现
路由系统只需关注
哀求路径与处置惩罚逻辑的映射关系
,而无需关心具体 Servlet 的实现细节。
3. 统一接口界说
Httpservlet通常界说了处置惩罚哀求的标准方法(如service()、doGet()、doPost()),所有子类必须实现这些方法。
4. 符合 Servlet 规范
在标准 Java Web 开辟中,所有 Servlet 都必须实现javax.servlet.Servlet接口(或继续HttpServlet)。这种设计模仿了标准 Servlet 容器的工作原理。
MyTomcat
package com.qcby;
//tomcat主启动类
import com.qcby.config.TomcatRoute;
import com.qcby.servlet.Httpservlet;
import com.qcby.Request.HttpServletRequest;
import com.qcby.Response.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
public class Mytomcat {
static HashMap<String,Httpservlet> routes= TomcatRoute.Route;
static HttpServletRequest request=new HttpServletRequest();
static HttpServletResponse response=new HttpServletResponse();
public static void dispatch(){
Httpservlet servlet=routes.get(request.getPath());
if(servlet!=null){
servlet.service(request,response);
}
}
public static void main(String[] args) {
try {
System.out.append("服务器启动......");
// 1.定义ServerSocket对象进行服务器的端口注册
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {
// 2.监听客户端的socket链接程序
Socket socket = serverSocket.accept();//阻塞监听
// 3.从socket对象当中获得一个字节流对象
InputStream iStream = socket.getInputStream();
// 打印输出
int len = 0;
int ReviceLen = 0;
// 计算机网络数据是以8bit为一个单元进行发送,我们接收到发送方发生的byte数据
// 将其转化为utf-8格式输出
byte[] recvBuf = new byte[1024];
while ((ReviceLen = iStream.read(recvBuf)) != -1) {
String count=new String(recvBuf,0,ReviceLen,"UTF-8");
String method=count.split(" ")[0];
String url=count.split(" ")[1];
request.setMethod(method);
request.setPath(url);
}
dispatch();
}
} catch(Exception e){
// TODO: handle exception
}
}
}
复制代码
1. 团体架构
这个浅易服务器包含三个核心组件:
Mytomcat
:主服务器类,负责接收哀求和分发。
TomcatRoute
:路由配置类,通过静态代码块扫描并注册所有 Servlet。
Httpservlet
:抽象 Servlet 基类,界说哀求处置惩罚接口。
2. 核心成员变量
static HashMap<String,Httpservlet> routes = TomcatRoute.Route;
static HttpServletRequest request = new HttpServletRequest();
static HttpServletResponse response = new HttpServletResponse();
复制代码
routes:从 TomcatRoute 获取的路由表,存储
URL → Servlet
的映射关系。
request 和 response:静态全局对象,用于存储当前哀求和相应信息。
3. 哀求分发逻辑
public static void dispatch() {
Httpservlet servlet = routes.get(request.getPath());
if (servlet != null) {
servlet.service(request, response);
}
}
复制代码
根据 request.getPath() 从路由表中查找对应的 Servlet。
调用 Servlet 的 service() 方法处置惩罚哀求(多态调用)。
4. 主服务器逻辑
public static void main(String[] args) {
try {
System.out.println("服务器启动......");
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {
// 1. 监听客户端连接(阻塞)
Socket socket = serverSocket.accept();
InputStream iStream = socket.getInputStream();
// 2. 解析HTTP请求
byte[] recvBuf = new byte[1024];
int ReviceLen = iStream.read(recvBuf);
String count = new String(recvBuf, 0, ReviceLen, "UTF-8");
String method = count.split(" ")[0];
String url = count.split(" ")[1];
// 3. 设置请求信息
request.setMethod(method);
request.setPath(url);
// 4. 分发请求
dispatch();
}
} catch (Exception e) {
e.printStackTrace();
}
}
复制代码
关键步调
:
创建服务器套接字
:监听 8080 端口。
接收客户端连接
:通过 serverSocket.accept() 壅闭等待哀求。
解析 HTTP 哀求
:
读取哀求头的第一行(格式:GET /path HTTP/1.1)。
提取 HTTP 方法(如 GET)和哀求路径(如 /login)。
设置哀求对象
:将解析结果存入静态 request 对象。
分发哀求
:调用 dispatch() 方法查找并执行对应的 Servlet。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/)
Powered by Discuz! X3.4