글래시 피 웹 응용 프로그램에서 동적 클래스로드를 구현하기로 결정했습니다.이 방법은 시도해 보는 방법으로 웹 응용 프로그램에서로드하여 실행할 수있는 작은 플러그인을 지원합니다. 실행 시간. 동적으로로드 된 플러그인 웹을 응용 프로그램에서 인식하도록 만드는 방법
public class PluginManager {
private static final String dropBoxDir = "file:///path/to/dropbox/";
private static final URLClassLoader dropBoxClassLoader;
static {
try {
URL dropBoxURL = new URL(dropBoxDir);
dropBoxClassLoader = URLClassLoader.newInstance(new URL[]{dropBoxURL});
}
catch (MalformedURLException mue) {
throw new RuntimeException("MalformedURLException thrown during PluginManager initialization - the hardcoded URL " + dropBoxDir + " must be invalid.", mue);
}
}
//this method is called by a web service
public static void runPluginFromDropBox(String fullClassName) {
try {
//load the plugin class
Class<?> pluginClass = dropBoxClassLoader.loadClass(fullClassName);
//instantiate it
Runnable plugin = (Runnable)pluginClass.newInstance();
//call its run() method
plugin.run();
}
catch (ClassNotFoundException cnfe) {
throw new RuntimeException("The class file for " + fullClassName + " could not be located at the designated directory (" + dropBoxDir + "). Check that the specified class name is correct, and that its file is in the right location.", cnfe);
}
catch (InstantiationException ie) {
throw new RuntimeException("InstantiationException thrown when attempting to instantiate the plugin class " + fullClassName + " - make sure it is an instantiable class with a no-arg constructor.", ie);
}
catch (IllegalAccessException iae) {
throw new RuntimeException("IllegalAccessException thrown when attempting to instantiate the plugin class " + fullClassName + " - make sure the class and its no-arg constructor have public access.", iae);
}
catch (ClassCastException cce) {
throw new RuntimeException("Plugin instance could not be cast to Runnable - plugin classes must implement this interface.", cce);
}
}
}
그런 다음 별도의 프로젝트에, 내가 테스트 플러그인 생성 :
나는 다음과 같은 클래스를 추가
public class TestPlugin implements Runnable {
@Override
public void run() {
System.out.println("plugin code executed");
}
}
내가 웹 응용 프로그램을 배포을, 다음 .class
파일로 TestPlugin
을 컴파일 그것을 지정된 폴더에 놓습니다. 나는 runPluginFromDropBox()
에 클래스 이름으로 도달하고 예상되는 출력을 얻은 웹 서비스를 호출했다.
이 모든 것이 개념의 증거로 사용되었지만 내 웹 응용 프로그램의 클래스를 인식 할 수 없다면 내 플러그인은 실제로 쓸모가 없습니다. 그 후 .war
은 독립 실행 형 응용 프로그램으로 만 사용되며 다른 라이브러리의 클래스 경로에는 포함되지 않으므로이 작은 사이드 프로젝트에 적합하지 않습니다.
나는이 토론을 보았다 : Extending Java Web Applications with plugins 그리고 거대한 이유가없는 디자인 도전의 늪에 빠져들고 돌아서 야한다는 느낌을 받는다. 그러나 그 포스트는 일종의 톰캣과 관련이 있기 때문에 정교한 제 3 자 프레임 워크 없이는이 접근법에 대한 직접적인 방법이 있는지 묻습니다.
"plugin classloader"라고 말하면 플러그인을로드하는 데 사용하는'URLClassLoader'를 의미합니까? 그 코드는 웹 응용 프로그램에 있지만. 어떻게 든 플러그인이 클래스 패스에 전쟁을 가져가는 것이 얼마나 힘든지 궁금합니다. 그래서 예를 들어 웹 애플리케이션에'Foo' 클래스가 있다면 플러그인은 mywebapp.Foo;를 가져 와서'run()'메소드에서'Foo'와 상호 작용할 수 있습니다 - 아니면 순진하게 벗어나나요? –
예, 저는 플러그인 클래스를로드하는 데 사용 된 클래스 로더에 대해 이야기하고 있습니다. 그리고 내 대답은이 클래스 로더는 전쟁의 클래스 로더가 부모 클래스 로더 여야한다는 것입니다. URLClassLoader의 생성자를 살펴보십시오. 부모 ClassLoader를 인수로 취하는 클래스가 있습니다. 가져 오기는 컴파일시에만 사용됩니다. 컴파일 할 때 웹 클래스에 접근 할 수 있도록 적절한 클래스 경로를 설정하기 만하면됩니다. 런타임에는 전쟁의 클래스 로더가 부모 클래스 로더로 필요합니다. –
좋아요, 부모 클래스 로더에 대해 당신이 말하는 것을 이해합니다. 그러나 나는 이것이 이미 사실이라고 생각한다 - 나는 'newInstance()'에 대한 호출이 부모 클래스 인'ClassLoader'를 디폴트로 사용하고 있다고 잘못 생각하지 않는다면, 이것은 웹 어플리케이션이어야한다. 그래서 내가 뭔가를 놓치지 않는 한 그것이 왜 관련이 있는지 잘 모르겠습니다. 제 질문은 플러그인 라이브러리의 웹 애플리케이션 클래스에 대한 컴파일 타임 인식에 달려 있다고 생각합니다. 나는 여기서 간단한 것을 놓치고 있는가 - 나는 단지 전쟁의 플러그를 클래스 패스에 놓을 수 있을까? –