从零手写实现 tomcat-07-war 如何解析处理三方的 war 包?

news/2024/5/20 20:41:24

创作缘由

平时使用 tomcat 等 web 服务器不可谓不多,但是一直一知半解。

于是想着自己实现一个简单版本,学习一下 tomcat 的精髓。

系列教程

从零手写实现 apache Tomcat-01-入门介绍

从零手写实现 apache Tomcat-02-web.xml 入门详细介绍

从零手写实现 tomcat-03-基本的 socket 实现

从零手写实现 tomcat-04-请求和响应的抽象

从零手写实现 tomcat-05-servlet 处理支持

从零手写实现 tomcat-06-servlet bio/thread/nio/netty 池化处理

从零手写实现 tomcat-07-war 如何解析处理三方的 war 包?

从零手写实现 tomcat-08-tomcat 如何与 springboot 集成?

从零手写实现 tomcat-09-servlet 处理类

从零手写实现 tomcat-10-static resource 静态资源文件

从零手写实现 tomcat-11-filter 过滤器

从零手写实现 tomcat-12-listener 监听器

前言

到目前为止,我们处理的都是自己的 servlet 等。

但是 tomcat 这种做一个 web 容器,坑定要能解析处理其他的 war 包。

这个要如何实现呢?

1-war 包什么样的?

源码

直接用一个 web 简单的项目。

https://github.com/houbb/servlet-webxml

项目目录

mvn clean
tree /fD:.
│
└─src└─main├─java│  └─com│      └─github│          └─houbb│              └─servlet│                  └─webxml│                          IndexServlet.java│└─webapp│  index.html│└─WEB-INFweb.xml

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.github.houbb</groupId><artifactId>servlet-webxml</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><plugin.tomcat.version>2.2</plugin.tomcat.version></properties><packaging>war</packaging><dependencies><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope></dependency><dependency><groupId>org.apache.tomcat</groupId><artifactId>tomcat-servlet-api</artifactId><version>9.0.0.M8</version><scope>provided</scope></dependency></dependencies><build><finalName>servlet</finalName><plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>${plugin.tomcat.version}</version><configuration><port>8080</port><path>/</path><uriEncoding>${project.build.sourceEncoding}</uriEncoding></configuration></plugin></plugins></build></project>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"xmlns="http://java.sun.com/xml/ns/j2ee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"><!--默认的欢迎页面--><welcome-file-list><welcome-file>/index.html</welcome-file></welcome-file-list><servlet><servlet-name>index</servlet-name><servlet-class>com.github.houbb.servlet.webxml.IndexServlet</servlet-class></servlet><servlet-mapping><servlet-name>index</servlet-name><url-pattern>/index</url-pattern></servlet-mapping></web-app>

index.html

<!DOCTYPE html>
<html>
<body>
Hello Servlet!
</body>
</html> 

servlet

package com.github.houbb.servlet.webxml;import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** @author binbin.hou* @since 0.1.0*/
public class IndexServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {resp.setContentType("text/html");// 实际的逻辑是在这里PrintWriter out = resp.getWriter();out.println("<h1>servlet index</h1>");}}

目录结构

打包成 war,然后解压:

mvn clean install

其实比较重要的就是 web.xml 作为一切的入口。

对应的 war

D:.
│  index.html
│
├─META-INF
│  │  MANIFEST.MF
│  │
│  └─maven
│      └─com.github.houbb
│          └─servlet-webxml
│                  pom.properties
│                  pom.xml
│
└─WEB-INF│  web.xml│└─classes└─com└─github└─houbb└─servlet└─webxmlIndexServlet.class

如何根据类路径加载类信息?类不是当前项目的

JVM-09-classloader

核心实现

package com.github.houbb.minicat.support.classloader;import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;/*** https://www.liaoxuefeng.com/wiki/1545956031987744/1545956487069728** 每一个 dir 的 classLoader 独立。*/
public class WebAppClassLoader extends URLClassLoader {private Path classPath;private Path[] libJars;public WebAppClassLoader(Path classPath, Path libPath) throws IOException {super(createUrls(classPath, libPath), ClassLoader.getSystemClassLoader());
//        super("WebAppClassLoader", createUrls(classPath, libPath), ClassLoader.getSystemClassLoader());
//this.classPath = classPath.toAbsolutePath().normalize();if(libPath.toFile().exists()) {this.libJars = Files.list(libPath).filter(p -> p.toString().endsWith(".jar")).map(p -> p.toAbsolutePath().normalize()).sorted().toArray(Path[]::new);}}static URL[] createUrls(Path classPath, Path libPath) throws IOException {List<URL> urls = new ArrayList<>();urls.add(toDirURL(classPath));//lib 可能不存在if(libPath.toFile().exists()) {Files.list(libPath).filter(p -> p.toString().endsWith(".jar")).sorted().forEach(p -> {urls.add(toJarURL(p));});}return urls.toArray(new URL[0]);}static URL toDirURL(Path p) {try {if (Files.isDirectory(p)) {String abs = toAbsPath(p);if (!abs.endsWith("/")) {abs = abs + "/";}return URI.create("file://" + abs).toURL();}throw new IOException("Path is not a directory: " + p);} catch (IOException e) {throw new UncheckedIOException(e);}}//D:\github\minicat\src\test\webapps\servlet\WEB-INF\classes//D:\github\minicat\src\test\webapps\WEB-INF\classesstatic URL toJarURL(Path p) {try {if (Files.isRegularFile(p)) {String abs = toAbsPath(p);return URI.create("file://" + abs).toURL();}throw new IOException("Path is not a jar file: " + p);} catch (IOException e) {throw new UncheckedIOException(e);}}static String toAbsPath(Path p) throws IOException {return p.toAbsolutePath().normalize().toString().replace('\\', '/');}}

开源地址

 /\_/\  
( o.o ) > ^ <

mini-cat 是简易版本的 tomcat 实现。别称【嗅虎】(心有猛虎,轻嗅蔷薇。)

开源地址:https://github.com/houbb/minicat


http://www.mrgr.cn/p/48848421

相关文章

Fatal error in launcher: Unable to create process using d:\python38\python3.exe ...

使用场景:本地主机安装好的python3.8 版本的运行环境,迁移道其他主机执行pip install -r .\requirements.txt 运行一下命令解决:python3 -m pip install watchdog

Nexpose v6.6.251 for Linux Windows - 漏洞扫描

Nexpose v6.6.251 for Linux & Windows - 漏洞扫描Nexpose v6.6.251 for Linux & Windows - 漏洞扫描 Rapid7 Vulnerability Management, Release May 08, 2024 请访问原文链接:Nexpose v6.6.251 for Linux & Windows - 漏洞扫描,查看最新版。原创作品,转载请保…

Prometheus+Alertmanager+webhook-dingtalk实现钉钉告警

文章目录 一、前提准备及规划 二、安装及启动 2.1 Prometheus安装启动 2.2 Node_export安装启动 2.3 Alertmanager安装启动 2.4 Webhook-dingtalk安装启动 三、配置及测试 3.1 Webhook-dingtalk配置钉钉webhook地址 3.2 Alertmanager配置钉钉告警 3.3 Prometheus集成Alertmanag…

mac本地搭建ollama

mac本地搭建ollama webUI *简介:ollama-webUI是一个开源项目,简化了安装部署过程,并能直接管理各种大型语言模型(LLM)。本文将介绍如何在你的macOS上安装Ollama服务并配合webUI调用api来完成聊天。 开源地址https://github.com/812781385/ollama-webUI.git,开源不易感谢s…

docker 安装elasticsearch8.X

docker 安装elasticsearch8.X 安装elasticsearch8.X前言安装elasticsearch安装elasticsearch-analysis-ik安装kibana 安装elasticsearch8.X 前言 由于需要安装elasticsearch、IK分词插件、kibana。所以需要保持这三者的版本一致性。 elasticsearch 8.12.2 kibana 8.12.2 ela…

如何安全高效地进行企业文档外发,一文了解!

企业文档外发是指将企业的内部文件、文档或信息发送给企业外部的个人或组织。目前使用比较多的企业文档外发的方式有以下几种,可以了解看一下: 1.邮件系统:通过电子邮件发送文档,这是最传统的文档外发方式之一。 2.即时通讯工具:如微信、QQ、企业微信、钉钉、飞书等,这些工…

Gantt图和PERT图的相关知识

1、Gantt 图Gantt图以时间为基准描述项目任务,可以清晰的描述每个任务从何时开始,到何时结束,以及每个任务的并行关系,但是不能反映项目各任务之间的依赖关系,也无法确定整个任务的关键所在。2、PERT图计划评审技术(Program Evaluation and Review Technique,简称PERT)…

ESP32引脚入门指南(三):从理论到实践(Touch Pin)

引言 ESP32作为物联网领域的明星微控制器&#xff0c;不仅以其强大的网络通信能力著称&#xff0c;还内置了丰富的外设资源&#xff0c;其中就包括电容式触摸传感&#xff08;Capacitive Touch&#xff09;功能。本文旨在深入浅出地介绍ESP32的Touch引脚&#xff0c;带你了解其…

【训练与预测】02 - 完整的模型验证套路

02 - 完整的模型验证套路 模型图 验证一个模型就是指使用已经训练好的模型&#xff0c;然后给它提供输入。 test.py import torch import torchvision from PIL import Imagedevice torch.device("cuda" if torch.cuda.is_available() else "cpu") ima…

Github 2024-05-10 Java开源项目日报Top10

根据Github Trendings的统计,今日(2024-05-10统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Java项目10C++项目2JavaGuide - Java 程序员学习和面试指南 创建周期:2118 天开发语言:Java协议类型:Apache License 2.0Star数量:140773 个…

Rust工作空间(workspace)实践

本文将介绍如何使用cargo workspace来管理多个package,并通过实践介绍workspace的一些基础场景下的使用、配置方式。在rust中编写某些中小型项目时,我们通常不会将一个工程拆分为多个package,而是通过一个package下不同的目录模块来实现模块拆分,尽管大部分场景下这种开发方…

C++三部曲|C++编程核心思想

| 导语 C 的起源可以追溯到 40 年前&#xff0c;但它仍然是当今使用最广泛的编程语言之一&#xff0c;C发明人Bjarne Stroustrup 一开始没想到 C 会获得如此大的成功&#xff0c;他说&#xff1a;“C 的成功显然令人惊讶。我认为它的成功取决于其最初的设计目标&#xff0c;就是…

一文读懂Vue生命周期(Vue2)

一文读懂Vue生命周期&#xff08;Vue2&#xff09; 目录 一文读懂Vue生命周期&#xff08;Vue2&#xff09;1 前言2 Vue生命周期2.1 基本生命周期2.1.1 8个生命周期2.1.2 案例 2.2 组件生命周期2.2.1 父子生命周期2.2.2 案例 2.3 keep-alive生命周期2.3.1 案例 2.4 其他 3 总结…

C#动态查询:巧用Expression组合多条件表达式

概述:在C#中,通过`Expression`类、`AndAlso`和`OrElse`方法可组合两个`Expression<Func<T, bool>>`,实现多条件动态查询。通过创建表达式树,可轻松构建复杂的查询条件。 在C#中,可以使用AndAlso和OrElse方法组合两个Expression<Func<T, bool>>类型…

《Decoupled Optimisation for Long-Tailed Visual Recognition》阅读笔记

论文标题 《Decoupled Optimisation for Long-Tailed Visual Recognition》 长尾视觉识别的解耦优化 作者 Cong Cong、Shiyu Xuan、Sidong Liu、Shiliang Zhang、Maurice Pagnucco 和 Yang Song、 来自新南威尔士大学计算机科学与工程学院、北京大学计算机学院多媒体信息处理国…

、、、、、

、、 Java虚拟机栈存储了Java方法调用时的栈帧&#xff0c;而本地方法栈存储的是native本地方法的栈帧。 这里的native本地方法、指的是&#xff1f; 在Java中&#xff0c;native本地方法指的是、使用其他语言&#xff08;如C、C等&#xff09;编写的方法&#xff0c;这些方…

Rocketmq 不同的topic要配不同的consumegroup

Rocketmq 不同的topic要配不同的consumegroup 使用Rocketmq一定要注意,如果项目中要订阅两个topic,一定要保证consumeGroup是两个不同的。这是因为,Consumer会定期发送心跳,默认是30s一次。心跳会像全部broker发送,心跳包内容包括groupname,topicname1。然后broker端会缓…

基于docker安装flink

文章目录 环境准备Flinkdocker-compose方式二进制部署 KafkaMysql Flink 执行 SQL命令进入SQL客户端CLI执行SQL查询表格模式变更日志模式Tableau模式窗口计算 窗口计算滚动窗口demo滑动窗口 踩坑 环境准备 Flink docker-compose方式 version: "3" services:jobman…

2022年windows的Visual Studio常用插件及使用手册

前景提要Viusual Studio 是一款很好用的C/C++集成开发工具,具有强大的扩展功能,好用的插件,但是,很多人都是只写了有什么插件,但是,没写怎么使用这种插件,使得使用的时候很是不方便,所以,笔者最近本着自己的学习,在这里写下自己关于好用的插件的研究,希望对您的学习/工作有帮助…

JDK源码阅读-------自学笔记(二十六)(java.util.Map 自定义讲解)

一、简介Map就是用来存储“键(key)-值(value)”对的. 通过键寻找value,所以键不能重复. 数组的本质也是一种键值对,区别就是索引一般是数字,而Map的Key可以是任意对象(字符串,数字),相当于把数组的索引范围扩的更大,使用更方便. 实际开发中较为常用.二、Map的常用方法实例(1)存…