springboot项目系列-博客系统06整合rabbitmq实现异步发邮件
今天突发奇想,既然会了rabbitmq为何不用,之前的注册发邮件功能是使用springboot的异步任务做的,但是想想以后还要搞微服务,就用rabbitmq大改了,顺便加上了邮箱验证登录,防止用户忘记密码导致无法登录.
1.首先导入amqp的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2.导入邮件任务的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
3.配置rabbitmq的相关配置
spring
application:
name: rabbitmq-springboot
rabbitmq:
host: 你的ip地址
port: 5672
username: 你设置的用户
password: 您设置的密码
virtual-host: /ems
4.用户注册的时候,我们需要给他发邮件,但是还不能让他体验差,所以使用rabbitmq异步来发送邮件完全不影响用户体验.
@Override
public int addUser(User user) {
redisUtil.incr("userCount",1);
user.setPassword(MD5Utils.code(user.getPassword()));
user.setCreateTime(new Date());
rabbitTemplate.convertAndSend("hello",user.getEmail());
return userDao.addUser(user);
}
下面这一句就是向mq中发送消息,也就是把用户注册的邮箱放到hello队列里面
rabbitTemplate.convertAndSend("hello",user.getEmail());
注册成功,消费消息队列中的消息
/**
* @Author: CYW
* @Date: 2021/1/5 11:53
* 监听用户注册,注册成功给用户发邮件
*/
@Component
@RabbitListener(queues = "hello")
public class HelloConsumer {
@Autowired
private SendMail sendMail;
@RabbitHandler
public void executeHello(String email){
System.out.println(email);
sendMail.sendmail(email,"欢迎来到Cyw的小家");
}
}
5.当用户忘记密码的时候,可以选择邮箱接收验证码登录
前台页面
当点击发送验证码的时候,后台会生成6位随机数,使用rabbitmq给用户发一份,存到redis中一份,用于判断用户输入的验证码对错
/**
* 邮箱登录
* @param email
* @return
*/
@RequestMapping("/emailLogin")
@ResponseBody
public String emailLogin(String email){
User user = userService.queryUserByEmail(email);
if (user == null){
return "fail";
}
userService.sendSms(email);//调用发邮件
return "success";
}
@Override
public void sendSms(String email) {
//生成6位随机数
String checkCode = RandomStringUtils.randomNumeric(6);
//向缓存中放一份
redisTemplate.opsForValue().set("checkCode_"+email,checkCode,1, TimeUnit.MINUTES);
redisTemplate.opsForValue().set("email_"+email,email,1, TimeUnit.MINUTES);
//给用户发一份(rabbitmq)
Map<String,String> map = new HashMap<>();
map.put("email",email);
map.put("checkCode",checkCode);
rabbitTemplate.convertAndSend("sms",map);
//控制台显示一份
System.out.println("验证码为:"+checkCode);
}
消费队列中发验证码的消息,给用户发验证码,异步快呀,设置redis存的验证码有效时间60s,因为后台根据redis取出来的验证码进行比对,如果过期则不能认证了
/**
* @Author: CYW
* @Date: 2021/1/1 00:01
* 监听用户的验证码....
*/
@Component
@RabbitListener(queues = "sms")
public class SmsConsumer {
@Autowired
private SendMail sendMail;
@RabbitHandler
public void executeSms(Map<String,String> map){
// System.out.println("邮箱:"+map.get("email"));
// System.out.println("验证码:"+map.get("checkCode"));
String email = map.get("email");
String checkCode = map.get("checkCode");
sendMail.sendmail(email,"验证码为:"+checkCode+"有效时间为60秒");
}
后台判断用户输入的验证码是否正确,如果正确,则根据邮箱查出用户名及密码,再次放到shiro中进行认证授权,因为是在数据库中查出的用户名及密码,必然正确,必然能登录成功
@RequestMapping("/emailCheckLogin")
@ResponseBody
public String emailCheckLogin(String email,String code,HttpSession session){
System.out.println(email);
System.out.println(code);
if (email.equals(redisUtil.get("email_"+email))
&& code.equals(redisUtil.get("checkCode_"+email))){
User user1 = userService.queryUserByEmail(email);
String username = user1.getUsername();
String password = user1.getPassword();
System.out.println("执行shiro");
AuthenticationToken token=new UsernamePasswordToken(username,password);
//调用Shiro进行认证
SecurityUtils.getSubject().login(token);
//从Shiro中拿出User对象,放到session中
User user=(User)SecurityUtils.getSubject().getPrincipal();
session.setAttribute("user",user);
System.out.println("登录成功!");
//msg = "success";
return "success";
}
return "fail";
}