diff --git a/sms4j-api/src/main/java/org/dromara/sms4j/api/SmsBlend.java b/sms4j-api/src/main/java/org/dromara/sms4j/api/SmsBlend.java
index fd341541..880d867d 100644
--- a/sms4j-api/src/main/java/org/dromara/sms4j/api/SmsBlend.java
+++ b/sms4j-api/src/main/java/org/dromara/sms4j/api/SmsBlend.java
@@ -3,12 +3,14 @@ package org.dromara.sms4j.api;
import org.dromara.sms4j.api.callback.CallBack;
import org.dromara.sms4j.api.entity.SmsResponse;
+import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
/**
* SmsBlend
*
通用接口,定义国内短信方法
+ *
* @author :Wind
* 2023/5/16 16:03
**/
@@ -16,12 +18,14 @@ public interface SmsBlend {
/**
* 获取短信实例唯一标识
+ *
* @return
*/
String getConfigId();
/**
* 获取供应商标识
+ *
* @return
*/
String getSupplier();
@@ -151,4 +155,43 @@ public interface SmsBlend {
*/
void delayMassTexting(List phones, String templateId, LinkedHashMap messages, Long delayedTime);
+ /**
+ * 说明:加入黑名单【这个需要有全局操作的同时需要操作缓存,那么不给smsblend实际处理,代理部分处理】
+ * joinInBlacklist
+ *
+ * @param phone 需要加入黑名单的手机号
+ * @author :sh1yu
+ */
+ default void joinInBlacklist(String phone) {
+ }
+
+ /**
+ *
说明:从黑名单移除【为了sms4j组件有统一入口,同时这个需要有全局操作的同时需要操作缓存,那么不给smsblend实际处理,代理部分处理】
+ * removeFromBlacklist
+ *
+ * @param phone 需要加入黑名单的手机号
+ * @author :sh1yu
+ */
+ default void removeFromBlacklist(String phone) {
+ }
+
+ /**
+ *
说明:批量加入黑名单【为了sms4j组件有统一入口,同时这个需要有全局操作的同时需要操作缓存,那么不给smsblend实际处理,代理部分处理】
+ * batchJoinBlacklist
+ *
+ * @param phones 需要加入黑名单的手机号数组
+ * @author :sh1yu
+ */
+ default void batchJoinBlacklist(List phones) {
+ }
+
+ /**
+ * 说明:批量从黑名单移除【为了sms4j组件有统一入口,同时这个需要有全局操作的同时需要操作缓存,那么不给smsblend实际处理,代理部分处理】
+ * batchRemovalFromBlacklist
+ *
+ * @param phones 需要移除黑名单的手机号数组
+ * @author :sh1yu
+ */
+ default void batchRemovalFromBlacklist(List phones) {
+ }
}
diff --git a/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/CoreMethodProcessor.java b/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/CoreMethodProcessor.java
new file mode 100644
index 00000000..effa18fe
--- /dev/null
+++ b/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/CoreMethodProcessor.java
@@ -0,0 +1,44 @@
+package org.dromara.sms4j.api.proxy;
+
+import org.dromara.sms4j.comm.constant.NumberOfParasmeters;
+
+import java.lang.reflect.Method;
+import java.util.LinkedHashMap;
+import java.util.List;
+/**
+ * 核心方法执行器接口
+ *
+ * @author sh1yu
+ * @since 2023/10/27 13:03
+ */
+public interface CoreMethodProcessor extends SmsProcessor {
+ default Object[] preProcessor(Method method, Object source, Object[] param) {
+ String name = method.getName();
+ int parameterCount = method.getParameterCount();
+ if ("sendMessage".equals(method.getName())) {
+ if (NumberOfParasmeters.TWO == NumberOfParasmeters.getNumberOfParasmetersEnum(parameterCount)) {
+ sendMessagePreProcess((String) param[0],(String) param[1]);
+ return param;
+ }
+ if (NumberOfParasmeters.THREE == NumberOfParasmeters.getNumberOfParasmetersEnum(parameterCount)) {
+ sendMessageByTemplatePreProcess((String)param[0],(String) param[1],(LinkedHashMap)param[2]);
+ return param;
+ }
+ }
+ if ("massTexting".equals(method.getName())) {
+ if (NumberOfParasmeters.TWO == NumberOfParasmeters.getNumberOfParasmetersEnum(parameterCount)) {
+ massTextingPreProcess((List)param[0],(String)param[1]);
+ return param;
+ }
+ if (NumberOfParasmeters.THREE == NumberOfParasmeters.getNumberOfParasmetersEnum(parameterCount)) {
+ massTextingByTemplatePreProcess((List)param[0],(String)param[1],(LinkedHashMap)param[2]);
+ return param;
+ }
+ }
+ return param;
+ }
+ void sendMessagePreProcess(String phone, String message);
+ void sendMessageByTemplatePreProcess(String phone, String templateId, LinkedHashMap messages);
+ void massTextingPreProcess(List phones, String message);
+ void massTextingByTemplatePreProcess(List phones, String templateId, LinkedHashMap messages);
+}
diff --git a/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/Order.java b/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/Order.java
new file mode 100644
index 00000000..c6b49e91
--- /dev/null
+++ b/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/Order.java
@@ -0,0 +1,12 @@
+package org.dromara.sms4j.api.proxy;
+/**
+ * 排序接口
+ *
+ * @author sh1yu
+ * @since 2023/10/27 13:03
+ */
+public interface Order {
+ default public int getOrder(){
+ return 999;
+ }
+}
diff --git a/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/RestrictedProcess.java b/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/RestrictedProcess.java
deleted file mode 100644
index 1d0457d9..00000000
--- a/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/RestrictedProcess.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.dromara.sms4j.api.proxy;
-
-import org.dromara.sms4j.comm.exception.SmsBlendException;
-
-/**
- * 短信拦截处理接口
- */
-public interface RestrictedProcess {
-
- /**
- * 拦截校验过程
- * @param phone
- * @return
- */
- SmsBlendException process(String phone);
-
-}
diff --git a/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/SmsProcessor.java b/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/SmsProcessor.java
new file mode 100644
index 00000000..8f506597
--- /dev/null
+++ b/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/SmsProcessor.java
@@ -0,0 +1,24 @@
+package org.dromara.sms4j.api.proxy;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+/**
+ * 执行器接口
+ *
+ * @author sh1yu
+ * @since 2023/10/27 13:03
+ */
+public interface SmsProcessor extends Order {
+ default Object[] preProcessor(Method method, Object source, Object[] param) {
+ return null;
+ }
+
+ default Object postProcessor(Object result, Object[] param) {
+ return null;
+ }
+
+ default Object exceptionHandleProcessor(Method method, Object source, Object[] param,Exception exception) throws InvocationTargetException, IllegalAccessException {
+ return null;
+ }
+}
diff --git a/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/SuppotFilter.java b/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/SuppotFilter.java
new file mode 100644
index 00000000..58453afa
--- /dev/null
+++ b/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/SuppotFilter.java
@@ -0,0 +1,12 @@
+package org.dromara.sms4j.api.proxy;
+
+import java.util.List;
+/**
+ * 支持接口,如果执行器需要根据支持厂商加载,那可以实现此接口
+ *
+ * @author sh1yu
+ * @since 2023/10/27 13:03
+ */
+public interface SuppotFilter{
+ List getSupports();
+}
diff --git a/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/aware/SmsBlendConfigAware.java b/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/aware/SmsBlendConfigAware.java
new file mode 100644
index 00000000..13e01430
--- /dev/null
+++ b/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/aware/SmsBlendConfigAware.java
@@ -0,0 +1,13 @@
+package org.dromara.sms4j.api.proxy.aware;
+
+import java.util.Map;
+
+/**
+ * 厂商配置感知接口
+ *
+ * @author sh1yu
+ * @since 2023/10/27 13:03
+ */
+public interface SmsBlendConfigAware {
+ void setSmsBlendsConfig(Map> blends);
+}
diff --git a/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/aware/SmsConfigAware.java b/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/aware/SmsConfigAware.java
new file mode 100644
index 00000000..34b6b38a
--- /dev/null
+++ b/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/aware/SmsConfigAware.java
@@ -0,0 +1,12 @@
+package org.dromara.sms4j.api.proxy.aware;
+
+
+/**
+ * 系统配置感知接口
+ *
+ * @author sh1yu
+ * @since 2023/10/27 13:03
+ */
+public interface SmsConfigAware {
+ void setSmsConfig(Object config);
+}
diff --git a/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/aware/SmsDaoAware.java b/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/aware/SmsDaoAware.java
new file mode 100644
index 00000000..f17a6297
--- /dev/null
+++ b/sms4j-api/src/main/java/org/dromara/sms4j/api/proxy/aware/SmsDaoAware.java
@@ -0,0 +1,12 @@
+package org.dromara.sms4j.api.proxy.aware;
+
+import org.dromara.sms4j.api.dao.SmsDao;
+/**
+ * 缓存感知接口
+ *
+ * @author sh1yu
+ * @since 2023/10/27 13:03
+ */
+public interface SmsDaoAware {
+ void setSmsDao(SmsDao smsDao);
+}
diff --git a/sms4j-comm/src/main/java/org/dromara/sms4j/comm/constant/NumberOfParasmeters.java b/sms4j-comm/src/main/java/org/dromara/sms4j/comm/constant/NumberOfParasmeters.java
new file mode 100644
index 00000000..fa5def49
--- /dev/null
+++ b/sms4j-comm/src/main/java/org/dromara/sms4j/comm/constant/NumberOfParasmeters.java
@@ -0,0 +1,35 @@
+package org.dromara.sms4j.comm.constant;
+
+
+/**
+ * NumberOfParasmeters
+ * 重载方法的参数个数
+ *
+ * @author :sh1yu
+ * 2023/11/01 19:33
+ **/
+public enum NumberOfParasmeters {
+ //一个参数
+ ONE(1),
+ //两个参数
+ TWO(2),
+ //三个参数
+ THREE(3);
+ private int code;
+
+ NumberOfParasmeters(int code) {
+ this.code = code;
+ }
+
+ public static NumberOfParasmeters getNumberOfParasmetersEnum(int index) {
+ switch (index) {
+ case 1:
+ return NumberOfParasmeters.ONE;
+ case 2:
+ return NumberOfParasmeters.TWO;
+ case 3:
+ return NumberOfParasmeters.THREE;
+ }
+ throw new IllegalArgumentException("building enum NumberOfParasmeters error,param not match");
+ }
+}
diff --git a/sms4j-core/src/main/java/org/dromara/sms4j/core/factory/SmsFactory.java b/sms4j-core/src/main/java/org/dromara/sms4j/core/factory/SmsFactory.java
index b6286a74..f9e1bf12 100644
--- a/sms4j-core/src/main/java/org/dromara/sms4j/core/factory/SmsFactory.java
+++ b/sms4j-core/src/main/java/org/dromara/sms4j/core/factory/SmsFactory.java
@@ -6,12 +6,11 @@ import org.dromara.sms4j.api.universal.SupplierConfig;
import org.dromara.sms4j.comm.exception.SmsBlendException;
import org.dromara.sms4j.core.datainterface.SmsReadConfig;
import org.dromara.sms4j.core.load.SmsLoad;
-import org.dromara.sms4j.core.proxy.SmsInvocationHandler;
+import org.dromara.sms4j.core.proxy.SmsProxyFactory;
import org.dromara.sms4j.provider.config.BaseConfig;
import org.dromara.sms4j.provider.factory.BaseProviderFactory;
import org.dromara.sms4j.provider.factory.ProviderFactoryHolder;
-import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -64,7 +63,6 @@ public abstract class SmsFactory {
*/
public static void createSmsBlend(SmsReadConfig smsReadConfig, String configId) {
BaseConfig supplierConfig = smsReadConfig.getSupplierConfig(configId);
- supplierConfig.setConfigId(configId);
SmsBlend smsBlend = create(supplierConfig);
register(smsBlend);
}
@@ -93,9 +91,9 @@ public abstract class SmsFactory {
* @param config 短信配置
* @author :Wind
*/
+ @Deprecated
public static void createRestrictedSmsBlend(SupplierConfig config) {
SmsBlend smsBlend = create(config);
- smsBlend = renderWithRestricted(smsBlend);
register(smsBlend);
}
@@ -109,11 +107,10 @@ public abstract class SmsFactory {
* @param configId 配置ID
* @author :Wind
*/
+ @Deprecated
public static void createRestrictedSmsBlend(SmsReadConfig smsReadConfig, String configId) {
BaseConfig supplierConfig = smsReadConfig.getSupplierConfig(configId);
- supplierConfig.setConfigId(configId);
SmsBlend smsBlend = create(supplierConfig);
- smsBlend = renderWithRestricted(smsBlend);
register(smsBlend);
}
@@ -126,11 +123,11 @@ public abstract class SmsFactory {
* @param smsReadConfig 读取额外配置接口
* @author :Wind
*/
+ @Deprecated
public static void createRestrictedSmsBlend(SmsReadConfig smsReadConfig) {
List supplierConfigList = smsReadConfig.getSupplierConfigList();
supplierConfigList.forEach(supplierConfig -> {
SmsBlend smsBlend = create(supplierConfig);
- smsBlend = renderWithRestricted(smsBlend);
register(smsBlend);
});
}
@@ -140,18 +137,22 @@ public abstract class SmsFactory {
if (factory == null) {
throw new SmsBlendException("不支持当前供应商配置");
}
- return factory.createSms(config);
+ SmsBlend sms = factory.createSms(config);
+ return renderWithProxy(sms);
+
}
+
+
/**
* renderWithRestricted
* 构建smsBlend对象的代理对象
*
* @author :Wind
*/
- private static SmsBlend renderWithRestricted(SmsBlend sms) {
- SmsInvocationHandler smsInvocationHandler = SmsInvocationHandler.newSmsInvocationHandler(sms);
- return (SmsBlend) Proxy.newProxyInstance(sms.getClass().getClassLoader(), new Class[]{SmsBlend.class}, smsInvocationHandler);
+ @Deprecated
+ private static SmsBlend renderWithProxy(SmsBlend sms) {
+ return SmsProxyFactory.getProxySmsBlend(sms);
}
/**
diff --git a/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/EnvirmentHolder.java b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/EnvirmentHolder.java
new file mode 100644
index 00000000..57a19d1d
--- /dev/null
+++ b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/EnvirmentHolder.java
@@ -0,0 +1,34 @@
+package org.dromara.sms4j.core.proxy;
+
+import org.dromara.sms4j.provider.config.SmsConfig;
+
+import java.util.Map;
+
+/**
+ * 环境信息持有
+ *
+ * @author sh1yu
+ * @since 2023/10/27 13:03
+ */
+public class EnvirmentHolder {
+ private static SmsConfig smsConfig = null;
+ private static Map> blends = null;
+
+ public static void frozenEnvirmet(SmsConfig smsConfig, Map> blends) {
+ if (null!=EnvirmentHolder.smsConfig||null!=EnvirmentHolder.blends){
+ return;
+ }
+ EnvirmentHolder.smsConfig = smsConfig;
+ EnvirmentHolder.blends = blends;
+ }
+
+ //只有核心包执行器部分才能获取
+ static SmsConfig getSmsConfig() {
+ return smsConfig;
+ }
+
+ //只有核心包执行器部分才能获取
+ static Map> getBlends() {
+ return blends;
+ }
+}
diff --git a/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/RestrictedProcessDefaultImpl.java b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/RestrictedProcessDefaultImpl.java
deleted file mode 100644
index 46d40ad2..00000000
--- a/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/RestrictedProcessDefaultImpl.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.dromara.sms4j.core.proxy;
-
-import lombok.Setter;
-import lombok.extern.slf4j.Slf4j;
-import org.dromara.sms4j.api.dao.SmsDao;
-import org.dromara.sms4j.api.proxy.RestrictedProcess;
-import org.dromara.sms4j.comm.exception.SmsBlendException;
-import org.dromara.sms4j.comm.utils.SmsUtils;
-import org.dromara.sms4j.provider.config.SmsConfig;
-import org.dromara.sms4j.provider.factory.BeanFactory;
-
-import java.util.Objects;
-
-@Slf4j
-public class RestrictedProcessDefaultImpl implements RestrictedProcess {
- static Long minTimer = 60 * 1000L;
- static Long accTimer = 24 * 60 * 60 * 1000L;
-
- /**
- * 缓存实例
- */
- @Setter
- private SmsDao smsDao;
-
- public SmsBlendException process(String phone) {
- if (Objects.isNull(smsDao)) {
- throw new SmsBlendException("The dao tool could not be found");
- }
- SmsConfig config = BeanFactory.getSmsConfig();
- Integer accountMax = config.getAccountMax(); // 每日最大发送量
- Integer minuteMax = config.getMinuteMax(); // 每分钟最大发送量
- if (SmsUtils.isNotEmpty(accountMax)) { // 是否配置了每日限制
- Integer i = (Integer) smsDao.get(phone + "max");
- if (SmsUtils.isEmpty(i)) {
- smsDao.set(phone + "max", 1, accTimer);
- } else if (i >= accountMax) {
- log.info("The phone:" + phone + ",number of short messages reached the maximum today");
- return new SmsBlendException("The phone:" + phone + ",number of short messages reached the maximum today");
- } else {
- smsDao.set(phone + "max", i + 1, accTimer);
- }
- }
- if (SmsUtils.isNotEmpty(minuteMax)) { // 是否配置了每分钟最大限制
- Integer o = (Integer) smsDao.get(phone);
- if (SmsUtils.isNotEmpty(o)) {
- if (o < minuteMax) {
- smsDao.set(phone, o + 1, minTimer);
- } else {
- log.info("The phone:" + phone + " Text messages are sent too often!");
- return new SmsBlendException("The phone:", phone + " Text messages are sent too often!");
- }
- } else {
- smsDao.set(phone, 1, minTimer);
- }
- }
- return null;
- }
-}
diff --git a/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/SmsInvocationHandler.java b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/SmsInvocationHandler.java
index d22760f2..493d5893 100644
--- a/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/SmsInvocationHandler.java
+++ b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/SmsInvocationHandler.java
@@ -2,45 +2,69 @@ package org.dromara.sms4j.core.proxy;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.api.SmsBlend;
-import org.dromara.sms4j.api.proxy.RestrictedProcess;
-import org.dromara.sms4j.comm.exception.SmsBlendException;
+import org.dromara.sms4j.api.proxy.SmsProcessor;
+import org.dromara.sms4j.api.proxy.SuppotFilter;
import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.util.Objects;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * SmsBlend增强,封装smsblend和执行器
+ *
+ * @author sh1yu
+ * @since 2023/10/27 13:03
+ */
@Slf4j
public class SmsInvocationHandler implements InvocationHandler {
private final SmsBlend smsBlend;
- private static RestrictedProcess restrictedProcess = new RestrictedProcessDefaultImpl();
+ private final LinkedList processors;
- private SmsInvocationHandler(SmsBlend smsBlend) {
+
+ public SmsInvocationHandler(SmsBlend smsBlend, LinkedList processors) {
this.smsBlend = smsBlend;
- }
-
- public static SmsInvocationHandler newSmsInvocationHandler(SmsBlend smsBlend) {
- return new SmsInvocationHandler(smsBlend);
+ this.processors = processors;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
- Object result;
- if ("sendMessage".equals(method.getName()) || "massTexting".equals(method.getName())) {
- //取手机号作为参数
- String phone = (String) objects[0];
- SmsBlendException smsBlendException = restrictedProcess.process(phone);
- if (!Objects.isNull(smsBlendException)) {
- throw smsBlendException;
- }
+ Object result = null;
+ //前置执行器
+ objects = doPreProcess(smsBlend, method, objects);
+ try {
+ result = method.invoke(smsBlend, objects);
+ } catch (Exception e) {
+ //错误执行器
+ doErrorHandleProcess(smsBlend, method, objects,e);
}
- result = method.invoke(smsBlend, objects);
+ //后置执行器
+ doPostrocess(smsBlend, method, objects, result);
return result;
}
- /**
- * 设置 restrictedProcess
- */
- public static void setRestrictedProcess(RestrictedProcess restrictedProcess) {
- SmsInvocationHandler.restrictedProcess = restrictedProcess;
+ public Object[] doPreProcess(Object o, Method method, Object[] objects) {
+ for (SmsProcessor processor : processors) {
+ objects = processor.preProcessor(method, o, objects);
+ }
+ return objects;
+ }
+
+ public void doErrorHandleProcess(Object o, Method method, Object[] objects,Exception e) throws InvocationTargetException, IllegalAccessException {
+ for (SmsProcessor processor : processors) {
+ processor.exceptionHandleProcessor(method, o, objects,e);
+ }
+ }
+
+ public Object doPostrocess(Object o, Method method, Object[] objects, Object result) {
+ for (SmsProcessor processor : processors) {
+ Object overrideResult = processor.postProcessor(result, objects);
+ if (overrideResult != null) {
+ return overrideResult;
+ }
+ }
+ return result;
}
}
diff --git a/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/SmsProxyFactory.java b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/SmsProxyFactory.java
new file mode 100644
index 00000000..5da1a4ba
--- /dev/null
+++ b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/SmsProxyFactory.java
@@ -0,0 +1,108 @@
+package org.dromara.sms4j.core.proxy;
+
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.sms4j.api.SmsBlend;
+import org.dromara.sms4j.api.dao.SmsDao;
+import org.dromara.sms4j.api.dao.SmsDaoDefaultImpl;
+import org.dromara.sms4j.api.proxy.Order;
+import org.dromara.sms4j.api.proxy.SmsProcessor;
+import org.dromara.sms4j.api.proxy.SuppotFilter;
+import org.dromara.sms4j.api.proxy.aware.SmsBlendConfigAware;
+import org.dromara.sms4j.api.proxy.aware.SmsDaoAware;
+import org.dromara.sms4j.api.proxy.aware.SmsConfigAware;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * SmsBlend代理工厂
+ *
+ * @author sh1yu
+ * @since 2023/10/27 13:03
+ */
+@Slf4j
+public abstract class SmsProxyFactory {
+ private static final LinkedList processors = new LinkedList<>();
+
+ public static SmsBlend getProxySmsBlend(SmsBlend smsBlend) {
+ LinkedList ownerProcessors = processors.stream().filter(processor -> !shouldSkipProcess(processor,smsBlend)).collect(Collectors.toCollection(LinkedList::new));
+ return (SmsBlend) Proxy.newProxyInstance(smsBlend.getClass().getClassLoader(), new Class[]{SmsBlend.class}, new SmsInvocationHandler(smsBlend, ownerProcessors));
+ }
+
+ /**
+ * 增加拦截器
+ */
+ public static void addProcessor(SmsProcessor processor) {
+ //校验拦截器是否正确
+ processorValidate(processor);
+ awareTransfer(processor);
+ processors.add(processor);
+ processors.sort(Comparator.comparingInt(Order::getOrder));
+ }
+
+ /*
+ * @see SuppotFilter
+ */
+ public static boolean shouldSkipProcess(SmsProcessor processor, SmsBlend smsBlend) {
+ //判断当前的执行器有没有开厂商过滤,支不支持当前厂商
+ if (processor instanceof SuppotFilter) {
+ List supports = ((SuppotFilter) processor).getSupports();
+ boolean exsit = supports.stream().filter(support -> support.equals(smsBlend.getSupplier())).findAny().isPresent();
+ if (!exsit) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ //所有处理器需要的各个参数可以通过这种aware接口形式传给对象
+ private static void awareTransfer(SmsProcessor processor) {
+ if (processor instanceof SmsDaoAware){
+ ((SmsDaoAware) processor).setSmsDao(getSmsDaoFromFramework());
+ }
+ if (processor instanceof SmsConfigAware){
+ ((SmsConfigAware) processor).setSmsConfig(EnvirmentHolder.getSmsConfig());
+ }
+ if (processor instanceof SmsBlendConfigAware){
+ ((SmsBlendConfigAware) processor).setSmsBlendsConfig(EnvirmentHolder.getBlends());
+ }
+ }
+
+ //校验拦截器是否正确
+ private static void processorValidate(SmsProcessor processor) {
+
+ }
+
+ //获取Sms的实现
+ private static SmsDao getSmsDaoFromFramework() {
+ SmsDao smsDao;
+ smsDao = getSmsDaoFromFramework("org.dromara.sms4j.starter.holder.SpringSmsDaoHolder", "SpringBoot");
+ if (null != smsDao) {
+ return smsDao;
+ }
+ smsDao = getSmsDaoFromFramework("org.dromara.sms4j.solon.holder.SolonSmsDaoHolder", "Solon");
+ if (null != smsDao) {
+ return smsDao;
+ }
+ log.error("尝试框架加载失败,最终使用默认SmsDao!");
+ return SmsDaoDefaultImpl.getInstance();
+ }
+
+ //获取Sms的实现
+ private static SmsDao getSmsDaoFromFramework(String className, String frameworkName) {
+ try {
+ Class> clazz = Class.forName(className);
+ Method getSmsDao = clazz.getMethod("getSmsDao", null);
+ return (SmsDao) getSmsDao.invoke(null, null);
+ } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+ log.error("{}:加载SmsDao失败,尝试其他框架加载......", frameworkName);
+ }
+ return null;
+ }
+
+}
diff --git a/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/processor/BlackListProcessor.java b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/processor/BlackListProcessor.java
new file mode 100644
index 00000000..b349704a
--- /dev/null
+++ b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/processor/BlackListProcessor.java
@@ -0,0 +1,58 @@
+package org.dromara.sms4j.core.proxy.processor;
+
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.sms4j.api.dao.SmsDao;
+import org.dromara.sms4j.api.proxy.CoreMethodProcessor;
+import org.dromara.sms4j.api.proxy.aware.SmsConfigAware;
+import org.dromara.sms4j.api.proxy.aware.SmsDaoAware;
+import org.dromara.sms4j.comm.exception.SmsBlendException;
+import org.dromara.sms4j.provider.config.SmsConfig;
+
+import java.util.*;
+
+/**
+ * 黑名单前置拦截执行器
+ *
+ * @author sh1yu
+ * @since 2023/10/27 13:03
+ */
+@Slf4j
+public class BlackListProcessor implements CoreMethodProcessor, SmsDaoAware {
+ @Setter
+ SmsDao smsDao;
+
+ @Override
+ public int getOrder() {
+ return 0;
+ }
+
+ @Override
+ public void sendMessagePreProcess(String phone, String message) {
+ doRestricted(Collections.singletonList(phone));
+ }
+
+ @Override
+ public void sendMessageByTemplatePreProcess(String phone, String templateId, LinkedHashMap messages) {
+ doRestricted(Collections.singletonList(phone));
+ }
+
+ @Override
+ public void massTextingPreProcess(List phones, String message) {
+ doRestricted(phones);
+ }
+
+ @Override
+ public void massTextingByTemplatePreProcess(List phones, String templateId, LinkedHashMap messages) {
+ doRestricted(phones);
+ }
+
+ public void doRestricted(List phones) {
+ ArrayList blackList = (ArrayList) smsDao.get("sms:blacklist:global");
+ for (String phone : phones) {
+ if (blackList.stream().filter(black -> black.replace("-","").equals(phone)).findAny().isPresent()) {
+ throw new SmsBlendException("The phone:", phone + " hit global blacklist!");
+ }
+ }
+ }
+}
diff --git a/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/processor/BlackListRecordingProcessor.java b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/processor/BlackListRecordingProcessor.java
new file mode 100644
index 00000000..eb2a60c6
--- /dev/null
+++ b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/processor/BlackListRecordingProcessor.java
@@ -0,0 +1,84 @@
+package org.dromara.sms4j.core.proxy.processor;
+
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.sms4j.api.dao.SmsDao;
+import org.dromara.sms4j.api.proxy.SmsProcessor;
+import org.dromara.sms4j.api.proxy.aware.SmsConfigAware;
+import org.dromara.sms4j.api.proxy.aware.SmsDaoAware;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 黑名单前置拦截执行器
+ *
+ * @author sh1yu
+ * @since 2023/10/27 13:03
+ */
+@Slf4j
+public class BlackListRecordingProcessor implements SmsProcessor, SmsDaoAware, SmsConfigAware {
+ @Setter
+ SmsDao smsDao;
+
+ @Setter
+ Object smsConfig;
+
+
+ @Override
+ public Object[] preProcessor(Method method, Object source, Object[] param) {
+ //添加到黑名单
+ if (method.getName().equals("joinInBlacklist")) {
+ String cacheKey = getCacheKey();
+ ArrayList blackList = getBlackList(cacheKey);
+ blackList.add((String) param[0]);
+ flushBlackList(cacheKey,blackList);
+ }
+ //从黑名单移除
+ if (method.getName().equals("removeFromBlacklist")) {
+ String cacheKey = getCacheKey();
+ ArrayList blackList = getBlackList(cacheKey);
+ blackList.remove((String) param[0]);
+ flushBlackList(cacheKey,blackList);
+ }
+ //批量添加到黑名单
+ if (method.getName().equals("batchJoinBlacklist")) {
+ String cacheKey = getCacheKey();
+ ArrayList blackList = getBlackList(cacheKey);
+ blackList.addAll((List) param[0]);
+ flushBlackList(cacheKey,blackList);
+ }
+ //批量从黑名单移除
+ if (method.getName().equals("batchRemovalFromBlacklist")) {
+ String cacheKey = getCacheKey();
+ ArrayList blackList = getBlackList(cacheKey);
+ blackList.removeAll((List) param[0]);
+ flushBlackList(cacheKey,blackList);
+ }
+ return param;
+ }
+
+ //构建cachekey
+ public String getCacheKey(){
+ return "sms:blacklist:global";
+ }
+
+ //获取黑名单,没有就新建
+ public ArrayList getBlackList(String cacheKey) {
+ ArrayList blackList;
+ Object cache = smsDao.get(cacheKey);
+ if (null != cache) {
+ blackList = (ArrayList) cache;
+ return blackList;
+ }
+ blackList = new ArrayList<>();
+ smsDao.set("sms:blacklist:global", blackList);
+ return blackList;
+ }
+
+ //让黑名单生效
+ public void flushBlackList(String cacheKey ,ArrayList blackList) {
+ smsDao.set(cacheKey, blackList);
+ }
+}
diff --git a/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/processor/CoreMethodParamValidateProcessor.java b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/processor/CoreMethodParamValidateProcessor.java
new file mode 100644
index 00000000..c15abcd1
--- /dev/null
+++ b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/processor/CoreMethodParamValidateProcessor.java
@@ -0,0 +1,76 @@
+package org.dromara.sms4j.core.proxy.processor;
+
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.sms4j.api.proxy.CoreMethodProcessor;
+import org.dromara.sms4j.comm.exception.SmsBlendException;
+
+import java.util.*;
+
+
+/**
+ * 核心方法参数校验前置拦截执行器
+ *
+ * @author sh1yu
+ * @since 2023/10/27 13:03
+ */
+@Slf4j
+public class CoreMethodParamValidateProcessor implements CoreMethodProcessor {
+ @Override
+ public int getOrder() {
+ return -1;
+ }
+
+ @Override
+ public void sendMessagePreProcess(String phone, String message) {
+ validatePhone(phone);
+ validateMessage(message);
+ }
+
+ @Override
+ public void sendMessageByTemplatePreProcess(String phone, String templateId, LinkedHashMap messages) {
+ validatePhone(phone);
+ validateMessages(templateId, messages);
+ }
+
+ @Override
+ public void massTextingPreProcess(List phones, String message) {
+ validateMessage(message);
+ validatePhones(phones);
+ }
+
+ @Override
+ public void massTextingByTemplatePreProcess(List phones, String templateId, LinkedHashMap messages) {
+ validatePhones(phones);
+ validateMessages(templateId, messages);
+ }
+
+ public void validateMessage(String message) {
+ if (null == message || "".equals(message)) {
+ throw new SmsBlendException("cant send a null message!");
+ }
+ }
+
+ public void validatePhone(String phone) {
+ if (null == phone || "".equals(phone)) {
+ throw new SmsBlendException("cant send message to null!");
+ }
+ }
+
+ public void validatePhones(List phones) {
+ if (null == phones) {
+ throw new SmsBlendException("cant send message to null!");
+ }
+ for (String phone : phones) {
+ if (null != phone && !"".equals(phone)) {
+ return;
+ }
+ }
+ throw new SmsBlendException("cant send message to null!");
+ }
+
+ public void validateMessages(String templateId, LinkedHashMap messages) {
+ if (null != templateId && !"".equals(templateId) && (messages == null || messages.size() < 1)) {
+ throw new SmsBlendException("cant use template without template param");
+ }
+ }
+}
diff --git a/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/processor/RestrictedProcessor.java b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/processor/RestrictedProcessor.java
new file mode 100644
index 00000000..609b7194
--- /dev/null
+++ b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/processor/RestrictedProcessor.java
@@ -0,0 +1,96 @@
+package org.dromara.sms4j.core.proxy.processor;
+
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.sms4j.api.dao.SmsDao;
+import org.dromara.sms4j.api.proxy.CoreMethodProcessor;
+import org.dromara.sms4j.api.proxy.aware.SmsDaoAware;
+import org.dromara.sms4j.comm.exception.SmsBlendException;
+import org.dromara.sms4j.comm.utils.SmsUtils;
+import org.dromara.sms4j.provider.config.SmsConfig;
+import org.dromara.sms4j.provider.factory.BeanFactory;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Objects;
+
+
+/**
+ * 短信发送账号级上限前置拦截执行器
+ *
+ * @author sh1yu
+ * @since 2023/10/27 13:03
+ */
+@Slf4j
+public class RestrictedProcessor implements CoreMethodProcessor, SmsDaoAware {
+ static Long minTimer = 60 * 1000L;
+ static Long accTimer = 24 * 60 * 60 * 1000L;
+ private static final String REDIS_KEY = "sms:restricted:";
+
+ /**
+ * 缓存实例
+ */
+ @Setter
+ private SmsDao smsDao;
+
+ @Override
+ public int getOrder() {
+ return 3;
+ }
+
+ @Override
+ public void sendMessagePreProcess(String phone, String message) {
+ doRestricted(Collections.singletonList(phone));
+ }
+
+ @Override
+ public void sendMessageByTemplatePreProcess(String phone, String templateId, LinkedHashMap messages) {
+ doRestricted(Collections.singletonList(phone));
+ }
+
+ @Override
+ public void massTextingPreProcess(List phones, String message) {
+ doRestricted(phones);
+ }
+
+ @Override
+ public void massTextingByTemplatePreProcess(List phones, String templateId, LinkedHashMap messages) {
+ doRestricted(phones);
+ }
+
+ public void doRestricted(List phones) {
+ if (Objects.isNull(smsDao)) {
+ throw new SmsBlendException("The dao tool could not be found");
+ }
+ SmsConfig config = BeanFactory.getSmsConfig();
+ Integer accountMax = config.getAccountMax(); // 每日最大发送量
+ Integer minuteMax = config.getMinuteMax(); // 每分钟最大发送量
+ for (String phone : phones) {
+ if (SmsUtils.isNotEmpty(accountMax)) { // 是否配置了每日限制
+ Integer i = (Integer) smsDao.get(REDIS_KEY + phone + "max");
+ if (SmsUtils.isEmpty(i)) {
+ smsDao.set(REDIS_KEY + phone + "max", 1, accTimer / 1000);
+ } else if (i >= accountMax) {
+ log.info("The phone:" + phone + ",number of short messages reached the maximum today");
+ throw new SmsBlendException("The phone:" + phone + ",number of short messages reached the maximum today");
+ } else {
+ smsDao.set(REDIS_KEY + phone + "max", i + 1, accTimer / 1000);
+ }
+ }
+ if (SmsUtils.isNotEmpty(minuteMax)) { // 是否配置了每分钟最大限制
+ Integer o = (Integer) smsDao.get(REDIS_KEY + phone);
+ if (SmsUtils.isNotEmpty(o)) {
+ if (o < minuteMax) {
+ smsDao.set(REDIS_KEY + phone, o + 1, minTimer / 1000);
+ } else {
+ log.info("The phone:" + phone + ",number of short messages reached the maximum today");
+ throw new SmsBlendException("The phone:", phone + " Text messages are sent too often!");
+ }
+ } else {
+ smsDao.set(REDIS_KEY + phone, 1, minTimer / 1000);
+ }
+ }
+ }
+ }
+}
diff --git a/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/processor/SingleBlendRestrictedProcessor.java b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/processor/SingleBlendRestrictedProcessor.java
new file mode 100644
index 00000000..3e93ecab
--- /dev/null
+++ b/sms4j-core/src/main/java/org/dromara/sms4j/core/proxy/processor/SingleBlendRestrictedProcessor.java
@@ -0,0 +1,66 @@
+package org.dromara.sms4j.core.proxy.processor;
+
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.sms4j.api.SmsBlend;
+import org.dromara.sms4j.api.dao.SmsDao;
+import org.dromara.sms4j.api.proxy.CoreMethodProcessor;
+import org.dromara.sms4j.api.proxy.SmsProcessor;
+import org.dromara.sms4j.api.proxy.aware.SmsBlendConfigAware;
+import org.dromara.sms4j.api.proxy.aware.SmsDaoAware;
+import org.dromara.sms4j.comm.exception.SmsBlendException;
+import org.dromara.sms4j.comm.utils.SmsUtils;
+import org.dromara.sms4j.provider.config.BaseConfig;
+import org.dromara.sms4j.provider.service.AbstractSmsBlend;
+
+import java.lang.reflect.Method;
+import java.util.*;
+
+
+/**
+ * 短信发送渠道级上限前置拦截执行器
+ *
+ * @author sh1yu
+ * @since 2023/10/27 13:03
+ */
+@Slf4j
+public class SingleBlendRestrictedProcessor implements SmsProcessor, SmsDaoAware, SmsBlendConfigAware {
+
+ private static final String REDIS_KEY = "sms:restricted:";
+
+ /**
+ * 缓存实例
+ */
+ @Setter
+ private SmsDao smsDao;
+
+ @Setter
+ Map smsBlendsConfig;
+
+ @Override
+ public int getOrder() {
+ return 2;
+ }
+
+ @Override
+ public Object[] preProcessor(Method method, Object source, Object[] param) {
+ String name = method.getName();
+ if (!"sendMessage".equals(name) && !"massText".equals(name)) {
+ return param;
+ }
+ SmsBlend smsBlend = (SmsBlend) source;
+ String configId = smsBlend.getConfigId();
+ Map targetConfig = (Map) smsBlendsConfig.get(configId);
+ int maximum = (int) targetConfig.get("maximum");
+ Integer i = (Integer) smsDao.get(REDIS_KEY + configId + "maximum");
+ if (SmsUtils.isEmpty(i)) {
+ smsDao.set(REDIS_KEY + configId + "maximum", 1);
+ } else if (i >= maximum) {
+ log.info("The channel:" + configId + ",messages reached the maximum");
+ throw new SmsBlendException("The channel:" + configId + ",messages reached the maximum");
+ } else {
+ smsDao.set(REDIS_KEY + configId + "maximum", i + 1);
+ }
+ return param;
+ }
+}
diff --git a/sms4j-javase-plugin/src/main/java/org/dromara/sms4j/javase/config/SEInitializer.java b/sms4j-javase-plugin/src/main/java/org/dromara/sms4j/javase/config/SEInitializer.java
index 49f8f101..c8409f50 100644
--- a/sms4j-javase-plugin/src/main/java/org/dromara/sms4j/javase/config/SEInitializer.java
+++ b/sms4j-javase-plugin/src/main/java/org/dromara/sms4j/javase/config/SEInitializer.java
@@ -19,9 +19,10 @@ import org.dromara.sms4j.cloopen.config.CloopenFactory;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.exception.SmsBlendException;
import org.dromara.sms4j.comm.utils.SmsUtils;
+import org.dromara.sms4j.core.proxy.EnvirmentHolder;
import org.dromara.sms4j.core.factory.SmsFactory;
-import org.dromara.sms4j.core.proxy.RestrictedProcessDefaultImpl;
-import org.dromara.sms4j.core.proxy.SmsInvocationHandler;
+import org.dromara.sms4j.core.proxy.processor.*;
+import org.dromara.sms4j.core.proxy.SmsProxyFactory;
import org.dromara.sms4j.ctyun.config.CtyunFactory;
import org.dromara.sms4j.emay.config.EmayFactory;
import org.dromara.sms4j.huawei.config.HuaweiFactory;
@@ -86,7 +87,7 @@ public class SEInitializer {
/**
* 从配置bean对象中加载配置
*
- * @param smsConfig 短信公共配置
+ * @param smsConfig 短信公共配置
* @param configList 各短信服务商配置列表
*/
public void fromConfig(SmsConfig smsConfig, List configList) {
@@ -95,20 +96,17 @@ public class SEInitializer {
// 初始化SmsConfig整体配置文件
BeanUtil.copyProperties(smsConfig, BeanFactory.getSmsConfig());
// 创建短信服务对象
- if(CollUtil.isEmpty(configList)) {
- return ;
+ if (CollUtil.isEmpty(configList)) {
+ return;
}
- for(SupplierConfig supplierConfig : configList) {
- if(Boolean.TRUE.equals(smsConfig.getRestricted())) {
- SmsFactory.createRestrictedSmsBlend(supplierConfig);
- } else {
- SmsFactory.createSmsBlend(supplierConfig);
- }
+ for (SupplierConfig supplierConfig : configList) {
+ SmsFactory.createSmsBlend(supplierConfig);
}
}
/**
* 注册服务商工厂
+ *
* @param factory 服务商工厂
*/
public SEInitializer registerFactory(BaseProviderFactory extends SmsBlend, ? extends SupplierConfig> factory) {
@@ -118,15 +116,13 @@ public class SEInitializer {
/**
* 注册DAO实例
+ *
* @param smsDao DAO实例
*/
public SEInitializer registerSmsDao(SmsDao smsDao) {
- if(smsDao == null) {
+ if (smsDao == null) {
throw new SmsBlendException("注册DAO实例失败,实例不能为空");
}
- RestrictedProcessDefaultImpl process = new RestrictedProcessDefaultImpl();
- process.setSmsDao(smsDao);
- SmsInvocationHandler.setRestrictedProcess(process);
this.smsDao = smsDao;
return this;
}
@@ -143,7 +139,7 @@ public class SEInitializer {
}
//注册默认DAO实例
- if(this.smsDao == null) {
+ if (this.smsDao == null) {
this.registerSmsDao(SmsDaoDefaultImpl.getInstance());
}
@@ -152,15 +148,26 @@ public class SEInitializer {
//初始化SmsConfig整体配置文件
BeanUtil.copyProperties(smsConfig, BeanFactory.getSmsConfig());
+
// 解析服务商配置
Map> blends = smsConfig.getBlends();
- for(String configId : blends.keySet()) {
+
+ //持有初始化配置信息
+ EnvirmentHolder.frozenEnvirmet(smsConfig, blends);
+
+ //注册执行器实现
+ SmsProxyFactory.addProcessor(new RestrictedProcessor());
+ SmsProxyFactory.addProcessor(new BlackListProcessor());
+ SmsProxyFactory.addProcessor(new BlackListRecordingProcessor());
+ SmsProxyFactory.addProcessor(new SingleBlendRestrictedProcessor());
+ SmsProxyFactory.addProcessor(new CoreMethodParamValidateProcessor());
+ for (String configId : blends.keySet()) {
Map configMap = blends.get(configId);
Object supplierObj = configMap.get(Constant.SUPPLIER_KEY);
String supplier = supplierObj == null ? "" : String.valueOf(supplierObj);
supplier = StrUtil.isEmpty(supplier) ? configId : supplier;
BaseProviderFactory providerFactory = (BaseProviderFactory) ProviderFactoryHolder.requireForSupplier(supplier);
- if(providerFactory == null) {
+ if (providerFactory == null) {
log.warn("创建\"{}\"的短信服务失败,未找到服务商为\"{}\"的服务", configId, supplier);
continue;
}
@@ -168,11 +175,7 @@ public class SEInitializer {
SmsUtils.replaceKeysSeperator(configMap, "-", "_");
JSONObject configJson = new JSONObject(configMap);
SupplierConfig supplierConfig = JSONUtil.toBean(configJson, providerFactory.getConfigClass());
- if(Boolean.TRUE.equals(smsConfig.getRestricted())) {
- SmsFactory.createRestrictedSmsBlend(supplierConfig);
- } else {
- SmsFactory.createSmsBlend(supplierConfig);
- }
+ SmsFactory.createSmsBlend(supplierConfig);
}
}
@@ -191,7 +194,7 @@ public class SEInitializer {
ProviderFactoryHolder.registerFactory(YunPianFactory.instance());
ProviderFactoryHolder.registerFactory(ZhutongFactory.instance());
ProviderFactoryHolder.registerFactory(LianLuFactory.instance());
- if(SmsUtils.isClassExists("com.jdcloud.sdk.auth.CredentialsProvider")) {
+ if (SmsUtils.isClassExists("com.jdcloud.sdk.auth.CredentialsProvider")) {
ProviderFactoryHolder.registerFactory(JdCloudFactory.instance());
}
}
diff --git a/sms4j-provider/src/main/java/org/dromara/sms4j/provider/config/BaseConfig.java b/sms4j-provider/src/main/java/org/dromara/sms4j/provider/config/BaseConfig.java
index c7e4721d..4ca77b64 100644
--- a/sms4j-provider/src/main/java/org/dromara/sms4j/provider/config/BaseConfig.java
+++ b/sms4j-provider/src/main/java/org/dromara/sms4j/provider/config/BaseConfig.java
@@ -78,4 +78,9 @@ public abstract class BaseConfig implements SupplierConfig {
}
this.maxRetries = maxRetries;
}
+
+ /**
+ * 最大发送数量,默认integer上限
+ */
+ private int maximum = Integer.MAX_VALUE;
}
diff --git a/sms4j-provider/src/main/java/org/dromara/sms4j/provider/config/SmsConfig.java b/sms4j-provider/src/main/java/org/dromara/sms4j/provider/config/SmsConfig.java
index 7c3d05c0..d20b8171 100644
--- a/sms4j-provider/src/main/java/org/dromara/sms4j/provider/config/SmsConfig.java
+++ b/sms4j-provider/src/main/java/org/dromara/sms4j/provider/config/SmsConfig.java
@@ -4,6 +4,8 @@ package org.dromara.sms4j.provider.config;
import lombok.Data;
import org.dromara.sms4j.comm.enumerate.ConfigType;
+import java.util.ArrayList;
+
@Data
public class SmsConfig {
@@ -53,4 +55,9 @@ public class SmsConfig {
/** 是否打印http log*/
private Boolean HttpLog = false;
+ /**
+ * 黑名单配置
+ */
+ private ArrayList blackList = new ArrayList<>();
+
}
diff --git a/sms4j-solon-plugin/src/main/java/org/dromara/sms4j/solon/aop/SolonRestrictedProcess.java b/sms4j-solon-plugin/src/main/java/org/dromara/sms4j/solon/aop/SolonRestrictedProcess.java
deleted file mode 100644
index 29aca011..00000000
--- a/sms4j-solon-plugin/src/main/java/org/dromara/sms4j/solon/aop/SolonRestrictedProcess.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package org.dromara.sms4j.solon.aop;
-
-import lombok.extern.slf4j.Slf4j;
-import org.dromara.sms4j.api.dao.SmsDao;
-import org.dromara.sms4j.api.dao.SmsDaoDefaultImpl;
-import org.dromara.sms4j.api.proxy.RestrictedProcess;
-import org.dromara.sms4j.comm.exception.SmsBlendException;
-import org.dromara.sms4j.comm.utils.SmsUtils;
-import org.dromara.sms4j.provider.config.SmsConfig;
-import org.dromara.sms4j.provider.factory.BeanFactory;
-import org.noear.solon.core.AppContext;
-
-@Slf4j
-public class SolonRestrictedProcess implements RestrictedProcess {
-
- private static final Long minTimer = 60 * 1000L;
- private static final Long accTimer = 24 * 60 * 60 * 1000L;
- private static final String REDIS_KEY = "sms:restricted:";
- private SmsDao smsDao;
-
- public SolonRestrictedProcess(AppContext context) {
- context.getBeanAsync(SmsDao.class, bean -> smsDao = bean);
- }
-
- @Override
- public SmsBlendException process(String phone) {
- if (SmsUtils.isEmpty(smsDao)){
- smsDao = SmsDaoDefaultImpl.getInstance();
- }
- SmsConfig config = BeanFactory.getSmsConfig();
- Integer accountMax = config.getAccountMax(); // 每日最大发送量
- Integer minuteMax = config.getMinuteMax(); // 每分钟最大发送量
-
- if (SmsUtils.isNotEmpty(accountMax)) { // 是否配置了每日限制
- Integer i = (Integer) smsDao.get(REDIS_KEY + phone + "max");
- if (SmsUtils.isEmpty(i)) {
- smsDao.set(REDIS_KEY + phone + "max", 1, accTimer / 1000);
- } else if (i >= accountMax) {
- log.info("The phone:" + phone + ",number of short messages reached the maximum today");
- return new SmsBlendException("The phone:" + phone + ",number of short messages reached the maximum today");
- } else {
- smsDao.set(REDIS_KEY + phone + "max", i + 1, accTimer / 1000);
- }
- }
- if (SmsUtils.isNotEmpty(minuteMax)) { // 是否配置了每分钟最大限制
- Integer o = (Integer) smsDao.get(REDIS_KEY + phone);
- if (SmsUtils.isNotEmpty(o)) {
- if (o < minuteMax) {
- smsDao.set(REDIS_KEY + phone, o + 1, minTimer / 1000);
- } else {
- log.info("The phone:" + phone + ",number of short messages reached the maximum today");
- return new SmsBlendException("The phone:", phone + " Text messages are sent too often!");
- }
- } else {
- smsDao.set(REDIS_KEY + phone, 1, minTimer / 1000);
- }
- }
-
- return null;
- }
-}
diff --git a/sms4j-solon-plugin/src/main/java/org/dromara/sms4j/solon/config/SmsBlendsInitializer.java b/sms4j-solon-plugin/src/main/java/org/dromara/sms4j/solon/config/SmsBlendsInitializer.java
index 8224ce15..da47f9af 100644
--- a/sms4j-solon-plugin/src/main/java/org/dromara/sms4j/solon/config/SmsBlendsInitializer.java
+++ b/sms4j-solon-plugin/src/main/java/org/dromara/sms4j/solon/config/SmsBlendsInitializer.java
@@ -10,8 +10,10 @@ import org.dromara.sms4j.api.universal.SupplierConfig;
import org.dromara.sms4j.cloopen.config.CloopenFactory;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.utils.SmsUtils;
+import org.dromara.sms4j.core.proxy.EnvirmentHolder;
import org.dromara.sms4j.core.factory.SmsFactory;
-import org.dromara.sms4j.core.proxy.SmsInvocationHandler;
+import org.dromara.sms4j.core.proxy.processor.*;
+import org.dromara.sms4j.core.proxy.SmsProxyFactory;
import org.dromara.sms4j.ctyun.config.CtyunFactory;
import org.dromara.sms4j.emay.config.EmayFactory;
import org.dromara.sms4j.huawei.config.HuaweiFactory;
@@ -21,7 +23,7 @@ import org.dromara.sms4j.netease.config.NeteaseFactory;
import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BaseProviderFactory;
import org.dromara.sms4j.provider.factory.ProviderFactoryHolder;
-import org.dromara.sms4j.solon.aop.SolonRestrictedProcess;
+import org.dromara.sms4j.solon.holder.SolonSmsDaoHolder;
import org.dromara.sms4j.tencent.config.TencentFactory;
import org.dromara.sms4j.unisms.config.UniFactory;
import org.dromara.sms4j.yunpian.config.YunPianFactory;
@@ -56,6 +58,16 @@ public class SmsBlendsInitializer {
this.registerDefaultFactory();
// 注册短信对象工厂
ProviderFactoryHolder.registerFactory(factoryList);
+ //持有初始化配置信息
+ EnvirmentHolder.frozenEnvirmet(smsConfig, blends);
+ //框架依赖持有缓存扩展
+ new SolonSmsDaoHolder(context);
+ //注册执行器实现
+ SmsProxyFactory.addProcessor(new RestrictedProcessor());
+ SmsProxyFactory.addProcessor(new BlackListProcessor());
+ SmsProxyFactory.addProcessor(new BlackListRecordingProcessor());
+ SmsProxyFactory.addProcessor(new SingleBlendRestrictedProcessor());
+ SmsProxyFactory.addProcessor(new CoreMethodParamValidateProcessor());
// 解析供应商配置
for(String configId : blends.keySet()) {
Map configMap = blends.get(configId);
@@ -71,15 +83,9 @@ public class SmsBlendsInitializer {
SmsUtils.replaceKeysSeperator(configMap, "-", "_");
JSONObject configJson = new JSONObject(configMap);
SupplierConfig supplierConfig = JSONUtil.toBean(configJson, providerFactory.getConfigClass());
- if(Boolean.TRUE.equals(smsConfig.getRestricted())) {
- SmsFactory.createRestrictedSmsBlend(supplierConfig);
- } else {
- SmsFactory.createSmsBlend(supplierConfig);
- }
+ SmsFactory.createSmsBlend(supplierConfig);
}
- //注册短信拦截实现
- SmsInvocationHandler.setRestrictedProcess(new SolonRestrictedProcess(context));
}
/**
diff --git a/sms4j-solon-plugin/src/main/java/org/dromara/sms4j/solon/holder/SolonSmsDaoHolder.java b/sms4j-solon-plugin/src/main/java/org/dromara/sms4j/solon/holder/SolonSmsDaoHolder.java
new file mode 100644
index 00000000..cef3c875
--- /dev/null
+++ b/sms4j-solon-plugin/src/main/java/org/dromara/sms4j/solon/holder/SolonSmsDaoHolder.java
@@ -0,0 +1,22 @@
+package org.dromara.sms4j.solon.holder;
+
+import org.dromara.sms4j.api.dao.SmsDao;
+import org.dromara.sms4j.api.dao.SmsDaoDefaultImpl;
+import org.dromara.sms4j.comm.utils.SmsUtils;
+import org.noear.solon.core.AppContext;
+
+public class SolonSmsDaoHolder{
+
+ private static SmsDao smsDao;
+
+ public SolonSmsDaoHolder(AppContext context) {
+ context.getBeanAsync(SmsDao.class, bean -> smsDao = bean);
+ }
+
+ public static SmsDao getSmsDao() {
+ if (SmsUtils.isEmpty(smsDao)){
+ smsDao = SmsDaoDefaultImpl.getInstance();
+ }
+ return smsDao;
+ }
+}
diff --git a/sms4j-spring-boot-example/src/main/resources/application.yml b/sms4j-spring-boot-example/src/main/resources/application.yml
index b9aecd22..6e4e119b 100644
--- a/sms4j-spring-boot-example/src/main/resources/application.yml
+++ b/sms4j-spring-boot-example/src/main/resources/application.yml
@@ -1,6 +1,8 @@
sms:
# 标注从yml读取配置
config-type: yaml
+ # 账户上限
+ account-max: 1
blends:
# 阿里短信例子
ali:
@@ -60,6 +62,8 @@ sms:
template-id: pub_verif_short
# 模版名称
templateName: code
+ # 渠道上限
+ maximum: 2
lianlu:
supplier: lianlu
templateId: 模板id
diff --git a/sms4j-spring-boot-example/src/test/java/org/dromara/sms4j/example/SmsProcessorTest.java b/sms4j-spring-boot-example/src/test/java/org/dromara/sms4j/example/SmsProcessorTest.java
new file mode 100644
index 00000000..ce7a8a02
--- /dev/null
+++ b/sms4j-spring-boot-example/src/test/java/org/dromara/sms4j/example/SmsProcessorTest.java
@@ -0,0 +1,138 @@
+package org.dromara.sms4j.example;
+
+import cn.hutool.core.lang.Assert;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.sms4j.api.SmsBlend;
+import org.dromara.sms4j.api.entity.SmsResponse;
+import org.dromara.sms4j.comm.constant.SupplierConstant;
+import org.dromara.sms4j.comm.exception.SmsBlendException;
+import org.dromara.sms4j.comm.utils.SmsUtils;
+import org.dromara.sms4j.core.factory.SmsFactory;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+
+/**
+ * @author sh1yu
+ */
+@Slf4j
+@SpringBootTest
+public class SmsProcessorTest {
+ /**
+ * 填测试手机号
+ */
+ private static final String PHONE = "13899998888";
+
+ //参数校验测试
+ @Test
+ public void testParamValidate() {
+ SmsBlendException knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.ALIBABA).sendMessage("", SmsUtils.getRandomInt(6));
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ }
+ Assert.notNull(knowEx);
+ knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.ALIBABA).sendMessage(PHONE, "");
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ }
+ Assert.notNull(knowEx);
+ knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.ALIBABA).sendMessage(PHONE, "111", new LinkedHashMap<>());
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ }
+ Assert.notNull(knowEx);
+ knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.ALIBABA).massTexting(Collections.singletonList(PHONE), "");
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ }
+ Assert.notNull(knowEx);
+ knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.ALIBABA).massTexting(Collections.singletonList(PHONE), "2222", new LinkedHashMap<>());
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ }
+ Assert.notNull(knowEx);
+ knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.ALIBABA).massTexting(new ArrayList(), "321321");
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ }
+ Assert.notNull(knowEx);
+ }
+
+ //黑名单测试 黑名单手机号13899998888
+ @Test
+ public void testBlackList() {
+ SmsBlend smsBlend = SmsFactory.getBySupplier(SupplierConstant.UNISMS);
+ //单黑名单添加
+ smsBlend.joinInBlacklist(PHONE);
+ SmsBlendException knowEx = null;
+ try {
+ smsBlend.sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ }
+ Assert.notNull(knowEx);
+ //单黑名单移除
+ smsBlend.removeFromBlacklist(PHONE);
+ SmsResponse smsResponse = smsBlend.sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ Assert.isTrue(smsResponse.isSuccess());
+ //批量黑名单添加
+ smsBlend.batchJoinBlacklist(Collections.singletonList(PHONE));
+ knowEx = null;
+ try {
+ smsBlend.sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ }
+ Assert.notNull(knowEx);
+ //批量黑名单添加
+ smsBlend.removeFromBlacklist(PHONE);
+ smsResponse = smsBlend.sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ Assert.isTrue(smsResponse.isSuccess());
+
+ }
+
+ //账号级上限测试、需成功发送一笔,特殊配置
+ @Test
+ public void testAcctLimt() {
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.UNISMS).sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ Assert.isTrue(smsResponse.isSuccess());
+ SmsBlendException knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.UNISMS).sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ }
+ Assert.notNull(knowEx);
+ }
+
+ //账号级上限测试、需成功发送一笔,特殊配置
+ @Test
+ public void testChannelLimt() {
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.UNISMS).sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ Assert.isTrue(smsResponse.isSuccess());
+
+ SmsBlendException knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.UNISMS).sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ }
+ Assert.notNull(knowEx);
+ }
+
+}
diff --git a/sms4j-spring-boot-starter/src/main/java/org/dromara/sms4j/starter/aop/SpringRestrictedProcess.java b/sms4j-spring-boot-starter/src/main/java/org/dromara/sms4j/starter/aop/SpringRestrictedProcess.java
deleted file mode 100644
index 387a0f92..00000000
--- a/sms4j-spring-boot-starter/src/main/java/org/dromara/sms4j/starter/aop/SpringRestrictedProcess.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.dromara.sms4j.starter.aop;
-
-import lombok.extern.slf4j.Slf4j;
-import org.dromara.sms4j.api.dao.SmsDao;
-import org.dromara.sms4j.api.dao.SmsDaoDefaultImpl;
-import org.dromara.sms4j.api.proxy.RestrictedProcess;
-import org.dromara.sms4j.comm.exception.SmsBlendException;
-import org.dromara.sms4j.comm.utils.SmsUtils;
-import org.dromara.sms4j.provider.config.SmsConfig;
-import org.dromara.sms4j.provider.factory.BeanFactory;
-import org.dromara.sms4j.starter.utils.SmsSpringUtils;
-
-@Slf4j
-public class SpringRestrictedProcess implements RestrictedProcess {
- private static final Long minTimer = 60 * 1000L;
- private static final Long accTimer = 24 * 60 * 60 * 1000L;
- private static final String REDIS_KEY = "sms:restricted:";
-
-
- @Override
- public SmsBlendException process(String phone) {
- SmsConfig config = BeanFactory.getSmsConfig();
- SmsDao smsDao = SmsSpringUtils.getBean(SmsDao.class);
- if (SmsUtils.isEmpty(smsDao)){
- smsDao = SmsDaoDefaultImpl.getInstance();
- }
- Integer accountMax = config.getAccountMax(); // 每日最大发送量
- Integer minuteMax = config.getMinuteMax(); // 每分钟最大发送量
- if (SmsUtils.isNotEmpty(accountMax)) { // 是否配置了每日限制
- Integer i = (Integer) smsDao.get(REDIS_KEY + phone + "max");
- if (SmsUtils.isEmpty(i)) {
- smsDao.set(REDIS_KEY + phone + "max", 1, accTimer / 1000);
- } else if (i >= accountMax) {
- log.info("The phone:" + phone + ",number of short messages reached the maximum today");
- return new SmsBlendException("The phone:" + phone + ",number of short messages reached the maximum today");
- } else {
- smsDao.set(REDIS_KEY + phone + "max", i + 1, accTimer / 1000);
- }
- }
- if (SmsUtils.isNotEmpty(minuteMax)) { // 是否配置了每分钟最大限制
- Integer o = (Integer) smsDao.get(REDIS_KEY + phone);
- if (SmsUtils.isNotEmpty(o)) {
- if (o < minuteMax) {
- smsDao.set(REDIS_KEY + phone, o + 1, minTimer / 1000);
- } else {
- log.info("The phone:" + phone + ",number of short messages reached the maximum today");
- return new SmsBlendException("The phone:", phone + " Text messages are sent too often!");
- }
- } else {
- smsDao.set(REDIS_KEY + phone, 1, minTimer / 1000);
- }
- }
- return null;
- }
-}
diff --git a/sms4j-spring-boot-starter/src/main/java/org/dromara/sms4j/starter/config/SmsBlendsInitializer.java b/sms4j-spring-boot-starter/src/main/java/org/dromara/sms4j/starter/config/SmsBlendsInitializer.java
index bccca3ab..bfec9afc 100644
--- a/sms4j-spring-boot-starter/src/main/java/org/dromara/sms4j/starter/config/SmsBlendsInitializer.java
+++ b/sms4j-spring-boot-starter/src/main/java/org/dromara/sms4j/starter/config/SmsBlendsInitializer.java
@@ -11,8 +11,10 @@ import org.dromara.sms4j.cloopen.config.CloopenFactory;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.enumerate.ConfigType;
import org.dromara.sms4j.comm.utils.SmsUtils;
+import org.dromara.sms4j.core.proxy.EnvirmentHolder;
import org.dromara.sms4j.core.factory.SmsFactory;
-import org.dromara.sms4j.core.proxy.SmsInvocationHandler;
+import org.dromara.sms4j.core.proxy.processor.*;
+import org.dromara.sms4j.core.proxy.SmsProxyFactory;
import org.dromara.sms4j.ctyun.config.CtyunFactory;
import org.dromara.sms4j.emay.config.EmayFactory;
import org.dromara.sms4j.huawei.config.HuaweiFactory;
@@ -22,7 +24,6 @@ import org.dromara.sms4j.netease.config.NeteaseFactory;
import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BaseProviderFactory;
import org.dromara.sms4j.provider.factory.ProviderFactoryHolder;
-import org.dromara.sms4j.starter.aop.SpringRestrictedProcess;
import org.dromara.sms4j.tencent.config.TencentFactory;
import org.dromara.sms4j.unisms.config.UniFactory;
import org.dromara.sms4j.yunpian.config.YunPianFactory;
@@ -53,7 +54,16 @@ public class SmsBlendsInitializer {
this.registerDefaultFactory();
// 注册短信对象工厂
ProviderFactoryHolder.registerFactory(factoryList);
+
if(ConfigType.YAML.equals(this.smsConfig.getConfigType())) {
+ //持有初始化配置信息
+ EnvirmentHolder.frozenEnvirmet(smsConfig, blends);
+ //注册执行器实现
+ SmsProxyFactory.addProcessor(new RestrictedProcessor());
+ SmsProxyFactory.addProcessor(new BlackListProcessor());
+ SmsProxyFactory.addProcessor(new BlackListRecordingProcessor());
+ SmsProxyFactory.addProcessor(new SingleBlendRestrictedProcessor());
+ SmsProxyFactory.addProcessor(new CoreMethodParamValidateProcessor());
// 解析供应商配置
for(String configId : blends.keySet()) {
Map configMap = blends.get(configId);
@@ -69,16 +79,11 @@ public class SmsBlendsInitializer {
SmsUtils.replaceKeysSeperator(configMap, "-", "_");
JSONObject configJson = new JSONObject(configMap);
org.dromara.sms4j.api.universal.SupplierConfig supplierConfig = JSONUtil.toBean(configJson, providerFactory.getConfigClass());
- if(Boolean.TRUE.equals(smsConfig.getRestricted())) {
- SmsFactory.createRestrictedSmsBlend(supplierConfig);
- } else {
- SmsFactory.createSmsBlend(supplierConfig);
- }
+ SmsFactory.createSmsBlend(supplierConfig);
}
}
- //注册短信拦截实现
- SmsInvocationHandler.setRestrictedProcess(new SpringRestrictedProcess());
+
}
/**
diff --git a/sms4j-spring-boot-starter/src/main/java/org/dromara/sms4j/starter/holder/SpringSmsDaoHolder.java b/sms4j-spring-boot-starter/src/main/java/org/dromara/sms4j/starter/holder/SpringSmsDaoHolder.java
new file mode 100644
index 00000000..b149f0f3
--- /dev/null
+++ b/sms4j-spring-boot-starter/src/main/java/org/dromara/sms4j/starter/holder/SpringSmsDaoHolder.java
@@ -0,0 +1,12 @@
+package org.dromara.sms4j.starter.holder;
+
+import org.dromara.sms4j.api.dao.SmsDao;
+import org.dromara.sms4j.api.dao.SmsDaoDefaultImpl;
+import org.dromara.sms4j.comm.utils.SmsUtils;
+import org.dromara.sms4j.starter.utils.SmsSpringUtils;
+
+public class SpringSmsDaoHolder {
+ public static SmsDao getSmsDao() {
+ return SmsSpringUtils.getBean(SmsDao.class);
+ }
+}