东方飘雪

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

页面效果:

代码:

SpringContextUtil.java (com.nsoft.dgc.dtschedule.exclass.SpringContextUtil)

package com.nsoft.dgc.dtschedule.exclass;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @Description: 获得容器中注入的对象
 * 参考:https://blog.csdn.net/weixin_43944305/article/details/106664830
 *      https://wenku.baidu.com/view/e24f1e15598102d276a20029bd64783e09127d01.html
 *      http://www.manongjc.com/article/92044.html
 *
 * @date: 2022.06.16
 */
@Component
public class SpringContextUtil implements ApplicationContextAware {

    // Spring应用上下文环境
    private static ApplicationContext applicationContext;
    /**
     * 实现ApplicationContextAware接口的回调方法,设置上下文环境
     *
     * @param applicationContext
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        SpringContextUtil.applicationContext = applicationContext;
    }
    /**
     * 获得Spring应用上下文
     * @return ApplicationContext
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    /**
     * 获取对象bean  通过id或name去查找获取bean
     * @param name name默认 = 类名(首字母小写)    参数name表⽰IOC容器中已经实例化的bean的id或者name,且⽆论是id还是name都要求在IOC容器中是唯⼀的不能重名。
     *             首字母小写的对象名称:  例如 com.nsoft.dgc.dtschedule.service.impl.DgcTaskServiceImpl ,可以加上注解@Service,默认了类名的首字母小写的名称,即等同于 @Service("dgcTaskServiceImpl"),
     *             另外注意 dgcTaskServiceImpl 必须是唯一的,不能重名,
     *             另由于bean类需要一个无参构造方法,显然容器并不能创建接口的bean,故抽象类只能作为其他bean的父类
     * @return Object
     * @throws BeansException
     */
    public static Object getBean(String name) throws BeansException {
        return applicationContext.getBean(name);
    }
    /**
     * 获取对象bean
     * @param name  同上面的解释
     * @param cla 对象类(注意:必须是已经被注入到Spring容器的类才可以)
     * @return Object
     * @throws BeansException
     */
    public static Object getBean(String name, Class cla) throws BeansException {
        return applicationContext.getBean(name, cla);
    }

}

 

ExcuteClass.java (com.nsoft.dgc.dtschedule.exclass.ExcuteClass)   方法调用ExcuteClassMethod()方法即可

package com.nsoft.dgc.dtschedule.exclass;


import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * @Description: 根据传过来的参数执行类方法(反射原理)
 * @date: 2022.06.14
 */
@Component
public class ExcuteClass {

    final protected Logger logger = LogManager.getLogger(getClass());

    /**
     * @Description: 根据所传参数,反射方法,并执行
     * @param classPath: 类路径 例如:com.nsoft.dgc.dtschedule.service.impl.DgcTaskServiceImpl
     * @param methodName: 方法名称  注意方法名称及大小写应与实际方法完全一致
     * @param parameters: 参数,以json格式编写,参数顺序与实际参数顺序相同;当前支持的参数类型包括int、long、double、float、String、boolean、Short、Integer、Long、Double、Float,
     *                     例如{int:12,long:123454567,String:'lala',boolean:true,Float:12.12,Double:null}
     * @return: void
     * @exception/throws:
     * @date:   2022/6/16
     */
    public void ExcuteClassMethod(String classPath,String methodName,String parameters) throws RuntimeException{
        Class clazz             = null;//
        String simpleName       = null;//类名
        String firstLowerName   = null; //首字母小写的类名
        Method method           = null;//方法
        Object instance         = null;//spring容器中的对象实例
        Class[] tempKey         = null;//参数类型数字
        Object[] tempValue      = null;//参数数值数组
        /**1.获得类相关信息**/
        try{
            clazz = Class.forName(classPath);//通过类路径获得类 这里的classPath路径是类的全路径,从包名到类名
            simpleName = clazz.getSimpleName();//获得类名称
            firstLowerName = simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1); //获得首字母小写的类名称
        }catch (Exception e){
            logger.error("获得类及名称时报错:classPath="+classPath+";clazz="+clazz+";simpleName="+simpleName+";firstLowerName="+firstLowerName,e);
            throw new RuntimeException(e);
        }
        /**2.去Spring容器中获得类对象**/
        try {
            //通过此方法去Spring容器中获取对象实例(此类必须是已经注入到Spring容器中的。注入Spring容器中是指使用@Controller@Service@Mapper@Component等注解注入的bean(接口interface不行),由spring进行管理的类)
            instance = SpringContextUtil.getBean(firstLowerName, clazz);
        }catch (Exception e){
            logger.error("spring容器获得对象时报错:firstLowerName="+firstLowerName+";clazz="+clazz,e);
            throw  new RuntimeException(e);
        }
        /**3.获得参数,将参数类型放到Class[]数组中,将参数数值放到Object[]数组中**/
        try{
            if(null != parameters &&!"".equals(parameters)){
                int i = 0;
                JSONObject jsonObject = JSONObject.parseObject(parameters, Feature.OrderedField);//将参数转换为json(Feature.OrderedField参数保证转换时顺序不变)
                if (!jsonObject.isEmpty()) {
                    tempKey     = new Class[jsonObject.size()];
                    tempValue   = new Object[jsonObject.size()];
                    for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {//fastjson解析方法  进行遍历 向tempKey 和 tempValue 数组赋值
                        this.getClass(entry.getKey(),entry.getValue(),i,tempKey,tempValue);
                        i++;
                    }
                }
            }
        }catch (Exception e){
            logger.error("参数转换时报错,请检查参数的正确性,错误信息为:"+ e.getMessage());
            throw new RuntimeException(e);
        }
        /**4.获得指定方法。两种方式,一种是不知道参数类型时,遍历类中所有的方法,对方法名称进行匹配,第二种是已知方法的参数类型,可直接获得方法**/
        try{
            //获得clazz类中所有的方法
//                tempClass = clazz.getMethods();
//                if(tempClass !=null && tempClass.length>0){
//                    for(int i =0;i<tempClass.length;i++){
//                        if(methodName.equals(tempClass[i].getName())){
//                            method = tempClass[i];//获得此类中的方法
//                            break;
//                        }
//                    }
//                }
            //指定方法(在已知方法参数的类型情况下,用下面这个可直接获得方法)
            method = clazz.getDeclaredMethod(methodName,tempKey);
        }catch (Exception e){
            logger.error("获得方法时报错:clazz="+clazz+";method="+method+";methodName="+methodName+"tempKey="+(tempKey!=null?tempKey.toString():null),e);
            throw new RuntimeException(e);
        }
        /**5.执行方法**/
        try{
            //调用方法
            method.invoke(instance,tempValue);//object为对象实例, tempValue为参数数值数组
        }catch (Exception e){
            logger.error("方法执行时报错:method="+method+";object="+instance+";tempValue="+(tempValue!=null?tempValue.toString():null),e);
            throw new RuntimeException(e);
        }

    }

    /**
     * @Description:  参数类型转换,并赋值(当前仅支持的参数类型包括int、long、double、float、String、boolean、Short、Integer、Long、Double、Float)
     * @param paraType: 参数类型
     * @param paraValue: 参数值
     * @param i: 第几个参数 从0开始
     * @param tempKey: 返回 参数类型数组
     * @param tempValue: 返回 参数数值数组
     * @return: void
     * @exception/throws:
     * @date:   2022/6/17
     */
    public void getClass(Object paraType,Object paraValue,int i,Class[] tempKey,Object[] tempValue) throws RuntimeException {
        boolean isMatch = false;//是否有匹配的类型
        try {
            if ("Short".equals(paraType)) {
                tempKey[i] = Short.class;
                tempValue[i] = paraValue == null ? null : Short.valueOf(String.valueOf(paraValue));
                isMatch = true;
            } else if ("Integer".equals(paraType)) {
                tempKey[i] = Integer.class;
                tempValue[i] = paraValue == null ? null : Integer.valueOf(String.valueOf(paraValue));
                isMatch = true;
            } else if ("Long".equals(paraType)) {
                tempKey[i] = Long.class;
                tempValue[i] = paraValue == null ? null : Long.valueOf(String.valueOf(paraValue));
                isMatch = true;
            } else if ("Double".equals(paraType)) {
                tempKey[i] = Double.class;
                tempValue[i] = paraValue == null ? null : Double.valueOf(String.valueOf(paraValue));
                isMatch = true;
            } else if ("Float".equals(paraType)) {
                tempKey[i] = Float.class;
                tempValue[i] = paraValue == null ? null : Float.valueOf(String.valueOf(paraValue));
                isMatch = true;
            } else if ("int".equals(paraType)) {
                tempKey[i] = int.class;
                tempValue[i] = Integer.valueOf(String.valueOf(paraValue)).intValue();
                isMatch = true;
            } else if ("long".equals(paraType)) {
                tempKey[i] = long.class;
                tempValue[i] = Long.valueOf(String.valueOf(paraValue)).longValue();
                isMatch = true;
            } else if ("double".equals(paraType)) {
                tempKey[i] = double.class;
                tempValue[i] = Double.valueOf(String.valueOf(paraValue)).doubleValue();
                isMatch = true;
            } else if ("float".equals(paraType)) {
                tempKey[i] = float.class;
                tempValue[i] = Float.valueOf(String.valueOf(paraValue)).floatValue();
                isMatch = true;
            } else if ("String".equals(paraType)) {
                tempKey[i] = String.class;
                tempValue[i] = paraValue == null ? null : String.valueOf(paraValue);
                isMatch = true;
            } else if ("boolean".equals(paraType)) {
                tempKey[i] = boolean.class;
                tempValue[i] = paraValue;
                isMatch = true;
            }
            if (!isMatch){
                logger.error("类型paraType="+paraType+"不匹配,不支持此数据类型");
                throw new Exception("类型paraType="+paraType+"不匹配,不支持此数据类型");
            }
        } catch (Exception e) {
            logger.error("第" + (i + 1) + "个参数转换时发生错误,错类型paraType=" + paraType + ";数值paraValue=" + paraValue ,e);
            throw new RuntimeException(e);
        }
    }

}

 

posted on 2022-12-06 11:16  东方飘雪  阅读(35)  评论(0编辑  收藏  举报