
最近在做公司一个消息网关的服务,包括:短信、微信、邮件等,所有请求通过一个入口,方便接口的管理(记录日志、接口限流白名单啥的)。如何写这个接口呢,还有为了以后扩展,对接过短信、微信、公众号的童鞋大概都了解,首先定义一个模板,然后后台传入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();
}AbsClassA
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");
}
}ClassB
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");
}
}ClassC
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");
}
}ClassD