feat(用户): 修改密码

This commit is contained in:
ovo 2024-12-23 16:08:26 +08:00
parent 9693cfc524
commit 556802f406
9 changed files with 206 additions and 16 deletions

Binary file not shown.

View File

@ -310,6 +310,12 @@
<artifactId>janino</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.8</version>
</dependency>
</dependencies>
<build>

View File

@ -1,12 +0,0 @@
package com.guwan.backend;
import com.guwan.backend.entity.BookOfUser;
import com.guwan.backend.enums.ReadStatus;
public class Demo1 {
public static void main(String[] args) {
BookOfUser bookOfUser = new BookOfUser();
bookOfUser.setReadStatus(ReadStatus.yes);
System.out.println("bookOfUser = " + bookOfUser);
}
}

View File

@ -0,0 +1,89 @@
package com.guwan.backend.config;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.stats.CacheStats;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@RestController
@RequestMapping("/api/cache")
public class CacheMonitor {
private final Cache<String, Object> userCache;
private final Cache<String, Object> productCache;
public CacheMonitor(Cache<String, Object> userCache,
Cache<String, Object> productCache) {
this.userCache = userCache;
this.productCache = productCache;
}
@GetMapping("/stats")
public Map<String, Object> getStats() {
Map<String, Object> stats = new HashMap<>();
// 用户缓存统计
Map<String, Object> userStats = new HashMap<>();
userStats.put("stats", userCache.stats());
userStats.put("estimatedSize", userCache.estimatedSize());
userStats.put("asMap", userCache.asMap());
stats.put("userCache", userStats);
// 产品缓存统计
Map<String, Object> productStats = new HashMap<>();
productStats.put("stats", productCache.stats());
productStats.put("estimatedSize", productCache.estimatedSize());
productStats.put("asMap", productCache.asMap());
stats.put("productCache", productStats);
return stats;
}
@GetMapping("/details")
public String getDetails() {
StringBuilder details = new StringBuilder();
details.append("=== Cache Details ===\n");
// 用户缓存详情
CacheStats userStats = userCache.stats();
details.append("User Cache:\n");
details.append(" Hit count: ").append(userStats.hitCount()).append("\n");
details.append(" Miss count: ").append(userStats.missCount()).append("\n");
details.append(" Load success count: ").append(userStats.loadSuccessCount()).append("\n");
details.append(" Load failure count: ").append(userStats.loadFailureCount()).append("\n");
details.append(" Total load time: ").append(userStats.totalLoadTime()).append("\n");
details.append(" Eviction count: ").append(userStats.evictionCount()).append("\n");
details.append(" Estimated size: ").append(userCache.estimatedSize()).append("\n");
// 产品缓存详情
CacheStats productStats = productCache.stats();
details.append("\nProduct Cache:\n");
details.append(" Hit count: ").append(productStats.hitCount()).append("\n");
details.append(" Miss count: ").append(productStats.missCount()).append("\n");
details.append(" Load success count: ").append(productStats.loadSuccessCount()).append("\n");
details.append(" Load failure count: ").append(productStats.loadFailureCount()).append("\n");
details.append(" Total load time: ").append(productStats.totalLoadTime()).append("\n");
details.append(" Eviction count: ").append(productStats.evictionCount()).append("\n");
details.append(" Estimated size: ").append(productCache.estimatedSize()).append("\n");
return details.toString();
}
// 每5分钟打印一次缓存统计信息
@Scheduled(fixedRate = 300000)
public void logCacheStats() {
log.info("=== Cache Stats ===");
log.info("User Cache: {}", userCache.stats());
log.info("Product Cache: {}", productCache.stats());
}
}

View File

@ -0,0 +1,57 @@
package com.guwan.backend.config;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import java.util.concurrent.TimeUnit;
@Slf4j
@EnableCaching
@Configuration
public class CaffeineConfig {
@Bean
@Primary
public CacheManager caffeineCacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder()
.recordStats()
.expireAfterAccess(60, TimeUnit.MINUTES)
.initialCapacity(100)
.maximumSize(1000));
return cacheManager;
}
@Bean
public Cache<String, Object> userCache() {
return Caffeine.newBuilder()
.recordStats()
.expireAfterWrite(10, TimeUnit.MINUTES)
.initialCapacity(100)
.maximumSize(1000)
.build();
}
@Bean
public Cache<String, Object> productCache() {
return Caffeine.newBuilder()
.recordStats()
.expireAfterWrite(30, TimeUnit.MINUTES)
.initialCapacity(100)
.maximumSize(1000)
.build();
}
@Bean
public CacheMonitor cacheMonitor(Cache<String, Object> userCache,
Cache<String, Object> productCache) {
return new CacheMonitor(userCache, productCache);
}
}

View File

@ -1,14 +1,19 @@
package com.guwan.backend.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guwan.backend.annotation.OperationLog;
import com.guwan.backend.common.BusinessException;
import com.guwan.backend.dto.user.ChangePasswordDTO;
import com.guwan.backend.dto.user.LoginDto;
import com.guwan.backend.dto.user.RegisterDTO;
import com.guwan.backend.dto.user.UserDTO;
import com.guwan.backend.entity.User;
import com.guwan.backend.enums.UserEnums;
import com.guwan.backend.mapper.BookMapper;
import com.guwan.backend.mapper.UserMapper;
import com.guwan.backend.mybatis.query.LambdaQueryWrapperX;
import com.guwan.backend.service.EmailService;
@ -19,11 +24,15 @@ import com.guwan.backend.util.SecurityUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
@Slf4j
@Service
@ -36,6 +45,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
private final RedisUtils redisUtil;
private final EmailService emailService;
private final SecurityUtil securityUtil;
private final BookMapper bookMapper;
private static final String USER_CACHE_KEY = "user:";
private static final long USER_CACHE_DURATION = 3600L; // 1小时
@ -150,7 +160,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Override
@OperationLog(description = "获取用户信息", operationType = "获取")
@OperationLog(description = "获取用户信息")
public UserDTO getCurrentUser() {
Long userId = securityUtil.getCurrentUserId();
if (userId == null) {
@ -163,13 +173,15 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Override
@OperationLog(description = "根据Id获取用户信息")
@Cacheable(value = "userCache", key = "#id")
public UserDTO getUserById(Long id) {
log.info("Checking Redis cache");
// 先从缓存获取
Object cached = redisUtil.get(USER_CACHE_KEY + id);
if (cached != null) {
return (UserDTO) cached;
}
log.info("Getting user from database, id: {}", id);
User user = userMapper.selectById(id);
if (user == null) {
return null;
@ -191,13 +203,35 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
public void resetPassword(ChangePasswordDTO changePasswordDTO) {
if(changePasswordDTO.getChangeWay().equals(UserEnums.ACCOUNT.getValue())){
User user = this.getOne(new LambdaQueryWrapper<User>()
.eq(User::getUsername, changePasswordDTO.getInfo()));
User user = this.lambdaQuery().eq(User::getUsername, changePasswordDTO.getInfo()).one();
//传入密码 库中密码
boolean matches = passwordEncoder.matches(changePasswordDTO.getCode(), user.getPassword());
if (!matches){
log.error("原密码不正确");
throw new BusinessException("原密码不正确");
}else{
String newPassword = passwordEncoder.encode(changePasswordDTO.getNewPassword());
boolean update = this.update(new LambdaUpdateWrapper<User>()
.eq(User::getId, user.getId())
.set(User::getPassword, newPassword));
if (!update) {
throw new BusinessException("密码更新失败");
}
}
}
if (changePasswordDTO.getChangeWay().equals(UserEnums.ACCOUNT.getValue())){
}
@ -257,4 +291,20 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
BeanUtils.copyProperties(user, dto);
return dto;
}
@CachePut(value = "userCache", key = "#user.id")
public UserDTO updateUser(UserDTO user) {
log.info("Updating user in cache, id: {}", user.getId());
// 更新数据库
//userMapper.updateById(user);
// 同时更新缓存
return user;
}
@CacheEvict(value = "userCache", key = "#id")
public void deleteUser(Long id) {
log.info("Removing user from cache, id: {}", id);
// 删除数据时同时删除缓存
userMapper.deleteById(id);
}
}