java插件化开发实例

1.项目分为3个模块 contract,service和plugin,分别提供 契约,服务和插件

2.在新增、编辑、删除插件时,不影响service/contract 本身

3.服务实现对字符串的分割,插件实现通过 逗号(comma)和 Tab键进行splite

 

4.contract代码如下:

package org.g2.contract;

public interface Resolver {
    /**
     * 是否支持当前的解析方式
     *
     * @param resolverName 解析方式
     * @return
     */
    String getName();

    /**
     * 解析字符串
     *
     * @param args 原始字符
     * @return 解析后的字符串
     */
    String[] resolve(String args);
}

 

5.service的代码如下:

package org.g2.service;

import org.g2.contract.Resolver;

import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;

public class ResolverFactory {
    public static Map<String, Resolver> load() {
        ServiceLoader<Resolver> resolvers = ServiceLoader.load(Resolver.class);
        Map<String, Resolver> result = new HashMap<>();
        for (Resolver resolver : resolvers) {
            result.put(resolver.getName(), resolver);
        }
        return result;
    }
}

 

package org.g2.service;

import org.g2.contract.Resolver;

import java.util.Arrays;
import java.util.Map;
import java.util.Optional;

/**
 * 入口
 */
public class App {
    public static void main(String[] args) {

        String content = "Hello,World";
        final String type = "comma";
        Map<String, Resolver> resolverMap = ResolverFactory.load();
        String[] resolve = Optional.ofNullable(resolverMap.get(type))
                .orElseThrow(() -> new RuntimeException("不支持的解析类型" + type))
                .resolve(content);
        System.out.println(Arrays.toString(resolve));

        content = "Hello\tWorld";
        final String type2 = "table";
        resolve =Optional.ofNullable(resolverMap.get(type2))
                .orElseThrow(() -> new RuntimeException("不支持的解析类型" + type2))
                .resolve(content);
        System.out.println(Arrays.toString(resolve));
    }
}

 

6.插件模块(plugin)的代码如下:

package org.g2.plugin.resolver.comma;

import org.g2.contract.Resolver;

public class CommaResolver implements  Resolver{
    @Override
    public String getName() {
        return "comma";
    }

    @Override
    public String[] resolve(String args) {
        return args.split(",");
    }
}

 

package org.g2.plugin.resolver.table;

import org.g2.contract.Resolver;

public class TableResolver implements Resolver {
    @Override
    public String getName() {
        return "table";
    }

    @Override
    public String[] resolve(String args) {
        return args.split("\t");
    }
}

 

另外,需要在plugin本项目的resources里添加 META-INF/services添加文件 org.g2.contract.Resolver (contract接口的完全路径名),文件的值为

org.g2.plugin.resolver.comma.CommaResolver
org.g2.plugin.resolver.table.TableResolver

 

7.最后对 service和plugin打包,生成两个jar包,上传到linux服务器上后执行如下命令

java -cp plugin-1.0-SNAPSHOT.jar:service-1.0-SNAPSHOT.jar org.g2.service.App

输出如下

[Hello, World]
[Hello, World]

 

8.后记

在windows 10 的powerShell执行总是不成功,在linux上才成功。

另外如果用 

java -cp plugin-1.0-SNAPSHOT.jar -jar service-1.0-SNAPSHOT.jar

也是不成功的。参考:Simple ServiceLoader - java.util.ServiceConfigurationError ... Provider ... not found - Stack Overflow

 

 

posted @ 2020-12-12 09:38  zslm___  阅读(3005)  评论(0编辑  收藏  举报