Skip to content

Commit

Permalink
perf: 对获取路由信息接口增加缓存处理
Browse files Browse the repository at this point in the history
1.优化 Spring Cache 配置
2.暂时移除 Jackson 针对数值类型:Long、BigInteger、BigDecimal 的 toString 处理(TreeUtil 疑似在字符串类型 parentId 时会出现转换异常)
  • Loading branch information
Charles7c committed Aug 31, 2023
1 parent d7c0dce commit 4639d13
Show file tree
Hide file tree
Showing 14 changed files with 181 additions and 105 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package top.charles7c.cnadmin.common.config;

import java.util.Map;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.redisson.codec.JsonJacksonCodec;
import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.*;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONUtil;

/**
* Redis 配置
*
* @author Charles7c
* @since 2022/12/28 23:17
*/
@Slf4j
@EnableCaching
@Configuration
@RequiredArgsConstructor
public class RedisConfiguration extends CachingConfigurerSupport {

private final ObjectMapper objectMapper;

/**
* Redisson 自定义配置
*/
@Bean
public RedissonAutoConfigurationCustomizer redissonCustomizer() {
// 解决序列化乱码问题
return config -> config.setCodec(new JsonJacksonCodec(objectMapper));
}

/**
* 解决 Spring Cache(@Cacheable)缓存乱码问题
*/
@Bean
public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {
ObjectMapper objectMapperCopy =
objectMapper.copy().enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer(objectMapperCopy)));
CacheProperties.Redis redisCacheProperties = cacheProperties.getRedis();
if (null != redisCacheProperties.getTimeToLive()) {
redisCacheConfiguration = redisCacheConfiguration.entryTtl(redisCacheProperties.getTimeToLive());
}
if (!redisCacheProperties.isCacheNullValues()) {
redisCacheConfiguration = redisCacheConfiguration.disableCachingNullValues();
}
return redisCacheConfiguration;
}

/**
* 自定义缓存 key 生成策略(如果 @Cacheable 不指定 key,则默认使用该策略)
*/
@Bean
@Override
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
String key = StrUtil.toUnderlineCase(method.getName()).toUpperCase();
Map<String, Object> paramMap = MapUtil.newHashMap(params.length);
for (int i = 0; i < params.length; i++) {
paramMap.put(String.valueOf(i), params[i]);
}
return String.format("%s:%s", key, DigestUtil.sha256Hex(JSONUtil.toJsonStr(paramMap)));
};
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

package top.charles7c.cnadmin.common.config.jackson;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
Expand All @@ -33,7 +31,6 @@

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
Expand All @@ -57,19 +54,12 @@
public class JacksonConfiguration {

/**
* 针对数值类型:Long、BigInteger、BigDecimal,时间类型:LocalDateTime、LocalDate、LocalTime 的序列化和反序列化
* 针对时间类型:LocalDateTime、LocalDate、LocalTime 的序列化和反序列化
*/
@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
return builder -> {
JavaTimeModule javaTimeModule = new JavaTimeModule();
// 针对数值类型:Long、BigInteger、BigDecimal 的序列化
javaTimeModule.addSerializer(Long.class, ToStringSerializer.instance);
javaTimeModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
javaTimeModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
javaTimeModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);

// 针对时间类型:LocalDateTime、LocalDate、LocalTime 的序列化和反序列化
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN);
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,9 @@ public class CacheConsts {
* 用户缓存键前缀
*/
public static final String USER_KEY_PREFIX = "USER";

/**
* 菜单缓存键前缀
*/
public static final String MENU_KEY_PREFIX = "MENU";
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@

package top.charles7c.cnadmin.auth.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;

import lombok.RequiredArgsConstructor;

Expand All @@ -44,7 +43,6 @@
import top.charles7c.cnadmin.common.util.helper.LoginHelper;
import top.charles7c.cnadmin.common.util.validate.CheckUtils;
import top.charles7c.cnadmin.system.model.entity.UserDO;
import top.charles7c.cnadmin.system.model.query.MenuQuery;
import top.charles7c.cnadmin.system.model.vo.DeptDetailVO;
import top.charles7c.cnadmin.system.model.vo.MenuVO;
import top.charles7c.cnadmin.system.service.DeptService;
Expand Down Expand Up @@ -91,21 +89,20 @@ public String login(String username, String password) {

@Override
public List<RouteVO> buildRouteTree(Long userId) {
Set<String> roleSet = permissionService.listRoleCodeByUserId(userId);
if (CollUtil.isEmpty(roleSet)) {
Set<String> roleCodeSet = permissionService.listRoleCodeByUserId(userId);
if (CollUtil.isEmpty(roleCodeSet)) {
return new ArrayList<>(0);
}

// 查询菜单列表
List<MenuVO> menuList;
if (roleSet.contains(SysConsts.ADMIN_ROLE_CODE)) {
MenuQuery menuQuery = new MenuQuery();
menuQuery.setStatus(DisEnableStatusEnum.ENABLE.getValue());
menuList = menuService.list(menuQuery, null);
Set<MenuVO> menuSet = new LinkedHashSet<>();
if (roleCodeSet.contains(SysConsts.ADMIN_ROLE_CODE)) {
menuSet.addAll(menuService.list());
} else {
menuList = menuService.listByUserId(userId);
roleCodeSet.forEach(roleCode -> menuSet.addAll(menuService.listByRoleCode(roleCode)));
}
menuList.removeIf(m -> MenuTypeEnum.BUTTON.equals(m.getType()));
List<MenuVO> menuList =
menuSet.stream().filter(m -> !MenuTypeEnum.BUTTON.equals(m.getType())).collect(Collectors.toList());

// 构建路由树
TreeField treeField = MenuVO.class.getDeclaredAnnotation(TreeField.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ public interface MenuMapper extends BaseMapper<MenuDO> {
Set<String> selectPermissionByUserId(@Param("userId") Long userId);

/**
* 根据用户 ID 查询
* 根据角色编码查询
*
* @param userId
* 用户 ID
* @param roleCode
* 角色编码
* @return 菜单列表
*/
List<MenuDO> selectListByUserId(@Param("userId") Long userId);
List<MenuDO> selectListByRoleCode(@Param("roleCode") String roleCode);
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,18 @@ public interface MenuService extends BaseService<MenuVO, MenuVO, MenuQuery, Menu
Set<String> listPermissionByUserId(Long userId);

/**
* 根据用户 ID 查询
* 根据角色编码查询
*
* @param roleCode
* 角色编码
* @return 菜单列表
*/
List<MenuVO> listByRoleCode(String roleCode);

/**
* 查询所有菜单
*
* @param userId
* 用户 ID
* @return 菜单列表
*/
List<MenuVO> listByUserId(Long userId);
List<MenuVO> list();
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@

import lombok.RequiredArgsConstructor;

import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.hutool.core.bean.BeanUtil;

import top.charles7c.cnadmin.common.base.BaseServiceImpl;
import top.charles7c.cnadmin.common.constant.CacheConsts;
import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum;
import top.charles7c.cnadmin.common.util.validate.CheckUtils;
import top.charles7c.cnadmin.system.mapper.MenuMapper;
Expand All @@ -43,10 +47,12 @@
*/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = CacheConsts.MENU_KEY_PREFIX)
public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, MenuDO, MenuVO, MenuVO, MenuQuery, MenuRequest>
implements MenuService {

@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public Long add(MenuRequest request) {
String title = request.getTitle();
Expand All @@ -58,6 +64,7 @@ public Long add(MenuRequest request) {
}

@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void update(MenuRequest request, Long id) {
String title = request.getTitle();
Expand All @@ -68,6 +75,7 @@ public void update(MenuRequest request, Long id) {
}

@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(List<Long> ids) {
baseMapper.lambdaUpdate().in(MenuDO::getParentId, ids).remove();
Expand All @@ -80,13 +88,22 @@ public Set<String> listPermissionByUserId(Long userId) {
}

@Override
public List<MenuVO> listByUserId(Long userId) {
List<MenuDO> menuList = baseMapper.selectListByUserId(userId);
@Cacheable(key = "#roleCode")
public List<MenuVO> listByRoleCode(String roleCode) {
List<MenuDO> menuList = baseMapper.selectListByRoleCode(roleCode);
List<MenuVO> list = BeanUtil.copyToList(menuList, MenuVO.class);
list.forEach(this::fill);
return list;
}

@Override
@Cacheable(key = "'ALL'")
public List<MenuVO> list() {
MenuQuery menuQuery = new MenuQuery();
menuQuery.setStatus(DisEnableStatusEnum.ENABLE.getValue());
return super.list(menuQuery, null);
}

/**
* 检查名称是否存在
*
Expand Down
Loading

0 comments on commit 4639d13

Please sign in to comment.