千家信息网

Java怎么实现短信发送

发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,本篇内容主要讲解"Java怎么实现短信发送",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Java怎么实现短信发送"吧!1. 引入相关maven依赖
千家信息网最后更新 2025年02月01日Java怎么实现短信发送

本篇内容主要讲解"Java怎么实现短信发送",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Java怎么实现短信发送"吧!

1. 引入相关maven依赖

        com.github.qcloudsms        qcloudsms        1.0.6    com.qcloud        qcloud-java-sdk        2.0.1        com.tencentcloudapi        tencentcloud-sdk-java        3.1.270        cn.hutool        hutool-all        5.4.2

2. 编写短信发送工具类

package com.cloud.system.common.utils; import ch.qos.logback.core.net.server.Client;import cn.hutool.core.util.RandomUtil;import com.cloud.system.api.enums.SmsLengthEnum;import com.cloud.system.api.enums.SmsTypeEnum;import com.tencentcloudapi.common.Credential;import com.tencentcloudapi.common.exception.TencentCloudSDKException;import com.tencentcloudapi.common.profile.ClientProfile;import com.tencentcloudapi.common.profile.HttpProfile;import com.tencentcloudapi.sms.v20210111.SmsClient;import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;import com.tencentcloudapi.sms.v20210111.models.SendStatus;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Component; import java.io.BufferedInputStream;import java.io.FileInputStream;import java.io.InputStream;import java.io.InputStreamReader;import java.util.Properties; /** * @program: server-master * @description: * @author: hjq * @create: 2021/12/17 */@Component@Slf4jpublic class SmsUtil {     /** 腾讯云账户密钥对secretId(在访问管理中配置) */    private static String secretId;     /** 腾讯云账户密钥对secretKey(在访问管理中配置) */    private static String secretKey;     /** 短信应用appId */    private static String appId;     /** 短信应用appKey */    private static String appKey;     /** 签名 */    private static String smsSign;     /** 过期时间 */    private static String expireTime;     /** 登录验证模板 */    private static String loginTemplateId;     /** 修改密码验证模板 */    private static String pwdTemplateId;     static {        try {            Properties prop=new Properties();            prop.load(new InputStreamReader(                    Client.class.getClassLoader().getResourceAsStream("sms.properties"), "gbk"));            secretId = prop.get("secretId").toString();            secretKey = prop.get("secretKey").toString();            appId = prop.get("appId").toString();            appKey = prop.get("appKey").toString();            smsSign = prop.get("smsSign").toString();            expireTime = prop.get("expireTime").toString();            loginTemplateId = prop.get("loginTemplateId").toString();            pwdTemplateId = prop.get("pwdTemplateId").toString();         } catch(Exception e) {            e.printStackTrace();        }    }     /**     * 短信发送工具类     * @param phoneNumbers 下发手机号码     * @param templateParamSet  模板参数     */    public static SendStatus sendMessage(String[] phoneNumbers, String[] templateParamSet,Integer type) throws TencentCloudSDKException {        // 实例化一个认证对象,入参需要传入腾讯云账户密钥对secretId,secretKey        Credential cred = new Credential(secretId, secretKey);        // 实例化一个http选项        HttpProfile httpProfile = new HttpProfile();        httpProfile.setReqMethod("POST");        httpProfile.setConnTimeout(60);         //实例化一个客户端配置对象,指定超时时间等配置        ClientProfile clientProfile = new ClientProfile();        /* SDK默认用TC3-HMAC-SHA256进行签名         * 非必要请不要修改这个字段 */        clientProfile.setSignMethod("HmacSHA256");        clientProfile.setHttpProfile(httpProfile);        SmsClient client = new SmsClient(cred, "ap-guangzhou",clientProfile);        SendSmsRequest req = new SendSmsRequest();        //短信应用ID        req.setSmsSdkAppId(appId);        //短信签名内容        req.setSignName(smsSign);        /* 模板 ID: 必须填写已审核通过的模板 ID。模板ID可登录 [短信控制台] 查看 */        //根据不同业务使用不同的模板        switch (type){            case 1:                req.setTemplateId(pwdTemplateId);                break;            case 2:                req.setTemplateId(loginTemplateId);                break;        }        //下发手机号码        req.setPhoneNumberSet(phoneNumbers);        /* 模板参数: 若无模板参数,则设置为空 */        req.setTemplateParamSet(templateParamSet);        SendSmsResponse res = client.SendSms(req);        return res.getSendStatusSet()[0];    }     /**     * 随机生成指定长度的短信的验证码     *     * @param smsLengthEnum 短信验证码长度枚举     * @return 随机验证码     */    public static String createSmsRandomCode(SmsLengthEnum smsLengthEnum) {        return RandomUtil.randomNumbers(smsLengthEnum.getLength());    }     /**     * 创建短信验证码,缓存键策略     * 策略:前缀_业务名_手机号     *     * @param prefix      前缀     * @param phone       手机号     * @param businessStr 业务名     * @return 短信验证码,缓存键策略     */    public static String createSmsCacheKey(String prefix, String phone, String businessStr) {        return prefix + "_" + businessStr + "_" + phone;    }}

3. 业务层

使用redis存储随机生成的验证码,并在使用后销毁

package com.cloud.system.api.service.impl; import com.cloud.system.api.bean.SmsPwdBean;import com.cloud.system.api.bean.SmsResult;import com.cloud.system.api.entity.HumanInfo;import com.cloud.system.api.entity.SmsRecord;import com.cloud.system.api.enums.SmsLengthEnum;import com.cloud.system.api.enums.SmsTypeEnum;import com.cloud.system.api.mapper.HumanInfoMapper;import com.cloud.system.api.mapper.SmsRecordMapper;import com.cloud.system.api.service.SmsRecordService;import com.cloud.system.common.utils.RedisUtil;import com.cloud.system.common.utils.RegUtils;import com.cloud.system.common.utils.SmsUtil;import com.tencentcloudapi.common.exception.TencentCloudSDKException;import com.tencentcloudapi.sms.v20210111.models.SendStatus;import lombok.extern.slf4j.Slf4j;import org.apache.commons.codec.digest.DigestUtils;import org.apache.commons.collections.CollectionUtils;import org.apache.commons.lang.StringUtils;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import tk.mybatis.mapper.entity.Example; import javax.annotation.Resource;import java.util.Date;import java.util.List;import java.util.Objects; /** * @program: server-master * @description: * @author: hjq * @create: 2021/12/20 */@Service("smsRecordService")@Transactional@Slf4jpublic class SmsRecordServiceImpl implements SmsRecordService {     @Resource    private SmsRecordMapper smsRecordMapper;     @Resource    private HumanInfoMapper humanInfoMapper;     @Resource    private RedisUtil redisUtil;     @Override    public SmsResult getModPwdVcode(String humanName, String phoneNumber) {        //首先校验手机号码        if (!RegUtils.isMoblie(phoneNumber)) return new SmsResult(500,"手机号格式不正确!",null);        //然后校验输入手机号是否和该用户名绑定        if (humanInfoMapper.existByNameAndPhone(humanName, phoneNumber) <= 0){            return new SmsResult(500,"该用户不存在,请联系管理员注册!",null);        }        //生成六位的随机验证码        return sendSms(phoneNumber, SmsTypeEnum.SMS_TYPE_1, humanName);    }     /**     * 修改密码     */    @Override    public SmsResult updatePwdByHuman(SmsPwdBean bean) {        //创建相同的缓存键        String cacheKey = SmsUtil.createSmsCacheKey(String.valueOf(bean.getUsername().hashCode()),bean.getPhoneNumber(),                SmsTypeEnum.SMS_TYPE_1.getTypeName());        //验证码校验,若返回500,则直接返回        SmsResult result = vCodeCheck(cacheKey, bean.getCaptcha());        if (500 == result.getCode()){            return result;        }        //获取人员id与密码进行加密,然后修改密码        Long humanId = humanInfoMapper.existByNameAndPhone(bean.getUsername(),bean.getPhoneNumber());        String code = DigestUtils.md5Hex(bean.getRepassword().concat(String.valueOf(humanId))).toUpperCase();        humanInfoMapper.modifyPwdByNameAndPhone(bean.getUsername(),bean.getPhoneNumber(),code);        //清除已使用的验证码        redisUtil.del(cacheKey);        return new SmsResult(200,"密码已重置!",null);    }      /**     * 用户登录获取验证码     * @param humanName 用户名     * @return     */    @Override    public SmsResult getLoginCode(String humanName){        //获取用户信息        Example example = new Example(HumanInfo.class);        Example.Criteria criteria = example.createCriteria();        criteria.andEqualTo("deleteFlag", 0);        criteria.andEqualTo("userName", humanName);        List humanInfoList = humanInfoMapper.selectByExample(example);        //校验用户手机号        if (CollectionUtils.isEmpty(humanInfoList) || humanInfoList.size() != 1            || StringUtils.isBlank(humanInfoList.get(0).getTelephone())            || !RegUtils.isMoblie(humanInfoList.get(0).getTelephone())) {            return new SmsResult(500,"手机号格式不正确!",null);        }        return sendSms(humanInfoList.get(0).getTelephone(), SmsTypeEnum.SMS_TYPE_2, humanInfoList.get(0).getHumanName());    }     /**     * 校验用户登录验证码     * @return     */    @Override    public SmsResult checkLoginCode(HumanInfo info,String captCha){        //创建相同的缓存键        String cacheKey = SmsUtil.createSmsCacheKey(String.valueOf(info.getHumanName().hashCode()),info.getTelephone(),                SmsTypeEnum.SMS_TYPE_2.getTypeName());        //验证码校验,若返回500,则直接返回        SmsResult result = vCodeCheck(cacheKey, captCha);        if (200 == result.getCode()){            //清除已使用的验证码            redisUtil.del(cacheKey);        }        return result;    }     /**     * 发送短信     * @param telephone 手机号     * @param smsType2  短信类型     * @param humanName 用户名     * @return     */    private SmsResult sendSms(String telephone, SmsTypeEnum smsType2, String humanName) {        //生成六位的随机验证码        String randomCode = SmsUtil.createSmsRandomCode(SmsLengthEnum.SMS_LENGTH_6);        //构建参数,发送短信        SendStatus sendStatus = null;        try {            sendStatus = SmsUtil.sendMessage(new String[]{telephone}, new String[]{randomCode}, smsType2.getType());        } catch (TencentCloudSDKException e) {            log.error("********短信发送失败" + e.getMessage() + "*********");            e.printStackTrace();        }        if (Objects.nonNull(sendStatus) && "Ok".equals(sendStatus.getCode())) {            //发送成功后往记录表插值同时将验证码存储至redis,300s过期            insertSmsRecord(telephone,smsType2.getType());            //创建缓存键            String cacheKey = SmsUtil.createSmsCacheKey(String.valueOf(humanName.hashCode()), telephone, smsType2.getTypeName());            redisUtil.set(cacheKey, randomCode, 300);            return new SmsResult(200, "验证码发送成功!", null);        } else {            return new SmsResult(500, "验证码发送失败!", null);        }    }     /**     * 插入短信发送记录     * @param phoneNumber     */    private void insertSmsRecord(String phoneNumber, int type) {        SmsRecord smsRecord = new SmsRecord();        smsRecord.setRecipient(phoneNumber);        smsRecord.setSendTime(new Date());        smsRecord.setSmsType(type);        smsRecordMapper.insert(smsRecord);    }     /**     * 验证码校验     */    private SmsResult vCodeCheck(String cacheKey,String captcha){        if (!redisUtil.hasKey(cacheKey)){            return new SmsResult(500,"验证码已过期,请重新获取!",null);        }        if (!captcha.equals(redisUtil.get(cacheKey))){            return new SmsResult(500,"验证码错误!",null);        }        return new SmsResult(200,"验证码正确!",null);    }}

3. 相关工具类

package com.cloud.system.common.utils; /** * @author: hjq * @create: 2021-01-07 09:54 **/import java.util.regex.Matcher;import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; /** * 正则表达式工具类 * */public class RegUtils {    /**     * 邮箱     */    public static final String EMAIL = "^\\w+((-\\w+)|(\\.\\w+))*\\@[A-Za-z0-9]+((\\.|-)[A-Za-z0-9]+)*\\.[A-Za-z0-9]+$";    /**     * 手机号码     */    public static final String PHONE = "^(1[3-9]([0-9]{9}))$";    /**     * 仅中文     */    public static final String CHINESE = "^[\\u4E00-\\u9FA5\\uF900-\\uFA2D]+$";    /**     * 整数     */    public static final String INTEGER = "^-?[1-9]\\d*$";    /**     * 数字     */    public static final String NUMBER = "^([+-]?)\\d*\\.?\\d+$";    /**     * 正整数     */    public static final String INTEGER_POS = "^[1-9]\\d*$";    /**     * 浮点数     */    public static final String FLOAT = "^([+-]?)\\d*\\.\\d+$";    /**     * 正浮点数     */    public static final String FLOAT_POS = "^[1-9]\\d*.\\d*|0.\\d*[1-9]\\d*$";    /**     * 是否为正整数数字,包括0(00,01非数字)     */    public static final String INTEGER_WITH_ZERO_POS = "^(([0-9])|([1-9]([0-9]+)))$";    /**     * 是否为整数数字,包括正、负整数,包括0(00,01非数字)     */    public static final String NUMBER_WITH_ZERO = "^((-)?(([0-9])|([1-9]([0-9]+))))$";    /**     * 是否为数字字符串     */    public static final String NUMBER_TEXT = "^([0-9]+)$";    /**     * 数字(整数、0、浮点数),可以判断是否金额,也可以是负数     */    public static final String NUMBER_ALL = "^((-)?(([0-9])|([1-9][0-9]+))(\\.([0-9]+))?)$";    /**     * QQ,5-14位     */    public static final String QQ = "^[1-9][0-9]{4,13}$";    /**     * IP地址     */    public static final String IP = "((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))";    /**     * 邮编     */    public static final String POST_CODE = "[1-9]\\d{5}(?!\\d)";    /**     * 普通日期     */    public static final String DATE = "^[1-9]\\d{3}-((0[1-9])|(1[0-2]))-((0[1-9])|([1-2][0-9])|(3[0-1]))$";    /**     * 复杂日期,不区分闰年的2月     * 日期格式:2017-10-19     * 或2017/10/19     * 或2017.10.19     * 或2017年10月19日     * 最大31天的月份:(((01|03|05|07|08|10|12))-((0[1-9])|([1-2][0-9])|(3[0-1])))     * 最大30天的月份:(((04|06|11))-((0[1-9])|([1-2][0-9])|(30)))     * 最大29天的月份:(02-((0[1-9])|([1-2][0-9])))     */    public static final String DATE_COMPLEX = "^(([1-2]\\d{3})(-|/|.|年)((((01|03|05|07|08|10|12))(-|/|.|月)((0[1-9])|([1-2][0-9])|(3[0-1])))|(((04|06|11))(-|/|.|月)((0[1-9])|([1-2][0-9])|(30)))|(02-((0[1-9])|([1-2][0-9]))))(日)?)$";     /**     * 复杂的日期,区分闰年的2月     * 这个日期校验能区分闰年的2月,格式如下:2017-10-19     * (见://www.yisu.com/article/50905.htm)     * ^((?!0000)[0-9]{4}-((0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-8])|(0[13-9]|1[0-2])-(29|30)|(0[13578]|1[02])-31)|([0-9]{2}(0[48]|[2468][048]|[13579][26])|(0[48]|[2468][048]|[13579][26])00)-02-29)$     */    public static final String DATE_COMPLEX_LEAP_YEAR = "^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$";      /**     * 正则表达式校验,符合返回True     * @param regex 正则表达式     * @param content 校验的内容     * @return     */    public static boolean isMatch(String regex, CharSequence content){        return Pattern.matches(regex, content);    }      /**     * 校验手机号码     * @param mobile     * @return     */    public static final boolean isMoblie(String mobile){        boolean flag = false;        if (null != mobile && !mobile.trim().equals("") && mobile.trim().length() == 11) {            Pattern pattern = Pattern.compile(PHONE);            Matcher matcher = pattern.matcher(mobile.trim());            flag = matcher.matches();        }        return flag;    }      /**     * 校验邮箱     * @param value     * @return     */    public static final boolean isEmail(String value){        boolean flag = false;        if (null != value && !value.trim().equals("")) {            Pattern pattern = Pattern.compile(EMAIL);            Matcher matcher = pattern.matcher(value.trim());            flag = matcher.matches();        }        return flag;    }      /**     * 校验密码     * @param password     * @return 长度符合返回true,否则为false     */    public static final boolean isPassword(String password){        boolean flag = false;        if (null != password && !password.trim().equals("")) {            password = password.trim();            if(password.length() >= 6 && password.length() <= 30){                return true;            }        }        return flag;    }      /**     * 校验手机验证码     * @param value     * @return 符合正则表达式返回true,否则返回false     */    public static final boolean isPhoneValidateCode(String value){        boolean flag = false;        if (null != value && !value.trim().equals("")) {            Pattern pattern = Pattern.compile("^8\\d{5}$");            Matcher matcher = pattern.matcher(value.trim());            flag = matcher.matches();        }        return flag;    }      /**     * 判断是否全部大写字母     * @param str     * @return     */    public static boolean isUpperCase(String str){        if(StringUtils.isEmpty(str)){            return false;        }        String reg = "^[A-Z]$";        return isMatch(reg,str);    }      /**     * 判断是否全部小写字母     * @param str     * @return     */    public static boolean isLowercase(String str){        if(StringUtils.isEmpty(str)){            return false;        }        String reg = "^[a-z]$";        return isMatch(reg,str);    }      /**     * 是否ip地址     * @param str     * @return     */    public static boolean isIP(String str){        if(StringUtils.isEmpty(str)){            return false;        }        return isMatch(IP, str);    }     /**     * 符合返回true,区分30、31天和闰年的2月份(最严格的校验),格式为2017-10-19     * @param str     * @return     */    public static boolean isDate(String str){        if(StringUtils.isEmpty(str)){            return false;        }        return isMatch(DATE_COMPLEX_LEAP_YEAR, str);    }      /**     * 简单日期校验,不那么严格     * @param str     * @return     */    public static boolean isDateSimple(String str){        if(StringUtils.isEmpty(str)){            return false;        }        return isMatch(DATE, str);    }      /**     * 区分30、31天,但没有区分闰年的2月份     * @param str     * @return     */    public static boolean isDateComplex(String str){        if(StringUtils.isEmpty(str)){            return false;        }        return isMatch(DATE_COMPLEX, str);    }      /**     * 判断是否为数字字符串,如0011,10101,01     * @param str     * @return     */    public static boolean isNumberText(String str){        if(StringUtils.isEmpty(str)){            return false;        }        return isMatch(NUMBER_TEXT, str);    }      /**     * 判断所有类型的数字,数字(整数、0、浮点数),可以判断是否金额,也可以是负数     * @param str     * @return     */    public static boolean isNumberAll(String str){        if(StringUtils.isEmpty(str)){            return false;        }        return isMatch(NUMBER_ALL, str);    }      /**     * 是否为正整数数字,包括0(00,01非数字)     * @param str     * @return     */    public static boolean isIntegerWithZeroPos(String str){        if(StringUtils.isEmpty(str)){            return false;        }        return isMatch(INTEGER_WITH_ZERO_POS, str);    }      /**     * 是否为整数,包括正、负整数,包括0(00,01非数字)     * @param str     * @return     */    public static boolean isIntegerWithZero(String str){        if(StringUtils.isEmpty(str)){            return false;        }        return isMatch(NUMBER_WITH_ZERO, str);    }      /**     * 符合返回true,QQ,5-14位     * @param str     * @return     */    public static boolean isQQ(String str){        if(StringUtils.isEmpty(str)){            return false;        }        return isMatch(QQ, str);    }      public static void main(String[] args) {        System.out.println(isMoblie("13430800244"));        System.out.println(isMoblie("17730800244"));        System.out.println(isMoblie("17630800244"));        System.out.println(isMoblie("14730800244"));        System.out.println(isMoblie("18330800244"));        System.out.println(isMoblie("19330800244"));        System.out.println(isMoblie("1333000244"));    }  }

到此,相信大家对"Java怎么实现短信发送"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

验证 短信 手机 数字 整数 模板 用户 短信发送 手机号 密码 日期 号码 手机号码 月份 格式 缓存 闰年 业务 内容 参数 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 格家网络技术营业执照 关于数据库的职位 国家电网网络安全教育 西安网络软件开发 关于网络安全的重大事件 创建修改和删除数据库的方法 辽宁oa管控软件开发平台 无线网络技术帧名词解释 详述网络安全的定义及重要性 网络安全色包括哪几种颜色 pcs9700数据库 如何恢复备份的数据库文件 办公软件开发靠谱臻动传媒 数据库中间层是什么意思 大马 网络安全 北京联通智慧安全网络技术罗静华 阿里云服务器刚购买能登录吗 阿里云云服务器管理与运维 淘宝软件开发是干什么的 陕西省网络安全等级测评 服务器域名没有注册能不能用 网络安全手抄报简单好看的 抖音阿雷很努力玩在那个服务器 普陀区定制网络技术哪家好 服务器进入桌面只显示一个鼠标 专科学游戏软件开发好就业吗 触犯法律的网络安全事件 关于规范促进网络安全 软件开发有限公司的企业使命 水利信息网络安全开展情况
0