上篇博文具體講了RabbitMQ的知識,這篇博文就實際應用一下RabbitMQ,並藉助阿里雲進行發送短信驗證碼的功能。
註冊阿里雲短信服務
如果要使用阿里雲的短信服務,就需要在阿里雲的官網上申請。
首先登錄阿里雲,支付寶或者淘寶登錄即可。
登錄完就是上面這個界面,然後在產品與服務中找到雲通信下面的短信服務。
如果沒有開通,直接點擊開通,因爲博主已經開通了,所以進來就是這個界面。
框框中的東西"簽名管理",“模板管理”,需要根據自己的情況自己申請的,然後等系統通過即可。
當然,阿里雲還提供了發送短信的代碼Demo,這個讀者可以自行查閱。
代碼實現
需求:用戶通過手機號註冊,需要手機發送驗證碼。填寫正確的驗證碼,就可以完成註冊。
此項目還是基於另一篇博文:《SpringBoot中使用RabbitMQ消息中間件》
因爲這裏還是要使用消息中間件,所以,先導入Maven依賴。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.1.0</version>
</dependency>
要用到阿里雲,所以也要將依賴導入。
然後修改配置文件。
spring:
# 配置rabbitmq
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
# 阿里雲相關配置
aliyun:
sms:
accessKeyId:
accessKeySecret:
signName1:
templateCode1:
上面是RabbitMQ的配置,下面是阿里雲的配置,accessKeyId和accessKeySecret如圖所示。
通過這裏點進去就能看到。下面兩個自定義配置就是剛纔需要申請的"簽名管理",“模板管理”,只有申請通過之後,才能使用。
創建生產者,發送短信驗證碼。
因爲要與數據庫交互,博主這裏使用了MySQL數據庫,使用JPA來操作,同時這裏還使用了Redis。
如果使用其他數據庫或者其他ORM框架的讀者,需要使用博主的例子修改的話,也沒有什麼影響!
創建一個實體類,User
@Data
@Entity
@Table(name = "qf_user")
@ApiModel(value = "User", description = "用戶")
public class User implements Serializable {
@Id
@ApiModelProperty(value = "主鍵")
private String id;
@ApiModelProperty(value = "手機")
private String mobile;
@ApiModelProperty(value = "密碼")
private String password;
@ApiModelProperty(value = "鹽值")
private String salt;
@Column(name = "nick_name")
@ApiModelProperty(value = "暱稱")
private String nickName;
@ApiModelProperty(value = "性別")
private String sex;
@ApiModelProperty(value = "生日")
private Date birthday;
@ApiModelProperty(value = "頭像")
private String avatar;
@ApiModelProperty(value = "郵箱")
private String email;
@Column(name = "reg_date")
@ApiModelProperty(value = "註冊日期")
private Date regDate;
@Column(name = "update_date")
@ApiModelProperty(value = "修改日期")
private Date updateDate;
@Column(name = "last_date")
@ApiModelProperty(value = "最後登錄日期")
private Date lastDate;
}
因爲這是博主項目中的一部分,爲了方便,我就直接拷貝過來了。
關於dao層的部分就不上代碼了,就一個增刪改查而已。下面是service層
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private RabbitTemplate rabbitTemplate;
@Value("${spring.redis.key.mobile}")
private String verifyCodeKey;
public void save(User user) {
user.setRegDate(new Date());
user.setUpdateDate(new Date());
user.setLastDate(new Date());
userRepository.save(user);
}
/**
*發送短信
*/
public void sendMobileMessage(String mobile) {
//生成六位隨機數
String verifyCode = RandomStringUtils.randomNumeric(6);
//寫入redis緩存
redisTemplate.opsForValue().set(verifyCodeKey + mobile, verifyCode, 5, TimeUnit.MINUTES);
//發給用戶
Map<String, String> stringMap = Maps.newHashMap();
stringMap.put("mobile", mobile);
stringMap.put("verifyCode", verifyCode);
//使用了direct模式
rabbitTemplate.convertAndSend(RabbitConstant.MOBILE_ROUTING_KEY, stringMap);
//記錄到日誌中
boolean enabled = log.isDebugEnabled();
if (enabled) {
log.debug("mobile:[{}],verifyCode:[{}]", mobile, verifyCode);
}
}
/**
*註冊
*/
public ResultBean register(User user, String code) {
//判斷redis中是否存在
String verifyCode = redisTemplate.opsForValue().get(verifyCodeKey + user.getMobile());
if (StringUtils.isEmpty(verifyCode)) {
return new ResultBean(new CustomerException("短信驗證碼爲空"), -1);
}
if (!verifyCode.equals(code)) {
return new ResultBean(new CustomerException("驗證碼錯誤!"), 100);
}
save(user);
return new ResultBean();
}
}
裏面有很多變量,博主都提取出來了,不可能將所有代碼都放入,如果不明白的讀者,可以給博主留言,博主一定會回答。
基本上生產者就完成了。執行上面的代碼,就將驗證碼放入Redis緩存中,將手機號和驗證碼封裝成Map放入消息隊列中,可以作爲一個僞發送短信的功能,只有等到發送短息的服務中的消費者來消費隊列中的消息時,才能真正的發送驗證碼。
接着,將創建消息的消費者。實際上,這裏需要提取出另一個服務,專門發送手機短信的服務。博主這裏將其提取出來並封裝了發送短信的工具類。
/**
* @ClassName: SmsUtil
* @Author: 清風一陣吹我心
* @Description: TODO 阿里雲發送短信驗證碼的工具類
* @Date: 2019/10/26 13:37
* @Version 1.0
**/
@Component
public class SmsUtil {
private static final String regionId = "cn-hangzhou";
/**
* 產品域名
*/
private static final String DOMAIN = "dysmsapi.aliyuncs.com";
/**
* 系統規定參數。取值:SendSms
*/
private static final String ACTION = "SendSms";
/**
* 可以得到當前配置文件中所有的信息
*/
@Autowired
private Environment environment;
/**
* //TODO
* 發送短信
*
* @param phoneNumbers 手機號
* @param signName 短信簽名名稱
* @param templateCode 短信模板ID
* @param templateParam 參數
* @return com.aliyuncs.CommonResponse
*/
public CommonResponse sendSms(String phoneNumbers, String signName, String templateCode, String templateParam) {
String accessKeyId = environment.getProperty("aliyun.sms.accessKeyId");
String accessKeySecret = environment.getProperty("aliyun.sms.accessKeySecret");
//調整超時時間
System.setProperty("sun.net.client.defaultConnectTimeout", "5000");
System.setProperty("sun.net.client.defaultReadTimeout", "5000");
DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
IAcsClient client = new DefaultAcsClient(profile);
CommonRequest request = new CommonRequest();
request.setMethod(MethodType.POST);
request.setDomain(DOMAIN);
request.setVersion("2017-05-25");
request.setAction(ACTION);
//待發送手機號
request.putQueryParameter("PhoneNumbers", phoneNumbers);
//短信簽名
request.putQueryParameter("SignName", signName);
//短信模板Id
request.putQueryParameter("TemplateCode", templateCode);
//短信模板變量對應的實際值,JSON格式。如果JSON中需要帶換行符,請參照標準的JSON協議處理。
request.putQueryParameter("TemplateParam", templateParam);
//上行短信擴展碼,無特殊需要此字段的用戶請忽略此字段。
//request.putQueryParameter("SmsUpExtendCode", "0000");
//外部流水擴展字段
//request.putQueryParameter("OutId", "0000");
CommonResponse commonResponse = null;
try {
commonResponse = client.getCommonResponse(request);
} catch (ClientException e) {
e.printStackTrace();
}
return commonResponse;
}
}
上面的代碼在阿里雲提供的文檔中都有詳細介紹,博主這裏只是做了簡單的修改。
發送短信的工具類完成後,需要用到RabbitMQ了,將消息隊列中的消息消費掉,發送真正的短信到用戶的手機上。
@Slf4j
@Component
@RabbitListener(queues = RabbitConstant.MOBILE_ROUTING_KEY)
public class MobileMessageListener {
@Autowired
private SmsUtil smsUtil;
@Value("${aliyun.sms.signName1}")
private String signName1;
@Value("${aliyun.sms.templateCode1}")
private String templateCode1;
@RabbitHandler
public void messageHandler(Map<String, String> map) {
String mobile = map.get("mobile");
String verifyCode = map.get("verifyCode");
boolean debugEnabled = log.isDebugEnabled();
if (debugEnabled) {
log.debug("手機號:[{}],驗證碼:[{}]", mobile, verifyCode);
}
String templateParam = "{" + "code" + ":" + verifyCode + "}";
smsUtil.sendSms(mobile, signName1, templateCode1, templateParam);
}
}
基本上發送短信的功能就完成了,下面就可以啓動服務測試了。
因爲功能並不複雜,通過文檔就能夠實現的。博主這裏只是做一個簡單的講解。
技術之外
昨天博主看騰訊視頻,發現《烈火英雄》可以看了,以前本來想去電影院看的,但是都沒時間去,主要是因爲“一個人不想出去”,emmmm~ 然後博主就借來一個騰訊視頻的會員,把電影看了一遍。基本上,全程都是揪着心看的。覺得這個電影拍的太好了。真的覺得"人名英雄"太偉大了。心中也與那句“此生無悔入華夏,來生願在種花家”,產生了共鳴。
千言萬語都沒有看一遍來的實際,如果有讀者讀到這裏,並且還沒有看過《烈火英雄》的,博主強烈建議大家去看呢,但是,首先要做好心理準備啊。
努力不一定成功,但不努力一定不成功