2012-06-26 2 views
0

독립 실행 형 Java 응용 프로그램의 경우 라이브러리 경로를 기반으로 런타임 중에 다음 코드를 사용하여 동적으로 jar lib를로드 할 수 있습니다. Java 웹 컨테이너에 동일한 코드를 배포하고 서블릿으로 실행하면 작동하지 않는 것 같습니다. 실제로 서블릿 요청에서 jar lib 경로를 기반으로 다른 jar 라이브러리를로드 할 수 있기를 원합니다.웹 컨테이너의 ClassLoader

그것은 하나의 서블릿이 /tmp/lib/v1.0/ 에서 jar 파일을로드 할 수 요청할 수 있습니다 비즈 논리를

USER1를 동적으로 런타임에 다른 항아리 libs와로드하고 이후 실행 할 수 있어야된다는 것을 의미합니다. 항아리
사용자 2는 (정확히 같은 클래스 이름을 가지고 1.0 버전과 1.1 버전의 jar 파일) /tmp/lib/v1.1/에서

감사를의 .jar
을 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()); 
      } 
     } 
    } 
} 

답변

0

그건 당신이 원하는 것이 아닙니다. 독립 실행 형 프로그램에서도이 기능은 실제로 작동하지 않습니다 (동일한 항아리의 여러 버전을 기본 클래스로 푸시 할 수 있기 때문에). 당신이 원하는 것은 새로운 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로 여러 버전의 서블릿을 배포하지 않는 이유는 확실하지 않습니다. (버전이 서블릿 경로의 일부임을 나타 내기 때문입니다.)

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); 
관련 문제