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

打印 上一主题 下一主题

主题 880|帖子 880|积分 2640

创作缘由

平常使用 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
项目目录
  1. mvn clean
  2. tree /f
  3. D:.
  4. └─src
  5.     └─main
  6.         ├─java
  7.         │  └─com
  8.         │      └─github
  9.         │          └─houbb
  10.         │              └─servlet
  11.         │                  └─webxml
  12.         │                          IndexServlet.java
  13.         │
  14.         └─webapp
  15.             │  index.html
  16.             │
  17.             └─WEB-INF
  18.                     web.xml
复制代码
pom.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5.     <modelVersion>4.0.0</modelVersion>
  6.     <groupId>com.github.houbb</groupId>
  7.     <artifactId>servlet-webxml</artifactId>
  8.     <version>1.0-SNAPSHOT</version>
  9.     <properties>
  10.         <maven.compiler.source>8</maven.compiler.source>
  11.         <maven.compiler.target>8</maven.compiler.target>
  12.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  13.         <plugin.tomcat.version>2.2</plugin.tomcat.version>
  14.     </properties>
  15.     <packaging>war</packaging>
  16.     <dependencies>
  17.         <dependency>
  18.             <groupId>javax.servlet</groupId>
  19.             <artifactId>servlet-api</artifactId>
  20.             <version>2.5</version>
  21.             <scope>provided</scope>
  22.         </dependency>
  23.         <dependency>
  24.             <groupId>org.apache.tomcat</groupId>
  25.             <artifactId>tomcat-servlet-api</artifactId>
  26.             <version>9.0.0.M8</version>
  27.             <scope>provided</scope>
  28.         </dependency>
  29.     </dependencies>
  30.     <build>
  31.         <finalName>servlet</finalName>
  32.         <plugins>
  33.             <plugin>
  34.                 <groupId>org.apache.tomcat.maven</groupId>
  35.                 <artifactId>tomcat7-maven-plugin</artifactId>
  36.                 <version>${plugin.tomcat.version}</version>
  37.                 <configuration>
  38.                     <port>8080</port>
  39.                     <path>/</path>
  40.                     <uriEncoding>${project.build.sourceEncoding}</uriEncoding>
  41.                 </configuration>
  42.             </plugin>
  43.         </plugins>
  44.     </build>
  45. </project>
复制代码
web.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app version="2.4"
  3.          xmlns="http://java.sun.com/xml/ns/j2ee"
  4.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5.          xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  6.    
  7.     <welcome-file-list>
  8.         <welcome-file>/index.html</welcome-file>
  9.     </welcome-file-list>
  10.     <servlet>
  11.         <servlet-name>index</servlet-name>
  12.         <servlet-class>com.github.houbb.servlet.webxml.IndexServlet</servlet-class>
  13.     </servlet>
  14.     <servlet-mapping>
  15.         <servlet-name>index</servlet-name>
  16.         <url-pattern>/index</url-pattern>
  17.     </servlet-mapping>
  18. </web-app>
复制代码
index.html
  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. Hello Servlet!
  5. </body>
  6. </html>
复制代码
servlet
  1. package com.github.houbb.servlet.webxml;
  2. import javax.servlet.http.HttpServlet;
  3. import javax.servlet.http.HttpServletRequest;
  4. import javax.servlet.http.HttpServletResponse;
  5. import java.io.IOException;
  6. import java.io.PrintWriter;
  7. /**
  8. * @author binbin.hou
  9. * @since 0.1.0
  10. */
  11. public class IndexServlet extends HttpServlet {
  12.     @Override
  13.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
  14.         resp.setContentType("text/html");
  15.         // 实际的逻辑是在这里
  16.         PrintWriter out = resp.getWriter();
  17.         out.println("<h1>servlet index</h1>");
  18.     }
  19. }
复制代码
目录结构

打包成 war,然后解压:
  1. mvn clean install
复制代码
其实比较重要的就是 web.xml 作为一切的入口。
对应的 war
  1. D:.
  2. │  index.html
  3. ├─META-INF
  4. │  │  MANIFEST.MF
  5. │  │
  6. │  └─maven
  7. │      └─com.github.houbb
  8. │          └─servlet-webxml
  9. │                  pom.properties
  10. │                  pom.xml
  11. └─WEB-INF
  12.     │  web.xml
  13.     │
  14.     └─classes
  15.         └─com
  16.             └─github
  17.                 └─houbb
  18.                     └─servlet
  19.                         └─webxml
  20.                                 IndexServlet.class
复制代码
如何根据类路径加载类信息?类不是当前项目的

JVM-09-classloader
核心实现
  1. package com.github.houbb.minicat.support.classloader;
  2. import java.io.IOException;
  3. import java.io.UncheckedIOException;
  4. import java.net.URI;
  5. import java.net.URL;
  6. import java.net.URLClassLoader;
  7. import java.nio.file.Files;
  8. import java.nio.file.Path;
  9. import java.nio.file.Paths;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. /**
  13. * https://www.liaoxuefeng.com/wiki/1545956031987744/1545956487069728
  14. *
  15. * 每一个 dir 的 classLoader 独立。
  16. */
  17. public class WebAppClassLoader extends URLClassLoader {
  18.     private Path classPath;
  19.     private Path[] libJars;
  20.     public WebAppClassLoader(Path classPath, Path libPath) throws IOException {
  21.         super(createUrls(classPath, libPath), ClassLoader.getSystemClassLoader());
  22. //        super("WebAppClassLoader", createUrls(classPath, libPath), ClassLoader.getSystemClassLoader());
  23. //
  24.         this.classPath = classPath.toAbsolutePath().normalize();
  25.         if(libPath.toFile().exists()) {
  26.             this.libJars = Files.list(libPath).filter(p -> p.toString().endsWith(".jar")).map(p -> p.toAbsolutePath().normalize()).sorted().toArray(Path[]::new);
  27.         }
  28.     }
  29.     static URL[] createUrls(Path classPath, Path libPath) throws IOException {
  30.         List<URL> urls = new ArrayList<>();
  31.         urls.add(toDirURL(classPath));
  32.         //lib 可能不存在
  33.         if(libPath.toFile().exists()) {
  34.             Files.list(libPath).filter(p -> p.toString().endsWith(".jar")).sorted().forEach(p -> {
  35.                 urls.add(toJarURL(p));
  36.             });
  37.         }
  38.         return urls.toArray(new URL[0]);
  39.     }
  40.     static URL toDirURL(Path p) {
  41.         try {
  42.             if (Files.isDirectory(p)) {
  43.                 String abs = toAbsPath(p);
  44.                 if (!abs.endsWith("/")) {
  45.                     abs = abs + "/";
  46.                 }
  47.                 return URI.create("file://" + abs).toURL();
  48.             }
  49.             throw new IOException("Path is not a directory: " + p);
  50.         } catch (IOException e) {
  51.             throw new UncheckedIOException(e);
  52.         }
  53.     }
  54.     //D:\github\minicat\src\test\webapps\servlet\WEB-INF\classes
  55.     //D:\github\minicat\src\test\webapps\WEB-INF\classes
  56.     static URL toJarURL(Path p) {
  57.         try {
  58.             if (Files.isRegularFile(p)) {
  59.                 String abs = toAbsPath(p);
  60.                 return URI.create("file://" + abs).toURL();
  61.             }
  62.             throw new IOException("Path is not a jar file: " + p);
  63.         } catch (IOException e) {
  64.             throw new UncheckedIOException(e);
  65.         }
  66.     }
  67.     static String toAbsPath(Path p) throws IOException {
  68.         return p.toAbsolutePath().normalize().toString().replace('\\', '/');
  69.     }
  70. }
复制代码
开源地址
  1. /\_/\  
  2. ( o.o )
  3. > ^ <
复制代码
mini-cat 是简易版本的 tomcat 实现。别称【嗅虎】(心有猛虎,轻嗅蔷薇。)
开源地址:https://github.com/houbb/minicat

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

万有斥力

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表