這次測試采用的是http://www.webchinese.com.cn/default.shtml平台的服務,代碼參考了https://blog.csdn.net/qq_33165600/article/details/79506936。
首先下載所需jar包:commons-logging-1.1.1.jar,commons-httpclient-3.1.jar,commons-codec-1.4.jar 。
到網站注冊好賬號,記下自己的賬戶和密鑰(不是登錄密碼)。
簽名就是短信最開始【】括住的部分。
發送短信生成驗證碼的工具類:
import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.PostMethod; import java.io.IOException; import java.util.HashMap; import java.util.Random; public class SendMessage { public static void main(String[] args) throws Exception{ SendMessage sendMessage = new SendMessage(); sendMessage.getMessageStatus("你的手機號碼"); } public HashMap<String,String> getMessageStatus(String phone) throws HttpException, IOException { HashMap<String,String> m = new HashMap<String,String>(); //http協議 HttpClient client = new HttpClient(); //連接第三方平台 PostMethod post = new PostMethod("http://gbk.api.smschinese.cn/"); post.addRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=gbk");//在頭文件中設置轉碼 //生成六位驗證碼 String charValue = ""; for (int i = 0; i < 6; i++) { char c = (char) (randomInt(0, 9) + '0'); charValue += String.valueOf(c); } //短信模板 NameValuePair[] data ={ new NameValuePair("Uid", "scxdhr"), //sms短信通 注冊的用戶名 new NameValuePair("Key", "d41d8cd98f00b204e980"), //密匙 new NameValuePair("smsMob",phone),//要發送的手機號 new NameValuePair("smsText","您的驗證碼是:"+charValue)//短信內容 }; post.setRequestBody(data); client.executeMethod(post); //獲取http頭 Header[] headers = post.getResponseHeaders(); int statusCode = post.getStatusCode(); System.out.println("statusCode:"+statusCode); for(Header h:headers){ System.out.println(h.toString()); } //獲取返回消息 String result = new String(post.getResponseBodyAsString().getBytes("gbk")); System.out.println(result); //打印返回消息狀態 //將返回消息和6位數驗證碼放入到m列表里面 m.put("result", result); m.put("code", charValue); //斷開與第三方平台的連接 post.releaseConnection(); return m; } //生成驗證碼 public static int randomInt(int from, int to) { Random r = new Random(); return from + r.nextInt(to - from); } }
result返回“1”就表示發送成功,手機上也會收到短信。
有三種方法在后台獲得手機驗證碼:
1.使用session的setAttribute方法,把數據存到頁面緩存中,但是關了頁面之后,儲存的驗證碼就會失效,所以不推薦使用這種方法。
2.使用redis數據庫緩存驗證碼,redis數據庫用來做這個契合度非常高,還能設置緩存失效時間,寫起來非常簡單。
3.寫了一個工具類CacheUtil,一個緩存用的map,也可以設置數據的失效時間,下面貼上代碼:
import java.util.Map; import java.util.concurrent.*; /** * 緩存工具類 * * @author lance * @since 2018-10-25 */ public class CacheUtil { /** * 存儲需緩存數據的map */ private final static Map<String, Entity> MAP = new ConcurrentHashMap<>(); /** * 定時器線程池,用於清除過期緩存 */ private final static ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor(); /** * 添加緩存 * * @param key map的key * @param data map的value */ public synchronized static void put(String key, Object data) { CacheUtil.put(key, data, 0); } /** * 添加緩存 * * @param key map的key * @param data map的value * @param expire 過期時間,單位:毫秒, 0表示無限長 */ public synchronized static void put(String key, Object data, long expire) { //清除原map CacheUtil.remove(key); //設置過期時間 if (expire > 0) { Future future = EXECUTOR.schedule(() -> { //過期后清除該map synchronized (CacheUtil.class) { MAP.remove(key); } }, expire, TimeUnit.MILLISECONDS); MAP.put(key, new Entity(data, future)); } else { //不設置過期時間 MAP.put(key, new Entity(data, null)); } } /** * 校驗緩存中是否存在key * * @param key map的key * @return 是否存在key */ public synchronized static boolean keyExists(String key) { return MAP.get(key) != null; } /** * 讀取緩存 * * @param key map的key * @return map的value */ public synchronized static Object get(String key) { Entity entity = MAP.get(key); return entity == null ? null : entity.getValue(); } /** * 讀取緩存 * * @param key 鍵 * @param cls 值類型 * @return map中value存儲的對象 */ public synchronized static <T> T get(String key, Class<T> cls) { return cls.cast(CacheUtil.get(key)); } /** * 清除緩存 * * @param key map的key * @return */ public synchronized static void remove(String key) { //清除原緩存數據 Entity entity = MAP.remove(key); //清除原map定時器 if (null != entity) { Future future = entity.getFuture(); if (future != null) { future.cancel(true); } } } /** * 緩存實體類 */ private static class Entity { /** * map的值 */ private Object value; /** * 定時器 */ private Future future; private Entity(Object value, Future future) { this.value = value; this.future = future; } /** * 獲取map值 * * @return map值 */ public Object getValue() { return value; } /** * 獲取Future對象 * * @return Future對象 */ private Future getFuture() { return future; } } }
剩下的就是校驗手機和前台發送過來的驗證碼是否一致,不再贅述。