手写Tomcat(一)
一、Tomcat简介
Tomcat 服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。
1.1 Tomcat基本架构
Servlet接口文件中定义的方法有以下几个:
- init():初始化Servlet
- getServletConfig():获取Servlet配置信息
- service():服务..........
- getServletInfo():获取Servlet的运行信息
- destroy():销毁,回收内存
补充:
- Servlet是接口文件,定义方法不需实现,通过其子类即GenericSrevlet(抽象类)及HttpSrevlet(抽象类)进行实现。
- 补充:抽象类中可以写抽象方法,也可以写实现方法,同时可以不实现接口中定义的全部抽象方法。
GenericSrevlet类中实现了init()、getServletConfig()、getServletInfo()、destroy()四个方法,把service()交由HttpSrevlet实现。
为什么在HttpSrevlet中实现service()方法?
HttpServlet中关于 service()定义如下:
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String method = req.getMethod();long lastModified;if (method.equals("GET")) {lastModified = this.getLastModified(req);if (lastModified == -1L) {this.doGet(req, resp);} else {long ifModifiedSince;try {ifModifiedSince = req.getDateHeader("If-Modified-Since");} catch (IllegalArgumentException var9) {ifModifiedSince = -1L;}if (ifModifiedSince < lastModified / 1000L * 1000L) {this.maybeSetLastModified(resp, lastModified);this.doGet(req, resp);} else {resp.setStatus(304);}}} else if (method.equals("HEAD")) {lastModified = this.getLastModified(req);this.maybeSetLastModified(resp, lastModified);this.doHead(req, resp);} else if (method.equals("POST")) {this.doPost(req, resp);} else if (method.equals("PUT")) {this.doPut(req, resp);} else if (method.equals("DELETE")) {this.doDelete(req, resp);} else if (method.equals("OPTIONS")) {this.doOptions(req, resp);} else if (method.equals("TRACE")) {this.doTrace(req, resp);} else {String errMsg = lStrings.getString("http.method_not_implemented");Object[] errArgs = new Object[]{method};errMsg = MessageFormat.format(errMsg, errArgs);resp.sendError(501, errMsg);}}
HttpServlet中定义service()是为了更好的匹配当前http的请求方式。
二、Tomcat简化模型构建知识补充
2.1 HTTP协议
HTTP是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP)。
2.1.1 请求部分
请求部分包括请求头、请求方式、请求内容,如请求方式等可以进行选择,但是在发送请求时不能删减。
2.1.1.1 请求头
注:可以通过f12,选择网络进行查看。
2.1.1.2 请求方式
GET
用途:获取资源(查询数据),参数通过 URL 的 Query String 传递(如
/users?id=123
)。特点:
可见性:参数暴露在 URL 和浏览器历史中。
长度限制:由浏览器和服务器共同决定(如 IE 限制为 2048 字符,Chrome 约 8KB),并非 HTTP 协议规定。
幂等性:多次请求结果相同(不修改资源)。
安全建议:避免用 GET 传输敏感信息(密码、Token)。
POST
用途:提交数据(创建或修改资源),参数在 请求体 中(支持多种编码格式,如
form-data
、JSON
)。特点:
无长度限制:理论上由服务器配置决定。
非幂等性:多次提交可能产生不同结果(如重复创建订单)。
相对安全误解:HTTP 明文传输下,POST 请求体仍可被拦截。真正的安全需依赖 HTTPS。
常见场景:表单提交、文件上传、复杂数据(如嵌套 JSON),一般用来做增删改操作。
HEAD
用途:获取资源的 元数据(响应头),不返回响应体。
典型应用:
检查资源是否存在(通过状态码
200
或404
)。验证资源是否修改(通过
Last-Modified
或ETag
头)。预加载资源信息(如
Content-Length
用于进度条)。
OPTIONS
用途:询问服务器支持的 HTTP 方法 或 CORS 预检请求。
CORS 预检:
浏览器在跨域请求前自动发送 OPTIONS 请求。
服务器需返回
Access-Control-Allow-Methods
等头,声明允许的方法、头、源。示例:
Access-Control-Allow-Methods: GET, POST, PUT
PUT
用途:完整替换资源(全量更新)。
幂等性:多次请求结果一致(如更新用户信息为固定值)。
与 POST 区别:
POST 用于创建资源时,URI 由服务器决定(如
/users
)。PUT 需客户端指定完整资源路径(如
/users/123
)。
PATCH
用途:局部更新资源(如只修改用户的邮箱)。
非幂等性:连续多次局部更新可能导致意外结果(如递增计数器)。
实现方式:需定义数据格式(如 JSON Patch 标准)。
DELETE
用途:删除指定资源。
幂等性:多次删除同一资源结果相同(首次返回
200
或204
,后续可能返回404
)。注意:实际业务中常采用 逻辑删除(标记为删除状态)而非物理删除。
TRACE
用途:回显客户端请求,用于调试。
安全风险:可能引发 跨站追踪攻击(XST),多数服务器默认禁用。
CONNECT
用途:建立到目标服务器的 隧道连接,用于代理 HTTPS 流量。
工作流程:
客户端发送
CONNECT example.com:443 HTTP/1.1
。代理服务器建立 TCP 连接到目标服务器。
后续数据直接透传(用于 TLS 加密通信)
关键对比总结
特性 | GET | POST | PUT | PATCH | DELETE |
---|---|---|---|---|---|
幂等性 | ✔️ | ❌ | ✔️ | ❌ | ✔️ |
安全性 | 低 | 中 | 中 | 中 | 中 |
数据位置 | URL | Body | Body | Body | URL |
2.1.2 响应部分
响应部分包括响应头、响应状态、响应内容。
2.1.2.1 响应头
注:可以通过f12,选择网络进行查看。
2.1.2.2 响应状态
- 200:ok
- 404:url出错
- 500:服务器内部错误
2.1.2.3 响应内容
响应内容就是传输的内容。
2.2 数据传输
在tomcat中,接口信息及参数等的数据传递的底层通过I/O实现,随后将数据给到ServletRequest/ServletReqsponse。
2.2.1 request
request中接受的信息(仅列举一部分):
- method:请求方式
- 编码方式:如JSON
- data:parameter
- url:请求地址
- cookie:获取登录信息
2.2.2 response
response中包含的信息(仅列举一部分):
- 状态码
- 编码方式:如JSON
- 字符集:如utf-8
- data数据