通过WebAppContext extraClasspath管理许多jar

时间:2014-09-30 19:08:31

标签: java jetty classpath

我有一个热插拔webapps的嵌入式jetty服务器。在部署其他战争时,我将部署descriptor.xml添加到目录以配置webappcontext。我希望在另一个位置添加一个可以在热部署战争(/ extJars)的类路径中构建的罐子目录。我看到如何在webapp descriptor.xml中执行此操作,我可以通过声明单个jar来完成此操作,但我尝试了多个配置来尝试简单地读取此目录中的所有jar,并且没有任何工作。这是我的otherWebApp.xml,我们将调用它,配置有效,并注释掉不起作用的配置。感谢。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
    <Configure class="org.eclipse.jetty.webapp.WebAppContext">
        <Set name="war"><SystemProperty name="JETTY_HOME" default="." />/extApps/otherWebApp.war</Set>
        <Set name="contextPath">/otherWebApp</Set>
        <Set name="tempDirectory" ><SystemProperty name="JETTY_HOME" />/jetty/webapps/otherWebApp</Set>  
<Set name="extraClasspath"><SystemProperty name="JETTY_HOME" />/extJars/cadi-core-1.0.12.jar,<SystemProperty name="JETTY_HOME" />/extJars/cadi-aaf-1.0.12.jar,<SystemProperty name="JETTY_HOME" />/extJars/GLCookieDecryption-1.0.jar,<SystemProperty name="JETTY_HOME" />/extJars/rosetta-1.1.1.jar,<SystemProperty name="AJSC_HOME" />/extJars/env-1.4.2.jar,<SystemProperty name="JETTY_HOME" />/extJars/dme2-2.5.22.jar</Set>
<!-- <Set name="extraClasspath"><SystemProperty name="JETTY_HOME" />/extJars/</Set>
    </Configure>  doesn't work -->
<!-- <Set name="extraClasspath"><SystemProperty name="JETTY_HOME" />/extJars/*</Set>
    </Configure> doesn't work -->
<!-- <Set name="extraClasspath"><SystemProperty name="JETTY_HOME" />/extJars/*.jar</Set>
    </Configure>  doesn't work -->
<!-- <Set name="extraClasspath"><SystemProperty name="JETTY_HOME" />/extJars</Set>
    </Configure> doesn't work -->

1 个答案:

答案 0 :(得分:2)

你有3个选择。

1:使用父级加载程序优先级

在嵌入式中,告诉WebAppContext使用父加载器优先级。 (这将有利于服务器类而不是webapp类)

<Configure class="org.eclipse.jetty.webapp.WebAppContext">
  <Set name="contextPath">/example</Set>
  <Set name="war">example.war</Set>
  <Set name="parentLoaderPriority">true</Set>
</Configure>

这有一个副作用,如果服务器类执行任何信息缓存(许多库中的常用技术),那么该缓存现在可用于所有Web应用程序。

2:使用自定义DeploymentManager绑定来管理WebAppClassloader

每个WebAppContext使用可配置为的WebAppClassloader:

  1. 从服务器类加载器中公开某些类
  2. 如果webapp和服务器之间存在冲突,请确定WebAppContext的作用。
  3. 由于您使用的是DeploymentManager,因此可以通过Bindings技术对其进行标准化。

    绑定本身:ExposeServerCommonBinding.java

    package jetty;
    
    import org.eclipse.jetty.deploy.App;
    import org.eclipse.jetty.deploy.AppLifeCycle;
    import org.eclipse.jetty.deploy.graph.Node;
    import org.eclipse.jetty.server.handler.ContextHandler;
    import org.eclipse.jetty.webapp.WebAppContext;
    
    public class ExposeServerCommonBinding implements AppLifeCycle.Binding
    {
        public String[] getBindingTargets()
        {
            return new String[]
            { "deploying" };
        }
    
        public void processBinding(Node node, App app) throws Exception
        {
            ContextHandler handler = app.getContextHandler();
            if (handler == null)
            {
                throw new NullPointerException("No Handler created for App: " + app);
            }
    
            if (handler instanceof WebAppContext)
            {
                WebAppContext webapp = (WebAppContext)handler;
    
                // System classes (or namespaces) present in server classloader to expose to webapp
                webapp.addSystemClass("org.apache.log4j.");
                webapp.addSystemClass("org.slf4j.");
                webapp.addSystemClass("org.apache.commons.logging.");
    
                // Server classes that cannot be overridden by webapp
                webapp.addServerClass("-org.apache.log4j.");
                webapp.addServerClass("-org.slf4j.");
                webapp.addServerClass("-org.apache.commons.logging.");
            }
        }
    }
    

    以及如何使用

    DeploymentManager mgr = new DeploymentManager();
    
    WebAppProvider provider = new WebAppProvider();
    provider.setMonitoredDirResource(Resource.newResource(new File("./webapps/")));
    mgr.addAppProvider(provider);
    
    mgr.addLifeCycleBinding(new ExposeServerCommonBinding());
    

    此技术将适用于通过DeploymentManager部署的所有WebAppContexts,允许您将这些规则同等地应用于所有Web应用程序。

    3:使用自定义DeploymentManager绑定来管理extraClasspath

    这是另一个Binding替代方案,您可以使用它在服务器端预构建extraClasspath,并且在部署WebApp时,它会自动将这些extraClasspath添加到WebApp。

    package jetty;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Locale;
    
    import org.eclipse.jetty.deploy.App;
    import org.eclipse.jetty.deploy.AppLifeCycle;
    import org.eclipse.jetty.deploy.graph.Node;
    import org.eclipse.jetty.server.handler.ContextHandler;
    import org.eclipse.jetty.webapp.WebAppContext;
    
    public class CommonExtraClasspathBinding implements AppLifeCycle.Binding
    {
        private List<File> extraClasspath = new ArrayList<>();
    
        public String[] getBindingTargets()
        {
            return new String[] { "deploying" };
        }
    
        public void addAllJars(File dir)
        {
            for (File file : dir.listFiles())
            {
                if (!file.isFile())
                {
                    continue;
                }
                if (file.getName().toLowerCase(Locale.ENGLISH).equals(".jar"))
                {
                    addJar(file);
                }
            }
        }
    
        public void addJar(File jar)
        {
            if (jar.exists() && jar.isFile())
            {
                extraClasspath.add(jar);
            }
        }
    
        public void processBinding(Node node, App app) throws Exception
        {
            ContextHandler handler = app.getContextHandler();
            if (handler == null)
            {
                throw new NullPointerException("No Handler created for App: " + app);
            }
    
            if (handler instanceof WebAppContext)
            {
                WebAppContext webapp = (WebAppContext)handler;
    
                StringBuilder xtraCp = new StringBuilder();
                boolean delim = false;
                for (File cp : extraClasspath)
                {
                    if (delim)
                    {
                        xtraCp.append(File.pathSeparatorChar);
                    }
                    xtraCp.append(cp.getAbsolutePath());
                    delim = true;
                }
    
                webapp.setExtraClasspath(xtraCp.toString());
            }
        }
    }