简体   繁体   English

带有Servlet 3.0的嵌入式Tomcat-如何在扫描时跳过某些jar?

[英]Embedded Tomcat with Servlet 3.0 - How to skip certain jars when scanning?

Here is a simple method for an embedded Tomcat server that scans for Servlet 3.0 initializers: 这是嵌入式Tomcat服务器扫描Servlet 3.0初始化程序的简单方法:

public static void main(String[] args) throws ServletException, LifecycleException {
    Tomcat tomcat = new Tomcat();
    tomcat.setPort(8080);

    StandardContext ctx = (StandardContext) tomcat.addWebapp("/", new File("web").getAbsolutePath());

    //declare an alternate location for your "WEB-INF/classes" dir:     
    File additionWebInfClasses = new File("target/classes");
    VirtualDirContext resources = new VirtualDirContext();
    resources.setExtraResourcePaths("/WEB-INF/classes=" + additionWebInfClasses);
    ctx.setResources(resources);

    tomcat.start();
    System.out.println("Started");
    tomcat.getServer().await();
}

I know that the property tomcat.util.scan.DefaultJarScanner.jarsToSkip in catalina.properties allows you to limit which jars are scanned to speed deployment time. 我知道catalina.properties中的属性tomcat.util.scan.DefaultJarScanner.jarsToSkip允许您限制扫描哪些jar来加快部署时间。 How would I incorporate this same idea into the embedded Tomcat code here? 我如何将相同的想法整合到嵌入式Tomcat代码中?

BONUS: Is there a way to specify which jars to include instead of which jars to skip ? 奖励:有没有一种方法可以指定要包括的jar而不是要跳过的 jar?

While I don't have a specific way of loading individual catalina.properties properties, I found it convenient enough to just overload the JarScanner itself on the Tomcat container contexts like so: 尽管我没有特定的方式来加载单个catalina.properties属性,但我发现它足以方便地在Tomcat容器上下文中重载JarScanner本身,如下所示:

Answer is in Groovy (sorry, I get lazy) 答案在Groovy中 (对不起,我很懒)

public static void main(String[] args) throws ServletException, LifecycleException {
    Tomcat tomcat = new TomcatWithFastJarScanner()
    tomcat.setPort(8080)

    StandardContext ctx = (StandardContext) tomcat.addWebapp("/", new File("web").getAbsolutePath())

    //declare an alternate location for your "WEB-INF/classes" dir:     
    VirtualDirContext resources = new VirtualDirContext()
    resources.setExtraResourcePaths("/WEB-INF/classes=" + new File("target/classes"))
    ctx.setResources(resources)

    tomcat.start()
    println "Started server on port 8080"
    tomcat.getServer().await()
}

private static class TomcatWithFastJarScanner extends Tomcat {
    @Override
    public void start() throws LifecycleException {
        getServer().findServices().each { service ->
            service.getContainer().findChildren().each { container ->
                container.findChildren().each { c ->
                    ((Context) c).setJarScanner(new FastJarScanner())
                }
            }
        }
        super.start()
    }
}


private static class FastJarScanner extends StandardJarScanner {
    def jarsToInclude = [ 'spring-web.*' ]

    @Override
    public void scan(ServletContext context, ClassLoader classloader,
            JarScannerCallback callback, Set<String> jarsToSkip) {
        jarsToSkip = new HashSet<String>();

        ((URLClassLoader) classloader.getParent()).getURLs().each {
            def jar = it.path.find(/[^\/]+\.jar$/)
            if(!jar) return
            for(String inclusionPattern : jarsToInclude) {
                if(jar.find(inclusionPattern))  
                    println "including jar: " + jar
                else jarsToSkip.add(jar)
            }
        }

        super.scan(context, classloader, callback, jarsToSkip);
    }
}

The basic idea is that we are looking at all the jars which the classloader can see, and excluding all of the jars that we don't want to include. 基本思想是,我们正在查看类加载器可以看到的所有jar,并排除了我们不想包含的所有jar。

Tomcat embedded starts up real fast like this! Tomcat嵌入式可以像这样快速启动!

The following is speculative, only reading the specs. 以下是推测性内容,仅阅读规格。 One could use a web-fragment, with its own META-INF/web.xml with metadata-complete=true signaling no annotation scanning. 可以使用网络片段,并使用自己的META-INF / web.xml,其中metadata-complete = true表示无注释扫描。

You can extend Tomcat setting scanClassPath to false, something like - this is on top of what user jkschneider here has pointed out): 您可以将Tomcat设置scanClassPath扩展为false,类似-这是在此处用户jkschneider指出的之上 ):

new Tomcat() {
    @Override
    public void start() throws LifecycleException {
        for (final org.apache.catalina.Service service : getServer().findServices()) {
            for (final Container container : service.getContainer().findChildren()) {
                for (final Container subContainer : container.findChildren()) {
                    final StandardJarScanner jarScanner = (StandardJarScanner) ((Context) subContainer).getJarScanner();
                    jarScanner.setScanClassPath(false);
                }
            }
        }
        super.start();
    }
};

btw better approach may be as follows: 更好的方法可能如下:

final Tomcat tomcat = new Tomcat();
final StandardHost tomcatHost = (StandardHost) tomcat.getHost();
        tomcatHost.setContextClass("com.fullclassname....FastStandardContext");

where FastStandardContext is FastStandardContext在哪里

public class FastStandardContext extends StandardContext {
    public FastStandardContext() {
        ((StandardJarScanner) getJarScanner()).setScanClassPath(false);
    }
}

This will cover cases where new webapps are added after tomcat is running. 这将涵盖在tomcat运行后添加新的Web应用程序的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM