MelonBlog

通过反射执行java方法

今天想实现一个功能就是通过一个交互式的环境,执行java函数。

思路

通过Cmd类来定义函数
通过一个Executor类来注册命令并且执行命令


Cmd.class

public class Cmd {
    public static Response hello(Request request) {
        return Response.success("hello " + request.getParams().get(0));
    }
    @Data
    public static class Request {
        private MapleCharacter player;
        private List<String> params;
    }
    @Builder
    @Data
    public static class Response {
        private boolean success;
        private String message;
        public static Response success() {
            return Response.builder().success(true).message("执行成功").build();
        }
        public static Response success(String message) {
            return Response.builder().success(true).message(message).build();
        }
    }
}

CmdExecutor.class

public class CmdExecutor {
    private static final Map<String, Method> methodMap = new HashMap<>();
    public static void init() {
        StringBuilder sb = new StringBuilder();
        Class<Cmd> cmdClass = Cmd.class;
        for (Method method : cmdClass.getMethods()) {
            Parameter[] parameters = method.getParameters();
            Class<?> returnType = method.getReturnType();
            if (parameters.length == 1 && parameters[0].getType()
                                                       .equals(Cmd.Request.class) && returnType.equals(Cmd.Response.class)) {
                sb.append(method.getName()).append(",");
                methodMap.put(method.getName().toLowerCase(), method);
            }
        }
        System.out.printf("注册命令: %s%n", sb);
    }
    public static void execute(String cmdLine) {
        String[] splitCmd = cmdLine.split(" ");
        List<String> stringList = Arrays.asList(splitCmd);
        String cmd = stringList.get(0).toLowerCase();
        List<String> params = stringList.subList(1, stringList.size());
        Method method = methodMap.get(cmd);
        if (Objects.isNull(method)) {
            System.out.printf("命令不存在: %s%n", cmd);
        }
        Cmd.Request request = new Cmd.Request();
        request.setPlayer(null);
        request.setParams(params);
        try {
            Cmd.Response response = (Cmd.Response) method.invoke(null, request);
            System.out.printf("执行结果: %s%n", response.getMessage());
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }
    public static void main(String[] args) {
        init();
        execute("hello java");
    }
}

执行结果:

注册命令: hello,
执行结果: hello java