java项目动态加载外部jar,调用其中类方法

一,背景

项目需要通过加载外部jar文件更新某项功能

1,这是ServiceImpl中的方法摘取,

处理业务:

简单点来说就是:接收前端上传的jar文件和请求数据,通过调用上传的jar文件中的类方法对请求数据做处理(实现动态加载)

/**
     * 这是ServiceImpl中的方法摘取
     *
     * @param abilityContributionStructDataReq 请求数据
     * @param file jar文件
     * @return
     * @Author zl
     */
    @Override
    public Double dynamicLoad(String abilityContributionStructDataReq, MultipartFile file) throws IOException {
        //上传文件不能为空
        if (file == null) {
            throw new CustomException("动态计算lib库不能为空");
        }

        //这就是一个封装的文件上传返回文件路径的方法
        String textUrl = FileUtil.uploadText(file);
        //jar文件
        File fileJar = new File(textUrl);

        URLClassLoader urlClassLoader = null;
        Class<?> mytest = null;
        

        String substring = null;
        if (file.getOriginalFilename() != null) {
            substring = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.') + 1);
        }
        //jar包校验
        if (!"jar".equals(substring)) {
            throw new CustomException("只能上传“.jar”文件");
        }

        try {
            //通过URLClassLoader加载外部jar
            urlClassLoader = new URLClassLoader(new URL[]{new URL("file:" + fileJar.getAbsolutePath())});

            //获取外部jar里面的具体类对象
            mytest = urlClassLoader.loadClass("jsyc.CalculateAbilityContribution");

            //创建对象实例
            Object instance = mytest.newInstance();
            //获取实例当中的方法名为calculate,参数只有一个且类型为String的public方法
            Method method = mytest.getMethod("calculate", String.class);
            //传入实例以及方法参数信息执行这个方法
            String ada = (String) method.invoke(instance, abilityContributionStructDataReq);

            TechOneAbilityContributionInputOutcomeData abilityContributionInputOutcomeData = JSON.parseObject(ada, TechOneAbilityContributionInputOutcomeData.class);
            coreApi.getInputOutcomeData().getAbilityContributionModuleDataMgr().saveData(abilityContributionInputOutcomeData);
            System.out.println(ada);
            return 0.0;
        } catch (Exception e) {
            throw new CustomException("计算出错,请导入正确动态计算库");
        } finally {
            //卸载关闭外部jar
            try {
                urlClassLoader.close();
            } catch (IOException e) {
                System.out.println("关闭外部jar失败:" + e.getMessage());
            }
        }
    }

二,一般情况下,我们动态加载的jar可能会引用第三方依赖,这里存在很多坑

一般情况下,我们动态加载的lib库的类名和方法,都是通过配置文件配置,也可以约束死

方法参数和返回值就像前后端接口一样要约束好

1,我这边主项目动态加载的jar文件都是我们自己设计的,我们已经在主项目里面添加了其相应的依赖,在编译器中启动项目操作前端页面没有任何问题,但是部署服务器就抛异常,

 

 我们编写的jar用到了alibaba的json,找不到异常

2,其实说到底还是编写jar文件打包的问题,需要把第三方依赖也打进去

我们现在把java代码打包有许多中方式:

1,jar -cvf my.jar jsyc #通过命令行,将文件夹jsyc下面所有的class文件打成jar包(不包括依赖)

2,通过编译器,普通maven项目,package打包(也不包含依赖)

3,build artifacts(包含依赖) 步骤如下:

 

 

打包成功的jar:



心有所想,必有回响
原文地址:https://www.cnblogs.com/zhulei2/p/15499662.html