0

スタンドアロン Java アプリケーションの場合、次のコードを使用して、実行時にライブラリ パスに基づいて jar lib を動的にロードできます。同じコードを Java Web コンテナーにデプロイしてサーブレットとして実行すると、うまくいかないようです。実際には、サーブレット リクエストの jar ライブラリ パスに基づいて、さまざまな jar ライブラリをロードできるようにしたいと考えています。

これは、単一のサーブレットが実行時にさまざまな jar ライブラリを動的にロードし、以降のビジネス ロジックを実行できる必要があることを意味します。

user1 は、/tmp/ lib/v1.0/ .jarの
下にある jar ファイルをロードするように要求する場合があります。 user2 は、
/tmp/lib/v1.1/ .jarの下にある jar ファイルをロードするように要求する場合があり
ます (v1.0 および v1.1 の jar ファイルまったく同じクラス名を取得しました)

ありがとう!!!

=== メイン =============

LibraryLoader loader = new LibraryLoader();
loader.addClassPath(<jar lib root path>);

// below will run biz logic

=== LibraryLoader.java ==========

public class LibraryLoader {

    URLClassLoader urlClassLoader;

    public LibraryLoader() {
        urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    }

    public void addClassPath(String jarLibPath) throws Exception {
        Class urlClass = URLClassLoader.class;
        File jarPath = new File(jarLibPath);

        FileFilter jarFilter = new FileFilter() {
            public boolean accept(File f) {
                if (f.isDirectory())
                    return true;
                String name = f.getName().toLowerCase();
                return name.endsWith("jar");
            }
        };

        File[] files = jarPath.listFiles(jarFilter);
        for (File file : files) {
            if (file.isFile()) {
                URI uriPath = file.toURI();
                URL urlPath = uriPath.toURL();
                Method method = urlClass.getDeclaredMethod("addURL", new Class[] { URL.class });
                method.setAccessible(true);
                method.invoke(urlClassLoader, new Object[] { urlPath });
                System.out.println(file.getCanonicalPath());
            } else {
                addClassPath(file.getCanonicalPath());
            }
        }
    }
}
4

2 に答える 2

0

それはあなたがしたいことではありません。スタンドアロン プログラムであっても、これは実際には機能しません (同じ jar の複数のバージョンをメイン クラスローダーにプッシュする可能性があるため)。あなたがしたいことは、新しいjarを含む新しいクラスローダーを作成し、新しいクラスローダーでいくつかのクラスを呼び出すことです。

例えば:

// get relevant jar urls
URL[] urls = ...;

ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
try {
  URLClassLoader loader = new URLClassLoader(urls);
  Thread.currentThread().setContextClassLoader(loader);

  Class<?> entryClass = loader.loadClass("entry.class.name");
  // do something here w/ entryClass (e.g. instantiate it) ...

} finally {
  Thread.currentThread().setContextClassLoader(oldLoader);
}

もちろん、これらのクラスローダーをキャッシュして、後続のリクエストで再利用したいでしょう。

もちろん、異なるバージョンの jar を使用してサーブレットの複数のバージョンを展開しない理由がわかりません (バージョンがサーブレット パスの一部であることを示しているため)。

于 2012-06-26T04:36:45.750 に答える
0

ユーザーごとに異なるクラスローダーを作成し、現在のスレッドに設定する必要があります。

ClassLoader ctxLoader = Thread.currentThread().getContextClassLoader();
ClassLoader currentLoader;
if(user1){
   //initialize classloader with jar files under /tmp/lib/v1.0/.jar
   currentLoader  = user1ClassLoader;
} else if(user2){
   //initialize classloader with jar files under /tmp/lib/v1.1/.jar
   currentLoader  = user2ClassLoader;
}
Thread.currentThread().setContextClassLoader(currentLoader  );

//invoke business logic

//reset the actual loader
Thread.currentThread().setContextClassLoader(ctxLoader );
于 2012-06-26T04:47:03.660 に答える