import com.google.common.reflect.TypeToken; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.reflect.FieldUtils; import org.apache.commons.lang3.reflect.MethodUtils; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*;

@RestController public class EchoController implements ApplicationContextAware, EnvironmentAware {

private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create();
private ApplicationContext applicationContext;
private Environment environment;

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

@Override
public void setEnvironment(Environment environment) {
    this.environment = environment;
}


//applicationContext中的对象反射调用,
//data为请求参数(LinkedHashMap的json格式,其中key为类型的全限定名)
//支持重载方法反射调用,因为LinkedHashMap包含参数类型的描述信息
@RequestMapping(method = RequestMethod.POST, value = "/invoke")
public String invoke(String objAccess, String methodName, @RequestParam(value = "data", required = false) String data) {
    try {
        Object object = objAccess(applicationContext, objAccess);
        LinkedHashMap<String, String> linkedHashMap = StringUtils.isBlank(data) ?
                new LinkedHashMap<>() : GSON.fromJson(data, new TypeToken<LinkedHashMap<String, String>>() {
        }.getType());
        Object[] args = linkedMap2args(linkedHashMap);
        try {
            Object invoke = MethodUtils.invokeMethod(object, methodName, args);
            return GSON.toJson(invoke);
        } catch (Exception e) {
            Method[] declaredMethods = MethodUtil.getMethods(object.getClass());
            for (Method m : declaredMethods) {
                if (m.getName().equals(methodName)) {
                    m.setAccessible(true);
                    Object invoke = m.invoke(object, args);
                    return GSON.toJson(invoke);
                }
            }
            for (Class parentClass = object.getClass().getSuperclass(); parentClass != null; parentClass = parentClass.getSuperclass()) {
                Method[] parentMethods = parentClass.getDeclaredMethods();
                for (Method m : parentMethods) {
                    if (m.getName().equals(methodName)) {
                        m.setAccessible(true);
                        Object invoke = m.invoke(object, args);
                        return GSON.toJson(invoke);
                    }
                }
            }
            throw new RuntimeException("未找到方法:" + methodName);
        }
    } catch (Exception e) {
        return e.getMessage();
    }
}

//json请求数据转方法参数
private Object[] linkedMap2args(LinkedHashMap<String, String> linkedHashMap) {
    if (CollectionUtils.isEmpty(linkedHashMap)) {
        return null;
    } else {
        List<Object> args = new ArrayList<>();
        linkedHashMap.entrySet().forEach(stringObjectEntry -> {
            String type = stringObjectEntry.getKey().split("_")[0];
            Class<?> clazz = null;
            try {
                clazz = Class.forName(type);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
            if (StringUtils.isNotBlank(stringObjectEntry.getValue())) {
                Object arg = GSON.fromJson(stringObjectEntry.getValue(), clazz);
                args.add(arg);
            } else {
                args.add(null);
            }
        });
        return args.toArray();
    }
}


//applicationContext中的对象属性访问,
//支持下标访问
//例如bean.field1.field2.xxxList(0).xxxMap(someKey).password
@RequestMapping("/getObj")
public String getObj(String obj) {
    Object object = objAccess(applicationContext, obj);
    return obj2String(object);
}


public static String obj2String(Object o) {
    if (String.class.equals(o.getClass())
            || Enum.class.equals(o.getClass())
            || Date.class.equals(o.getClass())
            || Long.class.equals(o.getClass())
            || long.class.equals(o.getClass())
            || Integer.class.equals(o.getClass())
            || int.class.equals(o.getClass())
            || Double.class.equals(o.getClass())
            || double.class.equals(o.getClass())
            || Float.class.equals(o.getClass())
            || float.class.equals(o.getClass())
            || Short.class.equals(o.getClass())
            || short.class.equals(o.getClass())
            || Boolean.class.equals(o.getClass())
            || boolean.class.equals(o.getClass())

    ) {
        return String.valueOf(o);
    } else {
        StringBuilder sb = new StringBuilder();
        Field[] allFields = FieldUtils.getAllFields(o.getClass());
        for (Field field : allFields) {
            sb.append(field.getName());
            sb.append("\n");
        }
        return sb.toString();
    }
}

private static Object objAccess(ApplicationContext ac, String propAccessChain) {
    Object o = null;
    if (StringUtils.isBlank(propAccessChain)) {
        System.out.println("参数不能为空");
        return null;
    }
    String[] split = propAccessChain.split("\\.");
    try {
        o = ac.getBean(split[0]);
    } catch (Exception e) {
        System.out.println("获取对象" + split[0] + "失败");
        return null;
    }
    int index = propAccessChain.indexOf(".") + 1;
    return index > 0 ? getPropObj(o, propAccessChain.substring(index)) : o;
}


private static Object getPropObj(Object o, String propAccessChainFromObj) {
    String[] split = propAccessChainFromObj.split("\\.");
    for (String next : split) {
        try {
            if (next.contains("(") && next.contains(")")) {
                String desc = next.substring(0, next.indexOf("("));
                String key = next.substring(next.indexOf("(") + 1, next.indexOf(")"));
                Object listOrMap = FieldUtils.readField(o, desc, true);
                if (Map.class.isAssignableFrom(listOrMap.getClass())) {
                    o = ((Map) listOrMap).get(key);
                } else if (List.class.isAssignableFrom(listOrMap.getClass())) {
                    o = ((List) listOrMap).get(Integer.parseInt(key));
                } else {
                    Object[] cast = Object[].class.cast(listOrMap);
                    o = cast[Integer.parseInt(key)];
                }
            } else {
                o = FieldUtils.readField(o, next, true);
            }
        } catch (Exception e) {
            throw new RuntimeException("获取属性" + next + "失败");
        }
    }
    return o;
}


//配置探测
@RequestMapping("/getConfig")
public String getConfig(String config) {
    String[] activeProfiles = environment.getActiveProfiles();
    environment.getDefaultProfiles();
    return GSON.toJson(environment.getProperty(config));
}

} // 使用方式