1.了解 Tomcat 类加载:
Tomcat 使用分层类加载模型,不同的类加载器负责从不同位置加载类:
Bootstrap 类加载器:加载核心 Java 类。
系统类加载器:从 CLASSPATH 加载类。
公共类加载器:加载所有网络应用程序共享的类。
网络应用程序类加载器:加载每个网络应用程序的特定类。
2.选择方法:
在 Tomcat 中加载自定义类有两种主要方法:
a) WEB-INF/lib 中的自定义类加载器:
这种方法是在网络应用程序中创建自定义类加载器,并将其置于 WEB-INF/lib 目录中。这种方法可提供特定于应用程序的控制。
b) catalina.properties 中的自定义类加载器:
这种方法是使用 catalina.properties 文件为 Tomcat 全局配置自定义类加载器。这种方法会影响所有已部署的应用程序。
3.实施自定义类加载器:
无论选择哪种方法,核心逻辑都是一样的:
public class MyCustomClassLoader extends URLClassLoader {
public MyCustomClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
@
Override protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
// 1. Check if class is already loaded
Class<?> loadedClass = findLoadedClass(name);
if (loadedClass != null) {
return loadedClass;
}
// 2. Custom logic to prioritize JARs
for (URL url : getURLs()) {
if (url.getFile().endsWith(".jar")) {
try (JarFile jarFile = new JarFile(new File(url.toURI()))) {
// 3. Iterate through entries in each JAR
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (entry.getName().endsWith(".class") &&
entry.getName().replace('/', '.').substring(0, entry.getName().length() - 6).equals(name)) {
byte[] classBytes = loadClassData(jarFile, entry);
return defineClass(name, classBytes, 0, classBytes.length);
}
}
}
}
}
// 4. Delegate to parent if not found
return super.loadClass(name, resolve);
}
// Helper method to load class data from JAR
private byte[] loadClassData(JarFile jarFile, JarEntry entry) throws IOException {
try (InputStream is = jarFile.getInputStream(entry)) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
return buffer.toByteArray();
}
}
}
4.配置 Tomcat (针对方法):
a) WEB-INF/lib 方法:
编译自定义类加载器并将其打包为 JAR 文件。
将 JAR 文件放到网络应用程序的 WEB-INF/lib 目录中。
b) catalina.properties 方法:
编译自定义类加载器并将其打包为 JAR 文件。
将 JAR 文件放到 Tomcat 的 lib 目录中。
编辑 catalina.properties 文件(位于 Tomcat 的 conf 目录中)并添加以下一行,用自定义类加载器的完全合格名称替换 com.example.MyCustomClassLoader:
loader.path=com.example.MyCustomClassLoader
5.自定义加载逻辑:
在自定义类加载器的 loadClass 方法中,可以实现优先加载 JAR 文件的逻辑。这可能包括
根据预定义顺序检查 JAR 文件名或路径。
根据 JAR 属性实施加权系统。
使用配置文件或系统属性确定加载顺序。
这种方法允许您通过自己的逻辑和顺序来控制类加载过程,从而自定义 Tomcat 如何加载目录中的 JAR 文件。