本文介绍了通过WebAppContext extraClasspath管理许多jar的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个嵌入式码头服务器,可以热部署Web应用程序.在部署其他战争时,我将部署描述符.xml添加到目录中以配置webappcontext.我希望将在另一个位置构建的jar的目录添加到热部署的战争(/extJars)的类路径中.我看到了如何在webapp描述符.xml中执行此操作,并且可以通过声明单个jar来完成此操作,但是我尝试了多种配置以尝试简单地读取此目录中的所有jar,但没有任何效果.这是我的otherWebApp.xml,我们将其命名为有效配置,并注释掉无效的配置.谢谢.

I have an embedded jetty server that hot deploys webapps. When deploying the other wars, I add a deployment descriptor.xml to the directory to configure the webappcontext. I wish to add a DIRECTORY of jars that gets built in another location to the classpath of the hot deployed war (/extJars). I see how to do this within the webapp descriptor.xml, and I can accomplish this by stating individual jars, but I have tried multiple configurations for trying to simply read ALL jars in this directory, and nothing has worked. Here is my otherWebApp.xml, we'll call it, with a configuration that works, and commented out configurations that don't work. Thanks.

<?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 -->

推荐答案

您有3个选择.

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

在嵌入式中,告诉WebAppContext使用父加载器优先级. (与Webapp类相比,这将更有利于服务器类)

In embedded, tell the WebAppContext to use parent loader priority. (this will favor server classes over webapp classes)

<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应用程序.

This does have a side effect that if the server class does any caching of information (a common technique in many libraries) then that cache is now available for all webapps.

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

每个WebAppContext使用一个WebAppClassloader,可以将其配置为:

Each WebAppContext uses a WebAppClassloader that can be configured to:

  1. 从服务器类加载器中公开某些类
  2. 确定如果webapp和服务器之间存在冲突,则WebAppContext会做什么.

由于您使用的是 DeploymentManager ,这可以通过Bindings技术进行标准化.

Since you are using the DeploymentManager, this can be standardized via the Bindings techniques.

绑定本身: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部署的所有WebAppContext,从而使您可以将这些规则均等地应用于所有webapp.

This technique will apply to all WebAppContexts that are deployed via the DeploymentManager, allowing you to apply these rules equally to all webapps.

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

这是您可以用来在服务器端预先构建extraClasspath的另一种绑定替代方法,并且在部署WebApp时,它将自动将这些extraClasspath添加到WebApp.

Here's another Binding alternative you can use to pre-build the extraClasspath at the server side, and when a WebApp is deployed, it automatically adds these extraClasspath to the 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());
        }
    }
}

这篇关于通过WebAppContext extraClasspath管理许多jar的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-23 21:35