Browse Source

BUG修改

dev
wangfukang 1 year ago
parent
commit
a57aefd68b
  1. 16
      hiver-admin/test-output/test-report.html
  2. 120
      hiver-core/src/main/java/cc/hiver/core/common/utils/SecurityUtil.java
  3. 122
      hiver-core/src/main/java/cc/hiver/core/config/cache/RedisCacheConfig.java
  4. 2
      hiver-core/src/main/resources/mapper/LogisticsAddressBookMapper.xml
  5. 4
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/AliOcrUtil.java

16
hiver-admin/test-output/test-report.html

@ -35,7 +35,7 @@
<a href="#"><span class="badge badge-primary">Hiver</span></a>
</li>
<li class="m-r-10">
<a href="#"><span class="badge badge-primary">三月 26, 2025 17:18:30</span></a>
<a href="#"><span class="badge badge-primary">三月 31, 2025 22:27:43</span></a>
</li>
</ul>
</div>
@ -84,7 +84,7 @@
<div class="test-detail">
<span class="meta text-white badge badge-sm"></span>
<p class="name">passTest</p>
<p class="text-sm"><span>17:18:30 下午</span> / <span>0.017 secs</span></p>
<p class="text-sm"><span>22:27:44 下午</span> / <span>0.028 secs</span></p>
</div>
<div class="test-contents d-none">
<div class="detail-head">
@ -92,9 +92,9 @@
<div class="info">
<div class='float-right'><span class='badge badge-default'>#test-id=1</span></div>
<h5 class="test-status text-pass">passTest</h5>
<span class='badge badge-success'>03.26.2025 17:18:30</span>
<span class='badge badge-danger'>03.26.2025 17:18:30</span>
<span class='badge badge-default'>0.017 secs</span>
<span class='badge badge-success'>03.31.2025 22:27:44</span>
<span class='badge badge-danger'>03.31.2025 22:27:44</span>
<span class='badge badge-default'>0.028 secs</span>
</div>
<div class="m-t-10 m-l-5"></div>
</div>
@ -104,7 +104,7 @@
<tbody>
<tr class="event-row">
<td><span class="badge log pass-bg">Pass</span></td>
<td>17:18:30</td>
<td>22:27:44</td>
<td>
Test passed
</td>
@ -128,13 +128,13 @@
<div class="col-md-3">
<div class="card"><div class="card-body">
<p class="m-b-0">Started</p>
<h3>三月 26, 2025 17:18:30</h3>
<h3>三月 31, 2025 22:27:43</h3>
</div></div>
</div>
<div class="col-md-3">
<div class="card"><div class="card-body">
<p class="m-b-0">Ended</p>
<h3>三月 26, 2025 17:18:30</h3>
<h3>三月 31, 2025 22:27:44</h3>
</div></div>
</div>
<div class="col-md-3">

120
hiver-core/src/main/java/cc/hiver/core/common/utils/SecurityUtil.java

@ -23,12 +23,14 @@ import cc.hiver.core.vo.PermissionDTO;
import cc.hiver.core.vo.RoleDTO;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.IdUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
@ -38,10 +40,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@ -77,7 +76,10 @@ public class SecurityUtil {
private MemberDao memberDao;
@Autowired
private RedisTemplateHelper redisTemplate;
private RedisTemplateHelper redisTemplateHelper;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private WorkerDao workerDao;
@ -88,6 +90,9 @@ public class SecurityUtil {
@Autowired
private LogisticsUserService logisticsUserService;
@Autowired
private ObjectMapper objectMapper;
/**
* -------------------ToB-------------------------
*/
@ -95,7 +100,7 @@ public class SecurityUtil {
public User findUserByUsername(String username) {
final String key = "username::" + username;
// 读取缓存
final String res = redisTemplate.get(key);
final String res = redisTemplateHelper.get(key);
if (CharSequenceUtil.isNotBlank(res)) {
final Gson oldUser = new GsonBuilder().setDateFormat("yyyy-MM-dd hh:mm:ss").create();
return userToDTO(oldUser.fromJson(res, User.class));
@ -103,30 +108,34 @@ public class SecurityUtil {
final User user = userToDTO(userDao.findByUsername(username));
// 缓存
final Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd hh:mm:ss").create();
redisTemplate.set(key, gson.toJson(user), tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
redisTemplateHelper.set(key, gson.toJson(user), tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
return user;
}
public Worker findWorkerByUsername(String username) {
final String key = "workername::" + username;
// 读取缓存
final String res = redisTemplate.get(key);
final String res = redisTemplateHelper.get(key);
if (CharSequenceUtil.isNotBlank(res)) {
return new Gson().fromJson(res, Worker.class);
}
final Worker worker = workerDao.findByUsername(username);
// 缓存
redisTemplate.set(key, new Gson().toJson(worker), 15L, TimeUnit.DAYS);
redisTemplateHelper.set(key, new Gson().toJson(worker), 15L, TimeUnit.DAYS);
return worker;
}
public LogiticsCompany findCompanyByUsername(String username) {
final String key = "companyName::" + username;
// 读取缓存
final String res = redisTemplate.get(key);
if (CharSequenceUtil.isNotBlank(res)) {
return new Gson().fromJson(res, LogiticsCompany.class);
}
// 直接使用 RedisTemplate 获取对象,不要手动反序列化
Object value = redisTemplate.opsForValue().get(key);
if (value instanceof LinkedHashMap) {
return objectMapper.convertValue(value, LogiticsCompany.class);
}
/*LogiticsCompany company = (LogiticsCompany) redisTemplate.opsForValue().get(key);
if (company != null) {
return company;
}*/
LogiticsCompany logiticsCompany = logiticsCompanyDao.findByUsername(username);
// 如果没有获取到,那么去搜索公司员工信息
if (logiticsCompany == null ) {
@ -145,7 +154,8 @@ public class SecurityUtil {
}
}
// 缓存
redisTemplate.set(key, new Gson().toJson(logiticsCompany), tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
// redisTemplate.set(key, logiticsCompany, tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
redisTemplate.opsForValue().set(key, logiticsCompany, tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
return logiticsCompany;
}
@ -294,41 +304,41 @@ public class SecurityUtil {
tokenUser = new TokenUser(user, tokenProperties.getStorePerms(), saved);
// 单设备登录 之前的token失效
if (tokenProperties.getSdl()) {
final String oldToken = redisTemplate.get(SecurityConstant.USER_TOKEN + user.getUsername() + "type:" + user.getType());
final String oldToken = redisTemplateHelper.get(SecurityConstant.USER_TOKEN + user.getUsername() + "type:" + user.getType());
if (CharSequenceUtil.isNotBlank(oldToken)) {
redisTemplate.delete(SecurityConstant.TOKEN_PRE + oldToken);
redisTemplateHelper.delete(SecurityConstant.TOKEN_PRE + oldToken);
final String userTokenKey = SecurityConstant.TOKEN_PRE + oldToken;
final String userTypeKey = SecurityConstant.TOKEN_USER_TYPE + oldToken + "type:";
redisTemplate.delete(userTokenKey);
redisTemplate.delete(userTypeKey);
redisTemplateHelper.delete(userTokenKey);
redisTemplateHelper.delete(userTypeKey);
// 店铺及商圈
final String shopIdKey = SecurityConstant.TOKEN_SHOP_ID + oldToken + "shopId:";
final String regionKey = SecurityConstant.TOKEN_REGION + oldToken + "region:";
redisTemplate.delete(shopIdKey);
redisTemplate.delete(regionKey);
redisTemplateHelper.delete(shopIdKey);
redisTemplateHelper.delete(regionKey);
}
}
// 是否记住账号/保存登录
if (saved) {
redisTemplate.set(SecurityConstant.USER_TOKEN + user.getUsername() + "type:" + user.getType(), token, tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
redisTemplate.set(SecurityConstant.TOKEN_PRE + token, new Gson().toJson(tokenUser), tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
redisTemplateHelper.set(SecurityConstant.USER_TOKEN + user.getUsername() + "type:" + user.getType(), token, tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
redisTemplateHelper.set(SecurityConstant.TOKEN_PRE + token, new Gson().toJson(tokenUser), tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
// 保存当前登录用户的角色
final String userTypeKey = SecurityConstant.TOKEN_USER_TYPE + token + "type:";
// 缓存
redisTemplate.set(userTypeKey, user.getType(), tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
redisTemplateHelper.set(userTypeKey, user.getType(), tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
} else {
redisTemplate.set(SecurityConstant.USER_TOKEN + user.getUsername() + "type:" + user.getType(), token, tokenProperties.getTokenExpireTime(), TimeUnit.MINUTES);
redisTemplate.set(SecurityConstant.TOKEN_PRE + token, new Gson().toJson(tokenUser), tokenProperties.getTokenExpireTime(), TimeUnit.MINUTES);
redisTemplateHelper.set(SecurityConstant.USER_TOKEN + user.getUsername() + "type:" + user.getType(), token, tokenProperties.getTokenExpireTime(), TimeUnit.MINUTES);
redisTemplateHelper.set(SecurityConstant.TOKEN_PRE + token, new Gson().toJson(tokenUser), tokenProperties.getTokenExpireTime(), TimeUnit.MINUTES);
// 保存当前登录用户的角色
final String userTypeKey = SecurityConstant.TOKEN_USER_TYPE + token + "type:";
// 缓存
redisTemplate.set(userTypeKey, user.getType(), tokenProperties.getTokenExpireTime(), TimeUnit.MINUTES);
redisTemplateHelper.set(userTypeKey, user.getType(), tokenProperties.getTokenExpireTime(), TimeUnit.MINUTES);
}
// 更新当前登录人的角色
final String key = "username::" + user.getUsername();
final Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd hh:mm:ss").create();
redisTemplate.set(key, gson.toJson(user), tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
redisTemplateHelper.set(key, gson.toJson(user), tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
} else {
// JWT 不缓存权限 避免JWT长度过长
tokenUser = new TokenUser(user, false, null);
@ -378,8 +388,8 @@ public class SecurityUtil {
public LogiticsCompany getCurrCompany() {
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
boolean authenticated = authentication.isAuthenticated();
String name = authentication.getName();
final boolean authenticated = authentication.isAuthenticated();
final String name = authentication.getName();
if (authentication == null || !authentication.isAuthenticated() || authentication.getName() == null
|| authentication instanceof AnonymousAuthenticationToken) {
throw new HiverException("未检测到登录用户");
@ -427,7 +437,7 @@ public class SecurityUtil {
final User u = getCurrUserSimple();
// 读取缓存
final String key = "userRole::depIds:" + u.getId();
final String v = redisTemplate.get(key);
final String v = redisTemplateHelper.get(key);
if (CharSequenceUtil.isNotBlank(v)) {
deparmentIds = new Gson().fromJson(v, new TypeToken<List<String>>() {
}.getType());
@ -487,7 +497,7 @@ public class SecurityUtil {
deparmentIds.clear();
deparmentIds.addAll(set);
// 缓存
redisTemplate.set(key, new Gson().toJson(deparmentIds), tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
redisTemplateHelper.set(key, new Gson().toJson(deparmentIds), tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
return deparmentIds;
}
@ -532,13 +542,13 @@ public class SecurityUtil {
public Member findMemberByMobile(String mobile) {
final String key = "member::" + mobile;
// 读取缓存
final String res = redisTemplate.get(key);
final String res = redisTemplateHelper.get(key);
if (CharSequenceUtil.isNotBlank(res)) {
return new Gson().fromJson(res, Member.class);
}
final Member member = memberDao.findByMobile(mobile);
// 缓存
redisTemplate.set(key, new Gson().toJson(member), tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
redisTemplateHelper.set(key, new Gson().toJson(member), tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
return member;
}
@ -567,13 +577,13 @@ public class SecurityUtil {
final String key = SecurityConstant.MEMBER_TOKEN + tokenMember.getUsername() + ':' + platform;
// 单平台登录 之前的token失效
if (appTokenProperties.getSpl()) {
final String oldToken = redisTemplate.get(key);
final String oldToken = redisTemplateHelper.get(key);
if (CharSequenceUtil.isNotBlank(oldToken)) {
redisTemplate.delete(SecurityConstant.TOKEN_MEMBER_PRE + oldToken);
redisTemplateHelper.delete(SecurityConstant.TOKEN_MEMBER_PRE + oldToken);
}
}
redisTemplate.set(key, token, appTokenProperties.getTokenExpireTime(), TimeUnit.DAYS);
redisTemplate.set(SecurityConstant.TOKEN_MEMBER_PRE + token, new Gson().toJson(tokenMember), appTokenProperties.getTokenExpireTime(), TimeUnit.DAYS);
redisTemplateHelper.set(key, token, appTokenProperties.getTokenExpireTime(), TimeUnit.DAYS);
redisTemplateHelper.set(SecurityConstant.TOKEN_MEMBER_PRE + token, new Gson().toJson(tokenMember), appTokenProperties.getTokenExpireTime(), TimeUnit.DAYS);
} else {
// JWT
tokenMember = new TokenMember(member, platform);
@ -651,13 +661,13 @@ public class SecurityUtil {
final String key = SecurityConstant.WORKER_TOKEN + tokenWorker.getWorkerId() + ':' + tokenWorker.getWorkerName();
// 单平台登录 之前的token失效
if (appTokenProperties.getSpl()) {
final String oldToken = redisTemplate.get(key);
final String oldToken = redisTemplateHelper.get(key);
if (CharSequenceUtil.isNotBlank(oldToken)) {
redisTemplate.delete(SecurityConstant.TOKEN_WORKER_PRE + oldToken);
redisTemplateHelper.delete(SecurityConstant.TOKEN_WORKER_PRE + oldToken);
}
}
redisTemplate.set(key, token, appTokenProperties.getTokenExpireTime(), TimeUnit.DAYS);
redisTemplate.set(SecurityConstant.TOKEN_WORKER_PRE + token, new Gson().toJson(tokenWorker), appTokenProperties.getTokenExpireTime(), TimeUnit.DAYS);
redisTemplateHelper.set(key, token, appTokenProperties.getTokenExpireTime(), TimeUnit.DAYS);
redisTemplateHelper.set(SecurityConstant.TOKEN_WORKER_PRE + token, new Gson().toJson(tokenWorker), appTokenProperties.getTokenExpireTime(), TimeUnit.DAYS);
} else {
// JWT
tokenWorker = new TokenWorker(worker, saved);
@ -719,13 +729,13 @@ public class SecurityUtil {
final String key = SecurityConstant.COMPANY_TOKEN + tokenCompany.getId() + ':' + tokenCompany.getCompanyName();
// 单平台登录 之前的token失效
if (appTokenProperties.getSpl()) {
final String oldToken = redisTemplate.get(key);
final String oldToken = redisTemplateHelper.get(key);
if (CharSequenceUtil.isNotBlank(oldToken)) {
redisTemplate.delete(SecurityConstant.TOKEN_COMPANY_PRE + oldToken);
redisTemplateHelper.delete(SecurityConstant.TOKEN_COMPANY_PRE + oldToken);
}
}
redisTemplate.set(key, token, appTokenProperties.getTokenExpireTime(), TimeUnit.DAYS);
redisTemplate.set(SecurityConstant.TOKEN_COMPANY_PRE + token, new Gson().toJson(tokenCompany), appTokenProperties.getTokenExpireTime(), TimeUnit.DAYS);
redisTemplateHelper.set(key, token, appTokenProperties.getTokenExpireTime(), TimeUnit.DAYS);
redisTemplateHelper.set(SecurityConstant.TOKEN_COMPANY_PRE + token, new Gson().toJson(tokenCompany), appTokenProperties.getTokenExpireTime(), TimeUnit.DAYS);
} else {
// JWT
tokenCompany = new TokenCompany(logiticsCompany, saved);
@ -756,13 +766,13 @@ public class SecurityUtil {
public User findByUserNameAndType(String username, String type) {
final String key = "username::" + username + "type:" + type;
// 读取缓存
final String res = redisTemplate.get(key);
final String res = redisTemplateHelper.get(key);
if (CharSequenceUtil.isNotBlank(res)) {
return userToDTO(new Gson().fromJson(res, User.class));
}
final User user = userToDTO(userDao.findByUserNameAndType(username, type));
// 缓存
redisTemplate.set(key, new Gson().toJson(user), tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
redisTemplateHelper.set(key, new Gson().toJson(user), tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
return user;
}
@ -770,8 +780,8 @@ public class SecurityUtil {
final String shopIdKey = SecurityConstant.TOKEN_SHOP_ID + token + "shopId:";
final String regionKey = SecurityConstant.TOKEN_REGION + token + "region:";
// 缓存
redisTemplate.set(shopIdKey, shopId, tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
redisTemplate.set(regionKey, region, tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
redisTemplateHelper.set(shopIdKey, shopId, tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
redisTemplateHelper.set(regionKey, region, tokenProperties.getSaveLoginTime(), TimeUnit.DAYS);
}
public String getShopId() {
@ -779,9 +789,9 @@ public class SecurityUtil {
// 获取请求token
// 从缓存中获取当前用户的shopId
final String tokenKey = SecurityConstant.USER_TOKEN + u.getUsername() + "type:" + u.getType();
final String token = redisTemplate.get(tokenKey);
final String token = redisTemplateHelper.get(tokenKey);
final String shopIdKey = SecurityConstant.TOKEN_SHOP_ID + token + "shopId:";
final String shopId = redisTemplate.get(shopIdKey);
final String shopId = redisTemplateHelper.get(shopIdKey);
return shopId;
}
@ -790,16 +800,16 @@ public class SecurityUtil {
// 获取请求token
// 从缓存中获取当前用户的shopId
final String tokenKey = SecurityConstant.USER_TOKEN + u.getUsername() + "type:" + u.getType();
final String token = redisTemplate.get(tokenKey);
final String token = redisTemplateHelper.get(tokenKey);
final String regionKey = SecurityConstant.TOKEN_REGION + token + "region:";
final String region = redisTemplate.get(regionKey);
final String region = redisTemplateHelper.get(regionKey);
return region;
}
public String getLoginUserType(String token) {
// 保存当前登录用户的角色
final String userTypeKey = SecurityConstant.TOKEN_USER_TYPE + token + "type:";
final String userType = redisTemplate.get(userTypeKey);
final String userType = redisTemplateHelper.get(userTypeKey);
return userType;
}
}

122
hiver-core/src/main/java/cc/hiver/core/config/cache/RedisCacheConfig.java

@ -3,6 +3,8 @@ package cc.hiver.core.config.cache;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
@ -14,82 +16,140 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.TimeZone;
/**
* Redis缓存
*
* @author Yazhi Li
* Redis缓存配置
* 优化内容
* 1. 完善日期序列化处理
* 2. 优化泛型使用
* 3. 增强异常处理
* 4. 改进代码可读性
*/
@Slf4j
@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport {
private static final String CACHE_ERROR_PREFIX = "Redis缓存操作异常 - ";
@Value("${hiver.cache.timeToLive:-1}")
private Duration timeToLive;
/**
* 自定义序列化方式
*
* @param factory
* @return
* 自定义缓存管理器
* 优化点
* 1. 使用泛型明确指定序列化类型
* 2. 配置完整的Jackson序列化规则
* 3. 支持Java8日期时间类型
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
// Key序列化器
RedisSerializer<String> keySerializer = new StringRedisSerializer();
// 解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(new ObjectMapper().getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// Value序列化器
Jackson2JsonRedisSerializer<Object> valueSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
// 配置序列化(解决乱码的问题)
// 配置ObjectMapper
ObjectMapper objectMapper = createObjectMapper();
log.info("ObjectMapper日期格式配置: {}", objectMapper.getDateFormat());
valueSerializer.setObjectMapper(objectMapper);
// 缓存配置
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer))
.disableCachingNullValues()
.entryTtl(timeToLive);
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config.entryTtl(timeToLive))
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.transactionAware() // 支持事务
.build();
return cacheManager;
}
/**
* 异常处理 当Redis缓存相关操作发生异常时 打印日志 程序正常走
*
* @return
* 创建并配置ObjectMapper
*/
private ObjectMapper createObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
// 设置可见性
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 支持多态类型
mapper.activateDefaultTyping(
mapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL);
// 禁用日期时间戳格式
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// 注册Java8日期时间模块
mapper.registerModule(new JavaTimeModule());
return mapper;
}
/**
* 缓存异常处理器
* 优化点
* 1. 更详细的错误日志
* 2. 统一错误前缀
*/
@Override
public CacheErrorHandler errorHandler() {
CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() {
return new CacheErrorHandler() {
@Override
public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
log.warn("Redis occur handleCacheGetError:key: [{}]", key);
log.error(CACHE_ERROR_PREFIX + "获取缓存失败 - 缓存名称:[{}], 键:[{}], 错误:[{}]",
cache.getName(), key, e.getMessage(), e);
}
@Override
public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
log.warn("Redis occur handleCachePutError:key: [{}];value: [{}]", key, value);
log.error(CACHE_ERROR_PREFIX + "写入缓存失败 - 缓存名称:[{}], 键:[{}], 值类型:[{}], 错误:[{}]",
cache.getName(), key,
value != null ? value.getClass().getSimpleName() : "null",
e.getMessage(), e);
}
@Override
public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
log.warn("Redis occur handleCacheEvictError:key: [{}]", key);
log.error(CACHE_ERROR_PREFIX + "清除缓存项失败 - 缓存名称:[{}], 键:[{}], 错误:[{}]",
cache.getName(), key, e.getMessage(), e);
}
@Override
public void handleCacheClearError(RuntimeException e, Cache cache) {
log.warn("Redis occur handleCacheClearError");
log.error(CACHE_ERROR_PREFIX + "清空缓存失败 - 缓存名称:[{}], 错误:[{}]",
cache.getName(), e.getMessage(), e);
}
};
return cacheErrorHandler;
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 使用Jackson序列化器
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
// 配置ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
serializer.setObjectMapper(objectMapper);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}

2
hiver-core/src/main/resources/mapper/LogisticsAddressBookMapper.xml

@ -185,7 +185,7 @@
select
<include refid="Base_Column_List" />
from t_logistics_address_book
where company_id = #{queryParams.companyId}
where company_id = #{companyId}
ORDER BY
create_time desc
</select>

4
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/AliOcrUtil.java

@ -1269,14 +1269,14 @@ public class AliOcrUtil {
final StringJoiner shipperQuestionMsgStr = new StringJoiner(",");
final StringBuilder receiverQuestionMsg = new StringBuilder("发货人列表:");
final StringJoiner receiverQuestionMsgStr = new StringJoiner(",");
if (!shipperLogisticsAddressBooks.isEmpty()) {
if (shipperLogisticsAddressBooks != null && !shipperLogisticsAddressBooks.isEmpty()) {
// shipperLogisticsAddressBooks 转逗号分隔字符串
for (LogisticsAddressBook shipperLogisticsAddressBook : shipperLogisticsAddressBooks) {
shipperQuestionMsgStr.add(shipperLogisticsAddressBook.getShipperOrReceiverName());
}
shipperQuestionMsg.append(shipperQuestionMsgStr);
}
if (!receiverLogisticsAddressBooks.isEmpty()) {
if (receiverLogisticsAddressBooks != null && !receiverLogisticsAddressBooks.isEmpty()) {
for (LogisticsAddressBook shipperLogisticsAddressBook : receiverLogisticsAddressBooks) {
receiverQuestionMsgStr.add(shipperLogisticsAddressBook.getShipperOrReceiverName());
}

Loading…
Cancel
Save