1. 入口类 DynamicExecuteController
@RestController
@RequestMapping("/dynamic")
public class DynamicExecuteController {
@Resource
private DynamicExecuteService dynamicExecuteService;
/**
* service: com.example.concrete.starter.service.GreetService
* method: com.example.concrete.starter.service.GreetService.greet()
* args: ["xing","Local"]
*
* @param param
* @return
*/
@RequestMapping("/execute")
public Object execute(String param) {
if ("greet".equals(param)) {
param = "{\"service\": \"com.example.concrete.starter.service.GreetService\",\n" +
" \"method\": \"public abstract java.lang.String com.example.concrete.starter.service.GreetService.greet()\"}";
} else if ("greet2".equals(param)){
param = "{\"service\": \"com.example.concrete.starter.service.GreetService\",\n" +
" \"method\": \"public abstract java.lang.String com.example.concrete.starter.service.GreetService.greet(java.lang.String)\",\n" +
" \"args\": [\n" +
" \"Tinyspot\"\n" +
" ]}";
} else if ("greet3".equals(param)) {
param = "{\"service\": \"com.example.concrete.starter.service.GreetService\",\n" +
" \"method\": \"public abstract java.lang.String com.example.concrete.starter.service.GreetService.greet(java.lang.String,java.lang.String)\",\n" +
" \"args\": [\"Alice\", \"Tinyspot\"]}";
} else if ("greet4".equals(param)) {
// 参数值组装
// List<String> list = Arrays.asList(JSON.toJSONString(new UserDTO("xing", 20)), "Local");
// System.out.println(JSON.toJSONString(list.toArray()));
param = "{\"service\": \"com.example.concrete.starter.service.GreetService\",\n" +
" \"method\": \"public abstract java.lang.String com.example.concrete.starter.service.GreetService.greeting(com.example.concrete.common.domain.UserDTO,java.lang.String)\",\n" +
" \"args\": [\"{\\\"age\\\":20,\\\"name\\\":\\\"Tinyspot\\\"}\",\"Local\"]}";
}
return dynamicExecuteService.execute(param);
}
}
请求URL http://localhost:8080/dynamic/execute?param=greet4
2. 业务类
@Description("工具测试")
public interface GreetService {
@Description("打招呼4")
String greeting(UserDTO userDTO, @Description("当前环境") String env);
@Description("打招呼")
String greet();
@Description("打招呼1")
String greet(Integer value);
@Description("打招呼2")
String greet(String name);
@Description("打招呼3")
String greet(String name, String myName);
}
@Service
public class GreetServiceImpl implements GreetService {
@Override
public String greeting(UserDTO userDTO, String env) {
return "greeting:" + userDTO.toString() + "; env=" + env;
}
@Override
public String greet(Integer value) {
return "Integer:" + value;
}
@Override
public String greet() {
return "greet...";
}
@Override
public String greet(String name) {
return "Hello " + name;
}
@Override
public String greet(String name, String myName) {
return "Hello " + name + ", my name is " + myName;
}
}
注解 @Description
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Description {
String value();
String remark() default "";
}
UserDTO 类
@Data
public class UserDTO extends BaseDTO {
private static final long serialVersionUID = 5196056007908280999L;
private String name;
private Integer age;
private Integer status;
private Long total;
private Boolean isOwner;
public UserDTO() {
}
public UserDTO(String name, Integer age) {
this.name = name;
this.age = age;
}
}
import org.apache.commons.lang3.builder.ToStringBuilder;
import java.io.Serializable;
public class BaseDTO implements Serializable {
private static final long serialVersionUID = 1208436728115984191L;
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}
3. 解析
@Service
public class DynamicExecuteService {
@Resource
protected ApplicationContext applicationContext;
public Object execute(String param) {
Object result = null;
try {
final Request request = JSON.parseObject(param, Request.class);
Class<?> clazz = Class.forName(request.getService());
Object service = this.applicationContext.getBean(clazz);
ServiceDescription serviceDescription = ServiceDescription.buildServiceDescription(clazz);
MethodDescription method = serviceDescription.findMethod(request.getMethod());
result = DescriptionUtil.execute(service, method, request.getArgs());
} catch (Throwable e) {
Map<String, String> errorMap = new HashMap<>();
errorMap.put("errorMessage", e.getMessage());
errorMap.put("stackTrace", ExceptionUtils.getStackTrace(e));
return errorMap;
}
return result;
}
@Data
public static class Request {
private String service;
private String method;
private List<String> args = new ArrayList<>();
}
}
public class DescriptionUtil {
public static Object execute(Object service, MethodDescription method, List<String> arguments) throws InvocationTargetException, IllegalAccessException {
if (method.getParameters().size() != arguments.size()) {
return "参数不对";
}
List<Object> args = new ArrayList<>();
for (int i = 0; i < arguments.size(); i++) {
args.add(getArgValue(method.getParameters().get(i).getParameterClazz(), arguments.get(i)));
}
return method.getMethod().invoke(service, args.toArray());
}
private static Object getArgValue(Class<?> parameterType, String arg) {
if (arg == null) {
return null;
}
arg = StringUtils.trim(arg);
if (parameterType.equals(String.class)) {
return arg;
}
if (parameterType.equals(Date.class)) {
if (arg.length() == 10) {
// 日期补全
arg += " 00:00:00";
}
return DateUtil.parseToDateTime(arg);
}
if (StringUtils.isBlank(arg)) {
return null;
}
return JSON.parseObject(arg, parameterType);
}
}
4. 模型
public class ServiceDescription {
private Description description;
private Class<?> serviceClazz;
private List<MethodDescription> methods = new ArrayList<>();
public Description getDescription() {
return description;
}
public void setDescription(Description description) {
this.description = description;
}
public Class<?> getServiceClazz() {
return serviceClazz;
}
public void setServiceClazz(Class<?> serviceClazz) {
this.serviceClazz = serviceClazz;
}
public List<MethodDescription> getMethods() {
return methods;
}
public MethodDescription findMethod(final String methodSign) {
return getMethods().stream()
.filter(methodDescription -> methodDescription.getMethodSign().equals(methodSign))
.findFirst()
.orElse(null);
}
public static ServiceDescription buildServiceDescription(Class<?> clazz) {
if (clazz == null) {
return null;
}
Description description = clazz.getAnnotation(Description.class);
if (description == null) {
return null;
}
ServiceDescription serviceDescription = new ServiceDescription();
serviceDescription.setDescription(description);
serviceDescription.setServiceClazz(clazz);
fillMethods(serviceDescription, clazz);
return serviceDescription;
}
private static void fillMethods(ServiceDescription serviceDescription, Class<?> clazz) {
for (Method method : clazz.getDeclaredMethods()) {
Description description = method.getAnnotation(Description.class);
if (description == null) {
continue;
}
MethodDescription methodDescription = new MethodDescription();
methodDescription.setDescription(description);
methodDescription.setMethod(method);
fillParameters(methodDescription, method);
serviceDescription.getMethods().add(methodDescription);
}
}
private static void fillParameters(MethodDescription methodDescription, Method method) {
for (int i = 0; i < method.getParameterTypes().length; i++) {
ParameterDescription parameterDescription = new ParameterDescription();
parameterDescription.setDescription(getDescriptions(method, i));
parameterDescription.setParameterClazz(method.getParameterTypes()[i]);
methodDescription.getParameters().add(parameterDescription);
}
}
private static Description getDescriptions(Method method, int paramIndex) {
Annotation[] annotations = method.getParameterAnnotations()[paramIndex];
for (Annotation annotation : annotations) {
if (annotation instanceof Description) {
return (Description) annotation;
}
}
return null;
}
}
@Data
public class MethodDescription {
private Description description;
private Method method;
private List<ParameterDescription> parameters = new ArrayList<>();
public String getMethodSign() {
return this.method.toString();
}
}
@Data
public class ParameterDescription {
private Description description;
private Class<?> parameterClazz;
}
网友评论