之前一篇,我们说了一些测试用函数的接口类与实现类,这样相当于我们已经构造了我们想使用的函数。那么,如何让程序知道我们使用的是函数,并调用接口实现类进行处理后将结果放入我们想要的地方呢?
在这里,我们需要整理一下我们的思路。
首先,我们可以通过正则表达式来匹配到我们的函数名称。其次,在得知函数名称的情况下,调用对应函数的接口实现类的方法去执行。最后,将值传递回我们需要填入的地方。
在这里,我们先看看如何使用正则表达式来实现匹配函数名称。(我们使用函数的样式为“__funcName(args)”)("注意:这里是两个下划线(有人已经提醒我了。)")
protected Pattern funPattern = Pattern .compile("__(\w*?)\((([\w\\\/:\.\$]*,?)*)\)");
可以使用这个正则表达式来匹配【_funcName(args)】的形式。有关正则这里不再详细说明。
关于正则表达式,这里再推荐一个网站。以便各位学习何使用:https://www.w3cschool.cn/regexp/x9hf1pq9.html
在知道了函数名称之后,怎样调用对应函数的接口实现类的方法去执行呢?这里我们还是整理一下思路。
----->先找到当前项目路径下所有的类,然后过滤获取这个路径下所有子类或接口实现类。通过一个集合,将函数名与测试函数接口对应起来,存入集合。最后,通过调用接口实现类来获取值。
首先,我们来看一下classFinder的查找类。
public class classFinder { static ClassLoader classloader = Thread.currentThread().getContextClassLoader(); /** * 获取同一路径下所有子类或接口实现类 * * @param intf * @return * @throws IOException * @throws ClassNotFoundException */ public static List<Class<?>> getAllAssignedClass(Class<?> cls) { List<Class<?>> classes = new ArrayList<Class<?>>(); for (Class<?> c : getClasses(cls)) { if (cls.isAssignableFrom(c) && !cls.equals(c)) { classes.add(c); } } return classes; } /** * 取得当前类路径下的所有类 * * @param cls * @return * @throws IOException * @throws ClassNotFoundException */ public static List<Class<?>> getClasses(Class<?> cls) { String pk = cls.getPackage().getName(); String path = pk.replace('.', '/'); try { String dirPath = URLDecoder.decode(classloader.getResource(path).getPath(),"utf-8"); return getClasses(new File(dirPath), pk); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return new ArrayList<Class<?>>(); } /** * 迭代查找 * * @param dir * @param pk * @return * @throws ClassNotFoundException */ private static List<Class<?>> getClasses(File dir, String pk) { List<Class<?>> classes = new ArrayList<Class<?>>(); if (!dir.exists()) { return classes; } for (File f : dir.listFiles()) { if (f.isDirectory()) { classes.addAll(getClasses(f, pk + "." + f.getName())); } String name = f.getName(); if (name.endsWith(".class")) { try{ classes.add(Class.forName(pk + "." + name.substring(0, name.length() - 6))); }catch(Exception ex){ //TODO console warn } } } return classes; } }
通过上面的查找类,我们可以获取到指定路径下的所有子类和接口实现类。
public class functionUtil { private static final Map<String, Class<? extends functionInterface>> functionsMap = new HashMap<String, Class<? extends functionInterface>>(); static { //bodyfile 特殊处理,这个bodyfile主要是应对POST有上传文件的情况。 functionsMap.put("bodyfile", null); List<Class<?>> clazzes = classFinder.getAllAssignedClass(functionInterface.class); clazzes.forEach((clazz) -> { try { // function functionInterface tempFunc = (functionInterface) clazz.newInstance(); String referenceKey = tempFunc.getReferenceKey(); if (referenceKey.length() > 0) { // ignore self functionsMap.put(referenceKey, tempFunc.getClass()); } } catch (Exception ex) { ex.printStackTrace(); //TODO } }); } public static boolean isFunction(String functionName){ return functionsMap.containsKey(functionName); } public static String getValue(String functionName,String[] args){ try { return functionsMap.get(functionName).newInstance().execute(args); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); return ""; } } }
在这个functionUtil里面我们实现了将找到的接口实现类存入Map,并根据函数名来调用相应的函数执行,并返回执行后的结果。