From ff1ae38707ce3463f5d3dac47a2d21c840c879f6 Mon Sep 17 00:00:00 2001 From: lensferno Date: Sat, 20 Aug 2022 11:20:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8B=86=E5=88=86=E9=83=A8=E5=88=86=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dscape/cache/InviteCodeService.java | 74 +++++++++++++++++ .../lensfrex/dscape/cache/UserBasicCache.java | 59 ++++++++++++++ .../dscape/configure/GlobalConstant.java | 15 ++++ .../user/admin/AdminController.java | 8 +- .../dscape/web/service/user/UserService.java | 74 ++++++++--------- .../web/service/user/admin/AdminService.java | 80 ++++++------------- 6 files changed, 210 insertions(+), 100 deletions(-) create mode 100644 src/main/java/net/lensfrex/dscape/cache/InviteCodeService.java create mode 100644 src/main/java/net/lensfrex/dscape/cache/UserBasicCache.java create mode 100644 src/main/java/net/lensfrex/dscape/configure/GlobalConstant.java diff --git a/src/main/java/net/lensfrex/dscape/cache/InviteCodeService.java b/src/main/java/net/lensfrex/dscape/cache/InviteCodeService.java new file mode 100644 index 0000000..d009eb5 --- /dev/null +++ b/src/main/java/net/lensfrex/dscape/cache/InviteCodeService.java @@ -0,0 +1,74 @@ +/* + * Class created by lensfrex. + */ + +package net.lensfrex.dscape.cache; + +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaFoxUtil; +import lombok.extern.slf4j.Slf4j; +import net.lensfrex.dscape.configure.GlobalConstant; +import net.lensfrex.dscape.dto.response.general.ResponseCode; +import net.lensfrex.dscape.exception.GlobalException; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +@Slf4j +@Service +public class InviteCodeService { + private static final int INVITE_CODE_LENGTH = 6; + + private static final String REGISTER_INVITE_CODE_KEY = GlobalConstant.REGISTER_INVITE_CODE_KEY; + + private static final String ADMIN_INVITE_CODE_COUNTER_KEY = GlobalConstant.ADMIN_INVITE_CODE_COUNTER_KEY; + + private final RedisTemplate redis; + + public InviteCodeService(RedisTemplate redis) { + this.redis = redis; + } + + public List generateInviteCode(long expired, int count) { + String adminUid = StpUtil.getLoginIdAsString(); + String adminInviteCodeCounterKey = String.format(ADMIN_INVITE_CODE_COUNTER_KEY, adminUid); + + String countResult = redis.opsForValue().get(adminInviteCodeCounterKey); + + if (countResult != null && Integer.parseInt(countResult) > 1024) { + throw new GlobalException(ResponseCode.INVITE_CODE_REACHED_LIMIT); + } + + List inviteCodes = new ArrayList<>(count); + + for (int i = 0; i < count; i++) { + inviteCodes.add(SaFoxUtil.getRandomString(INVITE_CODE_LENGTH)); + } + HashMap codeAdmin = new HashMap<>(count); + inviteCodes.forEach(inviteCode -> codeAdmin.put(inviteCode, adminUid)); + + redis.opsForHash().putAll(REGISTER_INVITE_CODE_KEY, codeAdmin); + redis.opsForValue().increment(adminInviteCodeCounterKey, count); + + return inviteCodes; + } + + public boolean checkInviteCode(String code) { + return redis.opsForHash().get(REGISTER_INVITE_CODE_KEY, code) == null; + } + + public String useInviteCode(String code) { + String superior = (String) redis.opsForHash().get(REGISTER_INVITE_CODE_KEY, code); + if (superior == null) { + throw new GlobalException(ResponseCode.INVITE_CODE_WRONG); + } + + redis.opsForHash().delete(REGISTER_INVITE_CODE_KEY, code); + redis.opsForValue().decrement(String.format(ADMIN_INVITE_CODE_COUNTER_KEY, superior)); + + return superior; + } +} diff --git a/src/main/java/net/lensfrex/dscape/cache/UserBasicCache.java b/src/main/java/net/lensfrex/dscape/cache/UserBasicCache.java new file mode 100644 index 0000000..e7ceceb --- /dev/null +++ b/src/main/java/net/lensfrex/dscape/cache/UserBasicCache.java @@ -0,0 +1,59 @@ +/* + * Class created by lensfrex. + */ + +package net.lensfrex.dscape.cache; + +import lombok.extern.slf4j.Slf4j; +import net.lensfrex.dscape.configure.GlobalConstant; +import net.lensfrex.dscape.dao.entity.UserBasic; +import net.lensfrex.dscape.utils.ObjectJsonSerializer; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class UserBasicCache { + + private static final String USER_INFO_CACHE_KEY = GlobalConstant.USER_INFO_CACHE_KEY; + + private static final String USERNAME_UID_CACHE_KEY = GlobalConstant.USERNAME_UID_CACHE_KEY; + + private final ObjectJsonSerializer objectJsonSerializer; + + private final RedisTemplate redis; + + public UserBasicCache(ObjectJsonSerializer objectJsonSerializer, RedisTemplate redis) { + this.objectJsonSerializer = objectJsonSerializer; + this.redis = redis; + } + + public UserBasic getUserByUid(String uid) { + String cacheData = (String) redis.opsForHash().get(USER_INFO_CACHE_KEY, uid); + if (cacheData != null) { + return objectJsonSerializer.deserialize(cacheData, UserBasic.class); + } else { + log.debug("缓存中没有用户信息"); + return null; + } + } + + public UserBasic getUserByUserName(String username) { + String uid = (String) redis.opsForHash().get(USERNAME_UID_CACHE_KEY, username); + if (uid != null) { + return this.getUserByUid(uid); + } else { + log.debug("缓存中没有用户名和uid的对应信息"); + return null; + } + } + + public void save(UserBasic userBasic) { + redis.opsForHash().put(USER_INFO_CACHE_KEY, userBasic.getUid(), objectJsonSerializer.serialize(userBasic)); + redis.opsForHash().put(USERNAME_UID_CACHE_KEY, userBasic.getUserName(), userBasic.getUid()); + } + + public void clear(String uid) { + redis.opsForHash().delete(USER_INFO_CACHE_KEY, uid); + } +} diff --git a/src/main/java/net/lensfrex/dscape/configure/GlobalConstant.java b/src/main/java/net/lensfrex/dscape/configure/GlobalConstant.java new file mode 100644 index 0000000..32337fd --- /dev/null +++ b/src/main/java/net/lensfrex/dscape/configure/GlobalConstant.java @@ -0,0 +1,15 @@ +/* + * Class created by lensfrex. + */ + +package net.lensfrex.dscape.configure; + +public class GlobalConstant { + public static final String USER_INFO_CACHE_KEY = "dscape:user:basic"; + + public static final String USERNAME_UID_CACHE_KEY = "dscape:user:uid"; + + public static final String REGISTER_INVITE_CODE_KEY = "dscape:user:inviteCodes"; + + public static final String ADMIN_INVITE_CODE_COUNTER_KEY = "dscape:admin:inviteCodeCounter:%s"; +} diff --git a/src/main/java/net/lensfrex/dscape/web/controllers/user/admin/AdminController.java b/src/main/java/net/lensfrex/dscape/web/controllers/user/admin/AdminController.java index e89fa30..ed27bd5 100644 --- a/src/main/java/net/lensfrex/dscape/web/controllers/user/admin/AdminController.java +++ b/src/main/java/net/lensfrex/dscape/web/controllers/user/admin/AdminController.java @@ -33,7 +33,7 @@ public class AdminController { } @PostMapping(value = "/modifyStatus", produces = "application/json") - public Response modifyStatus(@RequestParam String username, @RequestParam int status) { + public Response modifyStatus(@RequestParam String uid, @RequestParam int status) { if (!StpUtil.hasRole(String.valueOf(UserRoleEnum.ADMIN.getCode()))) { throw new GlobalException(ResponseCode.PERMISSION_DENIED); } @@ -41,13 +41,13 @@ public class AdminController { switch (status) { case 0: case 1: - adminService.modifyUserStatus(username, status); + adminService.modifyUserStatus(uid, status); break; case 2: - adminService.deleteUser(username); + adminService.deleteUser(uid); break; case 3: - adminService.addUserToBlackList(username); + adminService.addUserToBlackList(uid); break; default: throw new GlobalException(ResponseCode.PARAM_WRONG); diff --git a/src/main/java/net/lensfrex/dscape/web/service/user/UserService.java b/src/main/java/net/lensfrex/dscape/web/service/user/UserService.java index 577f045..d8f2b7a 100644 --- a/src/main/java/net/lensfrex/dscape/web/service/user/UserService.java +++ b/src/main/java/net/lensfrex/dscape/web/service/user/UserService.java @@ -8,6 +8,9 @@ import cn.dev33.satoken.stp.SaTokenInfo; import cn.dev33.satoken.stp.StpUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import lombok.extern.slf4j.Slf4j; +import net.lensfrex.dscape.cache.InviteCodeService; +import net.lensfrex.dscape.cache.UserBasicCache; +import net.lensfrex.dscape.configure.GlobalConstant; import net.lensfrex.dscape.dao.entity.UserBasic; import net.lensfrex.dscape.dao.entity.UserRole; import net.lensfrex.dscape.dao.service.UserBasicService; @@ -19,7 +22,6 @@ import net.lensfrex.dscape.dto.response.user.RegisterResponseBody; import net.lensfrex.dscape.enums.user.UserRoleEnum; import net.lensfrex.dscape.enums.user.UserStatusEnum; import net.lensfrex.dscape.exception.GlobalException; -import net.lensfrex.dscape.utils.ObjectJsonSerializer; import org.mindrot.jbcrypt.BCrypt; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; @@ -31,29 +33,24 @@ import java.util.UUID; @Slf4j @Service public class UserService { - - private static final String USER_INFO_CACHE_KEY = "dscape:user:basic"; - - private static final String REGISTER_INVITE_CODE_KEY = "dscape:user:inviteCodes"; - - private final ObjectJsonSerializer objectJsonSerializer; - - private final RedisTemplate redis; + private final UserBasicCache userBasicCache; private final UserBasicService userBasicService; private final UserRoleService userRoleService; + private final InviteCodeService inviteCodeService; + @Autowired - public UserService(ObjectJsonSerializer objectJsonSerializer, - RedisTemplate redis, + public UserService(UserBasicCache userBasicCache, UserBasicService userBasicService, - UserRoleService userRoleService) { + UserRoleService userRoleService, + InviteCodeService inviteCodeService) { - this.objectJsonSerializer = objectJsonSerializer; - this.redis = redis; + this.userBasicCache = userBasicCache; this.userBasicService = userBasicService; this.userRoleService = userRoleService; + this.inviteCodeService = inviteCodeService; } public SaTokenInfo checkLogin() { @@ -63,27 +60,11 @@ public class UserService { public SaTokenInfo login(UserLoginRequestBody requestBody) { String username = requestBody.getUserName(); String password = requestBody.getPassword(); - UserBasic userBasic; // 找缓存 - String cacheData = (String) redis.opsForHash().get(USER_INFO_CACHE_KEY, username); - if (cacheData != null) { - userBasic = objectJsonSerializer.deserialize(cacheData, UserBasic.class); - } else { - // 进数据库里边查 - QueryWrapper wrapper = new QueryWrapper<>(); - wrapper.lambda() - .eq(UserBasic::getUserName, username) - .eq(UserBasic::getIsDeleted, 0); - - userBasic = userBasicService.getOne(wrapper); - try { - if (userBasic != null) { - redis.opsForHash().put(USER_INFO_CACHE_KEY, username, objectJsonSerializer.serialize(userBasic)); - } - } catch (Exception e) { - log.info("将用户数据存入redis缓存时发生错误", e); - } + UserBasic userBasic = userBasicCache.getUserByUserName(username); + if (userBasic == null) { + userBasic = this.getUserAndCache(username); } // 验证密码 @@ -103,7 +84,24 @@ public class UserService { return StpUtil.getTokenInfo(); } - private static final String ADMIN_INVITE_CODE_COUNTER_KEY = "dscape:admin:inviteCodeCounter:%s"; + private UserBasic getUserAndCache(String username) { + // 进数据库里边查 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.lambda() + .eq(UserBasic::getUserName, username) + .eq(UserBasic::getIsDeleted, 0); + + UserBasic userBasic = userBasicService.getOne(wrapper); + try { + if (userBasic != null) { + userBasicCache.save(userBasic); + } + } catch (Exception e) { + log.info("将用户数据存入redis缓存时发生错误", e); + } + + return userBasic; + } @Transactional public RegisterResponseBody register(RegisterRequestBody requestBody, String registerIp) { @@ -128,16 +126,10 @@ public class UserService { String uid = addUserToDatabase(requestBody.getUserName(), requestBody.getPassword(), "null", UserRoleEnum.ADMIN, registerIp); registerResponseBody.setUid(uid); } else { - String superior = (String) redis.opsForHash().get(REGISTER_INVITE_CODE_KEY, inviteCode); - if (superior == null) { - throw new GlobalException(ResponseCode.INVITE_CODE_WRONG); - } + String superior = inviteCodeService.useInviteCode(inviteCode); String uid = addUserToDatabase(requestBody.getUserName(), requestBody.getPassword(), superior, UserRoleEnum.NORMAL_USER, registerIp); registerResponseBody.setUid(uid); - - redis.opsForHash().delete(REGISTER_INVITE_CODE_KEY, inviteCode); - redis.opsForValue().decrement(String.format(ADMIN_INVITE_CODE_COUNTER_KEY, superior)); } return registerResponseBody; diff --git a/src/main/java/net/lensfrex/dscape/web/service/user/admin/AdminService.java b/src/main/java/net/lensfrex/dscape/web/service/user/admin/AdminService.java index 29b927a..9daf362 100644 --- a/src/main/java/net/lensfrex/dscape/web/service/user/admin/AdminService.java +++ b/src/main/java/net/lensfrex/dscape/web/service/user/admin/AdminService.java @@ -5,21 +5,17 @@ package net.lensfrex.dscape.web.service.user.admin; import cn.dev33.satoken.stp.StpUtil; -import cn.dev33.satoken.util.SaFoxUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import net.lensfrex.dscape.cache.InviteCodeService; +import net.lensfrex.dscape.cache.UserBasicCache; import net.lensfrex.dscape.dao.entity.BlackList; import net.lensfrex.dscape.dao.entity.UserBasic; import net.lensfrex.dscape.dao.service.BlackListService; import net.lensfrex.dscape.dao.service.UserBasicService; -import net.lensfrex.dscape.dto.response.general.ResponseCode; import net.lensfrex.dscape.enums.user.BlackListTypeEnum; -import net.lensfrex.dscape.exception.GlobalException; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; @Service @@ -30,83 +26,57 @@ public class AdminService { private final BlackListService blackListService; + private final InviteCodeService inviteCodeService; + + private final UserBasicCache userBasicCache; + public AdminService(RedisTemplate redis, UserBasicService userBasicService, - BlackListService blackListService) { + BlackListService blackListService, + InviteCodeService inviteCodeService, + UserBasicCache userBasicCache) { this.redis = redis; this.userBasicService = userBasicService; this.blackListService = blackListService; + this.inviteCodeService = inviteCodeService; + this.userBasicCache = userBasicCache; } - private static final int INVITE_CODE_LENGTH = 6; - - private static final String REGISTER_INVITE_CODE_KEY = "dscape:user:inviteCodes"; - - private static final String ADMIN_INVITE_CODE_COUNTER_KEY = "dscape:admin:inviteCodeCounter:%s"; - public List generateInviteCode(long expired, int count) { - String adminUid = StpUtil.getLoginIdAsString(); - String adminInviteCodeCounterKey = String.format(ADMIN_INVITE_CODE_COUNTER_KEY, adminUid); - - String countResult = redis.opsForValue().get(adminInviteCodeCounterKey); - - if (countResult != null && Integer.parseInt(countResult) > 1024) { - throw new GlobalException(ResponseCode.INVITE_CODE_REACHED_LIMIT); - } - - List inviteCodes = new ArrayList<>(count); - - for (int i = 0; i < count; i++) { - inviteCodes.add(SaFoxUtil.getRandomString(INVITE_CODE_LENGTH)); - } - HashMap codeAdmin = new HashMap<>(count); - inviteCodes.forEach(inviteCode -> codeAdmin.put(inviteCode, adminUid)); - - redis.opsForHash().putAll(REGISTER_INVITE_CODE_KEY, codeAdmin); - redis.opsForValue().increment(adminInviteCodeCounterKey, count); - - return inviteCodes; + return inviteCodeService.generateInviteCode(expired, count); } - private static final String USER_INFO_CACHE_KEY = "dscape:user:basic"; - - public void modifyUserStatus(String username, int status) { + public void modifyUserStatus(String uid, int status) { UpdateWrapper wrapper = new UpdateWrapper<>(); wrapper.lambda() - .eq(UserBasic::getUserName, username) + .eq(UserBasic::getUid, uid) .eq(UserBasic::getSuperior, StpUtil.getLoginIdAsString()) .set(UserBasic::getStatus, status); - boolean success = userBasicService.update(wrapper); - - if (success) { - this.clearUserBasicCache(username); - } + this.clearUserBasicCache(uid); + userBasicService.update(wrapper); } - public void addUserToBlackList(String username) { + public void addUserToBlackList(String uid) { BlackList blackList = new BlackList(); - blackList.setData(username); + blackList.setData(uid); blackList.setType(BlackListTypeEnum.UID.getCode()); - boolean success = blackListService.save(blackList); + blackListService.save(blackList); } - public void deleteUser(String username) { + public void deleteUser(String uid) { UpdateWrapper wrapper = new UpdateWrapper<>(); wrapper.lambda() - .eq(UserBasic::getUserName, username) + .eq(UserBasic::getUid, uid) .set(UserBasic::getIsDeleted, 1); - boolean success = userBasicService.update(wrapper); - - if (success) { - this.clearUserBasicCache(username); - } + this.clearUserBasicCache(uid); + userBasicService.update(wrapper); } - private void clearUserBasicCache(String username) { - redis.opsForHash().delete(USER_INFO_CACHE_KEY, username); + private void clearUserBasicCache(String uid) { + userBasicCache.clear(uid); } } \ No newline at end of file