pull/4/head
zhouyu 9 months ago
parent dbef78e534
commit c53e71327a

@ -26,34 +26,81 @@ import java.util.concurrent.TimeUnit;
* @CONTACT 317758022@qq.com
* @DESC code=1,msg=xxx code=0,data=UserRespVO
*/
// @Service注解用于将当前类标记为Spring框架中的服务层组件表明该类是一个业务逻辑处理类会被Spring容器管理
// 方便在其他组件(如控制器层)中通过依赖注入的方式进行调用,实现业务逻辑与其他层的解耦。
@Service
// @Slf4j注解是lombok提供的一个便捷方式用于自动在类中生成一个名为log的日志记录器对象
// 可以通过它方便地记录不同级别如info、error等的日志信息便于在程序运行过程中对业务流程、异常情况等进行记录和跟踪方便后续的调试与监控。
@Slf4j
public class UserServiceImpl implements IUserService{
// 该类实现了IUserService接口意味着它需要按照接口中定义的方法契约来实现具体的业务逻辑
// 这样的设计符合面向接口编程的原则,使得代码结构更加清晰,便于替换不同的实现类(例如在测试环境或不同业务场景下使用不同的实现逻辑),
// 同时也方便其他代码依赖于接口进行调用,而不用关心具体的实现细节。
public class UserServiceImpl implements IUserService {
// 通过Spring的依赖注入机制使用@Autowired注解自动装配一个UserMapper类型的实例。
// UserMapper通常是一个MyBatis的Mapper接口定义了与数据库中用户表进行交互的各种方法比如查询用户信息、插入用户记录等操作
// 在这里被注入后,就可以在业务逻辑方法中调用它的方法来实现与数据库的数据交互,以完成诸如登录验证、注册用户等业务功能。
@Autowired
private UserMapper userMapper;
// 同样使用@Autowired注解注入CuratorFramework类型的实例CuratorFramework是一个用于与Zookeeper进行交互的客户端框架相关的类
// 在本代码中可能是用于实现分布式锁功能结合后续代码逻辑来看通过与Zookeeper的协作来保证在分布式环境下关键业务操作如用户注册的原子性和并发控制
// 避免多个实例同时操作产生的数据不一致等问题。
@Autowired
private CuratorFramework zkClient;
// 注入CommonCacheUtil类型的实例CommonCacheUtil是一个用于缓存操作的工具类
// 大概率是用于和缓存系统如Redis进行交互实现对常用数据比如用户登录状态信息、临时验证信息等的缓存管理
// 通过缓存数据可以减少对数据库的频繁访问,提高系统的整体性能和响应速度。
@Autowired
private CommonCacheUtil commonCacheUtil;
/**
*
*
*
* StringUtils.isEmpty
* SnailmallException
*
*
* userMapperselectByUsername
* 0
* SnailmallException
*
*
* MD5Util.MD5EncodeUtf8MD5
* 使userMapperselectByUsernameAndPasswd
* null
* SnailmallException
*
*
* UserResVO
* resultUserID
* UserResVOnew Date()
* ServerResponse.createBySuccessServerResponseUserResVO
*
*
* @param username
* @param password
* @return ServerResponse<UserResVO>UserResVO
* 便
*/
@Override
public ServerResponse<UserResVO> login(String username,String password) {
//1.校验参数不能为空
if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){
public ServerResponse<UserResVO> login(String username, String password) {
// 1.校验参数不能为空
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
throw new SnailmallException("温馨提示:用户名或密码不能为空");
}
//2.根据用户名去取用户信息(本系统用户名不能重复)
// 2.根据用户名去取用户信息(本系统用户名不能重复)
int resultCount = userMapper.selectByUsername(username);
if(resultCount == 0){
if (resultCount == 0) {
throw new SnailmallException("温馨提示:用户名不存在");
}
//3.走到这一步,说明存在该用户,下面就执行登陆校验
// 3.走到这一步,说明存在该用户,下面就执行登陆校验
String md5Passwd = MD5Util.MD5EncodeUtf8(password);
User resultUser = userMapper.selectByUsernameAndPasswd(username,md5Passwd);
if (resultUser == null){
User resultUser = userMapper.selectByUsernameAndPasswd(username, md5Passwd);
if (resultUser == null) {
throw new SnailmallException("温馨提示:用户名或者密码不正确,请重试");
}
//4.走到这一步,说明用户名密码正确,应该返回成功
// 4.走到这一步,说明用户名密码正确,应该返回成功
UserResVO userResVO = new UserResVO();
userResVO.setId(resultUser.getId());
userResVO.setUsername(resultUser.getUsername());
@ -65,58 +112,96 @@ public class UserServiceImpl implements IUserService{
userResVO.setCreateTime(resultUser.getCreateTime());
userResVO.setUpdateTime(new Date());
return ServerResponse.createBySuccess("用户登陆成功",userResVO);
return ServerResponse.createBySuccess("用户登陆成功", userResVO);
}
/**
*
*
* 1.
* User
* StringUtils.isBlankSnailmallException
*
*
* 2.
* - InterProcessLockInterProcessMutexzkClientConstants.USER_REGISTER_DISTRIBUTE_LOCK_PATH
* 线
* - do-whilelock.acquire3000TimeUnit.MILLISECONDS
*
* - log.info线便线
* - this.checkValidConstants.USERNAME
* ServerResponse
* - this.checkValidConstants.EMAIL
* 使
* - Constants.Role.ROLE_CUSTOME
* MD5使MD5Util.MD5EncodeUtf8userMapperinsert
* retryfalse
* log.info...
*
*
* 3.
* finally
* locknulllock.releaselog.info线便
* e.printStackTrace便
*
* 4.
*
* ServerResponse.createBySuccessMessageServerResponse
*
* @param user User
*
* @return ServerResponse
* 便
*/
@Override
public ServerResponse register(User user) {
//1.校验参数是否为空
if(StringUtils.isBlank(user.getUsername()) ||
// 1.校验参数是否为空
if (StringUtils.isBlank(user.getUsername()) ||
StringUtils.isBlank(user.getEmail()) ||
StringUtils.isBlank(user.getPassword()) ||
StringUtils.isBlank(user.getQuestion()) ||
StringUtils.isBlank(user.getAnswer())){
StringUtils.isBlank(user.getAnswer())) {
throw new SnailmallException("参数不能为空,请仔细填写");
}
//---开启锁
// ---开启锁
InterProcessLock lock = null;
try {
lock = new InterProcessMutex(zkClient, Constants.USER_REGISTER_DISTRIBUTE_LOCK_PATH);
boolean retry = true;
do {
if (lock.acquire(3000, TimeUnit.MILLISECONDS)){
log.info(user.getEmail()+Thread.currentThread().getName()+"获取锁");
//2.参数没问题的话,就校验一下名字是否已经存在
ServerResponse response = this.checkValid(user.getUsername(),Constants.USERNAME);
if(!response.isSuccess()){
//说明用户名已经重复了
if (lock.acquire(3000, TimeUnit.MILLISECONDS)) {
log.info(user.getEmail() + Thread.currentThread().getName() + "获取锁");
// 2.参数没问题的话,就校验一下名字是否已经存在
ServerResponse response = this.checkValid(user.getUsername(), Constants.USERNAME);
if (!response.isSuccess()) {
// 说明用户名已经重复了
return response;
}
//3.再校验一下邮箱是否存在
response = this.checkValid(user.getEmail(),Constants.EMAIL);
if(!response.isSuccess()){
//说明用户名已经重复了
// 3.再校验一下邮箱是否存在
response = this.checkValid(user.getEmail(), Constants.EMAIL);
if (!response.isSuccess()) {
// 说明用户名已经重复了
return response;
}
//4.重复校验通过之后就可以塞入这条数据了
user.setRole(Constants.Role.ROLE_CUSTOME);//普通用户
// 4.重复校验通过之后就可以塞入这条数据了
user.setRole(Constants.Role.ROLE_CUSTOME); // 普通用户
user.setPassword(MD5Util.MD5EncodeUtf8(user.getPassword()));
userMapper.insert(user);
//跳出循环
// 跳出循环
retry = false;
}
log.info("【获取锁失败,继续尝试...】");
//可以适当休息一会
}while (retry);
}catch (Exception e){
log.error("【校验用户所填的用户名或者密码出现问题】",e);
// 可以适当休息一会
} while (retry);
} catch (Exception e) {
log.error("【校验用户所填的用户名或者密码出现问题】", e);
throw new SnailmallException("分布式锁校验出错");
}finally {
//---释放锁
if(lock != null){
} finally {
// ---释放锁
if (lock!= null) {
try {
lock.release();
log.info(user.getEmail()+Thread.currentThread().getName()+"释放锁");
log.info(user.getEmail() + Thread.currentThread().getName() + "释放锁");
} catch (Exception e) {
e.printStackTrace();
}
@ -125,23 +210,50 @@ public class UserServiceImpl implements IUserService{
return ServerResponse.createBySuccessMessage("注册成功");
}
/**
*
*
* 1.
* StringUtils.isBlankstrtypestr
* SnailmallException
*
* 2.
* typeConstants.USERNAME
* userMapperselectByUsernamestr
* 0使ServerResponse.createByErrorMessageServerResponse
* 使
*
* typeConstants.EMAIL
* userMapperselectByEmailstr
* 0使ServerResponse.createByErrorMessageServerResponse
* 使
*
* 3.
* 0
* ServerResponse.createBySuccessServerResponse
*
*
* @param str type
* @param type strConstants
* @return ServerResponse便
*/
@Override
public ServerResponse checkValid(String str, String type) {
//校验参数是否为空
if(StringUtils.isBlank(str) || StringUtils.isBlank(type)){
if (StringUtils.isBlank(str) || StringUtils.isBlank(type)) {
throw new SnailmallException("参数有问题");
}
if(Constants.USERNAME.equalsIgnoreCase(type)){
if (Constants.USERNAME.equalsIgnoreCase(type)) {
//如果是username类型那么就根据str为username去数据库查询
int resultCount = userMapper.selectByUsername(str);
if(resultCount > 0){
if (resultCount > 0) {
//说明数据库已经存在这个username的用户了返回用户已存在
return ServerResponse.createByErrorMessage("用户已经存在");
}
}else if(Constants.EMAIL.equals(type)){
} else if (Constants.EMAIL.equals(type)) {
//如果是email类型就根据str为email去数据库查询
int resultCount = userMapper.selectByEmail(str);
if(resultCount > 0){
if (resultCount > 0) {
//说明数据库已经存在这个email的用户了返回用户已存在
return ServerResponse.createByErrorMessage("邮箱已经存在");
}
@ -149,120 +261,289 @@ public class UserServiceImpl implements IUserService{
return ServerResponse.createBySuccess("校验成功,用户名和邮箱都合法");
}
/**
*
*
* 1.
* StringUtils.isBlank
* ServerResponse.createByErrorMessageServerResponse
*
*
* 2.
* userMappergetUserByUsernameUseruser
* nullServerResponse.createByErrorMessageServerResponse
*
*
* 3.
* usernulluser.getQuestion
* StringUtils.isBlank
* ServerResponse.createByErrorMessageServerResponse
*
*
* 4.
* ServerResponse.createBySuccessServerResponse
* 便便
*
* @param username
* @return ServerResponse
* 便
*/
@Override
public ServerResponse getQuestionByUsername(String username) {
//1.校验参数
if(StringUtils.isBlank(username)){
if (StringUtils.isBlank(username)) {
return ServerResponse.createByErrorMessage("用户名不能为空");
}
//2.根据username去获取题目
User user = userMapper.getUserByUsername(username);
if(user == null){
if (user == null) {
return ServerResponse.createByErrorMessage("用户不存在");
}
String question = user.getQuestion();
if(StringUtils.isBlank(question)){
if (StringUtils.isBlank(question)) {
return ServerResponse.createByErrorMessage("该用户没有设置对应的问题");
}
return ServerResponse.createBySuccess(question);
}
/**
* token
*
* 1.
* StringUtils.isBlank
* ServerResponse.createByErrorMessageServerResponse
* token
*
* 2. token
* userMappergetUserByUsernameQuestionAnswer
* Useruserusernulltoken
*
* - RedistokencommonCacheUtilgetCacheValueConstants.TOKEN_PREFIXkeytoken
* tokenforgetToken
* - StringUtils.isNotBlankforgetTokenRedistoken
* ServerResponse.createBySuccesstokenServerResponse
* 使tokentoken
* - RedisforgetTokentokentoken
* tokenUUID.randomUUID().toStringtoken
* commonCacheUtilcacheNxExpiretokenConstants.TOKEN_PREFIXkeyRedis60 * 60 * 1212
* ServerResponse.createBySuccesstokenServerResponse便使token
*
* 3.
* usernull
* ServerResponse.createByErrorMessageServerResponse
*
* @param username token
* @param question
* @param answer
* @return ServerResponsetokentokentoken
* 便
*/
@Override
public ServerResponse checkAnswer(String username, String question, String answer) {
//1.校验参数是否正确
if(StringUtils.isBlank(username) || StringUtils.isBlank(question) || StringUtils.isBlank(answer)){
if (StringUtils.isBlank(username) || StringUtils.isBlank(question) || StringUtils.isBlank(answer)) {
return ServerResponse.createByErrorMessage("参数有问题");
}
//2.参数没有问题之后,就可以去校验答案是否正确了
User user = userMapper.getUserByUsernameQuestionAnswer(username,question,answer);
if(user != null){
User user = userMapper.getUserByUsernameQuestionAnswer(username, question, answer);
if (user!= null) {
//首先根据规则key去redis取如果还有没有过期的key就可以直接拿来用了不用再重新生成
String forgetToken = commonCacheUtil.getCacheValue(Constants.TOKEN_PREFIX+username);
if(StringUtils.isNotBlank(forgetToken)){
String forgetToken = commonCacheUtil.getCacheValue(Constants.TOKEN_PREFIX + username);
if (StringUtils.isNotBlank(forgetToken)) {
return ServerResponse.createBySuccess(forgetToken);
}
//取不到值,并且答案是对的,那么就重新生成一下吧!
forgetToken = UUID.randomUUID().toString();
commonCacheUtil.cacheNxExpire(Constants.TOKEN_PREFIX+username,forgetToken,60*60*12);
commonCacheUtil.cacheNxExpire(Constants.TOKEN_PREFIX + username, forgetToken, 60 * 60 * 12);
return ServerResponse.createBySuccess(forgetToken);
}
return ServerResponse.createByErrorMessage("问题答案有误");
}
/**
*
*
* 1.
* StringUtils.isBlanktoken
* ServerResponse.createByErrorMessageServerResponse
*
*
* 2.
* userMappergetUserByUsernameUseruser
* nullServerResponse.createByErrorMessageServerResponse
*
*
* 3. token
* usernullRedistokencommonCacheUtilgetCacheValueConstants.TOKEN_PREFIXkeytoken
* tokenredisToken
* redisTokennullRedistokentokenServerResponse.createByErrorMessagetokenServerResponse
* token
*
* 4. token
* redisTokenStringUtils.equalsforgetTokenRedisredisToken
* tokenServerResponse.createByErrorMessagetokenServerResponse
* token
*
* 5.
* tokenMD5Util.MD5EncodeUtf8MD5MD5Passwd
* user.getPassword().equals
* ServerResponse.createByErrorMessage使ServerResponse
* 使
*
* 6.
* user.setPasswordMD5Passwd
* userMapperupdateByPrimaryKeySelectiveuserID
* resultresult0ServerResponse.createBySuccessMessageServerResponse
*
*
* 7.
* result0ServerResponse.createByErrorMessageServerResponse
*
*
* @param username token
* @param passwordNew
* @param forgetToken tokenRedistoken
* @return ServerResponsetoken
* 便
*/
/**
*
*
* 1.
* 使StringUtils.isBlankusernamepasswordNewtokenforgetToken
* ServerResponse.createByErrorMessageServerResponse
*
*
* 2.
* userMappergetUserByUsernameUseruser
* usernull
* ServerResponse.createByErrorMessageServerResponse
*
* 3. token
* usernullcommonCacheUtilgetCacheValueConstants.TOKEN_PREFIXkey
* RedistokenredisToken
* redisTokennullRedistokentokenServerResponse.createByErrorMessagetokenServerResponse
* tokentoken
*
* 4. token
* RedisredisToken使StringUtils.equalsforgetTokenRedisredisToken
* tokenServerResponse.createByErrorMessagetokenServerResponse
* tokentoken
*
* 5.
* tokenpasswordNewMD5Util.MD5EncodeUtf8MD5MD5Passwd
* 使user.getPassword().equalsMD5Passwduser
* ServerResponse.createByErrorMessage使ServerResponse
* 使
*
* 6.
* token
* user.setPassworduserMD5PasswduserMapperupdateByPrimaryKeySelective
* userID
* updateCountupdateCount0
* ServerResponse.createBySuccessMessageServerResponse
*
* 7.
* updateCount0
* ServerResponse.createByErrorMessageServerResponse
*
* @param username token
* @param passwordNew
* @param forgetToken tokenRedistoken
* @return ServerResponsetoken
* 便
*/
@Override
public ServerResponse forgetResetPasswd(String username, String passwordNew, String forgetToken) {
//1.校验参数
if(StringUtils.isBlank(username) || StringUtils.isBlank(passwordNew) || StringUtils.isBlank(forgetToken)){
if (StringUtils.isBlank(username) || StringUtils.isBlank(passwordNew) || StringUtils.isBlank(forgetToken)) {
return ServerResponse.createByErrorMessage("参数有误,修改密码操作失败");
}
//2.根据username去获取用户
User user = userMapper.getUserByUsername(username);
if(user == null){
if (user == null) {
return ServerResponse.createByErrorMessage("用户名不存在,修改密码操作失败");
}
//3.从redis中获取token看是否超时
String redisToken = commonCacheUtil.getCacheValue(Constants.TOKEN_PREFIX+username);
if(redisToken == null){
String redisToken = commonCacheUtil.getCacheValue(Constants.TOKEN_PREFIX + username);
if (redisToken == null) {
return ServerResponse.createByErrorMessage("token已经过期修改密码操作失败");
}
//4.看前端传过来的token与redis中取出来的token是否相等
if(!StringUtils.equals(redisToken,forgetToken)){
if (!StringUtils.equals(redisToken, forgetToken)) {
return ServerResponse.createByErrorMessage("token错误修改密码操作失败");
}
//5.判断密码是否重复
String MD5Passwd = MD5Util.MD5EncodeUtf8(passwordNew);
if(user.getPassword().equals(MD5Passwd)){
if (user.getPassword().equals(MD5Passwd)) {
return ServerResponse.createByErrorMessage("不要使用重复密码!");
}
//6.重置密码
user.setPassword(MD5Passwd);
int result = userMapper.updateByPrimaryKeySelective(user);
if(result > 0){
int updateCount = userMapper.updateByPrimaryKeySelective(user);
if (updateCount > 0) {
return ServerResponse.createBySuccessMessage("修改密码成功");
}
return ServerResponse.createByErrorMessage("修改密码失败");
}
@Override
public ServerResponse resetPasswd(String passwordOld, String passwordNew, int userId) {
//1.校验参数
if(StringUtils.isBlank(passwordOld) || StringUtils.isBlank(passwordNew)){
return ServerResponse.createByErrorMessage("参数有误");
}
User user = userMapper.selectByPrimaryKey(userId);
if (user == null){
return ServerResponse.createByErrorMessage("无用户登陆");
}
//2.校验老的密码
String passwordOldMD5 = MD5Util.MD5EncodeUtf8(passwordOld);
if(!StringUtils.equals(passwordOldMD5,user.getPassword())){
return ServerResponse.createByErrorMessage("老密码输错啦...");
}
//3.重置新的密码
user.setPassword(MD5Util.MD5EncodeUtf8(passwordNew));
int updateCount = userMapper.updateByPrimaryKeySelective(user);
if(updateCount > 0){
return ServerResponse.createBySuccessMessage("更新密码成功");
}
return ServerResponse.createByErrorMessage("更新密码失败");
}
/**
*
*
* 1.
* userMapperselectByPrimaryKeyIDuserIdUseruser
* usernullIDID
* ServerResponse.createByErrorMessageServerResponse
*
*
* 2.
* 使StringUtils.isBlankemailphonequestionanswer
*
* ServerResponse.createByErrorMessage!ServerResponse
*
*
* 3.
* 使
* userMappercheckEmailValidemailIDuserId使
* queryCount0使
* ServerResponse.createByErrorMessage~ServerResponse使
*
* 4.
* UserupdateUsersetIDIDuserId
* emailphonequestionanswer
* userMapperupdateByPrimaryKeySelectiveupdateUseruserId
* updateCount
*
* 5.
* updateCount0ServerResponse.createBySuccessMessageServerResponse
*
* updateCount0
* ServerResponse.createByErrorMessageServerResponse
*
* @param email
* @param phone
* @param question
* @param answer
* @param userId
* @return ServerResponse
* 便
*/
@Override
public ServerResponse updateInfomation(String email, String phone, String question, String answer, Integer userId) {
//1.获取当前登陆用户
User user = userMapper.selectByPrimaryKey(userId);
if (user == null){
if (user == null) {
return ServerResponse.createByErrorMessage("获取当前登陆用户失败,请重新登陆");
}
//2.校验参数
if(StringUtils.isBlank(email) || StringUtils.isBlank(phone) || StringUtils.isBlank(question) || StringUtils.isBlank(answer)){
if (StringUtils.isBlank(email) || StringUtils.isBlank(phone) || StringUtils.isBlank(question) || StringUtils.isBlank(answer)) {
return ServerResponse.createByErrorMessage("更新的数据不能存在空值!");
}
//2.修改用户信息应该并发不大,所以不用加锁了,这里校验邮箱是否重复
Integer queryCount = userMapper.checkEmailValid(email,userId);
if(queryCount > 0){
Integer queryCount = userMapper.checkEmailValid(email, userId);
if (queryCount > 0) {
//说明这个邮箱已经被其他用户占用了,所以不能使用
return ServerResponse.createByErrorMessage("此邮箱已经被占用,换个试试~");
}
@ -276,18 +557,32 @@ public class UserServiceImpl implements IUserService{
int updateCount = userMapper.updateByPrimaryKeySelective(updateUser);
if(updateCount > 0){
if (updateCount > 0) {
return ServerResponse.createBySuccessMessage("更新信息成功");
}
return ServerResponse.createByErrorMessage("更新用户信息失败");
}
/**
* IDUserResVO
*
* UserResVOuserResVO
* userMapperselectByPrimaryKeyIDuserIdUseruserDB
* userDBnullID
* userResVOsetUserResVO
* userResVO便
* userDBnullUserResVO
*
* @param userId
* @return UserResVOID便
* UserResVO
*/
@Override
public UserResVO getUserInfoFromDB(Integer userId) {
UserResVO userResVO = new UserResVO();
User userDB = userMapper.selectByPrimaryKey(userId);
if(userDB != null){
if (userDB!= null) {
userResVO.setId(userId);
userResVO.setUsername(userDB.getUsername());
userResVO.setEmail(userDB.getEmail());
@ -299,7 +594,4 @@ public class UserServiceImpl implements IUserService{
userResVO.setUpdateTime(userDB.getUpdateTime());
}
return userResVO;
}
}
}
Loading…
Cancel
Save