之前一篇,我們說了一些測試用函數的接口類與實現類,這樣相當於我們已經構造了我們想使用的函數。那么,如何讓程序知道我們使用的是函數,並調用接口實現類進行處理后將結果放入我們想要的地方呢?
在這里,我們需要整理一下我們的思路。
首先,我們可以通過正則表達式來匹配到我們的函數名稱。其次,在得知函數名稱的情況下,調用對應函數的接口實現類的方法去執行。最后,將值傳遞回我們需要填入的地方。
在這里,我們先看看如何使用正則表達式來實現匹配函數名稱。(我們使用函數的樣式為“__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,並根據函數名來調用相應的函數執行,並返回執行后的結果。