diff --git a/docs/Guwan-awd.exe b/docs/Guwan-awd.exe
deleted file mode 100644
index c0fdaf3..0000000
Binary files a/docs/Guwan-awd.exe and /dev/null differ
diff --git a/pom.xml b/pom.xml
index 3b6e392..3f9eec3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -310,6 +310,12 @@
janino
+
+ com.github.ben-manes.caffeine
+ caffeine
+ 3.1.8
+
+
diff --git a/src/main/java/com/guwan/backend/Demo1.java b/src/main/java/com/guwan/backend/Demo1.java
deleted file mode 100644
index d178b9a..0000000
--- a/src/main/java/com/guwan/backend/Demo1.java
+++ /dev/null
@@ -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);
- }
-}
diff --git a/src/main/java/com/guwan/backend/config/CacheMonitor.java b/src/main/java/com/guwan/backend/config/CacheMonitor.java
new file mode 100644
index 0000000..fa32081
--- /dev/null
+++ b/src/main/java/com/guwan/backend/config/CacheMonitor.java
@@ -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 userCache;
+ private final Cache productCache;
+
+ public CacheMonitor(Cache userCache,
+ Cache productCache) {
+ this.userCache = userCache;
+ this.productCache = productCache;
+ }
+
+ @GetMapping("/stats")
+ public Map getStats() {
+ Map stats = new HashMap<>();
+
+ // 用户缓存统计
+ Map userStats = new HashMap<>();
+ userStats.put("stats", userCache.stats());
+ userStats.put("estimatedSize", userCache.estimatedSize());
+ userStats.put("asMap", userCache.asMap());
+ stats.put("userCache", userStats);
+
+ // 产品缓存统计
+ Map 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());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/guwan/backend/config/CaffeineConfig.java b/src/main/java/com/guwan/backend/config/CaffeineConfig.java
new file mode 100644
index 0000000..9acf3c2
--- /dev/null
+++ b/src/main/java/com/guwan/backend/config/CaffeineConfig.java
@@ -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 userCache() {
+ return Caffeine.newBuilder()
+ .recordStats()
+ .expireAfterWrite(10, TimeUnit.MINUTES)
+ .initialCapacity(100)
+ .maximumSize(1000)
+ .build();
+ }
+
+ @Bean
+ public Cache productCache() {
+ return Caffeine.newBuilder()
+ .recordStats()
+ .expireAfterWrite(30, TimeUnit.MINUTES)
+ .initialCapacity(100)
+ .maximumSize(1000)
+ .build();
+ }
+
+ @Bean
+ public CacheMonitor cacheMonitor(Cache userCache,
+ Cache productCache) {
+ return new CacheMonitor(userCache, productCache);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/guwan/backend/service/impl/UserServiceImpl.java b/src/main/java/com/guwan/backend/service/impl/UserServiceImpl.java
index 0975393..a83b106 100644
--- a/src/main/java/com/guwan/backend/service/impl/UserServiceImpl.java
+++ b/src/main/java/com/guwan/backend/service/impl/UserServiceImpl.java
@@ -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 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 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 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 implements Us
public void resetPassword(ChangePasswordDTO changePasswordDTO) {
if(changePasswordDTO.getChangeWay().equals(UserEnums.ACCOUNT.getValue())){
- User user = this.getOne(new LambdaQueryWrapper()
- .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()
+ .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 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);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/guwan/backend/Demo.java b/src/test/java/com/guwan/backend/Demo.java
similarity index 100%
rename from src/main/java/com/guwan/backend/Demo.java
rename to src/test/java/com/guwan/backend/Demo.java
diff --git a/src/main/java/com/guwan/backend/OkHttpExample.java b/src/test/java/com/guwan/backend/OkHttpExample.java
similarity index 100%
rename from src/main/java/com/guwan/backend/OkHttpExample.java
rename to src/test/java/com/guwan/backend/OkHttpExample.java
diff --git a/src/main/java/com/guwan/backend/OkHttpExample2.java b/src/test/java/com/guwan/backend/OkHttpExample2.java
similarity index 100%
rename from src/main/java/com/guwan/backend/OkHttpExample2.java
rename to src/test/java/com/guwan/backend/OkHttpExample2.java