平时使用 tomcat 等 web 服务器不可谓不多,但是一直一知半解。
于是想着自己实现一个简单版本,学习一下 tomcat 的精髓。
从零手写实现 apache Tomcat-02-web.xml 入门详细介绍
从零手写实现 tomcat-03-基本的 socket 实现
从零手写实现 tomcat-06-servlet bio/thread/nio/netty 池化处理
从零手写实现 tomcat-07-war 如何解析处理三方的 war 包?
从零手写实现 tomcat-08-tomcat 如何与 springboot 集成?
从零手写实现 tomcat-10-static resource 静态资源文件
到目前为止,我们处理的都是自己的 servlet 等。
但是 tomcat 这种做一个 web 容器,坑定要能解析处理其他的 war 包。
这个要如何实现呢?
直接用一个 web 简单的项目。
https://github.com/houbb/servlet-webxml
mvn clean
tree /f
D:.
│
└─src
└─main
├─java
│ └─com
│ └─github
│ └─houbb
│ └─servlet
│ └─webxml
│ IndexServlet.java
│
└─webapp
│ index.html
│
└─WEB-INF
web.xml
4.0.0
com.github.houbb
servlet-webxml
1.0-SNAPSHOT
8
8
UTF-8
2.2
war
javax.servlet
servlet-api
2.5
provided
org.apache.tomcat
tomcat-servlet-api
9.0.0.M8
provided
servlet
org.apache.tomcat.maven
tomcat7-maven-plugin
${plugin.tomcat.version}
8080
/
${project.build.sourceEncoding}
/index.html
index
com.github.houbb.servlet.webxml.IndexServlet
index
/index
Hello 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 {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("text/html");
// 实际的逻辑是在这里
PrintWriter out = resp.getWriter();
out.println("servlet index
");
}
}
打包成 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
└─webxml
IndexServlet.class
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 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:githubminicatsrctestwebappsservletWEB-INFclasses
//D:githubminicatsrctestwebappsWEB-INFclasses
static 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 实现。别称【嗅虎】(心有猛虎,轻嗅蔷薇。)
参与评论
手机查看
返回顶部