java怎么实现群发短信的功能

Python010

java怎么实现群发短信的功能,第1张

JAVA实现短信群发的步骤:

1、使用第三方短信平台服务商,接入短信服务;

2、调用短信提交页面发送请求;

3、服务器向第三方短信平台提交发送请求;

4、短信平台通过运营商将短信下发至用户的手机上。

以下是秒赛短信平台JAVA短信验证码接口代码示例

package test

import java.io.IOException

import java.io.UnsupportedEncodingException

import java.net.URISyntaxException

import java.net.URLEncoder

import org.apache.commons.httpclient.HttpClient

import org.apache.commons.httpclient.NameValuePair

import org.apache.commons.httpclient.methods.PostMethod

import org.apache.commons.lang3.StringUtils

public class Apis {

// 短信发送接口的http地址,请咨询客服

private static String url = “xxxxxxxxxxxxxxxxxxxxxxxxxxxx”

// 编码格式。发送编码格式统一用UTF-8

private static String ENCODING = “UTF-8”

public static void main(String[] args) throws IOException, URISyntaxException {

// 账号

String account = “************************”

// 密码

String pswd = “************************”

// 修改为您要发送的手机号,多个用,分割

String mobile = “13*********”

// 设置您要发送的内容

String msg = “【秒赛科技】您的验证码是:1234”

// 发短信调用示例

System.out.println(Apis.send(account,pswd, mobile, msg));

}

/**

* 发送短信

*

* @param account

*            account

* @param pswd

*            pswd

* @param mobile

*            手机号码

* @param content

*            短信发送内容

*/

public static String send(String account,String pswd, String mobile, String msg) {

NameValuePair[] data = { new NameValuePair(“account”, account),

new NameValuePair(“pswd”, pswd),

new NameValuePair(“mobile”, mobile),

new NameValuePair(“msg”, msg),

new NameValuePair(“needstatus”, “true”),

new NameValuePair(“product”, “”) }

return doPost(url, data);

}

/**

* 基于HttpClient的post函数

* PH

* @param url

*            提交的URL

*

* @param data

*            提交NameValuePair参数

* @return 提交响应

*/

private static String doPost(String url, NameValuePair[] data) {

HttpClient client = new HttpClient();

PostMethod method = new PostMethod(url);

// method.setRequestHeader(“ContentType”,

// “application/x-www-form-urlencodedcharset=UTF-8”);

method.setRequestBody(data);

// client.getParams()。setContentCharset(“UTF-8”);

client.getParams()。setConnectionManagerTimeout(10000);

try {

client.executeMethod(method);

return method.getResponseBodyAsString();

} catch (Exception e) {

e.printStackTrace();

}

return null

}

}

1、创建一个Http的模拟请求工具类,然后写一个POST方法或者GET方法

/** * 文件说明 * @Description:扩展说明 * @Copyright: XXXX dreamtech.com.cn Inc. All right reserved * @Version: V6.0 */package com.demo.utilimport java.io.IOExceptionimport java.util.Mapimport org.apache.commons.httpclient.HttpClientimport org.apache.commons.httpclient.HttpExceptionimport org.apache.commons.httpclient.SimpleHttpConnectionManagerimport org.apache.commons.httpclient.methods.GetMethodimport org.apache.commons.httpclient.methods.PostMethod/** * @Author: feizi * @Date: XXXX年XX月XX日 XX:XX:XX * @ModifyUser: feizi * @ModifyDate: XXXX年XX月XX日 XX:XX:XX * @Version:V6.0 */public class HttpRequestUtil { /** * HttpClient 模拟POST请求 * 方法说明 * @Discription:扩展说明 * @param url * @param params * @return String * @Author: feizi * @Date: XXXX年XX月XX日 XX:XX:XX * @ModifyUser:feizi * @ModifyDate: XXXX年XX月XX日 XX:XX:XX */ public static String postRequest(String url, Map<String, String>params) { //构造HttpClient的实例 HttpClient httpClient = new HttpClient() //创建POST方法的实例 PostMethod postMethod = new PostMethod(url) //设置请求头信息 postMethod.setRequestHeader("Connection", "close") //添加参数 for (Map.Entry<String, String>entry : params.entrySet()) { postMethod.addParameter(entry.getKey(), entry.getValue()) } //使用系统提供的默认的恢复策略,设置请求重试处理,用的是默认的重试处理:请求三次 httpClient.getParams().setBooleanParameter("http.protocol.expect-continue", false) //接收处理结果 String result = null try { //执行Http Post请求 httpClient.executeMethod(postMethod) //返回处理结果 result = postMethod.getResponseBodyAsString() } catch (HttpException e) { // 发生致命的异常,可能是协议不对或者返回的内容有问题 System.out.println("请检查输入的URL!") e.printStackTrace() } catch (IOException e) { // 发生网络异常 System.out.println("发生网络异常!") e.printStackTrace() } finally { //释放链接 postMethod.releaseConnection() //关闭HttpClient实例 if (httpClient != null) {((SimpleHttpConnectionManager) httpClient.getHttpConnectionManager()).shutdown() httpClient = null } } return result} /** * HttpClient 模拟GET请求 * 方法说明 * @Discription:扩展说明 * @param url * @param params * @return String * @Author: feizi * @Date: XXXX年XX月XX日 XX:XX:XX * @ModifyUser:feizi * @ModifyDate: XXXX年XX月XX日 XX:XX:XX */ public static String getRequest(String url, Map<String, String>params) { //构造HttpClient实例 HttpClient client = new HttpClient() //拼接参数 String paramStr = "" for (String key : params.keySet()) { paramStr = paramStr + "&" + key + "=" + params.get(key) } paramStr = paramStr.substring(1) //创建GET方法的实例 GetMethod method = new GetMethod(url + "?" + paramStr) //接收返回结果 String result = null try { //执行HTTP GET方法请求 client.executeMethod(method) //返回处理结果 result = method.getResponseBodyAsString() } catch (HttpException e) { // 发生致命的异常,可能是协议不对或者返回的内容有问题 System.out.println("请检查输入的URL!") e.printStackTrace() } catch (IOException e) { // 发生网络异常 System.out.println("发生网络异常!") e.printStackTrace() } finally { //释放链接 method.releaseConnection() //关闭HttpClient实例 if (client != null) {((SimpleHttpConnectionManager) client.getHttpConnectionManager()).shutdown() client = null } } return result}}

2、在创建一个类,生成验证码,然后传递相应的参数(不同的短信平台接口会有不同的参数要求,这个一般短信平台提供的接口文档中都会有的,直接看文档然后按要求来即可)

/** * 文件说明 * @Description:扩展说明 * @Copyright: XXXX dreamtech.com.cn Inc. All right reserved * @Version: V6.0 */package com.demo.utilimport java.net.URLEncoderimport java.util.HashMapimport java.util.Map/** * @Author: feizi * @Date: XXXX年XX月XX日 XX:XX:XX * @ModifyUser: feizi * @ModifyDate: XXXX年XX月XX日 XX:XX:XX * @Version:V6.0 */public class SendMsgUtil { /** * 发送短信消息 * 方法说明 * @Discription:扩展说明 * @param phones * @param content * @return * @return String * @Author: feizi * @Date: 2015年4月17日 下午7:18:08 * @ModifyUser:feizi * @ModifyDate: 2015年4月17日 下午7:18:08 */ @SuppressWarnings("deprecation") public static String sendMsg(String phones,String content){ //短信接口URL提交地址 String url = "短信接口URL提交地址" Map<String, String>params = new HashMap<String, String>() params.put("zh", "用户账号") params.put("mm", "用户密码") params.put("dxlbid", "短信类别编号") params.put("extno", "扩展编号") //手机号码,多个号码使用英文逗号进行分割 params.put("hm", phones) //将短信内容进行URLEncoder编码 params.put("nr", URLEncoder.encode(content)) return HttpRequestUtil.getRequest(url, params)} /** * 随机生成6位随机验证码 * 方法说明 * @Discription:扩展说明 * @return * @return String * @Author: feizi * @Date: 2015年4月17日 下午7:19:02 * @ModifyUser:feizi * @ModifyDate: 2015年4月17日 下午7:19:02 */ public static String createRandomVcode(){ //验证码 String vcode = "" for (int i = 0i <6i++) { vcode = vcode + (int)(Math.random() * 9) } return vcode} /** * 测试 * 方法说明 * @Discription:扩展说明 * @param args * @return void * @Author: feizi * @Date: XXXX年XX月XX日 XX:XX:XX * @ModifyUser:feizi * @ModifyDate: XXXX年XX月XX日 XX:XX:XX */ public static void main(String[] args) {// System.out.println(SendMsgUtil.createRandomVcode())// System.out.println("&ecb=12".substring(1)) System.out.println(sendMsg("18123456789,15123456789", "尊敬的用户,您的验证码为" + SendMsgUtil.createRandomVcode() + ",有效期为60秒,如有疑虑请详询XXX-XXX-XXXX【XXX中心】"))}

然后执行一下,一般的情况下参数传递正确,按照接口文档的规范来操作的话,都会发送成功的,手机都能收到验证码的,然后可能会出现的问题就是:发送的短信内容有可能会出现中文乱码,然后就会发送不成功,按照短信平台的要求进行相应的编码即可。一般都会是UTF-8编码。

发送短信的接口

根据自己的情况选择服务商。

开发文档

从开发文档中我们可以看到. 可以直接使用http请求也可以使用WebService请求发送短信. 由于DEMO文件夹下的java和jsp文件夹中的代码都是使用http请求发送短信. 所以这里就不再细说了, 我们使用WebService的方式演示发送短信.

生成客户端代码

从接口文档中我们知道它的WebService的WSDL的url为: http://106.ihuyi.cn/webservice/sms.php?WSDL那么我们可以执行下面的命令生成客户端代码:

wsimport -keep http://106.ihuyi.cn/webservice/sms.php?WSDL

其中wsimport是JDK自带的工具, -keep url选项是"保留生成的文件". 该命令会在当前目录下生成sms.cn.ihuyi._106包, 以及众多的类. 接下来开始编写我们自己的代码.

定义接口

为了方便, 这里我们首先定义一个接口:

Sms.java

public interface Sms {

 /**

  * 向mobile发送短信, 内容为message

  * 

  * @param mobile 手机号

  * @param message 短信内容

  * @return 成功返回-1, 否则返回其他值

  */

 int sendMessage(String mobile, String message)

}

这个接口很简单, 只有一个方法. 这个方法用来发送短信.

同步发送短信

接下来我们首先实现一个同步发送短信的类:

IhuyiSmsImpl.java

public class IhuyiSmsImpl implements Sms {

 private String account

 private String password

 public void setAccount(String account) {

  this.account = account

 }

 public void setPassword(String password) {

  this.password = password

 }

 @Override

 public int sendMessage(String mobile, String message) {

  cn.ihuyi._106.Sms factory = new cn.ihuyi._106.Sms()

  SmsSoap smsSoap = factory.getSmsSoap()

  SubmitResult submit = smsSoap.submit(account, password, mobile, message)

  int code = submit.getCode()

  if(code == 2){

   return -1

  }

  System.out.println("发送短信失败, code:" + code)

  return code

 }

}

异步发送短信

由于发送短信涉及到网络通信, 因此sendMessage方法可能会有一些延迟. 为了改善用户体验, 我们可以使用异步发送短信的方法. 原理很简单: 如果用户请求发送短信, 我们不是直接调用IhuyiSmsImpl的sendMessage方法, 而是将请求保存起来(生产者), 然后告诉用户: 短信发送成功. 之后有若干个消费者取出任务, 调用sendMessage方法发送短信.

这里, 我使用线程池完成上面的任务:

AsyncSmsImpl.java

public class AsyncSmsImpl implements Sms {

 public Sms sendSms

 private ExecutorService executorService = Executors.newFixedThreadPool(3)

 public void setSendSms(Sms sendSms) {

  this.sendSms = sendSms

 }

 @Override

 public int sendMessage(String mobile, String message) {

  try {

   executorService.submit(() -> sendSms.sendMessage(mobile, message))

  }

  catch(Exception e) {

   Sysemt.out.println("提交任务时发生错误" + e)

   return 0

  }

  return -1

 }

 public void destroy(){

  try{

   executorService.shutdown()

  }

  catch(Exception e){}

 }

}

在第17行, 我们获得远程对象的一个代理对象. 之后就可以通过这个代理对象进行发送短信, 查询账户余额等操作.

第18行, 使用该代理对象的submit方法提交了短信内容. 该方法的参数信息及返回值含义在接口文档中有详细的说明.

第19行我们获得了结果的状态码. 根据文档上的说明, 状态码为2说明提交成功. 简单起见, 这里我们只关注提交成功的情况. 需要注意的是, 状态码为2只是说明提交成功. 根据官网上的"3-5秒内响应、100%到达", 我们可以推测. 如果提交成功, 那么基本上3-5秒内,短信就会发送成功, 根据用户的网络情况, 可能稍有延迟用户就可以收到短信.

使用这段代码发送短信也很简单, 直接new一个对象, 设置好账号和密码就可以发送短信了.

代码很简单, 直接将Sms接口的sendMessage(mobile, message)方法作为一个任务加到线程池的任务队列中. 这样等到有空闲线程时, 就会执行sendSms.sendMessage(mobile, message)发送短信. 这里我们假设只要保存到线程池就可以成功发送短信. 因为发送失败的情况实际上很罕见.