導讀
最近在做公司一個訊息閘道器的服務,包括:簡訊、微信、郵件等,所有請求通過一個入口,方便介面的管理(記錄日誌、介面限流白名單啥的)。如何寫這個介面呢,還有為了以後擴充套件,對接過簡訊、微信、公眾號的童鞋大概都瞭解,首先定義一個模板,然後後臺傳入json,替換模板中的值,然後傳送。設計框架大概思路是這樣的
- 第一層:通過策略模式,選擇出具體的傳送型別,比如:簡訊、微信、郵件。。。。。
- 第二層:再次通過策略模式,選擇出具體的第三方平臺,比如簡訊平臺:阿里雲、騰訊雲、華為雲。。。。。。
- 第三層:通過一個簡單的工廠,選擇出具體的模板,然後傳送出去
第一二層,以後可能會擴充套件出2、3家第三方平臺,使用策略模式還是可以接受的,但是到了第三層的話,可能會出現一二十個模板,這樣子的話,會出現一大堆if else等等(寫過簡單工廠的都清楚),然後自己手動封裝一個工具類,獲取一個類下的所有子類,然後通過一個欄位建立物件,這裡我做了一個優化,找到的值,我會先放到一個Map中,第二次請求來的時候,先去Map中查詢下,是否有值,有值的話,直接呼叫,沒有值的話,才會去重新找一遍,這樣子效能也得到了提高
專案結構
工具類
package com.ybchen.messagegateway; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.List; /** * @ClassName:TestMain * @Description:TODO * @Author:chenyb * @Date:2020/12/1 9:19 上午 * @Versiion:1.0 */ public class TestMain { public static void main(String[] args) throws Exception { System.out.println("介面實現類:"); for (Class<?> c : getAllAssignedClass(AbsClassA.class)) { if (c.getName().contains("D")){ AbsClassA obj =(AbsClassA) c.newInstance(); obj.speak(); } System.out.println(c.getName()); } System.out.println("子類:"); for (Class<?> c : getAllAssignedClass(AbsClassA.class)) { System.out.println(c.getName()); } } /** * 獲取同一路徑下所有子類或介面實現類 * * @param intf * @return * @throws IOException * @throws ClassNotFoundException */ public static List<Class<?>> getAllAssignedClass(Class<?> cls) throws Exception { List<Class<?>> classes = new ArrayList<>(); 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) throws Exception { String pk = cls.getPackage().getName(); String path = pk.replace('.', '/'); ClassLoader classloader = Thread.currentThread().getContextClassLoader(); URL url = classloader.getResource(path); return getClasses(new File(url.getFile()), pk); } /** * 迭代查詢類 * * @param dir * @param pk * @return * @throws ClassNotFoundException */ private static List<Class<?>> getClasses(File dir, String pk) throws ClassNotFoundException { List<Class<?>> classes = new ArrayList<>(); 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")) { classes.add(Class.forName(pk + "." + name.substring(0, name.length() - 6))); } } return classes; } }
package com.ybchen.messagegateway; /** * @ClassName:AbsClassA * @Description:TODO * @Author:chenyb * @Date:2020/12/1 9:16 上午 * @Versiion:1.0 */ public abstract class AbsClassA { public abstract void speak(); }
package com.ybchen.messagegateway; /** * @ClassName:ClassB * @Description:TODO * @Author:chenyb * @Date:2020/12/1 9:16 上午 * @Versiion:1.0 */ public class ClassB extends AbsClassA { @Override public void speak() { System.out.println("BBBBBBB"); } }
package com.ybchen.messagegateway; /** * @ClassName:ClassC * @Description:TODO * @Author:chenyb * @Date:2020/12/1 9:16 上午 * @Versiion:1.0 */ public class ClassC extends AbsClassA{ @Override public void speak() { System.out.println("CCC"); } }
package com.ybchen.messagegateway.de; import com.ybchen.messagegateway.AbsClassA; /** * @ClassName:ClassD * @Description:TODO * @Author:chenyb * @Date:2020/12/1 9:17 上午 * @Versiion:1.0 */ public class ClassD extends AbsClassA { @Override public void speak() { System.out.println("ddd"); } }