Spring注册Bean通用方法调用

实现思路

1. 根据bean工厂查找beanName对应的Bean

2. 查找对应的字节码文件

3. 根据方法名(methodName)和参数(params)查找方法

3.1 遍历bean的所有方法

3.2 根据方法名和参数数量过滤

3.3 当所有参数类型一致时找到唯一方法

3.4 当类型不同时,判断类型是否都为数字(Number)类型

3.5 如果都是数字类型也当做参数类型一致(postman无法区分Integer类型和Long类型)

3.6 如果都是数字类型,调用数字类型的valueOf方法强转参数

4. 调用方法

具体实现请看代码

前言

使用postman测试接口方法时,经常需要更换url。针对当前问题尝试实现通用方法调用。

一、数据准备

Spring容器:获取Spring容器中注册的Bean

参数对象:封装请求的参数

返回结果:封装返回为自定义的Json结果

二、使用步骤

1.参数对象

代码如下(示例):

@Data
class MethodParam {
    private String beanName;
    private String methodName;
    private Object[] params;
}

2.返回结果

package org.yanse.vo;

import lombok.Data;
import org.yanse.model.ErrorCode;

/**
 * 返回前端的结果
 */
@Data
public class JsonResult {
    private boolean success = true;
    private String msg;
    private Object data;
    private int code;

    private JsonResult() {

    }

    private JsonResult(boolean success, String msg) {
        this.success = success;
        this.msg = msg;
    }

    private JsonResult(boolean success, String msg, Object data) {
        this.success = success;
        this.msg = msg;
        this.data = data;
    }

    private JsonResult(boolean success, String msg, int code) {
        this.success = success;
        this.msg = msg;
        this.code = code;
    }

    private JsonResult(boolean success, String msg, int code, Object data) {
        this.success = success;
        this.msg = msg;
        this.code = code;
        this.data = data;
    }

    /**
     * 成功无返回结果
     *
     * @return JsonResult
     */
    public static JsonResult success() {
        return new JsonResult(true, null);
    }

    /**
     * 成功有返回信息
     *
     * @param msg 接口状态信息
     * @return JsonResult
     */
    public static JsonResult success(String msg) {
        return new JsonResult(true, msg);
    }

    /**
     * 成功有返回数据和信息
     *
     * @param msg 接口状态信息
     * @param data 返回给前端的数据
     * @return JsonResult
     */
    public static JsonResult success(String msg, Object data) {
        return new JsonResult(true, msg, data);
    }

    /**
     * 成功只返回数据
     *
     * @param data 返回给前端的数据
     * @return JsonResult
     */
    public static JsonResult success(Object data) {
        return new JsonResult(true, null, data);
    }

    /**
     * 失败只返回数据
     *
     * @param data 返回给前端的数据
     * @return JsonResult
     */
    public static JsonResult error(Object data) {
        return new JsonResult(false, null, data);
    }

    /**
     * 失败有返回信息
     *
     * @param msg 接口状态信息
     * @return JsonResult
     */
    public static JsonResult error(String msg) {
        return new JsonResult(false, msg);
    }

    /**
     * 失败有返回信息和数据
     *
     * @param msg 接口状态信息
     * @param data 返回给前端的数据
     * @return JsonResult
     */
    public static JsonResult error(String msg, Object data) {
        return new JsonResult(false, msg, data);
    }

    public static JsonResult info(ErrorCode errorCode) {
        int code = errorCode.getCode();
        boolean success = code == 200;
        return new JsonResult(success, errorCode.getMsg(), code);
    }

    public static JsonResult info(ErrorCode errorCode, Object data) {
        int code = errorCode.getCode();
        boolean success = code == 200;
        return new JsonResult(success, errorCode.getMsg(), code, data);
    }
}

3.错误码

package org.yanse.model;

/**
 * 使用枚举类型来封装异常码和异常信息
 */
public enum ErrorCode {
    //RPC层调用错误码
    DB_SERVICE_OK(20100, "服务正常"),
    DB_SERVICE_DB_DAO_ERROR(20104, "返回数据库的具体异常信息"),
    DB_SERVICE_UNKNOWN_ERROR(20101, "未知异常"),
    DB_SERVICE_AGENT_ERROR(20102, "DBServiceAgent异常"),
    DB_SERVICE_NETWORK_ERROR(20103, "网络异常"),
    DB_SERVICE_INVALID_FUNCTION(20105, "方法名不存在"),
    DB_SERVICE_INVALID_PARAMETER(20106, "方法参数错误"),
    DB_SERVICE_FUNCTION_NO_ACCESS(20107, "对此方法无访问权限");

    private String msg;
    private int code;

    private ErrorCode(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public String getMsg() {
        return this.msg;
    }

    public int getCode() {
        return this.code;
    }
}

2.实现方法

代码如下(示例):

@RestController
public class MethodTest {
    @Autowired
    private ApplicationContext context;

    @PostMapping("/method/test")
    public JsonResult methodTest(@RequestBody MethodParam methodParam) throws InvocationTargetException, IllegalAccessException {
        // 获取bean工厂
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getAutowireCapableBeanFactory();
        // 获取bean实例
        Object bean = beanFactory.getBean(methodParam.getBeanName());
        // 获取bean字节码文件
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition(methodParam.getBeanName());
        String beanClassName = beanDefinition.getBeanClassName();
        Class<?> beanClass;
        try {
            beanClass = Class.forName(beanClassName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return JsonResult.error("ClassNotFoundException", e.getMessage());
        }
        Method method = null;
        Method[] methods = beanClass.getDeclaredMethods();
        for (Method beanMethod : methods) {
            int parameterCount = beanMethod.getParameterCount();
            String name = beanMethod.getName();
            // 先根据方法名和参数数量过滤
            if (parameterCount == methodParam.getParams().length && name.equals(methodParam.getMethodName())) {
                // 在根据参数顺序过滤
                Class<?>[] parameterTypes = beanMethod.getParameterTypes();
                boolean match = true;
                for (int i = 0; i < parameterTypes.length; i++) {
                    Class<?> parameterType = parameterTypes[i];
                    Object param = methodParam.getParams()[i];
                    Class<?> paramClass = param.getClass();
                    // 同时是基本数据类型或相同类型
                    boolean equalsType = paramClass.equals(parameterType);
                    boolean isNumber = Number.class.isAssignableFrom(paramClass) && Number.class.isAssignableFrom(parameterType);
                    if (!equalsType) {
                        if (isNumber) {
                            Method valueOf = null;
                            try {
                                valueOf = parameterType.getDeclaredMethod("valueOf", String.class);
                            } catch (NoSuchMethodException e) {
                                e.printStackTrace();
                                return JsonResult.error("NoSuchMethodException", e.getMessage());
                            }
                            methodParam.getParams()[i] = valueOf.invoke(null, param.toString());
                            continue;
                        }
                        match = false;
                        break;
                    }
                }
                if (match) {
                    method = beanMethod;
                    break;
                }
            }
        }
        if (method == null) {
            return JsonResult.error("The method name does not exist or the number of parameters is incorrect");
        }
        Object result;
        try {
            result = method.invoke(bean, methodParam.getParams());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return JsonResult.error("IllegalAccessException", e.getMessage());
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            return JsonResult.error("InvocationTargetException", e.getMessage());
        }
        return result instanceof JsonResult ? (JsonResult) result : JsonResult.success(result);
    }
}

测试

postman调用测试

emp表根据eno查询数据

请求和参数

 返回结果

 

目录

实现思路

具体实现请看代码

一、数据准备

二、使用步骤

1.参数对象

2.返回结果

3.错误码

2.实现方法

测试


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值