From 493ecd302150359b16acb0910744cc3e0713a2ef Mon Sep 17 00:00:00 2001 From: liwentao Date: Fri, 15 May 2026 17:32:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Redis=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=20=E6=B3=A8=EF=BC=9A/api/groupCourse/cache/g?= =?UTF-8?q?et=E6=8E=A5=E5=8F=A3=E4=B8=BA=E6=B5=8B=E8=AF=95=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gym-manage-api/gym-groupCourse/pom.xml | 7 ++ .../handler/GroupCourseHandler.java | 92 ++++++++++++++- .../repository/IGroupCourseRepository.java | 5 + .../impl/GroupCourseRepository.java | 75 ++++++++++++ .../service/IGroupCourseService.java | 4 + .../groupcourse/service/RedisService.java | 76 +++++++++++++ .../service/impl/GroupCourseService.java | 107 +++++++++++++++++- .../gym/manage/app/config/RedisConfig.java | 43 +++++++ .../gym/manage/app/config/SystemRouter.java | 27 +---- .../src/main/resources/application.yml | 13 +++ .../gym/manage/sys/config/SecurityConfig.java | 3 +- 11 files changed, 422 insertions(+), 30 deletions(-) create mode 100644 gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/RedisService.java create mode 100644 gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/RedisConfig.java diff --git a/gym-manage-api/gym-groupCourse/pom.xml b/gym-manage-api/gym-groupCourse/pom.xml index 3fc53bb..a7bfc02 100644 --- a/gym-manage-api/gym-groupCourse/pom.xml +++ b/gym-manage-api/gym-groupCourse/pom.xml @@ -67,6 +67,13 @@ 2.2.43 compile + + + + + org.springframework.boot + spring-boot-starter-data-redis + diff --git a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/handler/GroupCourseHandler.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/handler/GroupCourseHandler.java index 920786f..db6c601 100644 --- a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/handler/GroupCourseHandler.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/handler/GroupCourseHandler.java @@ -1,8 +1,11 @@ package cn.novalon.gym.manage.groupcourse.handler; +import cn.novalon.gym.manage.common.dto.PageRequest; import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; import cn.novalon.gym.manage.groupcourse.service.IGroupCourseService; +import cn.novalon.gym.manage.groupcourse.service.RedisService; +import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Validator; @@ -11,15 +14,25 @@ import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; import reactor.core.publisher.Mono; +import java.util.HashMap; +import java.util.Map; + @Component @Tag(name="团课管理",description = "团课相关操作") public class GroupCourseHandler { private final IGroupCourseService groupCourseService; private final Validator validator; + private final RedisService redisService; + private final ObjectMapper objectMapper; - public GroupCourseHandler(IGroupCourseService groupCourseService, Validator validator){ + public GroupCourseHandler(IGroupCourseService groupCourseService, + Validator validator, + RedisService redisService, + ObjectMapper objectMapper){ this.groupCourseService = groupCourseService; this.validator = validator; + this.redisService = redisService; + this.objectMapper = objectMapper; } @Operation(summary = "获取所有团课", description = "获取系统中所有团课列表") @@ -29,10 +42,87 @@ public class GroupCourseHandler { .body(groupCourseService.findAll(includeDeleted), GroupCourse.class); } + @Operation(summary = "分页获取团课", description = "根据分页参数获取团课列表") + public Mono getGroupCoursesByPage(ServerRequest request) { + return request.bodyToMono(PageRequest.class) + .flatMap(pageRequest -> { + boolean includeDeleted = request.queryParam("includeDeleted") + .map(Boolean::parseBoolean) + .orElse(false); + + if (pageRequest.getPage() < 0) { + pageRequest.setPage(0); + } + if (pageRequest.getSize() <= 0 || pageRequest.getSize() > 100) { + pageRequest.setSize(10); + } + if (pageRequest.getSort() == null || pageRequest.getSort().isEmpty()) { + pageRequest.setSort("id"); + } + if (pageRequest.getOrder() == null || pageRequest.getOrder().isEmpty()) { + pageRequest.setOrder("asc"); + } + + return groupCourseService.findByPage(pageRequest, includeDeleted) + .flatMap(response -> ServerResponse.ok().bodyValue(response)); + }); + } + @Operation(summary = "根据ID获取团课", description = "根据ID获取团课详情") public Mono getGroupCourseById(ServerRequest request){ Long id = Long.valueOf(request.pathVariable("id")); return ServerResponse.ok() .body(groupCourseService.findById(id), GroupCourse.class); } + + @Operation(summary = "测试-根据Key获取Redis缓存", description = "测试接口:根据传入的key值获取Redis中缓存的数据") + public Mono getCacheByKey(ServerRequest request) { + return request.bodyToMono(Map.class) + .flatMap(body -> { + String key = (String) body.get("key"); + + if (key == null || key.isEmpty()) { + Map error = new HashMap<>(); + error.put("success", false); + error.put("message", "key参数不能为空"); + return ServerResponse.badRequest().bodyValue(error); + } + + Object cachedValue = redisService.get(key); + + Map result = new HashMap<>(); + if (cachedValue != null) { + result.put("success", true); + result.put("key", key); + result.put("value", cachedValue); + result.put("message", "缓存命中"); + + try { + if (cachedValue instanceof String) { + Object jsonObject = objectMapper.readValue((String) cachedValue, Object.class); + result.put("parsedValue", jsonObject); + result.put("valueType", "JSON字符串"); + } else { + result.put("valueType", cachedValue.getClass().getSimpleName()); + } + } catch (Exception e) { + result.put("parsedValue", null); + result.put("valueType", "无法解析"); + } + } else { + result.put("success", false); + result.put("key", key); + result.put("value", null); + result.put("message", "缓存未命中"); + } + + return ServerResponse.ok().bodyValue(result); + }) + .onErrorResume(error -> { + Map errorResponse = new HashMap<>(); + errorResponse.put("success", false); + errorResponse.put("message", "请求处理失败: " + error.getMessage()); + return ServerResponse.status(500).bodyValue(errorResponse); + }); + } } diff --git a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/IGroupCourseRepository.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/IGroupCourseRepository.java index 4ade673..1a2d402 100644 --- a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/IGroupCourseRepository.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/IGroupCourseRepository.java @@ -1,6 +1,8 @@ package cn.novalon.gym.manage.groupcourse.repository; +import cn.novalon.gym.manage.common.dto.PageRequest; +import cn.novalon.gym.manage.common.dto.PageResponse; import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; import org.springframework.data.domain.Sort; import reactor.core.publisher.Flux; @@ -12,4 +14,7 @@ public interface IGroupCourseRepository { Flux findAll(Sort sort); Flux findByDeletedAtIsNull(); Flux findByDeletedAtIsNull(Sort sort); + + Mono> findByPage(PageRequest pageRequest); + Mono> findByPageAndNotDeleted(PageRequest pageRequest); } diff --git a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/impl/GroupCourseRepository.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/impl/GroupCourseRepository.java index 5c11325..aa249d1 100644 --- a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/impl/GroupCourseRepository.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/impl/GroupCourseRepository.java @@ -1,16 +1,22 @@ package cn.novalon.gym.manage.groupcourse.repository.impl; +import cn.novalon.gym.manage.common.dto.PageRequest; +import cn.novalon.gym.manage.common.dto.PageResponse; import cn.novalon.gym.manage.groupcourse.converter.GroupCourseConverter; import cn.novalon.gym.manage.groupcourse.dao.GroupCourseDao; import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; +import cn.novalon.gym.manage.groupcourse.entity.GroupCourseEntity; import cn.novalon.gym.manage.groupcourse.repository.IGroupCourseRepository; import org.springframework.data.domain.Sort; import org.springframework.data.r2dbc.core.R2dbcEntityTemplate; +import org.springframework.data.relational.core.query.Query; import org.springframework.stereotype.Repository; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.util.List; + @Repository public class GroupCourseRepository implements IGroupCourseRepository { private final GroupCourseDao groupCourseDao; @@ -53,4 +59,73 @@ public class GroupCourseRepository implements IGroupCourseRepository { return groupCourseDao.findAllByDeletedAtIsNull(sort) .map(groupCourseConverter::toDomain); } + + @Override + public Mono> findByPage(PageRequest pageRequest) { + int page = pageRequest.getPage(); + int size = pageRequest.getSize(); + String sort = pageRequest.getSort(); + String order = pageRequest.getOrder(); + + Sort sortObj = Sort.unsorted(); + if (sort != null && !sort.isEmpty()) { + sortObj = Sort.by(Sort.Direction.fromString(order), sort); + } + + org.springframework.data.domain.PageRequest pageable = org.springframework.data.domain.PageRequest.of(page, size, sortObj); + + Query query = Query.empty(); + + return r2dbcEntityTemplate.select(GroupCourseEntity.class) + .matching(query.with(pageable)) + .all() + .collectList() + .zipWith(r2dbcEntityTemplate.count(query, GroupCourseEntity.class)) + .map(tuple -> { + long total = tuple.getT2(); + int totalPages = (int) Math.ceil((double) total / size); + List courseList = tuple.getT1().stream() + .map(groupCourseConverter::toDomain) + .toList(); + return new PageResponse<>(courseList, totalPages, total, page, size); + }); + } + + @Override + public Mono> findByPageAndNotDeleted(PageRequest pageRequest) { + int page = pageRequest.getPage(); + int size = pageRequest.getSize(); + String sort = pageRequest.getSort(); + String order = pageRequest.getOrder(); + + Sort sortObj = Sort.unsorted(); + if (sort != null && !sort.isEmpty()) { + sortObj = Sort.by(Sort.Direction.fromString(order), sort); + } + + org.springframework.data.domain.PageRequest pageable = org.springframework.data.domain.PageRequest.of(page, size, sortObj); + + return groupCourseDao.findAllByDeletedAtIsNull(sortObj) + .collectList() + .zipWith(groupCourseDao.findAllByDeletedAtIsNull().count()) + .map(tuple -> { + List allEntities = tuple.getT1(); + long total = tuple.getT2(); + + int fromIndex = page * size; + int toIndex = Math.min(fromIndex + size, allEntities.size()); + + List courseList; + if (fromIndex < allEntities.size()) { + courseList = allEntities.subList(fromIndex, toIndex).stream() + .map(groupCourseConverter::toDomain) + .toList(); + } else { + courseList = List.of(); + } + + int totalPages = (int) Math.ceil((double) total / size); + return new PageResponse<>(courseList, totalPages, total, page, size); + }); + } } diff --git a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/IGroupCourseService.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/IGroupCourseService.java index d43b396..7fa0b70 100644 --- a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/IGroupCourseService.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/IGroupCourseService.java @@ -1,6 +1,8 @@ package cn.novalon.gym.manage.groupcourse.service; +import cn.novalon.gym.manage.common.dto.PageRequest; +import cn.novalon.gym.manage.common.dto.PageResponse; import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -9,4 +11,6 @@ public interface IGroupCourseService { Mono findById(Long id); Flux findAll(); Flux findAll(boolean includeDeleted); + + Mono> findByPage(PageRequest pageRequest, boolean includeDeleted); } diff --git a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/RedisService.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/RedisService.java new file mode 100644 index 0000000..aa92e38 --- /dev/null +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/RedisService.java @@ -0,0 +1,76 @@ +package cn.novalon.gym.manage.groupcourse.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * @author:liwentao + * @date:2026/5/15-05-15-16:05 + */ +@Service +public class RedisService { + + @Autowired + private RedisTemplate redisTemplate; + + // 设置值 + public void set(String key, Object value) { + redisTemplate.opsForValue().set(key, value); + } + + // 设置值并指定过期时间(秒) + public void setWithExpire(String key, Object value, long timeout) { + redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS); + } + + // 获取值 + public Object get(String key) { + return redisTemplate.opsForValue().get(key); + } + + // 删除key + public Boolean delete(String key) { + return redisTemplate.delete(key); + } + + // 判断key是否存在 + public Boolean hasKey(String key) { + return redisTemplate.hasKey(key); + } + + // 设置过期时间 + public Boolean expire(String key, long timeout) { + return redisTemplate.expire(key, timeout, TimeUnit.SECONDS); + } + + // Hash操作 + public void putHash(String key, String hashKey, Object value) { + redisTemplate.opsForHash().put(key, hashKey, value); + } + + public Object getHash(String key, String hashKey) { + return redisTemplate.opsForHash().get(key, hashKey); + } + + // List操作 + public void leftPush(String key, Object value) { + redisTemplate.opsForList().leftPush(key, value); + } + + public Object rightPop(String key) { + return redisTemplate.opsForList().rightPop(key); + } + + // Set操作 + public void addToSet(String key, Object... values) { + redisTemplate.opsForSet().add(key, values); + } + + public Set getSet(String key) { + return redisTemplate.opsForSet().members(key); + } +} diff --git a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/impl/GroupCourseService.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/impl/GroupCourseService.java index 6e409e3..70a43cc 100644 --- a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/impl/GroupCourseService.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/impl/GroupCourseService.java @@ -1,24 +1,79 @@ package cn.novalon.gym.manage.groupcourse.service.impl; +import cn.novalon.gym.manage.common.dto.PageRequest; +import cn.novalon.gym.manage.common.dto.PageResponse; import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; import cn.novalon.gym.manage.groupcourse.repository.IGroupCourseRepository; import cn.novalon.gym.manage.groupcourse.service.IGroupCourseService; +import cn.novalon.gym.manage.groupcourse.service.RedisService; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.time.Duration; +import java.util.List; + @Service public class GroupCourseService implements IGroupCourseService { - private final IGroupCourseRepository groupCourseRepository; + private static final Logger logger = LoggerFactory.getLogger(GroupCourseService.class); - public GroupCourseService(IGroupCourseRepository groupCourseRepository){ + private final IGroupCourseRepository groupCourseRepository; + private final RedisService redisService; + private final ObjectMapper objectMapper; + + private static final String CACHE_KEY_PREFIX = "group_course:page:"; + private static final String CACHE_KEY_ID_PREFIX = "group_course:id:"; + private static final long CACHE_EXPIRE_SECONDS = 300; + + public GroupCourseService(IGroupCourseRepository groupCourseRepository, + RedisService redisService, + ObjectMapper objectMapper){ this.groupCourseRepository = groupCourseRepository; + this.redisService = redisService; + this.objectMapper = objectMapper; } @Override public Mono findById(Long id) { - return groupCourseRepository.findByIdAndDeletedAtIsNull(id); + String cacheKey = CACHE_KEY_ID_PREFIX + id; + + Object cachedData = redisService.get(cacheKey); + if (cachedData != null) { + try { + String json; + if (cachedData instanceof String) { + json = (String) cachedData; + } else { + json = objectMapper.writeValueAsString(cachedData); + } + + GroupCourse groupCourse = objectMapper.readValue(json, GroupCourse.class); + logger.info("缓存命中 - findById: id={}", id); + return Mono.just(groupCourse); + } catch (JsonProcessingException e) { + logger.warn("缓存解析失败,删除缓存 - id: {}, error: {}", id, e.getMessage()); + redisService.delete(cacheKey); + } + } + + logger.debug("缓存未命中,查询数据库 - findById: id={}", id); + return groupCourseRepository.findByIdAndDeletedAtIsNull(id) + .doOnSuccess(groupCourse -> { + if (groupCourse != null) { + try { + String jsonData = objectMapper.writeValueAsString(groupCourse); + redisService.setWithExpire(cacheKey, jsonData, CACHE_EXPIRE_SECONDS); + logger.debug("缓存已设置 - findById: id={}", id); + } catch (JsonProcessingException e) { + logger.error("缓存设置失败 - id: {}, error: {}", id, e.getMessage()); + } + } + }); } @Override @@ -34,4 +89,50 @@ public class GroupCourseService implements IGroupCourseService { return groupCourseRepository.findByDeletedAtIsNull(); } } + + @Override + public Mono> findByPage(PageRequest pageRequest, boolean includeDeleted) { + int page = pageRequest.getPage(); + int size = pageRequest.getSize(); + + String cacheKey = CACHE_KEY_PREFIX + page + ":" + size + ":" + includeDeleted; + + Object cachedData = redisService.get(cacheKey); + if (cachedData != null) { + try { + String json; + if (cachedData instanceof String) { + json = (String) cachedData; + } else { + json = objectMapper.writeValueAsString(cachedData); + } + + PageResponse pageResponse = objectMapper.readValue(json, + objectMapper.getTypeFactory().constructParametricType(PageResponse.class, GroupCourse.class)); + logger.info("缓存命中 - findByPage: key={}", cacheKey); + return Mono.just(pageResponse); + } catch (JsonProcessingException e) { + logger.warn("缓存解析失败,删除缓存 - key: {}, error: {}", cacheKey, e.getMessage()); + redisService.delete(cacheKey); + } + } + + logger.debug("缓存未命中,查询数据库 - findByPage: key={}", cacheKey); + Mono> resultMono; + if (includeDeleted) { + resultMono = groupCourseRepository.findByPage(pageRequest); + } else { + resultMono = groupCourseRepository.findByPageAndNotDeleted(pageRequest); + } + + return resultMono.doOnSuccess(pageResponse -> { + try { + String jsonData = objectMapper.writeValueAsString(pageResponse); + redisService.setWithExpire(cacheKey, jsonData, CACHE_EXPIRE_SECONDS); + logger.debug("缓存已设置 - findByPage: key={}", cacheKey); + } catch (JsonProcessingException e) { + logger.error("缓存设置失败 - key: {}, error: {}", cacheKey, e.getMessage()); + } + }); + } } diff --git a/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/RedisConfig.java b/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/RedisConfig.java new file mode 100644 index 0000000..12d804e --- /dev/null +++ b/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/RedisConfig.java @@ -0,0 +1,43 @@ +package cn.novalon.gym.manage.app.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @author:liwentao + * @date:2026/5/15-05-15-16:01 + */ +@Configuration +public class RedisConfig { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(factory); + + // 创建ObjectMapper并配置 + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL); + + // 使用GenericJackson2JsonRedisSerializer替代已弃用的方式 + GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(om); + + // 使用StringRedisSerializer来序列化和反序列化redis的key值 + StringRedisSerializer stringSerializer = new StringRedisSerializer(); + template.setKeySerializer(stringSerializer); + template.setValueSerializer(genericJackson2JsonRedisSerializer); + template.setHashKeySerializer(stringSerializer); + template.setHashValueSerializer(genericJackson2JsonRedisSerializer); + + template.afterPropertiesSet(); + return template; + } +} \ No newline at end of file diff --git a/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/SystemRouter.java b/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/SystemRouter.java index 185540b..ff82abc 100644 --- a/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/SystemRouter.java +++ b/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/SystemRouter.java @@ -24,16 +24,6 @@ import org.springframework.web.reactive.function.server.ServerResponse; import static org.springframework.web.reactive.function.server.RouterFunctions.route; -/** - * 系统路由配置类 - * - * 文件定义:配置WebFlux函数式路由,将HTTP请求映射到对应的Handler方法 - * 涉及业务:用户、角色、字典、菜单、公告、文件等所有RESTful API路由 - * 算法:使用RouterFunctions.route()构建函数式路由规则 - * - * @author 张翔 - * @date 2026-03-13 - */ @Configuration public class SystemRouter { @Bean @@ -56,10 +46,8 @@ public class SystemRouter { PasswordDiagnosticHandler passwordDiagnosticHandler) { return route() - // ========== 诊断路由 ========== .GET("/api/diagnostic/password", passwordDiagnosticHandler::diagnose) - // ========== 字典路由 ========== .GET("/api/dictionaries", dictionaryHandler::getAllDictionaries) .GET("/api/dictionaries/{id}", dictionaryHandler::getDictionaryById) .GET("/api/dictionaries/type/{type}", dictionaryHandler::getDictionariesByType) @@ -68,7 +56,6 @@ public class SystemRouter { .PUT("/api/dictionaries/{id}", dictionaryHandler::updateDictionary) .DELETE("/api/dictionaries/{id}", dictionaryHandler::deleteDictionary) - // ========== 用户路由 ========== .GET("/api/users", userHandler::getAllUsers) .GET("/api/users/page", userHandler::getUsersByPage) .GET("/api/users/count", userHandler::getUserCount) @@ -87,7 +74,6 @@ public class SystemRouter { .GET("/api/users/{id}/roles", userHandler::getUserRoles) .POST("/api/users/{id}/roles", userHandler::assignRoles) - // ========== 菜单路由 ========== .GET("/api/menus", menuHandler::getAllMenus) .GET("/api/menus/tree", menuHandler::getMenuTree) .GET("/api/menus/{id}", menuHandler::getMenuById) @@ -95,7 +81,6 @@ public class SystemRouter { .PUT("/api/menus/{id}", menuHandler::updateMenu) .DELETE("/api/menus/{id}", menuHandler::deleteMenu) - // ========== 角色路由 ========== .GET("/api/roles", roleHandler::getAllRoles) .GET("/api/roles/page", roleHandler::getRolesByPage) .GET("/api/roles/count", roleHandler::getRoleCount) @@ -109,7 +94,6 @@ public class SystemRouter { .GET("/api/roles/{id}/permissions", permissionHandler::getPermissionsByRoleId) .POST("/api/roles/{id}/permissions", permissionHandler::assignPermissionsToRole) - // ========== 配置路由 ========== .GET("/api/config", configHandler::getAllConfigs) .GET("/api/config/{id}", configHandler::getConfigById) .GET("/api/config/key/{configKey}", configHandler::getConfigByKey) @@ -117,7 +101,6 @@ public class SystemRouter { .PUT("/api/config/{id}", configHandler::updateConfig) .DELETE("/api/config/{id}", configHandler::deleteConfig) - // ========== 日志路由 ========== .GET("/api/logs/login", logHandler::getAllLoginLogs) .GET("/api/logs/login/page", logHandler::getLoginLogsByPage) .GET("/api/logs/login/count", logHandler::getLoginLogCount) @@ -137,15 +120,12 @@ public class SystemRouter { .GET("/api/logs/operation/{id}", operationLogHandler::getOperationLogById) .POST("/api/logs/operation", operationLogHandler::createOperationLog) - // ========== 认证路由 ========== .POST("/api/auth/login", authHandler::login) .POST("/api/auth/register", authHandler::register) .POST("/api/auth/logout", authHandler::logout) - // ========== 统计路由 ========== .GET("/api/stats/overview", statsHandler::getOverview) - // ========== 数据字典路由 ========== .GET("/api/dict/types", dictHandler::getAllDictTypes) .GET("/api/dict/types/{id}", dictHandler::getDictTypeById) .GET("/api/dict/types/type/{dictType}", dictHandler::getDictTypeByType) @@ -159,7 +139,6 @@ public class SystemRouter { .PUT("/api/dict/data/{id}", dictHandler::updateDictData) .DELETE("/api/dict/data/{id}", dictHandler::deleteDictData) - // ========== 公告路由 ========== .GET("/api/notices", noticeHandler::getAllNotices) .GET("/api/notices/{id}", noticeHandler::getNoticeById) .GET("/api/notices/status/{status}", noticeHandler::getNoticesByStatus) @@ -167,7 +146,6 @@ public class SystemRouter { .PUT("/api/notices/{id}", noticeHandler::updateNotice) .DELETE("/api/notices/{id}", noticeHandler::deleteNotice) - // ========== 消息路由 ========== .GET("/api/messages/user/{userId}", messageHandler::getMessagesByUser) .GET("/api/messages/user/{userId}/unread", messageHandler::getUnreadCount) .GET("/api/messages/user/{userId}/unread/list", messageHandler::getUnreadList) @@ -175,7 +153,6 @@ public class SystemRouter { .PUT("/api/messages/{id}/read", messageHandler::markAsRead) .DELETE("/api/messages/{id}", messageHandler::deleteMessage) - // ========== 文件路由 ========== .GET("/api/files", fileHandler::getAllFiles) .GET("/api/files/{id}", fileHandler::getFileById) .POST("/api/files/upload", fileHandler::uploadFile) @@ -185,7 +162,6 @@ public class SystemRouter { .GET("/api/files/preview/{fileName}", fileHandler::previewFileByName) .DELETE("/api/files/{id}", fileHandler::deleteFile) - // ========== 权限路由 ========== .GET("/api/permissions", permissionHandler::getAllPermissions) .GET("/api/permissions/{id}", permissionHandler::getPermissionById) .GET("/api/permissions/code/{code}", permissionHandler::getPermissionByCode) @@ -195,8 +171,9 @@ public class SystemRouter { .PUT("/api/permissions/{id}", permissionHandler::updatePermission) .DELETE("/api/permissions/{id}", permissionHandler::deletePermission) - // ========== 团课路由 ========== .GET("/api/groupCourse", groupCourseHandler::getAllGroupCourse) + .POST("/api/groupCourse/page", groupCourseHandler::getGroupCoursesByPage) + .POST("/api/groupCourse/cache/get", groupCourseHandler::getCacheByKey) .GET("/api/groupCourse/{id}", groupCourseHandler::getGroupCourseById) .build(); diff --git a/gym-manage-api/manage-app/src/main/resources/application.yml b/gym-manage-api/manage-app/src/main/resources/application.yml index 0d7edda..91f237f 100644 --- a/gym-manage-api/manage-app/src/main/resources/application.yml +++ b/gym-manage-api/manage-app/src/main/resources/application.yml @@ -38,9 +38,22 @@ spring: user: name: disabled password: disabled + data: + redis: + host: ${REDIS_HOST:localhost} + port: ${REDIS_PORT:6379} + password: ${REDIS_PASSWORD:novalon123} + timeout: 5000 + lettuce: + pool: + max-active: 8 # 最大连接数 + max-idle: 8 # 最大空闲连接 + min-idle: 0 # 最小空闲连接 + max-wait: -1ms # 连接等待时间 profiles: active: dev + management: endpoints: web: diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java index a824830..83ea7df 100644 --- a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java +++ b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java @@ -50,7 +50,8 @@ public class SecurityConfig { spec.pathMatchers("/api/auth/**").permitAll() .pathMatchers("/api/public/**").permitAll() .pathMatchers("/ws/**").permitAll() - .pathMatchers("/actuator/**").permitAll(); + .pathMatchers("/actuator/**").permitAll() + .pathMatchers("/api/groupCourse/**").permitAll(); if (isDevOrTest) {