需要源码小伙伴可以到微信小程序:”MINIIT资源库“获取,作者承诺免费
PS:在编写功能之前,需要得到阿里云短信服务API;
使用消息队列(mq)可以将主业务和副业务分离,主业务是用户注册,注册成功通知是副业务,将主业务和副业务分离
application.yml
spring:
redis:
host: 填入自己虚拟机IP #linuxIP
port: 填入自己Redis端口 #端口
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springbootregisterlogin?serverTimezone=UTC
username: root
password: 123456
default-encoding: UTF-8 #编码字符集
rabbitmq:
host: 填入自己虚拟机IP #linuxIP
port: 填入自己rabbitmq端口 #rabbitmq端口,默认5672
username: 自己的用户名 #用户名
password: 自己的密码 #密码
template:
exchange: mq.user.exchange #交换机
retry:
initial-interval: 1000
max-interval: 10000
multiplier: 2
enabled: true
publisher-confirms: true
aliyun:
accessKeyId: 填写自己的短信服务ID #短信服务ID
accessKeySecret: 填写短信服务授权码 #短信服务授权码
signName: 填写短息服务名称 #短息服务名称
templateCode: 填写自己的发送短信模板编号 #发送短信模板编号
mybatis:
configuration:
map-underscore-to-camel-case: true #开启驼峰映射
User.java
package com.doll.springbootregisterlogin.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
private Integer id; //id
private String phone; // 电话
private String password; //密码
private String salt; //盐值
private String confirmCode; //确认码/验证码
}
UserDto.java
package com.doll.springbootregisterlogin.dto;
import lombok.Data;
@Data
public class UserDto {
private String phone;
private String email;
}
MsgServiceImpl.java
package com.doll.springbootregisterlogin.service.impl;
import com.alibaba.fastjson.JSON;
import com.doll.springbootregisterlogin.constants.Constants;
import com.doll.springbootregisterlogin.pojo.User;
import com.doll.springbootregisterlogin.service.MsgService;
import com.doll.springbootregisterlogin.utils.NumberUtil;
import com.doll.springbootregisterlogin.utils.SmsUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Service
public class MsgServiceImpl implements MsgService {
@Resource
private SmsUtil smsUtil;
@Resource
private RedisTemplate<String,Object> redisTemplate;
/**
* 发送短信验证码并存入redis
* @param user
*/
@Override
public void sendVerifyCode(User user) {
String code = NumberUtil.generateCode(6);//生成验证码
Map<String,String> map=new HashMap<>();
map.put("code",code);
smsUtil.send(user.getPhone(), JSON.toJSONString(map));//发送验证码
String key = Constants.VERIFY_CODE_PREFIX + user.getPhone();
redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);//验证码存入redis
}
/**
* 读取redis验证码并判断输入验证码
* @param user
* @return
*/
@Override
public Map<String, String> doVerification(User user) {
Map<String,String> resultMap=new HashMap<>();
Object VerificationCode = redisTemplate.opsForValue().get(Constants.VERIFY_CODE_PREFIX +user.getPhone());
if(user.getConfirmCode().equals(VerificationCode)){
resultMap.put("code","200");
}else {
resultMap.put("code","401");
}
return resultMap;
}
}
UserServiceImpl.java
package com.doll.springbootregisterlogin.service.impl;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSON;
import com.doll.springbootregisterlogin.constants.Constants;
import com.doll.springbootregisterlogin.dto.UserDto;
import com.doll.springbootregisterlogin.mapper.UserMapper;
import com.doll.springbootregisterlogin.pojo.User;
import com.doll.springbootregisterlogin.service.MsgService;
import com.doll.springbootregisterlogin.service.UserService;
import com.doll.springbootregisterlogin.utils.BeanCopyUtil;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Resource
private MsgService msgService;
@Resource
private RedisTemplate<String,String> redisTemplate;
@Resource
private AmqpTemplate amqpTemplate;
@Override
public Map<String, Object> createByMessage(User user) {
Map<String,Object> resultMap=new HashMap<>();
//盐值
String salt= RandomUtil.randomString(6);
//加密密码:原始密码+盐值
String md5Pwd= SecureUtil.md5(user.getPassword()+salt);
String key = Constants.VERIFY_CODE_PREFIX + user.getPhone();
//初始化账号信息
user.setPhone(user.getPhone());
user.setSalt(salt);
user.setPassword(md5Pwd);
//判断短信验证是否正确,正确则调用doVerification()方法,将注册信息存入数据库,并删除redis中验证码,将电话信息写入MQ
Map<String, String> result = msgService.doVerification(user);
if (result.get("code").equals("200")){
int i = userMapper.insertUser(user);
System.out.println("i---------->"+i);
if(i==1){
resultMap.put("code",200);
redisTemplate.delete(key);//验证成功删除redis中验证码
//将用户信息写入MQ
UserDto userDto=new UserDto();
BeanCopyUtil.copyProperties(user,userDto);
String message = JSON.toJSONString(userDto);
amqpTemplate.convertAndSend("user.insert", message);
}else {
resultMap.put("code",400);
}
}else if (result.get("code").equals("401")){
resultMap.put("code",401);
}
else {
resultMap.put("code",400);
}
return resultMap;
}
}
Usercontroller.java
package com.doll.springbootregisterlogin.controller;
import com.doll.springbootregisterlogin.pojo.User;
import com.doll.springbootregisterlogin.service.MsgService;
import com.doll.springbootregisterlogin.service.UserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("user")
public class UserController {
@Resource
private UserService userService;
@Resource
private MsgService msgService;
/**
* 发送短信验证码
* @param user
* @return
*/
@PostMapping("sendVerificationCode")
public Map<String,Object> sendVerificationCode(User user){
Map<String,Object> resultMap=new HashMap<>();
msgService.sendVerifyCode(user);
resultMap.put("code",200);//发送成功返回成功代码
return resultMap;
}
/**
* 注册
* @param user
* @return
*/
@PostMapping("createByMessage")
public Map<String,Object> createByMessage(User user){
System.out.println("已进createByMessage"+user.getPhone());
return userService.createByMessage(user);
}
}
注册成功将手机号写入消息队列
application.yml
aliyun:
accessKeyId: 填自己的 #短信服务ID
accessKeySecret: 填自己的 #短信服务授权码
signName: 填自己的 #短信服务名称
templateCode: 填自己的 #短信服务模板
server:
port: 8082 #tomcat端口
spring:
rabbitmq:
host: 填自己linuxIp# linuxIp
port: 填自己的rabbitmq端口 #rabbitmq端口
username: 用户名 #用户名
password: 密码 #密码
SmsUtil.java(发送短信方法)
package com.doll.utils;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.teaopenapi.models.Config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "aliyun")
@Data
public class SmsUtil {
private String accessKeyId;
private String accessKeySecret;
private String signName;
private String templateCode;
public void send(String phone, String code) {
Config config = new Config()
.setAccessKeyId(accessKeyId)
.setAccessKeySecret(accessKeySecret);
// 访问的域名
config.endpoint = "dysmsapi.aliyuncs.com";
Client client = null;
try {
client = new Client(config);
} catch (Exception e) {
//throw new BasicException(ExceptionEnum.ALIYUN_CREATE_CLIENT_FAIL);
}
SendSmsRequest sendSmsRequest = new SendSmsRequest()
.setPhoneNumbers(phone)
.setSignName(signName)
.setTemplateCode(templateCode)
.setTemplateParam(code);
try {
client.sendSms(sendSmsRequest);
} catch (Exception e) {
//throw new BasicException(ExceptionEnum.CALL_SMS_API_FAIL);
}
}
}
MsgListener.java(监听mq,监听到手机号就调用执行发送短信通知注册成功)
package com.doll.liseners;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.doll.utils.SmsUtil;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@Component
public class MsgListener {
@Resource
private SmsUtil smsUtil;
@RabbitListener(
bindings = @QueueBinding(
value = @Queue(value = "msg.queue"),
exchange = @Exchange(value = "mq.user.exchange",type = ExchangeTypes.TOPIC),
key = {"user.insert"}
)
)
public void sendMsg(String message){
System.out.println("msg===========>"+message);
JSONObject jsonObject = JSONObject.parseObject(message);
String phone = jsonObject.getString("phone");
Map<String, String> map = new HashMap<>();
map.put("code",phone);
String value = JSON.toJSONString(map);
smsUtil.send(phone,value);
}
}