Merge branch 'master-jdk21' of https://gitee.com/zhijiantianya/yudao-cloud
						commit
						5517dc7d4a
					
				|  | @ -1,12 +1,10 @@ | |||
| package cn.iocoder.yudao.framework.common.util.cache; | ||||
| 
 | ||||
| import com.alibaba.ttl.threadpool.TtlExecutors; | ||||
| import com.google.common.cache.CacheBuilder; | ||||
| import com.google.common.cache.CacheLoader; | ||||
| import com.google.common.cache.LoadingCache; | ||||
| 
 | ||||
| import java.time.Duration; | ||||
| import java.util.concurrent.Executor; | ||||
| import java.util.concurrent.Executors; | ||||
| 
 | ||||
| /** | ||||
|  | @ -16,14 +14,36 @@ import java.util.concurrent.Executors; | |||
|  */ | ||||
| public class CacheUtils { | ||||
| 
 | ||||
|     /** | ||||
|      * 构建异步刷新的 LoadingCache 对象 | ||||
|      * | ||||
|      * 注意:如果你的缓存和 ThreadLocal 有关系,要么自己处理 ThreadLocal 的传递,要么使用 {@link #buildCache(Duration, CacheLoader)} 方法 | ||||
|      * | ||||
|      * 或者简单理解: | ||||
|      * 1、和“人”相关的,使用 {@link #buildCache(Duration, CacheLoader)} 方法 | ||||
|      * 2、和“全局”、“系统”相关的,使用当前缓存方法 | ||||
|      * | ||||
|      * @param duration 过期时间 | ||||
|      * @param loader  CacheLoader 对象 | ||||
|      * @return LoadingCache 对象 | ||||
|      */ | ||||
|     public static <K, V> LoadingCache<K, V> buildAsyncReloadingCache(Duration duration, CacheLoader<K, V> loader) { | ||||
|         Executor executor = Executors.newCachedThreadPool(  // TODO 芋艿:可能要思考下,未来要不要做成可配置
 | ||||
|                 TtlExecutors.getDefaultDisableInheritableThreadFactory()); // TTL 保证 ThreadLocal 可以透传
 | ||||
|         return CacheBuilder.newBuilder() | ||||
|                 // 只阻塞当前数据加载线程,其他线程返回旧值
 | ||||
|                 .refreshAfterWrite(duration) | ||||
|                 // 通过 asyncReloading 实现全异步加载,包括 refreshAfterWrite 被阻塞的加载线程
 | ||||
|                 .build(CacheLoader.asyncReloading(loader, executor)); | ||||
|                 .build(CacheLoader.asyncReloading(loader, Executors.newCachedThreadPool())); // TODO 芋艿:可能要思考下,未来要不要做成可配置
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 构建同步刷新的 LoadingCache 对象 | ||||
|      * | ||||
|      * @param duration 过期时间 | ||||
|      * @param loader  CacheLoader 对象 | ||||
|      * @return LoadingCache 对象 | ||||
|      */ | ||||
|     public static <K, V> LoadingCache<K, V> buildCache(Duration duration, CacheLoader<K, V> loader) { | ||||
|         return CacheBuilder.newBuilder().refreshAfterWrite(duration).build(loader); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -12,6 +12,8 @@ import lombok.extern.slf4j.Slf4j; | |||
| 
 | ||||
| import java.time.Duration; | ||||
| 
 | ||||
| import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; | ||||
| 
 | ||||
| /** | ||||
|  * 字典工具类 | ||||
|  * | ||||
|  | @ -27,7 +29,7 @@ public class DictFrameworkUtils { | |||
|     /** | ||||
|      * 针对 {@link #getDictDataLabel(String, String)} 的缓存 | ||||
|      */ | ||||
|     private static final LoadingCache<KeyValue<String, String>, DictDataRespDTO> GET_DICT_DATA_CACHE = CacheUtils.buildAsyncReloadingCache( | ||||
|     private static final LoadingCache<KeyValue<String, String>, DictDataRespDTO> GET_DICT_DATA_CACHE = buildAsyncReloadingCache( | ||||
|             Duration.ofMinutes(1L), // 过期时间 1 分钟
 | ||||
|             new CacheLoader<KeyValue<String, String>, DictDataRespDTO>() { | ||||
| 
 | ||||
|  | @ -42,7 +44,7 @@ public class DictFrameworkUtils { | |||
|     /** | ||||
|      * 针对 {@link #parseDictDataValue(String, String)} 的缓存 | ||||
|      */ | ||||
|     private static final LoadingCache<KeyValue<String, String>, DictDataRespDTO> PARSE_DICT_DATA_CACHE = CacheUtils.buildAsyncReloadingCache( | ||||
|     private static final LoadingCache<KeyValue<String, String>, DictDataRespDTO> PARSE_DICT_DATA_CACHE = buildAsyncReloadingCache( | ||||
|             Duration.ofMinutes(1L), // 过期时间 1 分钟
 | ||||
|             new CacheLoader<KeyValue<String, String>, DictDataRespDTO>() { | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,6 +11,8 @@ import lombok.SneakyThrows; | |||
| import java.time.Duration; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; | ||||
| 
 | ||||
| /** | ||||
|  * Tenant 框架 Service 实现类 | ||||
|  * | ||||
|  | @ -24,7 +26,7 @@ public class TenantFrameworkServiceImpl implements TenantFrameworkService { | |||
|     /** | ||||
|      * 针对 {@link #getTenantIds()} 的缓存 | ||||
|      */ | ||||
|     private final LoadingCache<Object, List<Long>> getTenantIdsCache = CacheUtils.buildAsyncReloadingCache( | ||||
|     private final LoadingCache<Object, List<Long>> getTenantIdsCache = buildAsyncReloadingCache( | ||||
|             Duration.ofMinutes(1L), // 过期时间 1 分钟
 | ||||
|             new CacheLoader<Object, List<Long>>() { | ||||
| 
 | ||||
|  | @ -38,7 +40,7 @@ public class TenantFrameworkServiceImpl implements TenantFrameworkService { | |||
|     /** | ||||
|      * 针对 {@link #validTenant(Long)} 的缓存 | ||||
|      */ | ||||
|     private final LoadingCache<Long, CommonResult<Boolean>> validTenantCache = CacheUtils.buildAsyncReloadingCache( | ||||
|     private final LoadingCache<Long, CommonResult<Boolean>> validTenantCache = buildAsyncReloadingCache( | ||||
|             Duration.ofMinutes(1L), // 过期时间 1 分钟
 | ||||
|             new CacheLoader<Long, CommonResult<Boolean>>() { | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,6 +20,8 @@ import java.time.Duration; | |||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; | ||||
| import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildCache; | ||||
| import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||||
| 
 | ||||
| /** | ||||
|  | @ -35,7 +37,7 @@ public class SecurityFrameworkServiceImpl implements SecurityFrameworkService { | |||
|     /** | ||||
|      * 针对 {@link #hasAnyRoles(String...)} 的缓存 | ||||
|      */ | ||||
|     private final LoadingCache<KeyValue<Long, List<String>>, Boolean> hasAnyRolesCache = CacheUtils.buildAsyncReloadingCache( | ||||
|     private final LoadingCache<KeyValue<Long, List<String>>, Boolean> hasAnyRolesCache = buildCache( | ||||
|             Duration.ofMinutes(1L), // 过期时间 1 分钟
 | ||||
|             new CacheLoader<KeyValue<Long, List<String>>, Boolean>() { | ||||
| 
 | ||||
|  | @ -49,7 +51,7 @@ public class SecurityFrameworkServiceImpl implements SecurityFrameworkService { | |||
|     /** | ||||
|      * 针对 {@link #hasAnyPermissions(String...)} 的缓存 | ||||
|      */ | ||||
|     private final LoadingCache<KeyValue<Long, List<String>>, Boolean> hasAnyPermissionsCache = CacheUtils.buildAsyncReloadingCache( | ||||
|     private final LoadingCache<KeyValue<Long, List<String>>, Boolean> hasAnyPermissionsCache = buildCache( | ||||
|             Duration.ofMinutes(1L), // 过期时间 1 分钟
 | ||||
|             new CacheLoader<KeyValue<Long, List<String>>, Boolean>() { | ||||
| 
 | ||||
|  |  | |||
|  | @ -26,6 +26,9 @@ import java.time.Duration; | |||
| import java.util.Objects; | ||||
| import java.util.function.Function; | ||||
| 
 | ||||
| import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; | ||||
| import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildCache; | ||||
| 
 | ||||
| /** | ||||
|  * Token 过滤器,验证 token 的有效性 | ||||
|  * 1. 验证通过时,将 userId、userType、tenantId 通过 Header 转发给服务 | ||||
|  | @ -59,7 +62,7 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered { | |||
|      * key1:多租户的编号 | ||||
|      * key2:访问令牌 | ||||
|      */ | ||||
|     private final LoadingCache<KeyValue<Long, String>, LoginUser> loginUserCache = CacheUtils.buildAsyncReloadingCache(Duration.ofMinutes(1), | ||||
|     private final LoadingCache<KeyValue<Long, String>, LoginUser> loginUserCache = buildAsyncReloadingCache(Duration.ofMinutes(1), | ||||
|             new CacheLoader<KeyValue<Long, String>, LoginUser>() { | ||||
| 
 | ||||
|                 @Override | ||||
|  |  | |||
|  | @ -31,6 +31,7 @@ import java.util.List; | |||
| 
 | ||||
| import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||||
| import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; | ||||
| import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildCache; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||||
| 
 | ||||
| @Tag(name = "用户 App - 砍价活动") | ||||
|  | @ -42,7 +43,7 @@ public class AppBargainActivityController { | |||
|     /** | ||||
|      * {@link AppBargainActivityRespVO} 缓存,通过它异步刷新 {@link #getBargainActivityList0(Integer)} 所要的首页数据 | ||||
|      */ | ||||
|     private final LoadingCache<Integer, List<AppBargainActivityRespVO>> bargainActivityListCache = buildAsyncReloadingCache(Duration.ofSeconds(10L), | ||||
|     private final LoadingCache<Integer, List<AppBargainActivityRespVO>> bargainActivityListCache = buildCache(Duration.ofSeconds(10L), | ||||
|             new CacheLoader<Integer, List<AppBargainActivityRespVO>>() { | ||||
| 
 | ||||
|                 @Override | ||||
|  |  | |||
|  | @ -32,6 +32,7 @@ import java.util.List; | |||
| 
 | ||||
| import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||||
| import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; | ||||
| import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildCache; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||||
| 
 | ||||
| @Tag(name = "用户 APP - 拼团活动") | ||||
|  | @ -43,7 +44,7 @@ public class AppCombinationActivityController { | |||
|     /** | ||||
|      * {@link AppCombinationActivityRespVO} 缓存,通过它异步刷新 {@link #getCombinationActivityList0(Integer)} 所要的首页数据 | ||||
|      */ | ||||
|     private final LoadingCache<Integer, List<AppCombinationActivityRespVO>> combinationActivityListCache = buildAsyncReloadingCache(Duration.ofSeconds(10L), | ||||
|     private final LoadingCache<Integer, List<AppCombinationActivityRespVO>> combinationActivityListCache = buildCache(Duration.ofSeconds(10L), | ||||
|             new CacheLoader<Integer, List<AppCombinationActivityRespVO>>() { | ||||
| 
 | ||||
|                 @Override | ||||
|  |  | |||
|  | @ -39,6 +39,7 @@ import java.util.List; | |||
| 
 | ||||
| import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||||
| import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; | ||||
| import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildCache; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.findFirst; | ||||
| import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.isBetween; | ||||
|  | @ -52,7 +53,7 @@ public class AppSeckillActivityController { | |||
|     /** | ||||
|      * {@link AppSeckillActivityNowRespVO} 缓存,通过它异步刷新 {@link #getNowSeckillActivity()} 所要的首页数据 | ||||
|      */ | ||||
|     private final LoadingCache<String, AppSeckillActivityNowRespVO> nowSeckillActivityCache = buildAsyncReloadingCache(Duration.ofSeconds(10L), | ||||
|     private final LoadingCache<String, AppSeckillActivityNowRespVO> nowSeckillActivityCache = buildCache(Duration.ofSeconds(10L), | ||||
|             new CacheLoader<String, AppSeckillActivityNowRespVO>() { | ||||
| 
 | ||||
|                 @Override | ||||
|  |  | |||
|  | @ -82,7 +82,7 @@ public class MemberAuthServiceImpl implements MemberAuthService { | |||
|     public AppAuthLoginRespVO smsLogin(AppAuthSmsLoginReqVO reqVO) { | ||||
|         // 校验验证码
 | ||||
|         String userIp = getClientIP(); | ||||
|         smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_LOGIN.getScene(), userIp)); | ||||
|         smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_LOGIN.getScene(), userIp)).getCheckedData(); | ||||
| 
 | ||||
|         // 获得获得注册用户
 | ||||
|         MemberUserDO user = userService.createUserIfAbsent(reqVO.getMobile(), userIp, getTerminal()); | ||||
|  |  | |||
|  | @ -158,11 +158,11 @@ public class MemberUserServiceImpl implements MemberUserService { | |||
|         // 补充说明:从安全性来说,老手机也校验 oldCode 验证码会更安全。但是由于 uni-app 商城界面暂时没做,所以这里不强制校验
 | ||||
|         if (StrUtil.isNotEmpty(reqVO.getOldCode())) { | ||||
|             smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getOldCode()) | ||||
|                     .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())); | ||||
|                     .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())).getCheckedData(); | ||||
|         } | ||||
|         // 2.2 使用新验证码
 | ||||
|         smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getMobile()).setCode(reqVO.getCode()) | ||||
|                 .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())); | ||||
|                 .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())).getCheckedData(); | ||||
| 
 | ||||
|         // 3. 更新用户手机
 | ||||
|         memberUserMapper.updateById(MemberUserDO.builder().id(userId).mobile(reqVO.getMobile()).build()); | ||||
|  | @ -187,7 +187,7 @@ public class MemberUserServiceImpl implements MemberUserService { | |||
|         MemberUserDO user = validateUserExists(userId); | ||||
|         // 校验验证码
 | ||||
|         smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getCode()) | ||||
|                 .setScene(SmsSceneEnum.MEMBER_UPDATE_PASSWORD.getScene()).setUsedIp(getClientIP())); | ||||
|                 .setScene(SmsSceneEnum.MEMBER_UPDATE_PASSWORD.getScene()).setUsedIp(getClientIP())).getCheckedData(); | ||||
| 
 | ||||
|         // 更新用户密码
 | ||||
|         memberUserMapper.updateById(MemberUserDO.builder().id(userId) | ||||
|  | @ -201,7 +201,7 @@ public class MemberUserServiceImpl implements MemberUserService { | |||
| 
 | ||||
|         // 使用验证码
 | ||||
|         smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_RESET_PASSWORD, | ||||
|                 getClientIP())); | ||||
|                 getClientIP())).getCheckedData(); | ||||
| 
 | ||||
|         // 更新密码
 | ||||
|         memberUserMapper.updateById(MemberUserDO.builder().id(user.getId()) | ||||
|  |  | |||
|  | @ -122,7 +122,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { | |||
|     @Override | ||||
|     public AuthLoginRespVO smsLogin(AuthSmsLoginReqVO reqVO) { | ||||
|         // 校验验证码
 | ||||
|         smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.ADMIN_MEMBER_LOGIN.getScene(), getClientIP())); | ||||
|         smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.ADMIN_MEMBER_LOGIN.getScene(), getClientIP())).getCheckedData(); | ||||
| 
 | ||||
|         // 获得用户信息
 | ||||
|         AdminUserDO user = userService.getUserByMobile(reqVO.getMobile()); | ||||
|  |  | |||
|  | @ -46,6 +46,7 @@ import java.time.Duration; | |||
| import java.util.Objects; | ||||
| 
 | ||||
| import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||||
| import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; | ||||
| import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | ||||
| import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||||
| 
 | ||||
|  | @ -75,7 +76,7 @@ public class SocialClientServiceImpl implements SocialClientService { | |||
|      * | ||||
|      * 为什么要做 WxMpService 缓存?因为 WxMpService 构建成本比较大,所以尽量保证它是单例。 | ||||
|      */ | ||||
|     private final LoadingCache<String, WxMpService> wxMpServiceCache = CacheUtils.buildAsyncReloadingCache( | ||||
|     private final LoadingCache<String, WxMpService> wxMpServiceCache = buildAsyncReloadingCache( | ||||
|             Duration.ofSeconds(10L), | ||||
|             new CacheLoader<String, WxMpService>() { | ||||
| 
 | ||||
|  | @ -96,7 +97,7 @@ public class SocialClientServiceImpl implements SocialClientService { | |||
|      * | ||||
|      * 说明同 {@link #wxMpServiceCache} 变量 | ||||
|      */ | ||||
|     private final LoadingCache<String, WxMaService> wxMaServiceCache = CacheUtils.buildAsyncReloadingCache( | ||||
|     private final LoadingCache<String, WxMaService> wxMaServiceCache = buildAsyncReloadingCache( | ||||
|             Duration.ofSeconds(10L), | ||||
|             new CacheLoader<String, WxMaService>() { | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 YunaiV
						YunaiV