一、项目回顾
会员注册流程
会员注册的时候,通过MQ异步推送邮件有什么好处?
答:因为通过传统的http来进行同步来推送,是非常耗费时间的,
有时候也会因为网络问题而影响了注册的流程。这个时候我们只需要通过
MQ进行缓存消息,然后异步推送消息,就可以保证消息的一致性。
公司消息服务平台主要是处理什么业务的?
答:消息服务平台主要处理公司内部消息请求,比如发送邮件、
发送短信、微信发送。
难点:
1、消息服务平台进行推送邮件
2、登录:要支持多端登录、移动APP登录设计
使用token令牌进行登录。token存放在redis中,设置有效期为90天等。
问题:
消费者宕机了而且没有高可用的情况下,生产者一直发送消息会怎么处理?
答:使用MQ缓存机制将生产者生产的消息存放在MQ消息队列中,采用持久化存储。
等重启消费者后再使用MQ进行消息推送。
二、发送邮件功能
大公司发送邮件是自己单间邮件服务器的或者去购买邮件服务器
package com.leeue.email.service;
import javax.security.auth.Subject;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.leeue.adapter.MessageAdapter;
import lombok.extern.slf4j.Slf4j;
/**
* @classDesc: 功能描述:(发送邮件 实现 主要是处理调用第三方接口发送邮件)
* @author:<a href="leeue@foxmail.com">李月</a>
* @Version:v1.0
* @createTime:2018年12月19日 下午3:35:22
*/
@Service
@Slf4j
public class EmailService implements MessageAdapter{
/**
* 发送邮件的主题
*/
@Value("${msg.subject}")
private String subject;
/**
* 发送邮件的内容
*/
@Value("${msg.text}")
private String text;
/**
* 发送邮件
*/
@Autowired
private JavaMailSender javaMailSender;
/**
* 发送邮件服务器
*/
@Value("${fromEmail}")
private String fromEmail;
@Override
public void sendMsg(JSONObject body) {
//处理发送邮件的
String email = body.getString("email");
if(StringUtils.isEmpty(email)) {
return;
}
log.info("消息服务平台发送邮件到....:{}",email);
//发送邮件 SpringBoot已经封装好了
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
//这里测试我们是自己给自己发送邮件
log.info("####消息服务平台发送邮件到:{}开始",email);
//来自账号:发件人
simpleMailMessage.setFrom(fromEmail);
//要发送的的账号
simpleMailMessage.setTo(email);
//标题
simpleMailMessage.setSubject(subject);
//发送内容 {} 替换这个字符变成email
simpleMailMessage.setText(text.replace("{}", email));
javaMailSender.send(simpleMailMessage);
log.info("####消息服务平台发送邮件到:{}成功",email);
}
}
三、移动App登录
1、多端登录SSO
移动端登录是使用token方式进行登录的
pc端是跟根据session、cookie来保证会话信息的。
移动端登录使用token登录方案:
1、移动过端调用登录接口传入参数用户名称和登录密码
2、服务器端收到客户端传入的参数进行数据验证,如果服务器端
验证正确进行3
3、验证正确把用户信息存放在redis中,
其中token 为key value 为用户的ID userID
4、什么是token?只是一个令牌、临时唯一的。
5、服务器返回token给客户端,客户端拿到token后,存放在本地
6、移动端调用服务器使用token查询用户信息
7、查询用户信息的接口是通过移动端传过来的token查找redis
取出userID,通过userID来查数据库里面用户信息。返回用户信息
给客户端。
登录部分代码:注意里面存放的redis配置上次已经放到了配置文件中了。
@Override
public ResponseBase login(@RequestBody UserEntity user) {
//1.验证传来的参数
String username = user.getUsername();
String password = user.getPassword();
if(StringUtils.isEmpty(username)) {
return setResultError("用户名为空!");
}
if(StringUtils.isEmpty(password)) {
return setResultError("密码为空!");
}
//2.数据库查找账号和密码是否正确
String newPassword = MD5Util.MD5(password);
UserEntity userEntity = memberDao.login(username, newPassword);
if(userEntity == null) {
return setResultError("账号或者密码不正确");
}
//3.如果账号密码正确,对应生成token
String memberToken = TokenUtils.getMemberToken();
//4.存放在redis中,key为token value为用户的userid
Integer userId = userEntity.getId();
log.info("####用户信息存放在了redis中#### key=:{},value=:{}",memberToken,userId);
baseRedisService.setString(memberToken, userId+"", Constants.tOKEN_MEMBER_TIME_OUT);
//将token封装在json对象里面去
JSONObject jsonObject = new JSONObject();
jsonObject.put("memberToken", memberToken);
//5.返回结果
return setResultSuccess(jsonObject);
}
使用token来查询用户的信息
@Override
public ResponseBase findByTokenUser(String token) {
//1.验证参数
if(StringUtils.isEmpty(token)) {
return setResultError("token不能为空");
}
//2.从redis中使用token查找对应的userid
String userIdStr = (String) baseRedisService.getString(token);
if(StringUtils.isEmpty(userIdStr)) {
return setResultError("该用户的token信息不存在");
}
Long userId = Long.valueOf(userIdStr);
//3.拿到了userid 从数据库中通过userid来查找当前的用户信息并且返回
UserEntity userEntity = memberDao.findByID(userId);
if(userEntity == null) {
return setResultError("该用户信息不存在");
}
//为了安全,查询到的密码不能被返回
userEntity.setPassword(null);
//4.返回当前的user信息,
JSONObject jsonObject = new JSONObject();
jsonObject.put("userInfo", userEntity);
return setResultSuccess(jsonObject);
}
在企业项目中,用户表肯定有许多数据,要加个字段来判断当前的用户信息有没有存放在redis中。
如果已经存在redis中就可以查到当前的用户信息,如果已经有了,用户又登录了。可以通过
这个状态值,覆盖掉当前存放在redis中的值。
这个是移动端的会话token,类似web端的的session.
在做核心业务的时候一定要使用手机验证码来验证。
确保是真实身份来做该操作。