Map参数解析

> 以下的案例只是提出一种方案,意在拓展大家的思维 ```java /** * 接口文档配置 */ @Configuration public class EasyApiConfig extends DefaultConfigurationCreator { @Override public AllConfiguration replenish(AllConfiguration configuration) { //拿到入参拦截器 ReadRequestConfig requestConfig = configuration.getReadRequestConfig(); //添加自定义参数拦截方法 requestConfig.addReadParams(this::params); //刷新配置 return super.replenish(configuration); } public List<MethodParam> params(Method method, ApiExtra extra) { List<MethodParam> result = new ArrayList<>(); Parameter[] parameters = method.getParameters(); //如果只有一个Map参数 if(parameters.length>0 && parameters[0].getType().equals(Map.class)){ DefaultParameterNameDiscoverer discover = new DefaultParameterNameDiscoverer(); // 实际方法参数形参名称 String name = discover.getParameterNames(method)[0]; // 获取方法源码的每一行 List<String> lines = extra.getMethodComment().getLines(); for (String line : lines) { //发现有从Map中取值的代码并赋值的时候,取值字符串即为参数,赋值对象即为参数类型 if(line.contains("=") && line.contains(name+".get(")){ String sub = line.substring(line.indexOf(name + ".get(") + name.length() + 5); String paramName = sub.substring(0,sub.indexOf(")")).replace("\"",""); String pre = line.substring(0,line.indexOf("=")).trim(); //通过层层截取,拿到参数名称和参数赋值对象字符串 String type = pre.substring(0, pre.indexOf(" ")); //再读取类源码文件,去import中寻找赋值对象的全类名 for (String s : extra.getControllerComment().getLines()) { if(s.contains("import") && s.endsWith(type+";")){ type = s.substring(s.indexOf("import")+6,s.length()-1).trim(); break; } } //以上数据全部得到以后,可以组装参数了 MethodParam mp = new MethodParam(); //如果是java基础类型,import中找不到的,需要自行处理,下面只是举个String例子 if(type.equals("String")){ type = "java.lang."+type; } //通过反射拿到真实类型 try { mp.setParamType(Class.forName(type)); } catch (ClassNotFoundException e) { e.printStackTrace(); } mp.setParamName(paramName); result.add(mp); } } return result; } return null; } } ``` > 代码思路 1. 添加[接口入参拦截器](doc:I10gUElT),实现拦截方法 2. 通过**反射**的参数来判断是否有**Map类型**参数,如果有则获取Map参数的形参名称 3. 逐行**读取方法源码**,只要发现这个形参名称有**get()操作**并包含**赋值符号**的代码,就认为Map中的key应当为接口参数,于是有了**入参名称** 4. 将上述赋值的代码再进行解析,拿到赋值前的代码,假设为 **A a = map.get("a")**,那么**A**就是这个形参的**实际类型** 5. 拿到A之后接下来就应该去包含这个方法的**文件源码**中查找**import**,也就是去**controller源文件**中查找,逐行遍历源码,发现有import开头并且以A;结尾的,认为是加载的该类**全类名** 6. 之后就通过**反射**来获取全类名的**class**,然后进行下一步处理 7. 需要注意的是,并不是所有的类型都会以import的方式被找到,java基础类型都是没有的,需要自行处理,还有如果是import *进来的也是找不到。