diff --git a/sms4j-api/src/main/java/org/dromara/sms4j/api/universal/ProxyConfig.java b/sms4j-api/src/main/java/org/dromara/sms4j/api/universal/ProxyConfig.java new file mode 100644 index 00000000..4c54325a --- /dev/null +++ b/sms4j-api/src/main/java/org/dromara/sms4j/api/universal/ProxyConfig.java @@ -0,0 +1,27 @@ +package org.dromara.sms4j.api.universal; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 短信代理配置类 + */ +@Data +public class ProxyConfig implements Serializable { + + /** + * 是否启用代理 默认不启用 + */ + private Boolean enable = false; + + /** + * 代理服务器地址 + */ + private String host; + + /** + * 代理服务器端口 + */ + private Integer port; +} diff --git a/sms4j-api/src/main/java/org/dromara/sms4j/api/universal/SupplierConfig.java b/sms4j-api/src/main/java/org/dromara/sms4j/api/universal/SupplierConfig.java index 4537cab3..8d2d8ba5 100644 --- a/sms4j-api/src/main/java/org/dromara/sms4j/api/universal/SupplierConfig.java +++ b/sms4j-api/src/main/java/org/dromara/sms4j/api/universal/SupplierConfig.java @@ -22,4 +22,9 @@ public interface SupplierConfig { */ String getSupplier(); + /** + * 获取代理配置 + * + */ + ProxyConfig getProxy(); } diff --git a/sms4j-comm/src/main/java/org/dromara/sms4j/comm/utils/SmsHttpUtils.java b/sms4j-comm/src/main/java/org/dromara/sms4j/comm/utils/SmsHttpUtils.java index 7048e0e4..c931e9db 100644 --- a/sms4j-comm/src/main/java/org/dromara/sms4j/comm/utils/SmsHttpUtils.java +++ b/sms4j-comm/src/main/java/org/dromara/sms4j/comm/utils/SmsHttpUtils.java @@ -1,9 +1,11 @@ package org.dromara.sms4j.comm.utils; import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.URLUtil; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; +import cn.hutool.http.Method; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import org.dromara.sms4j.comm.exception.SmsBlendException; @@ -12,15 +14,108 @@ import java.util.Map; public class SmsHttpUtils { + /** + * 是否启用代理 默认不启用 + */ + private final Boolean enable; + + /** + * 代理服务器地址 + */ + private final String host; + + /** + * 代理服务器端口 + */ + private final Integer port; + + // 无代理单例(饿汉式加载) + private static final SmsHttpUtils NON_PROXY_INSTANCE = new SmsHttpUtils(); + + // 代理单例(双重校验锁延迟加载) + private static volatile SmsHttpUtils PROXY_INSTANCE; + + // 无代理构造方法 private SmsHttpUtils() { + this.enable = false; + this.host = null; + this.port = null; } - private static class SmsHttpHolder { - private static final SmsHttpUtils INSTANCE = new SmsHttpUtils(); + // 代理构造方法 + private SmsHttpUtils(String host, Integer port) { + this.enable = true; + this.host = host; + this.port = port; } + /** + * 获取无代理单例 + */ public static SmsHttpUtils instance() { - return SmsHttpHolder.INSTANCE; + return NON_PROXY_INSTANCE; + } + + /** + * 获取代理单例(线程安全 + 参数校验) + */ + public static SmsHttpUtils instance(String host, Integer port) { + if (PROXY_INSTANCE == null) { + synchronized (SmsHttpUtils.class) { + if (PROXY_INSTANCE == null) { + validateProxyParams(host, port); + PROXY_INSTANCE = new SmsHttpUtils(host, port); + } + } + } else { + // 二次调用时校验参数一致性 + if (!PROXY_INSTANCE.host.equals(host) || !PROXY_INSTANCE.port.equals(port)) { + throw new IllegalStateException("Proxy parameters cannot be modified after initialization"); + } + } + return PROXY_INSTANCE; + } + + // 代理参数校验 + private static void validateProxyParams(String host, Integer port) { + if (StrUtil.isBlank(host) || port == null || port <= 0) { + throw new IllegalArgumentException("Invalid proxy host or port"); + } + } + + /** + * 配置请求 是否走代理 + * @param url 请求地址 + * @return HttpRequest + */ + private HttpRequest request(String url){ + HttpRequest request = HttpRequest.of(url); + if (enable){ + request.setHttpProxy(host, port); + } + return request; + } + + /** + * 构造post请求 + * @param url 请求地址 + * @return HttpRequest + */ + private HttpRequest post(String url){ + HttpRequest post = request(url); + post.setMethod(Method.POST); + return post; + } + + /** + * 构造get请求 + * @param url 请求地址 + * @return HttpRequest + */ + private HttpRequest get(String url){ + HttpRequest get = request(url); + get.setMethod(Method.GET); + return get; } /** @@ -32,7 +127,7 @@ public class SmsHttpUtils { * @return 返回体 */ public JSONObject postJson(String url, Map headers, String body) { - try (HttpResponse response = HttpRequest.post(url) + try (HttpResponse response = post(url) .addHeaders(headers) .body(body) .execute()) { @@ -63,7 +158,7 @@ public class SmsHttpUtils { * @return 返回体 */ public JSONObject postFrom(String url, Map headers, Map body) { - try (HttpResponse response = HttpRequest.post(url) + try (HttpResponse response = post(url) .addHeaders(headers) .form(body) .execute()) { @@ -84,7 +179,7 @@ public class SmsHttpUtils { * @return 返回体 */ public JSONObject postBasicFrom(String url, Map headers, String username, String password, Map body) { - try (HttpResponse response = HttpRequest.post(url) + try (HttpResponse response = post(url) .addHeaders(headers) .basicAuth(username, password) .form(body) @@ -105,7 +200,7 @@ public class SmsHttpUtils { */ public JSONObject postUrl(String url, Map headers, Map params) { String urlWithParams = url + "?" + URLUtil.buildQuery(params, null); - try (HttpResponse response = HttpRequest.post(urlWithParams) + try (HttpResponse response = post(urlWithParams) .addHeaders(headers) .execute()) { return JSONUtil.parseObj(response.body()); @@ -121,7 +216,7 @@ public class SmsHttpUtils { * @return 返回体 */ public JSONObject getBasic(String url, String username, String password) { - try (HttpResponse response = HttpRequest.get(url) + try (HttpResponse response = get(url) .basicAuth(username, password) .execute()) { return JSONUtil.parseObj(response.body()); @@ -137,7 +232,7 @@ public class SmsHttpUtils { * @return 返回体 */ public JSONObject getUrl(String url) { - try (HttpResponse response = HttpRequest.get(url) + try (HttpResponse response = get(url) .execute()) { return JSONUtil.parseObj(response.body()); } catch (Exception e) { 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 99b1a002..24826d64 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 @@ -1,6 +1,7 @@ package org.dromara.sms4j.provider.config; import lombok.Data; +import org.dromara.sms4j.api.universal.ProxyConfig; import org.dromara.sms4j.api.universal.SupplierConfig; import org.dromara.sms4j.comm.exception.SmsBlendException; @@ -56,6 +57,12 @@ public abstract class BaseConfig implements SupplierConfig { */ private String configId; + /** + * 代理配置 + * + */ + private ProxyConfig proxy; + /** * 重试间隔(单位:秒),默认为5秒 */ diff --git a/sms4j-provider/src/main/java/org/dromara/sms4j/provider/service/AbstractSmsBlend.java b/sms4j-provider/src/main/java/org/dromara/sms4j/provider/service/AbstractSmsBlend.java index 915a9b82..daadbc8f 100644 --- a/sms4j-provider/src/main/java/org/dromara/sms4j/provider/service/AbstractSmsBlend.java +++ b/sms4j-provider/src/main/java/org/dromara/sms4j/provider/service/AbstractSmsBlend.java @@ -5,6 +5,7 @@ import lombok.Getter; import org.dromara.sms4j.api.SmsBlend; import org.dromara.sms4j.api.callback.CallBack; import org.dromara.sms4j.api.entity.SmsResponse; +import org.dromara.sms4j.api.universal.ProxyConfig; import org.dromara.sms4j.api.universal.SupplierConfig; import org.dromara.sms4j.api.utils.SmsRespUtils; import org.dromara.sms4j.comm.delayedTime.DelayedTime; @@ -32,13 +33,19 @@ public abstract class AbstractSmsBlend implements SmsB protected final DelayedTime delayed; - protected final SmsHttpUtils http = SmsHttpUtils.instance(); + protected final SmsHttpUtils http; protected AbstractSmsBlend(C config, Executor pool, DelayedTime delayed) { this.configId = StrUtil.isEmpty(config.getConfigId()) ? getSupplier() : config.getConfigId(); this.config = config; this.pool = pool; this.delayed = delayed; + ProxyConfig proxy = config.getProxy(); + if (proxy != null && proxy.getEnable()){ + this.http = SmsHttpUtils.instance(proxy.getHost(), proxy.getPort()); + }else { + this.http = SmsHttpUtils.instance(); + } } protected AbstractSmsBlend(C config) { @@ -46,6 +53,12 @@ public abstract class AbstractSmsBlend implements SmsB this.config = config; this.pool = BeanFactory.getExecutor(); this.delayed = BeanFactory.getDelayedTime(); + ProxyConfig proxy = config.getProxy(); + if (proxy != null && proxy.getEnable()){ + this.http = SmsHttpUtils.instance(proxy.getHost(), proxy.getPort()); + }else { + this.http = SmsHttpUtils.instance(); + } } protected C getConfig() { diff --git a/sms4j-spring-boot-example/src/main/resources/application.yml b/sms4j-spring-boot-example/src/main/resources/application.yml index 6018467c..84556af2 100644 --- a/sms4j-spring-boot-example/src/main/resources/application.yml +++ b/sms4j-spring-boot-example/src/main/resources/application.yml @@ -18,6 +18,12 @@ sms: template-id: SMS_272470496 # 模版名称 templateName: code + # 代理 + proxy: + # 是否启用代理 默认关闭 需手动开启 + enable: true + host: 127.0.0.1 + port: 8080 # 腾讯短信例子 tx: #厂商标识