今天收到老大布置的任务,就是要起服的时候校验一下某些数据的合法性,防止策划配错表格导致运行出错。
本来想着就是写一个方法,然后在每个配置文件数据中去进行校验的。就是谁建表,谁校验,我只提供一个校验的方法出来,你调用即可。但是这种方式很明显会增加无畏的工作量,且容易漏掉(不是每一个程序员都是负责任的程序员)。好吧,那就只能通过做成通用的方式咯。
怎么才能通用呢?
要想通用,无非就是在配置文件加载完成的时候,在内存中对他们进行校验数据。但是我怎么知道哪一个配表数据文件是我要去检验的,而且他们的命名方式也不一样啊。如我要检查每一张表格中设计到变量UnlockCondition的变量包含的数据是否满足相关配表的。那么此时我只需要遍历每一张配表中的方法返回值中包含了UnlockCondition的方法,然后通过java的反射调用这个方法从而拿到方法中的数据,然后就可以用这些数据进行校验了。
代码搞起来
有了思路,那么就实践起来吧。
由于项目中配置文件加载完成之后会调用一个监听器,我们监听这个监听器即可
public static void onLoadFinish(AllConfigFinish allConfigFinish) {
}
所有的配置文件我们都放到了一个内存变量中,我们只需要拿到这个内存变量就能拿到所有的配置文件数据对象
com.manling.core.config.container.ContainerManager
private Map<String, Container<? extends Wrapper>> containers = new ConcurrentHashMap();
其中key是配置表的名字,value是配置表的所有数据
我们调用如下的方法来获取对应的配置文件对象并使用反射来获得数据
private static void checkConditionAndWealth() {
ContainerManager containerManager = SpringContextUtils.getBean(ContainerManager.class);
Set<String> strings = containerManager.getContainers().keySet();
for (String className : strings) {
Container<? extends Wrapper> container = containerManager.getContainers().get(className);
//获取每一张配表的数据
List<? extends Wrapper> dataList = container.getDataList();
for (Wrapper wrapper : dataList) {
Class<? extends Wrapper> aClass = wrapper.getClass();
//获取对象的所有方法
Method[] methods = aClass.getMethods();
for (Method method : methods) {
//由于配表数据对象获取数据的方法都是非static,因此过滤掉所有的static方法即可
int modifiers = method.getModifiers();
if (Modifier.isStatic(modifiers)) {
continue;
}
//获取方法的名字,只有get开头的方法才是获取数据的方法,也是我们需要的方法
String name = method.getName();
if (name.startsWith("get")) {
//获取方法的返回值
Type returnType = method.getGenericReturnType();
try {
//如果是List
if (returnType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) returnType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type type : actualTypeArguments) {
//判断每一个列表中的对象是否是UnlockCondition类型
if (type == com.manling.game.config.bean.UnlockCondition.class) {
//若是,则是我们需要判断的类型
List<UnlockCondition> os = (List<UnlockCondition>) method.invoke(wrapper, null);
checkUnLockCondition(os, className);
}
}
//对象
} else {
if (returnType == com.manling.game.config.bean.UnlockCondition.class) {
UnlockCondition o = (UnlockCondition) method.invoke(wrapper, null);
checkUnLockCondition(Arrays.asList(o), className);
}
}
} catch (Exception e) {
System.err.println(className + ":" + wrapper.getId());
e.printStackTrace();
}
}
}
}
}
}
最后在此方法中处理具体的逻辑
private static void checkUnLockCondition(List<UnlockCondition> os, String cfgName) {
}
总结
1.拿到配表对象
2.获取配表对象的所有方法,并筛选出那些方法里面的数据是我们需要对比
3.java发射获得此方法包含的数据然后对比数据即可