我正在使用带有eclipse的tomcat .
根据tomcat的文档:
from the perspective of a web application, class or resource loading looks in the following repositories, in this order:
-
JVM系统类加载器类的Bootstrap类(如上所述)
-
/ WEB-INF /您的Web应用程序的类
您的Web应用程序的 -
/WEB-INF/lib/*.jar
-
公共类加载器类(如上所述)
因此,在加载类时,tomcat将在 WEB-INF/lib 之前查找 WEB-INF/classes . 我们可以在WEB-INF / lib中覆盖jar文件中的某些类,tomcat将获取覆盖的类 .
但是现在如果我通过选中“使用out publish服务模块”来更改tomcat服务器选项,那么将不再加载被覆盖的类 .
有没有任何解决方案可以让它再次工作,但我仍然希望tomcat在没有发布的情况下提供模块服务 .
编辑:
我发现有些东西可能有用,在这个文件夹中 f:\eclipse_projects.metadata.plugins\org.eclipse.wst.server.core\tmp0\conf 有一个server.xml它包含这样的内容:
<Resources className="org.eclipse.jst.server.tomcat.loader.WtpDirContext"
extraResourcePaths=""
virtualClasspath="F:\eclipse_projects\ALS7C3\bin"/>
<Loader className="org.eclipse.jst.server.tomcat.loader.WtpWebappLoader"
useSystemClassLoaderAsParent="false"
virtualClasspath="F:\eclipse_projects\ALS7C3\bin"/>
看来当运行带有选项"Serve modules without publishing"的tomcat时,eclipse将使用它自己的loader.This加载器包含在一个jar文件中,该文件将被复制到 f:\eclipse_projects.metadata.plugins\org.eclipse.wst.server.core\tmp0\lib when you start tomcat in eclipse. Here is part of source code of org.eclipse.jst.server.tomcat.loader.WtpDirContext :
public Object lookup(String name) throws NamingException {
if (name.startsWith("/WEB-INF/") && name.endsWith(".tld")) {
String tldName = name.substring(name.lastIndexOf("/") + 1);
if (virtualMappings != null && virtualMappings.containsKey(tldName)) {
return new FileResource(virtualMappings.get(tldName));
}
} else if (tagfileMappings != null && name.startsWith("/META-INF/tags")
&& (name.endsWith(".tag") || name.endsWith(".tagx"))) {
// already loaded tag file
return new FileResource(tagfileMappings.get(name));
}
Object retSuper;
NamingException superEx;
try {
retSuper = super.lookup(name);
return retSuper;
} catch (NamingException ex) {
retSuper = null;
superEx = ex;
}
if (mappedResourcePaths != null) {
// Perform lookup using the extra resource paths
for (Map.Entry<String, List<String>> mapping : mappedResourcePaths.entrySet()) {
String path = mapping.getKey();
List<String> dirList = mapping.getValue();
if (name.equals(path)) {
for (String resourcesDir : dirList) {
File f = new File(resourcesDir);
if (f.exists() && f.canRead()) {
if (f.isFile()) {
return new FileResource(f);
}
else {
// TODO Handle directory
}
}
}
}
path += "/";
if (name.startsWith(path)) {
String res = name.substring(path.length());
for (String resourcesDir : dirList) {
File f = new File (resourcesDir + "/" + res);
if (f.exists() && f.canRead()) {
if (f.isFile()) {
return new FileResource(f);
}
else {
// TODO Handle directory
}
}
}
}
}
}
throw superEx;
}
似乎如果它首先处理jsp标签库然后调用 super.lookup ,如果在 super.lookup 中找不到,它将尝试在我的示例中加载virtualClasspath中的资源,"F:\eclipse_projects\ALS7C3\bin",这是eclipse输出类文件时服务模块而不发布的地方 .
所以,我想,如果我可以覆盖 org.eclipse.jst.server.tomcat.loader.WtpDirContext 的 lookup 方法,我可以得到我想要的东西,但是这个jar文件包含在 org.eclipse.jst.server.tomcat.core.jar 中,两者都是签名的 .
我不知道如何覆盖这样的jar文件 .
任何人都可以帮忙吗?
2 回答
以下是我使用eclipse / tomcat进行热部署的方法:
停止tomcat
打开tomcat配置菜单
在“服务器选项”选项卡中选中"Serve modules without publishing"
在“发布”选项卡中选中"Never publish automatically"
保存配置
在调试模式下启动tomcat(这非常重要)
如果您更改了配置文件,可以尝试使用新的tomcat .
覆盖这些类的解决方案是在工作空间项目中修改
Servers\???-config\catalina.properties
.属性
common.loader
是Tomcat公共ClassLoader的类路径设置 .Webtools插件将 org.eclipse.jst.server.tomcat.core.jar 复制到
${catalina.base}/lib
. 您可以覆盖这些类并将${catalina.base}/lib,${catalina.base}/lib/*.jar
替换为新路径 .