Java桌面应用批量发送SMS遇问题:多浏览器窗口及HTTP 400错误
解决Java桌面应用批量SMS发送的两个核心问题
我之前也踩过类似的坑,结合你的情况给你梳理一下可行的解决方案:
一、搞定批量发送时多浏览器窗口的痛点
之前每个收件人开一个浏览器窗口的方案确实不适合批量场景,完全没必要依赖浏览器来做请求转发。直接用Java发送HTTP请求和短信网关交互才是正确的打开方式,全程后台处理,不会弹出任何窗口,效率也高很多。
这里给你两种实现方式:
1. 用JDK原生的HttpURLConnection
不用额外依赖第三方库,适合轻量场景:
import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.List; public class BatchSmsSender { public static void sendSmsBatch(String username, String password, String smsContent, List<String> phoneNumbers) throws Exception { // 替换成你的短信网关实际接口地址 String smsApiUrl = "https://your-sms-gateway.com/send"; for (String phone : phoneNumbers) { // 对所有参数做UTF-8编码,避免乱码和参数解析错误 String encodedUsername = URLEncoder.encode(username, StandardCharsets.UTF_8.name()); String encodedPassword = URLEncoder.encode(password, StandardCharsets.UTF_8.name()); String encodedContent = URLEncoder.encode(smsContent, StandardCharsets.UTF_8.name()); String encodedPhone = URLEncoder.encode(phone, StandardCharsets.UTF_8.name()); // 构造表单格式的请求参数 String requestParams = String.format("username=%s&password=%s&content=%s&phone=%s", encodedUsername, encodedPassword, encodedContent, encodedPhone); URL url = new URL(smsApiUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); // 明确指定请求编码,避免网关解析错误 conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); // 发送请求参数 try (OutputStream os = conn.getOutputStream()) { os.write(requestParams.getBytes(StandardCharsets.UTF_8)); os.flush(); } // 处理响应 int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { System.out.printf("号码%s短信发送成功%n", phone); } else { System.out.printf("号码%s发送失败,响应码:%d%n", phone, responseCode); } conn.disconnect(); // 可选:添加延迟,避免触发网关频率限制 Thread.sleep(500); } } }
2. 用OkHttp库(更简洁易维护)
如果项目可以引入第三方库,OkHttp的代码可读性和容错性更好:
import okhttp3.FormBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import java.util.List; public class OkHttpSmsSender { // 全局复用OkHttpClient实例,提升性能 private static final OkHttpClient HTTP_CLIENT = new OkHttpClient(); public static void sendBatchSms(String username, String password, String content, List<String> phoneNumbers) throws Exception { String apiUrl = "https://your-sms-gateway.com/send"; for (String phone : phoneNumbers) { // 自动处理参数编码 FormBody formBody = new FormBody.Builder() .addEncoded("username", username) .addEncoded("password", password) .addEncoded("content", content) .addEncoded("phone", phone) .build(); Request request = new Request.Builder() .url(apiUrl) .post(formBody) .addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") .build(); try (Response response = HTTP_CLIENT.newCall(request).execute()) { if (response.isSuccessful()) { System.out.printf("号码%s发送成功%n", phone); } else { System.out.printf("号码%s发送失败,响应码:%d,响应信息:%s%n", phone, response.code(), response.body().string()); } } Thread.sleep(500); } } }
二、修复HTTP 400错误的常见排查点
用URLEncoder编码后还是返回400,大概率是请求格式或参数不符合网关要求,你可以按以下步骤排查:
- 核对参数名称是否完全匹配:有些网关的参数名可能不是
phone而是mobile,content可能是msg,一定要对照网关的官方文档确认,差一个字符都会报错。 - 检查参数格式要求:比如密码是否需要MD5/SHA加密?收件人号码是否必须加国家区号(比如+86)?短信内容是否有长度限制?这些细节都要严格遵守。
- 校验请求头设置:部分网关要求必须指定
User-Agent,或者要求请求体是JSON格式而不是表单。如果是JSON格式,你需要把参数封装成JSON字符串,并且设置Content-Type: application/json; charset=UTF-8。 - URLEncoder的特殊处理:
URLEncoder会把空格编码成+,有些网关只认%20,可以手动替换:
String encodedContent = URLEncoder.encode(content, StandardCharsets.UTF_8.name()).replace("+", "%20");
- 测试单个请求是否正常:先用Postman或curl手动发送单个号码的请求,确认参数和格式没问题后,再套用到批量代码里,这样更容易定位问题。
总的来说,放弃浏览器窗口的方案,改用后台HTTP请求是解决批量问题的关键,而400错误的核心是严格对齐网关的接口要求,多做小范围测试就能快速定位问题。
内容的提问来源于stack exchange,提问作者joppiealiw
相关产品推荐
相关产品推荐

