在webapp中加载Java dynamic类

在webapp中加载Java dynamic类,java,jar,classloader,urlclassloader,Java,Jar,Classloader,Urlclassloader,我制作了一个java项目,该项目仅包含此类: package test.processor; public abstract class Processor { public abstract void loadData(String objectId); public abstract void processData(); public abstract void saveData(String objectId); } 项目导出为jar文件(processo

我制作了一个java项目,该项目仅包含此类:

package test.processor;

public abstract class Processor {

    public abstract void loadData(String objectId);
    public abstract void processData();
    public abstract void saveData(String objectId);

}
项目导出为jar文件(processor.jar)

然后我做了另一个导入processor.jar的项目,有一个类扩展了processor:

package test.process;

import test.processor.Processor;

public class Process extends Processor{

    @Override
    public void loadData(String objectId) {
        System.out.println("LOAD DATAAAAAAAAAAAA");     
    }

    @Override
    public void processData() {
        System.out.println("PROCESS DATAAAAAAAAAAAA");
    }

    @Override
    public void saveData(String objectId) {
        System.out.println("SAVE DATAAAAAAAAAAAA");
    }

}
public void testPlugins(){

    Processor plugin = (Processor) loadJars("C:\\Users\\...\\Desktop\\processor.jar",
            "C:\\Users\\...\\Desktop\\plugin.jar",
            "test.process.Process");
    processor.loadData("dada");

}
这个项目也被导出为jar(plugin.jar)

最后,我编写了一些代码来动态加载插件:

import test.processor.Processor;

public class Test {

    public void testPlugins(){

        Processor plugin = (Processor) loadJar(
                "C:\\Users\\...\\Desktop\\plugin.jar",
                "test.process.Process");
        processor.loadData("dada");

    }

    private Object loadJar(String jar, String className){

        File jarFile = new File(jar);
        Object instance = null;
        try {
            URL jarpath = jarFile.toURI().toURL();
            String jarUrl = "jar:" + jarpath + "!/";
            URL urls[] = { new URL(jarUrl) };
            URLClassLoader child = new URLClassLoader(urls);
            Class classToLoad = Class.forName(nomeClasse, true, child);
            instance = classToLoad.newInstance();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return instance;

    }


} 
如果我在一个主方法中运行该代码,它就会正常工作,一旦我尝试在服务器中运行它,加载该类时就会出现问题,我会得到一个ClassNotFoundException(处理器)。 我试着将jar放在tomcat/lib、project/WEB-INF/lib中,但没有任何改变


知道我做错了什么吗

我没有按我想要的方式解决它,但我解决了它:

首先,我尝试手动加载process.jar:

private Object loadJars(String processJar, String pluginJar, String className){

    File processJarFile = new File(processJar);
    File pluginJarFile = new File(pluginJar);


    Object instance = null;
    try {

        URL processJarPath = processJarFile.toURI().toURL();
        String processJarUrl = "jar:" + processJarPath + "!/";

        URL pluginJarPath = pluginJarFile.toURI().toURL();
        String pluginJarUrl = "jar:" + pluginJarPath + "!/";


        URL urls[] = { new URL(processJarUrl), new URL(pluginJarUrl) };
        URLClassLoader child = new URLClassLoader(urls);
        Class classToLoad = Class.forName(nomeClasse, true, child);
        instance = classToLoad.newInstance();
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return instance;

}
如果正确加载Process类,则问题发生在testPlugins方法中,一旦它尝试强制转换到处理器(ClassCastException,无法强制转换Process到处理器):

仍然需要阅读大量关于类加载的内容,但我想问题是它无法识别从C:\Users\…\Desktop\Processor.jar加载的处理器与从webapp上下文加载的处理器相同,或者它“忘记”了进程扩展了处理器

我很匆忙,所以没有时间研究,为了解决问题,我调用了使用反射的方法:

public void modifiedTestPlugins(){

    Object plugin = loadJar("C:\\Users\\...\\Desktop\\processor.jar",
            "C:\\Users\\...\\Desktop\\plugin.jar",
            "test.process.Process");

    try {
        Method processData = findMethod(obj.getClass(), "processData");

        //here I invoke the processData method, it prints: PROCESS DATAAAAAAAAAAAA
        loadData.invoke(processData, new Object[]{});
    } catch (Exception e) {
        e.printStackTrace();
    }

}

private static Method findMethod(Class clazz, String methodName) throws Exception {
    Method[] methods = clazz.getMethods();
    for (int i = 0; i < methods.length; i++) {
        if (methods[i].getName().equals(methodName))
            return methods[i];
    }
    return null;
}
public void modifiedTestPlugins(){
Object plugin=loadJar(“C:\\Users\\…\\Desktop\\processor.jar”,
“C:\\Users\\…\\Desktop\\plugin.jar”,
“测试、过程、过程”);
试一试{
方法processData=findMethod(obj.getClass(),“processData”);
//这里我调用processData方法,它打印:processDataaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
调用(processData,新对象[]{});
}捕获(例外e){
e、 printStackTrace();
}
}
私有静态方法findMethod(类clazz,字符串methodName)引发异常{
方法[]methods=clazz.getMethods();
for(int i=0;i
我没有按照我想要的方式解决它,但我解决了它:

首先,我尝试手动加载process.jar:

private Object loadJars(String processJar, String pluginJar, String className){

    File processJarFile = new File(processJar);
    File pluginJarFile = new File(pluginJar);


    Object instance = null;
    try {

        URL processJarPath = processJarFile.toURI().toURL();
        String processJarUrl = "jar:" + processJarPath + "!/";

        URL pluginJarPath = pluginJarFile.toURI().toURL();
        String pluginJarUrl = "jar:" + pluginJarPath + "!/";


        URL urls[] = { new URL(processJarUrl), new URL(pluginJarUrl) };
        URLClassLoader child = new URLClassLoader(urls);
        Class classToLoad = Class.forName(nomeClasse, true, child);
        instance = classToLoad.newInstance();
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return instance;

}
如果正确加载Process类,则问题发生在testPlugins方法中,一旦它尝试强制转换到处理器(ClassCastException,无法强制转换Process到处理器):

仍然需要阅读大量关于类加载的内容,但我想问题是它无法识别从C:\Users\…\Desktop\Processor.jar加载的处理器与从webapp上下文加载的处理器相同,或者它“忘记”了进程扩展了处理器

我很匆忙,所以没有时间研究,为了解决问题,我调用了使用反射的方法:

public void modifiedTestPlugins(){

    Object plugin = loadJar("C:\\Users\\...\\Desktop\\processor.jar",
            "C:\\Users\\...\\Desktop\\plugin.jar",
            "test.process.Process");

    try {
        Method processData = findMethod(obj.getClass(), "processData");

        //here I invoke the processData method, it prints: PROCESS DATAAAAAAAAAAAA
        loadData.invoke(processData, new Object[]{});
    } catch (Exception e) {
        e.printStackTrace();
    }

}

private static Method findMethod(Class clazz, String methodName) throws Exception {
    Method[] methods = clazz.getMethods();
    for (int i = 0; i < methods.length; i++) {
        if (methods[i].getName().equals(methodName))
            return methods[i];
    }
    return null;
}
public void modifiedTestPlugins(){
Object plugin=loadJar(“C:\\Users\\…\\Desktop\\processor.jar”,
“C:\\Users\\…\\Desktop\\plugin.jar”,
“测试、过程、过程”);
试一试{
方法processData=findMethod(obj.getClass(),“processData”);
//这里我调用processData方法,它打印:processDataaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
调用(processData,新对象[]{});
}捕获(例外e){
e、 printStackTrace();
}
}
私有静态方法findMethod(类clazz,字符串methodName)引发异常{
方法[]methods=clazz.getMethods();
for(int i=0;i