首页 文章

服务模块时Tomcat类加载顺序而不发布

提问于
浏览
7

我正在使用带有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.WtpDirContextlookup 方法,我可以得到我想要的东西,但是这个jar文件包含在 org.eclipse.jst.server.tomcat.core.jar 中,两者都是签名的 .

我不知道如何覆盖这样的jar文件 .

任何人都可以帮忙吗?

2 回答

  • 0

    以下是我使用eclipse / tomcat进行热部署的方法:

    • 停止tomcat

    • 打开tomcat配置菜单

    • 在“服务器选项”选项卡中选中"Serve modules without publishing"

    • 在“发布”选项卡中选中"Never publish automatically"

    • 保存配置

    • 在调试模式下启动tomcat(这非常重要)

    如果您更改了配置文件,可以尝试使用新的tomcat .

  • 0

    覆盖这些类的解决方案是在工作空间项目中修改 Servers\???-config\catalina.properties .

    common.loader = $ / lib,$ / lib / * .jar,$ / lib,$ / lib / * .jar

    属性 common.loader 是Tomcat公共ClassLoader的类路径设置 .
    Webtools插件将 org.eclipse.jst.server.tomcat.core.jar 复制到 ${catalina.base}/lib . 您可以覆盖这些类并将 ${catalina.base}/lib,${catalina.base}/lib/*.jar 替换为新路径 .

相关问题