V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  IDAEngine  ›  全部回复第 8 页 / 共 80 页
回复总数  1595
1 ... 4  5  6  7  8  9  10  11  12  13 ... 80  
176 天前
回复了 zhangjiashu2023 创建的主题 iPhone iPhone 去广告优雅的方式
Ad block one ,趋势科技开发的,挺好用的
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 文件。
GPT:

一般来说,您不应该依赖 Tomcat 的 lib 目录中 JAR 文件的特定加载顺序。Java 的类加载机制并不保证特定的加载顺序,试图强制加载顺序可能会导致脆性和不可预测的行为。
但是,如果您绝对必须控制特定 JAR 文件的加载顺序(例如,由于库冲突或非常特定的初始化需求),以下是一些方法及其注意事项:
1.Manifest 中的类路径:
工作原理在网络应用程序 WAR 文件(位于 WEB-INF/classes/META-INF/)的 MANIFEST.MF 文件中,您可以指定一个 Class-Path 条目。该条目列出了应用程序所依赖的其他 JAR ,它们将按照指定的顺序加载。
例如
Manifest-Version: 1.0
类路径:library1.jar library2.jar
注意事项
这种方法只能控制网络应用程序加载其依赖项的顺序。它不会影响 Tomcat 在其全局 lib 目录中加载 JAR 的顺序。
如果管理不慎,它可能会导致 "JAR 地狱",尤其是复杂的依赖关系树。
2.Tomcat 的共享类加载器:
如何工作 Tomcat 有一个 "共享类加载器 "的概念,它从 $CATALINA_HOME/lib 目录中的 JAR 中加载类。从该目录加载 JAR 的顺序会受到操作系统文件系统中 JAR 列出顺序的影响。
注意事项
不建议使用这种方法,因为它会破坏部署在同一 Tomcat 实例上的其他应用程序。
它完全依赖于环境(依赖于文件系统顺序),因此不具备可移植性。
3.自定义类加载器(高级且有风险):
工作原理:您可以在网络应用程序中创建自定义类加载器,以受控顺序从特定 JAR 中加载类。这是一种非常高级的技术,需要深入了解 Java 的类加载机制。
注意事项
这种方法非常复杂,如果不仔细实施,很容易导致微妙的类加载问题。
它会使应用程序的架构和调试变得非常复杂。
为什么依赖加载顺序会产生问题?
易损坏:如果依赖于特定的 JAR 加载顺序,Tomcat 版本、操作系统甚至目录中文件顺序的变化都可能导致应用程序崩溃。
难以调试:当出现类加载问题时,诊断和修复是出了名的困难,尤其是当你以非常规的方式操作类路径时。
违背最佳实践:Java 的类加载系统旨在以稳健、可预测的方式处理依赖关系。试图规避这种机制往往会导致问题多于解决。
推荐方法:
与其试图强制执行特定的加载顺序,不如将重点放在以下方面:
依赖关系管理:使用 Maven 或 Gradle 等构建工具来管理应用程序的依赖关系。这些工具擅长解决冲突,并确保在 WAR 文件中包含正确版本的库。
隔离:将应用程序及其所有必要的依赖项打包到自己的 WAR 文件(或作为 "胖 JAR")中。这样可以确保您的应用程序有自己独立的类路径,避免与同一服务器上运行的其他应用程序发生冲突。
代码设计:如果可能,重构代码以消除对特定 JAR 加载顺序的需求。这可能需要使用接口和依赖注入将代码与具体实现解耦。
通过遵循这些最佳实践,您可以创建更健壮、可维护和可移植的 Java 网络应用程序。
买比亚迪秦 L 呀,代步用,便宜而且还可以偶尔跑一跑滴滴
181 天前
回复了 magic3584 创建的主题 北京 明年幼升小了,放弃北漂,求城市推荐
东北可以呀,去年冬天去哈尔滨旅游了一下,哈尔滨确实不错哦
公司名:智行信息有限公司
域名:WisdomWalk.com
理由:“智行”寓意智慧引领前行。
公司名:云翼信息有限公司
域名:CloudWing.com
理由:“云翼”代表云计算的翅膀。
公司名:码匠信息有限公司
域名:CodeCraft.com
理由:“码匠”强调编程如同手工艺。
公司名:创界信息有限公司
域名:InnovRealm.com
理由:“创界”寓意开创一个全新的世界。
公司名:智汇信息有限公司
域名:WisdomHub.com
理由:“智汇”代表智慧的汇聚。
公司名:源动力信息有限公司
域名:SourcePower.com
理由:“源动力”表示源源不断的动力。
公司名:智途信息有限公司
域名:WisdomPath.com
理由:“智途”表示智慧引领的途径。
公司名:码界信息有限公司
域名:CodeWorld.com
理由:“码界”直接表示编程的世界。
公司名:智网信息有限公司
域名:WisdomNet.com
理由:“智网”代表智能网络。
公司名:智海信息有限公司
域名:WisdomOcean.com
理由:“智海”象征智慧的海洋。
公司名:智光信息有限公司
域名:WisdomLight.com
理由:“智光”代表智慧的光芒。
公司名:智源信息有限公司
域名:WisdomSource.com
理由:“智源”表示智慧的源头。
公司名:码艺信息有限公司
域名:CodeArt.com
理由:“码艺”结合编程和艺术。
公司名:创梦信息有限公司
域名:DreamMaker.com
理由:“创梦”寓意创造梦想。
公司名:智领信息有限公司
域名:WisdomLead.com
理由:“智领”表示智慧引领。
公司名:云游信息有限公司
域名:CloudRoam.com
理由:“云游”代表在云端自由游弋。
公司名:智启信息有限公司
域名:WisdomStart.com
理由:“智启”表示智慧的启动。
公司名:智悦信息有限公司
域名:WisdomJoy.com
理由:“智悦”表示智慧带来的快乐。
公司名:智汇星信息有限公司
域名:WisdomStar.com
理由:“智汇星”结合智慧和星星,寓意璀璨夺目。
公司名:码行者信息有限公司
域名:CodeWalker.com
理由:“码行者”表示编程的探索者。
safari brave
185 天前
回复了 newtonMiku 创建的主题 宽带症候群 高校如何高效利用 40G 对等线路
开个公益 JS CDN 、NPM 、Python PIP 镜像加速,各种 AI 模型镜像站
185 天前
回复了 hahahenimei 创建的主题 汽车 10-15w 买给媳妇的通勤车
女生其实买本田飞度很好的
185 天前
回复了 name1991 创建的主题 随想 如果不当码农大家想做什么?
社会闲散人员
intel 兼容性好呀,而且和其他的硬件厂商配合比较紧密,AMD 相差有点大
估计是 PCDN 上传太大
内存基本 100M 内,问题不大
188 天前
回复了 carpeDiemJll 创建的主题 职场话题 想听听 35+的大佬真心话
现金 600W 毫无压力
188 天前
回复了 LuffyPro 创建的主题 程序员 前端校验还是后端校验的问题
必须都校验,要么就全部交给后端,肯定不能交给用户
1 ... 4  5  6  7  8  9  10  11  12  13 ... 80  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1349 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 42ms · UTC 23:37 · PVG 07:37 · LAX 15:37 · JFK 18:37
Developed with CodeLauncher
♥ Do have faith in what you're doing.