利用线程创建发送手机验证码的工具类

Posted 持.之.以.恒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用线程创建发送手机验证码的工具类相关的知识,希望对你有一定的参考价值。

1、生成验证码类

 

package com.util;

import java.util.Timer;
import java.util.TimerTask;

/**
 * @description 手机发送验证码工具类
 */
public class MessageCode extends TimerTask{

	private Timer timer;
	/**
	 * @description 短信验证码的内容
	 */
	private String messageCode;
	/**
	 * @description 毫秒,默认60秒后过期
	 */
	private long maXtime = 180000;
	/**
	 * @description 短信验证码长度
	 */
	private int length = 6;
	/**
	 * @description 短信验证码可取值
	 */
	private final String charOfMessage = "0123456789";
	//0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
	@Override
	public void run() {
		this.messageCode = null;//过期后短信验证码信息置为null
		this.timer.cancel();
	}

	/**
	 * @decription 使用默认值
	 */
	public MessageCode() {
		super();
		this.timer = new Timer();
		genMessageCode(this.length);
		this.timer.schedule(this, this.maXtime);
	}

	/**
	 * @description 自定义最大过期时间,验证码最大长度
	 * @param maXtime
	 * @param length
	 */
	public MessageCode(long maXtime, int length) {
		super();
		this.maXtime = maXtime;
		this.length = length;
		genMessageCode(this.length);
		this.timer.schedule(this, this.maXtime);
	}

	/**
	 * @description 生成随机验证码
	 * @param length
	 * @return void 返回值类型
	 
	 */
	private final void genMessageCode(int length){
		StringBuffer tempB = new StringBuffer(length);
		final int charOfMassegeLength = this.charOfMessage.length();
		for(int i = 0; i < length; i++){
			double d = Math.random();
			int index  = (int)(Math.floor(d * charOfMassegeLength) / 1);
			tempB.append(this.charOfMessage.charAt(index));
		}
		this.messageCode = tempB.toString();
	}
	/**
	 * @description 获取验证码信息,如果为空表示验证码超时
	 * @return
	 * @return String 返回值类型
		 */
	public String getMessageCode() {
		return messageCode;
	}

}


 

 

 

2、 MessageThread.java 线程类

 


 

package com.util;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;

import org.apache.commons.lang.StringUtils;

/**
 * @description 使用线程发送消息,以免主线程等待

 */
public final class MessageThread implements Runnable{
	/**
	 * @description 发送请求的URL
	 */
	private final static String url = "http:192.168.1.127/sms/send/smsSend.action?businessName=c1&isLong=3&appName=useraccount&smsKey=powsword";
	private String msg;
	private String phonenumber;
	
	@Override
	public void run() {
		sendMessage();
	}
	/**
	 * @description
	 * @return void 返回值类型

	 */
	private void sendMessage(){
		String phone = this.phonenumber;
		if(StringUtils.isBlank(this.phonenumber)){//手机号为空时,禁止消息发送
			return;
		}
		String tempUrl = url;
		try {
			//经过两次转码。短消息显示正常
			msg = java.net.URLEncoder.encode(msg, "UTF-8");
			tempUrl = (tempUrl + "&uuid=" + java.util.UUID.randomUUID().toString().replaceAll("-", ""));
			tempUrl = (tempUrl + "&phone=" + phone);
			tempUrl = (tempUrl + "&content=" + java.net.URLEncoder.encode(msg, "UTF-8"));
			URLConnection connection = new URL(tempUrl).openConnection();
			connection.setConnectTimeout(2000);
			connection.setReadTimeout(2000);
			connection.connect();
			BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
//			String x = reader.readLine();
//			System.out.println(x);
			reader.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * @decription 初始化发送信息线程数据
	 * @param msg 
	 * @param phonenumber
	 */
	public MessageThread(String msg, String phonenumber) {
		super();
		this.msg = msg;
		this.phonenumber = phonenumber;
	}
	
	public String getMsg() {
		return msg;
	}
	public void setMsg(String msg) {
		this.msg = msg;
	}
	public String getPhonenumber() {
		return phonenumber;
	}
	public void setPhonenumber(String phonenumber) {
		this.phonenumber = phonenumber;
	}
}


 

 

 

3、发送消息工具类

 

package com.util;

/**
 * @description <p>发送消息工具类,具体的消息发送方法参见MessageThread.java</p>
 * <p>调用sendMessage方法 ,传入消息内容和手机号发送消息。</p>
 * <p>当手机号为空时,不发送消息</p>

 */
public final class MessageUtil {

	
	/**
	* @description 调用此方法发送消息内容
	 * @param msg 发送消息内容
	 * @param phone 发送消息的手机号。当手机号为空时,不发送消息
	 */
	public final static void sendMessage (String msg, String phone){
		new Thread(new MessageThread(msg, phone)).start();
	}
}


 ——————————————————————————————————————————————————————
——————————————————————————————————————————————————————
短信重置密码类调用以上工具示例:

 

package com.ww.k.a.action;


import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.ww.k.a.action.form.WwAc01UserForm;
import com.ww.k.a.action.form.WwkaForm;
import com.ww.k.a.manager.WwkaMng;
import com.ww.k.a.manager.dto.WwkaDto;
import com.ww.z.util.MessageCode;
import com.ww.z.util.MessageUtil;
import com.util.DtoUtil;
import com.JSONUtil;
import com.validate.CJobBeanValidator;
@Controller
@RequestMapping(value = "/k/a/")
public class WwkaAct {

	@Autowired
	private WwkaMng wwkaMng;
	
	/**
	 * 
	 * @Description: 找回密码页面入口
	 * @param request
	 * @param response
	 * @param model
	 */
	@RequestMapping(value = "wwka_cont.html")
	public String cont(HttpServletRequest request, HttpServletResponse response, ModelMap model) {
	
		return "k/a/wwka_contnew";
	}
	/**
	 * 
	 * @Description: 找回密码 通过邮箱
	 * @param form
	 * @param find
	 * @param req
	 * @param resp
		 */
	@ResponseBody
	@RequestMapping(value = "wwka_mail.html")
	public String doFindBackMail(WwkaForm form,HttpServletRequest req, HttpServletResponse resp)throws IOException {
		Map<String, String> result = new HashMap<String, String>();
		if ("".equals(form.getAccount())
				|| "".equals(form.getMail())
				|| !(wwkaMng.hasuser(form.getAccount(), form.getMail()))) {
			result.put("hasError", "2");//帐号或者邮箱不正确
		} else {
			result.put("hasError", "1");//帐号、邮箱正确
			WwkaDto maildto = new WwkaDto();
			DtoUtil.copyProperties(form, maildto);
			wwkaMng.sentmail(req,maildto);//邮件找回密码
		}
		JSONObject json = JSONObject.fromObject(result);
		return json.toString();
	}

	/**
	 * 
	 * @Description: 通过账号名获取Dto,从而获取安全问题
	 * @param account
	 * @param req
	 * @param resp
	 * @return
	 * @throws IOException
		 */
	@ResponseBody
	@RequestMapping(value = "wwka_findQ.html")
	public String doFindQ(String account,HttpServletRequest req, HttpServletResponse resp)throws IOException {
		Map<String, String> result = new HashMap<String, String>();
		WwkaDto dtoQ = wwkaMng.findoutQ(account);
		String question = dtoQ.getQuestion();
		if("".equals(question)||question==null){
			result.put("noQ", "1");
		}else{
			result.put("question", question);
		}
		JSONObject json = JSONObject.fromObject(result);
		return json.toString();

	}
	/**
	 * 
	 * @Description: 找回密码 之 安全问题找回密码
	 * @param form
	 * @param req
	 * @param resp
	 * @return
	 * @throws IOException
	 */
	@ResponseBody
	@RequestMapping(value = "wwka_question.html")
	public String doFindByQ(WwkaForm form,HttpServletRequest req, HttpServletResponse resp)throws IOException {
		Map<String, String> result = new HashMap<String, String>();
		if ("".equals(form.getAccount2())
				|| form.getAccount2()==null
				|| !(wwkaMng.hasQ(form.getAccount2(), form.getAnswer()))) {
			result.put("hasError", "2");//帐号或者答案不正确
			JSONObject json = JSONObject.fromObject(result);
			return json.toString();
		} else {
			//生成6位随机数作为找回的新密码
			Random rd = new Random();
			int num  = rd.nextInt(1000000);
			while(num < 100000){
				num  = rd.nextInt(1000000);
			}
			String passwd = String.valueOf(num);
			//获得原来数据
			WwkaDto dtopwd = wwkaMng.findoutQ(form.getAccount2());
			dtopwd.setPassword(passwd);
			//将新密码同步到数据库
			wwkaMng.resetNewPwd(dtopwd);
			//返回给用户的新密码
			result.put("showMail", dtopwd.getMail());
			result.put("showQ", dtopwd.getQuestion());
			result.put("showLnum", dtopwd.getLoginNum()!=null?String.valueOf(dtopwd.getLoginNum()):"0");
			result.put("showLtime", dtopwd.getLoginTime()!=null?String.valueOf(dtopwd.getLoginTime()):"无");
			result.put("showRtime", String.valueOf(dtopwd.getRegisterTime()));
			result.put("newPwd", passwd);
			result.put("showaccount", form.getAccount2());
			result.put("hasError", "1");//帐号、答案正确
		}
		JSONObject json = JSONObject.fromObject(result);
		return json.toString();
	}
	
	/**
	 * @description 发送手机验证码,校验账号是否存在,并且账号的手机号码与输入的手机号码是否一致
	 * @param request
	 * @param response
	 * @param phonenumber
	 * @param account
	 * @return void 返回值类型
	 */
	@ResponseBody
	@RequestMapping("wwka_getcode.html")
	public void getCode(HttpServletRequest request, HttpServletResponse response, String phonenumber, String account){
		StringBuffer errerB = new StringBuffer();
		if(StringUtils.isBlank(account)){
			errerB.append("请输入您的个人账号。<br>");
		}else if(!account.matches("^[1-9]{1}[0-9]{16}[0-9Xx]{1}$")){
			errerB.append("您的个人账号输入错误。<br>");
		}
		
		if(StringUtils.isBlank(phonenumber)){
			errerB.append("请输入手机号码。<br>");
		}else if(!phonenumber.matches("^1[0-9]{10}$")){
			errerB.append("您的手机号码输入错误。<br>");
		}
		if(errerB.toString().endsWith("<br>")){//如果以<br>结尾,去掉<br>
			errerB.setLength(errerB.length() - 4);
		}
		Map<String, String> rs = new HashMap<String, String>();
		//校验不通过
		if(errerB.length() != 0){
			rs.put("msg", errerB.toString());
			rs.put("status", "-1");
			JSONUtil.write(response, rs);
			return;
		}
		//校验通过,判断账号是否存在
		WwAc01UserForm form = wwkaMng.getUserInfo(account);
		if(form == null){
			rs.put("msg", "您输入的账号不存在。");
			rs.put("status", "-1");
			JSONUtil.write(response, rs);
			return;
		}else if(!phonenumber.equals(form.getPhonenumber())){//账号存在,判断手机号码是否与系统一致
			rs.put("msg", "您输入的手机账号与该账号在系统中预留的手机号码不一致。");
			rs.put("status", "-1");
			JSONUtil.write(response, rs);
			return;
		}
		//以上都通过,发送验证码
		HttpSession session = request.getSession();
		MessageCode code = new MessageCode();
		String msg = code.getMessageCode();
		session.setAttribute(session.getId() + "_resetpassword", code);
		MessageUtil.sendMessage(msg, phonenumber);
		rs.put("msg", "手机验证码已由系统发出,请您注意查收。");
		rs.put("status", "1");
		JSONUtil.write(response, rs);
	}
	
	/**
	 * @description 重置密码。密码发送到系统中预留的手机号码
	 * @param request
	 * @param response
	 * @param phonenumber
	 * @param account
	 * @param phonecode
	 * @return void 返回值类型
	 */
	@ResponseBody
	@RequestMapping("wwka_resetpsw.html")
	public void resetPassword(HttpServletRequest request, HttpServletResponse response, String phonenumber, String account, String phonecode){
		//先取出验证码,以免校验时过期
		HttpSession session = request.getSession();
		Map<String, String> rs = new HashMap<String, String>();
		Object obj = session.getAttribute(session.getId() + "_resetpassword");
		if(obj == null){
			rs.put("msg", "请先获取手机验证码。");
			rs.put("status", "-1");
			JSONUtil.write(response, rs);
			return;
		}else{
			MessageCode code = (MessageCode)obj;
			String codestr = code.getMessageCode();
			if(StringUtils.isBlank(codestr)){
				rs.put("msg", "您输入手机验证码已过期,请重新获取。");
				rs.put("status", "-1");
				JSONUtil.write(response, rs);
				return;
			}else{//再次校验信息是否合法
				StringBuffer errerB = new StringBuffer();
				if(StringUtils.isBlank(account)){
					errerB.append("请输入您的个人账号。<br>");
				}else if(!account.matches("^[1-9]{1}[0-9]{16}[0-9Xx]{1}$")){
					errerB.append("您的个人账号输入错误。<br>");
				}
				
				if(StringUtils.isBlank(phonenumber)){
					errerB.append("请输入手机号码。<br>");
				}else if(!phonenumber.matches("^1[0-9]{10}$")){
					errerB.append("您的手机号码输入错误。<br>");
				}
				
				if(StringUtils.isBlank(phonecode)){
					errerB.append("请输入手机接收到验证码。<br>");
				}else if(!phonecode.matches("^[0-9]{6}$")){
					errerB.append("您的手机验证码输入格式不正确。<br>");
				}
				
				if(errerB.toString().endsWith("<br>")){//如果以<br>结尾,去掉<br>
					errerB.setLength(errerB.length() - 4);
				}
				
				//校验不通过
				if(errerB.length() != 0){
					rs.put("msg", errerB.toString());
					rs.put("status", "-1");
					JSONUtil.write(response, rs);
					return;
				}
				//校验通过,判断账号是否存在
				WwAc01UserForm form = wwkaMng.getUserInfo(account);
				if(form == null){
					rs.put("msg", "您输入的账号不存在。");
					rs.put("status", "-1");
					JSONUtil.write(response, rs);
					return;
				}else if(!phonenumber.equals(form.getPhonenumber())){//账号存在,判断手机号码是否与系统一致
					rs.put("msg", "您输入的手机账号与该账号在系统中预留的手机号码不一致。");
					rs.put("status", "-1");
					JSONUtil.write(response, rs);
					return;
				}
				//以上都通过
				if(codestr.equals(phonecode)){//验证码正确重置密码
					//生成随机验证码
					String password = new MessageCode().getMessageCode();
					WwkaDto dto = new WwkaDto();
					dto.setAccount(account);
					dto.setPassword(password);
					//重置密码
					wwkaMng.resetNewPwd(dto);
					String msg = "您的个人账号密码已重置为:" + password
							+ ",请您及时使用重置的新密码登陆并修改密码。";
					MessageUtil.sendMessage(msg, phonenumber);
					session.removeAttribute(session.getId() + "_resetpassword");
					rs.put("msg", "您个人账号的密码已发送到您的手机。请您及时登陆并修改密码。");
					rs.put("status", "1");
					JSONUtil.write(response, rs);
				}else{
					rs.put("msg", "您输入的手机验证码不正确,请重新输入。");
					rs.put("status", "-1");
					JSONUtil.write(response, rs);
				}
			}
		}
		
		
	}
	
}


前端页面在此省略。

 

以上是关于利用线程创建发送手机验证码的工具类的主要内容,如果未能解决你的问题,请参考以下文章

解决申请开发者office E5中无法发送手机验证码,reCaptcha加载失败

分享一个免费接收短信验证码的网站

手机验证码的相关知识

用Java redis 实现发送手机验证码的功能

短信验证码的工作原理

防止验证码的恶意发送