概述
在 Java Web 开发中,Tomcat 是一个广为人知的开源 Servlet 容器,它能够处理客户端的请求并返回响应。本文将深入分析一系列自定义的 Java 代码,这些代码实现了一个简易的 Tomcat 服务器,包括请求处理、路由分发、静态资源响应等核心功能。
整体架构概述
Tomcat 服务器主要由以下几个核心部分组成:
- 主启动类:负责启动服务器并监听客户端请求。
- 请求和响应处理类:用于解析客户端请求和生成服务器响应。
- Servlet 类:处理具体的业务逻辑。
- 路由配置类:管理请求路径和对应的 Servlet 映射关系。
- 工具类:提供文件操作、响应头设置等辅助功能。
详细代码
启动类MyTomcat
package com.qcby;
import com.qcby.config.TomcatRoute;
import com.qcby.request.HttpServletRequest;
import com.qcby.response.HttpServletResponse;
import com.qcby.servlet.HttpServlet;
import com.qcby.util.ResponseUtil;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
public class MyTomcat {
static HashMap<String, HttpServlet> routes = TomcatRoute.routes;
public void dispatch(HttpServletRequest request, HttpServletResponse response) throws IOException {
HttpServlet servlet = routes.get(request.getUrl());
if (servlet != null) {
servlet.service(request, response);
}
}
public void start() throws IOException {
ServerSocket serverSocket = new ServerSocket(4700);
while (true) {
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
HttpServletRequest request = new HttpServletRequest();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String str = reader.readLine();
request.setMethod(str.split("\\s")[0]);
request.setUrl(str.split("\\s")[1]);
OutputStream outputStream = socket.getOutputStream();
HttpServletResponse response = new HttpServletResponse(outputStream);
dispatch(request, response);
}
}
public static void main(String[] args) throws IOException {
MyTomcat myTomcat = new MyTomcat();
myTomcat.start();
}
}
MyTomcat 类是整个服务器的入口点。start 方法通过 ServerSocket 监听 4700 端口,当有客户端连接时,获取输入流解析请求信息,同时创建 HttpServletRequest 和 HttpServletResponse 对象。dispatch 方法根据请求的 URL 从路由表中查找对应的 Servlet 并调用其 service 方法处理请求。
2.请求和响应处理类
package com.qcby.request;
public class HttpServletRequest {
private String method;
private String url;
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
package com.qcby.response;
import com.qcby.util.FileUtil;
import com.qcby.util.ResponseUtil;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
public class HttpServletResponse {
private OutputStream outputStream;
public HttpServletResponse(OutputStream outputStream) {
this.outputStream = outputStream;
}
public void write(String context) throws IOException {
outputStream.write(context.getBytes());
}
public void writeHtml(String path) throws Exception {
String resourcesPath = FileUtil.getResoucePath(path);
File file = new File(resourcesPath);
if (file.exists()) {
System.out.println("静态文件存在");
FileUtil.writeFile(file, outputStream);
} else {
System.out.println("静态文件不存在");
write(ResponseUtil.getResponseHeader404());
}
}
}
HttpServletRequest 类用于封装客户端请求的信息,包括请求方法和请求 URL。
HttpServletResponse 类用于封装服务器的响应信息,提供了 write 方法用于返回动态资源,writeHtml 方法用于返回静态资源。如果静态文件存在,则使用 FileUtil 类将文件内容写入输出流。
3.Servlet类
package com.qcby.servlet;
import com.qcby.request.HttpServletRequest;
import com.qcby.response.HttpServletResponse;
import java.io.IOException;
public abstract class HttpServlet implements servlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {}
public void doPost(HttpServletRequest request, HttpServletResponse response) {}
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
if (request.getMethod().equals("GET")) {
doGet(request, response);
} else if (request.getMethod().equals("POST")) {
doPost(request, response);
}
}
}
HttpServlet 是一个抽象类,实现了 servlet 接口。service 方法根据请求方法调用相应的 doGet 或 doPost 方法。具体的业务逻辑可以在子类中重写 doGet 和 doPost 方法来实现。
4.路由配置类
package com.qcby.config;
import com.qcby.servlet.HttpServlet;
import com.qcby.util.SearchClassUtil;
import com.qcby.zj.DjyServlet;
import java.util.HashMap;
import java.util.List;
public class TomcatRoute {
public static HashMap<String, HttpServlet> routes = new HashMap<>();
static {
List<String> paths = SearchClassUtil.searchClass();
for (String path : paths) {
try {
Class clazz = Class.forName(path);
DjyServlet webServlet = (DjyServlet) clazz.getDeclaredAnnotation(DjyServlet.class);
routes.put(webServlet.url(), (HttpServlet) clazz.getDeclaredConstructor().newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
TomcatRoute 类负责管理请求路径和对应的 Servlet 映射关系。在静态代码块中,使用 SearchClassUtil 类查找所有带有 DjyServlet 注解的类,并将注解中的 URL 与对应的 Servlet 实例添加到路由表中
1285

被折叠的 条评论
为什么被折叠?



