美文网首页
日拱一卒:通用 Bean 方法调用

日拱一卒:通用 Bean 方法调用

作者: Tinyspot | 来源:发表于2023-12-25 19:00 被阅读0次

1. 通用工具

入口 http://localhost:8080/tool

执行结果:

2. 获取所有Bean

@Controller
@RequestMapping("tool")
public class BeanTools {
    @GetMapping(value = {"", "/common"})
    public ModelAndView common() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("beanNames", getBeanNames());
        modelAndView.setViewName("invoke.html");
        return modelAndView;
    }

    private List<JSONObject> getBeanNames() {
        List<String> beanNames = SpringBeanUtils.getBeans();
        List<JSONObject> beanObjs = new ArrayList();
        beanNames.forEach(str -> {
            JSONObject obj = new JSONObject();
            obj.put("text", str);
            obj.put("value", str);
            beanObjs.add(obj);
        });
        return beanObjs;
    }
}
@Component
public class SpringBeanUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringBeanUtils.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static List<String> getBeans() {
        String[] beanDefinitionNames = getApplicationContext().getBeanDefinitionNames();
        List<String> beanNames = Arrays.stream(beanDefinitionNames)
                .filter(str -> !str.contains("."))
                .collect(Collectors.toList());
        beanNames.sort(String::compareTo);

        return beanNames;
    }
}

3. 获取 Bean 的方法

@RestController
@RequestMapping("/ajax")
public class BeanAjax {

    @GetMapping("/getMethods")
    public List<Item> getMethods(String beanName) {
        return getBeanMethods(beanName);
    }

    @PostMapping("/beanMethods")
    public List<Item> beanMethods(AjaxPojo ajaxPojo) {
        return getBeanMethods(ajaxPojo.getBeanName());
    }

    private List<Item> getBeanMethods(String beanName) {
        List<Item> list = new ArrayList();

        Object bean = SpringBeanUtils.getBean(beanName);
        Method[] methods = bean.getClass().getMethods();
        for (Method method : methods) {
            String methodSign = method.toString();
            String paramSign = methodSign.substring(methodSign.indexOf("("), methodSign.indexOf(")") + 1);
            list.add(new Item(method.getName() + paramSign, method.getName() + paramSign));
        }

        return list;
    }

    @Data
    public class Item implements Serializable {
        private static final long serialVersionUID = -6504357622310055548L;
        private String text;
        private String value;

        public Item(String text, String value) {
            this.text = text;
            this.value = value;
        }
    }

    @Data
    public class AjaxPojo implements Serializable {
        private String appName;
        private String beanName;
        private String methodName;
        private List<String> args = new ArrayList<>();
    }
}

4. 执行方法

@RestController
@RequestMapping("/ajax")
public class BeanAjax {
    
    @PostMapping("/invoke")
    public JSONObject invoke(AjaxPojo ajaxPojo) throws InvocationTargetException, IllegalAccessException {
        String beanName = ajaxPojo.getBeanName();
        String methodName = ajaxPojo.getMethodName();
        List<String> args = ajaxPojo.getArgs();

        Object bean = SpringBeanUtils.getBean(beanName);
        Method method = findMethod(bean, methodName);
        Object invoke = method.invoke(bean, ReflectDemo.assemblyArgs(args, method.getParameterTypes()));

        JSONObject result = new JSONObject();
        JSONObject request = new JSONObject();
        request.put("beanName", beanName);
        request.put("methodName", method.getName());
        request.put("params", ajaxPojo.getArgs());
        request.put("paramTypes", method.getParameterTypes());
        JSONObject response = new JSONObject();
        response.put("data", invoke);
        response.put("success", "true");
        result.put("request", request);
        result.put("response", response);
        return result;
    }

    private Method findMethod(Object bean, String methodName) {
        Method[] methods = bean.getClass().getMethods();
        for (Method method : methods) {
            String methodSign = method.toString();
            if (methodSign.contains(methodName)) {
                return method;
            }
        }
        return null;
    }

    @Data
    public class AjaxPojo implements Serializable {
        private String appName;
        private String beanName;
        private String methodName;
        private List<String> args = new ArrayList<>();
    }
}
public class ReflectDemo {

    /**
     * 参数组装
     *
     * @param arguments      参数值
     * @param parameterTypes 参数类型
     * @return
     */
    public static Object[] assemblyArgs(List<String> arguments, Class<?>[] parameterTypes) {
        List<Object> args = new ArrayList<>();

        for (int i = 0; i < arguments.size(); i++) {
            args.add(getArgValue(parameterTypes[i], arguments.get(i)));
        }
        return args.toArray();
    }

    public static Object getArgValue(Class<?> parameterType, String arg) {
        if (StringUtils.isBlank(arg)) {
            return null;
        }
        arg = StringUtils.trim(arg);

        if (parameterType.equals(String.class)) {
            return arg;
        }

        if (parameterType.equals(Integer.class)) {
            return Integer.valueOf(arg);
        }

        if (parameterType.equals(Date.class)) {
            if (arg.length() == 10) {
                // 例如:2023-01-01
                arg += " 00:00:00";
            }
            return DateUtil.parseToDateTime(arg);
        }

        // 转为对象
        return JSON.parseObject(arg, parameterType);
    }
}

5. 页面 invoke.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Invoke</title>

    <style type="text/css">
        .tool_class {
            height: 40px;
        }
        .form_class {
            height: 30px;
        }
        .b_select {
            width: 500px;
            height: 26px;
        }
        .arg_class {
            width: 500px;
        }
        .span_class {
            display: inline-block;
            width: 120px;
            text-align: right;
            vertical-align: top;
        }
        .button {
            position: absolute;
            background-color: #0a0a23;
            color: #fff;
            border: none;
            width: 100px;
            border-radius: 2px;
            padding: 5px;
        }
        .button:focus {
            outline-color: transparent;
            outline-style: solid;
            box-shadow: 0 0 0 2px #333338;
        }
    </style>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
<div class="tool_class">通用工具</div>
<form>
    <div class="form_class">
        <span class="span_class">IP地址:</span>
        <input id="targetIp" placeholder="127.0.0.1"/><br>
    </div>
    <div class="form_class">
        <span class="span_class">所属应用:</span>
        <select id="appName" name="appName" class="b_select">
            <option value="">请选择</option>
            <option value="concrete" selected="selected">concrete</option>
        </select>
    </div>
    <div class="form_class">
        <span class="span_class">bean名称:</span>
        <select id="beanName" name="beanName" class="b_select">
            <option value="">请选择</option>
            <option th:each="item:${beanNames}"
                    th:value="${item.value}" th:text="${item.text}">
            </option>
        </select>
    </div>
    <div class="form_class" id="methodDiv">
        <span class="span_class">method名称:</span>
        <select id="methodName" name="methodName" class="b_select">
            <option value="">请选择</option>
        </select>
    </div>
    <div class="form_class" id="submitDiv">
        <button id="btn_click" class="button" type="button">提交</button>
    </div>
</form>

<script>
    var tmpEle = [];

    $().ready(function () {
        // change事件
        $("#beanName").change(function () {
            // var value = $("#beanName").val();
            var value = $(this).val();
            // $.ajax({
            //     type: "GET",
            //     url: "/ajax/getMethods?beanName=" + value,
            //     async: true,
            //     dataType: "json",
            //     success: function (data) {
            //         //清空下拉框选项
            //         // $("#methodName").empty();
            //         // $("#methodName").append("<option value=''>请选择</option>");
            //         if (data && data.length > 0) {
            //             // for循环:https://blog.csdn.net/hani_wen/article/details/81878112
            //             // for (var i = 0; i < data.length; i++) { data[i].value }
            //             // for (var item in data) { 下标 }
            //
            //             for (item of data) {
            //                 var option = "<option value=" + item.value + ">" + item.text + "</option>";
            //                 $("#methodName").append(option);
            //             }
            //         }
            //     }
            // });

            // let paramObj = {
            //     beanName : value
            // }
            $.ajax({
                type: "POST",
                url: "/ajax/beanMethods",
                data: {beanName: value},
                async: true,
                dataType: "json",
                success: function (data) {
                    // 清空下拉框选项
                    $("#methodName").empty();
                    $("#methodName").append("<option value=''>请选择</option>");
                    if (data && data.length > 0) {
                        for (item of data) {
                            // 注意可能会有转义符号 <>
                            var option = "<option value=" + item.value + ">" + item.text + "</option>";
                            $("#methodName").append(option);
                        }
                    }
                }
            });
        });

        // 方法参数
        $("#methodName").change(function () {
            cleanParams();
            $('#result').remove();

            var startElement = $('#methodDiv');
            var methodName = $(this).val();
            var methodType = methodName.substring(methodName.indexOf("(") + 1, methodName.indexOf(")"));
            if (methodType.length > 0) {
                var paramTypeArray = methodType.split(",");
                for (var i in paramTypeArray) {
                    var newElement;
                    if (isBasicType(paramTypeArray[i])) {
                        newElement = '<div id="methodDiv' + i + '" > <span class="span_class">arg-' + i +
                            ':</span> <input type="text" id="arg-' + i + '" class="arg_class" style="height: 26px;" placeholder="' + paramTypeArray[i] + '" /></div>';
                    } else {
                        newElement = '<div id="methodDiv' + i + '" > <span class="span_class">arg-' + i +
                            '(对象JSON串):</span> <textarea id="arg-' + i + '" class="arg_class" style="resize:none;" rows="5" placeholder="' + paramTypeArray[i] + '"></textarea> </div>';
                    }

                    startElement.after(newElement);
                    startElement = $('#methodDiv' + i);
                    tmpEle.push(startElement);
                }
            }
        });

        // 按钮
        $("#btn_click").click(function () {
            $('#result').remove();

            var beanName = $("#beanName").val();
            var methodName = $("#methodName").val();
            // 参数
            var args = [];
            // $("input[name='arg']").each(function () {
            //     args.push($(this).val());
            // });
            $(".arg_class").each(function () {
                args.push($(this).val());
            });

            $.ajax({
                type: "POST",
                url: "/ajax/invoke",
                data: {
                    beanName: beanName,
                    methodName: methodName,
                    args: args
                },
                async: true,
                dataType: "json",
                success: function (data) {
                    // JSON.stringify(data)
                    // JSON.stringify()方法最多接受三个参数:JSON对象,替换器和空格。 只有JSON对象是必需的,其余两个参数是可选的

                    var startElement = $('#submitDiv');
                    var resultEle = '<div class="result" id="result"> <span class="span_class">执行结果:</span> ' +
                        '<textarea style="resize:none; width: 500px;" rows="10" >' + JSON.stringify(data, null, 4) + '</textarea></div>';
                    startElement.after(resultEle);
                }
            });

        });
    });

    function isBasicType(type) {
        var basicTypes = [
            "java.lang.Byte",
            "java.lang.Boolean",
            "java.lang.Integer",
            "java.lang.Character",
            "java.lang.Double",
            "java.lang.Short",
            "java.lang.Long",
            "java.lang.Float",
            "java.lang.String",
            "int", "long", "byte", "boolean", "char", "float", "short", "double"
        ];
        for (const basicType of basicTypes) {
            if (basicType === type) {
                return true;
            }
        }
        return false;
    }

    function cleanParams() {
        for (var i in tmpEle) {
            $(tmpEle[i]).remove();
        }
        tmpEle = [];
    }
</script>

</body>
</html>

相关文章

网友评论

      本文标题:日拱一卒:通用 Bean 方法调用

      本文链接:https://www.haomeiwen.com/subject/rxvkndtx.html