From 7fffd1c84c4d53aca8a5694580b53fc6e850f39d Mon Sep 17 00:00:00 2001 From: quyixiao <2621048238@qq.com> Date: Tue, 1 Sep 2020 18:38:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lz/common/constant/CacheConstants.java | 75 +++ .../java/com/lz/common/utils/Constant.java | 6 + .../com/lz/common/utils/RedisCacheUtil.java | 636 ++++++++++++++++++ src/main/java/com/lz/config/RedisConfig.java | 32 +- .../controller/ResultRecordController.java | 113 +--- .../lz/modules/app/resp/ResultRecordResp.java | 5 + .../sys/service/app/ResultRecordService.java | 7 + .../app/impl/ResultDetailServiceImpl.java | 13 +- .../app/impl/ResultRecordServiceImpl.java | 111 ++- src/main/resources/application-test.yml | 2 + src/main/resources/application.yml | 3 +- 11 files changed, 893 insertions(+), 110 deletions(-) create mode 100644 src/main/java/com/lz/common/constant/CacheConstants.java create mode 100644 src/main/java/com/lz/common/utils/RedisCacheUtil.java diff --git a/src/main/java/com/lz/common/constant/CacheConstants.java b/src/main/java/com/lz/common/constant/CacheConstants.java new file mode 100644 index 00000000..aff342de --- /dev/null +++ b/src/main/java/com/lz/common/constant/CacheConstants.java @@ -0,0 +1,75 @@ +package com.lz.common.constant; + +/** + * @author yuzhong + * @date 2017-12-20 10:46 AM + */ +public enum CacheConstants { + + KEY_SYS_CONFIG("sys_config_%s", CacheConstants.DEFAULT_EXPIRE_SECOND), + KEY_QUOTA_MAX_CONFIG("quota_max_config_%s", CacheConstants.SECOND_OF_HALF_HOUR), + KEY_RULE_GROUP("rule_group_%s", CacheConstants.SECOND_OF_HALF_HOUR), + KEY_SCENE_OWN_TABLE("rule_scene_own_table_%s", CacheConstants.SECOND_OF_HALF_HOUR), + KEY_RULE_ENGINE_INFO("rule_engine_info_%s", CacheConstants.SECOND_OF_HALF_HOUR), + KEY_RULE_ENGINE_CONFIG("rule_engine_config_%s", CacheConstants.SECOND_OF_HALF_HOUR), + KEY_QUOTA_MODEL("quota_model_%s_%s", CacheConstants.SECOND_OF_HALF_HOUR), + KEY_QUOTA_BASE_CONFIG("quota_base_config_%s", CacheConstants.SECOND_OF_TEN_MINITS), + KEY_FAMILY_USER_DIRECTORY("family_user_directory_%s", CacheConstants.SECOND_OF_TWO_DAY), + KEY_EVENT_MANAGE_DTO("event_manage_%s", CacheConstants.SECOND_OF_HALF_HOUR), + HASH_KEY_RULE_RESULT("rule_result_%s", CacheConstants.SECOND_OF_ONE_WEEK), + KEY_TEST_USER_STATUS("test_user_status_%s",CacheConstants.SECOND_OF_ONE_WEEK), + KEY_PHONE_ADDR_BOOK("phone_addr_book_%s",CacheConstants.SECOND_OF_HALF_HOUR), + KEY_USER_POOL_COUNT("user_pool_count",CacheConstants.SECOND_OF_AN_HOUR),//用户池用户数量 + KEY_FINAL_USER_POOL_COUNT("final_user_pool_count",CacheConstants.SECOND_OF_AN_HOUR),//最终用户池用户数量 + KEY_USER_POOL_COUNT_FOR_LIANTONG("user_pool_count_for_liantong",CacheConstants.SECOND_OF_AN_HOUR),//用户池用户数量(联通redis用) + KEY_USER_POOL_COUNT_FOR_LZ("user_pool_count_for_linzi",CacheConstants.SECOND_OF_AN_HOUR),//用户池用户数量(LINZIredis用) + KEY_FINAL_USER_POOL_COUNT_FOR_LZ("final_user_pool_count_for_linzi",CacheConstants.SECOND_OF_AN_HOUR),//最终用户池用户数量 + KEY_RULE_MODEL("rule_model_%s", CacheConstants.SECOND_OF_ONE_DAY), + KEY_RULE_TREE("rule_tree_%s_%s", CacheConstants.SECOND_OF_ONE_DAY), + KEY_XINSHEN_PERSON_TASK("xinshen_person_task_%s", CacheConstants.SECOND_OF_ONE_YEAR), + KEY_XINSHEN_PERSON_COUNT("xinshen_person_count_%s", CacheConstants.SECOND_OF_ONE_YEAR), + ; + + // 单位秒 + public static final long SECOND_OF_ONE_MINITS = 1 * 60l; + public static final long SECOND_OF_ONE = 1L; + public static final long FIVETY_MINITS = 1 * 50l; + public static final long SECOND_OF_THREE_MINITS = 3 * 60l; + public static final long SECOND_OF_TEN_MINITS = 10 * 60l; + public static final long SECOND_OF_THREE = 30l;// 30秒 + public static final long SECOND_OF_HALF_HOUR = 30 * 60l; + public static final long SECOND_OF_AN_HOUR = 60 * 60l; + public static final long SECOND_OF_SIX_HOUR = 6 * 60 * 60l; + public static final long SECOND_OF_ONE_DAY = 24 * 60 * 60l; + public static final long SECOND_OF_TWO_DAY = 2 * 24 * 60 * 60l; + public static final long SECOND_OF_ONE_WEEK = 7 * 24 * 60 * 60l; + public static final long SECOND_OF_TWO_WEEK = 14 * 24 * 60 * 60l; + public static final long SECOND_OF_ONE_MONTH = 30 * 24 * 60 * 60l; + public static final long SECOND_OF_ONE_YEAR = 12 * 30 * 24 * 60 * 60l; + public static final long DEFAULT_EXPIRE_SECOND = SECOND_OF_SIX_HOUR; + + private String key; + + private long expire; + + private CacheConstants(String key, long expire) { + this.key = key; + this.expire = expire; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public long getExpire() { + return expire; + } + + public void setExpire(long expire) { + this.expire = expire; + } +} diff --git a/src/main/java/com/lz/common/utils/Constant.java b/src/main/java/com/lz/common/utils/Constant.java index 27e1b144..bb4c61f7 100644 --- a/src/main/java/com/lz/common/utils/Constant.java +++ b/src/main/java/com/lz/common/utils/Constant.java @@ -19,7 +19,12 @@ public class Constant { /** * 当前页码 */ + + public static final long SECOND_OF_5_MINITE = 5 * 60l;// 60秒 + public static final String PAGE = "page"; + public static final long SECOND_OF_SIXTY = 60l;// 60秒 + /** * 每页显示记录数 */ @@ -32,6 +37,7 @@ public class Constant { * 排序方式 */ public static final String ORDER = "order"; + public static final long SECOND_OF_THREE = 30l;// 30秒 /** * 升序 */ diff --git a/src/main/java/com/lz/common/utils/RedisCacheUtil.java b/src/main/java/com/lz/common/utils/RedisCacheUtil.java new file mode 100644 index 00000000..ad87b175 --- /dev/null +++ b/src/main/java/com/lz/common/utils/RedisCacheUtil.java @@ -0,0 +1,636 @@ +package com.lz.common.utils; + +import com.fasterxml.jackson.databind.JavaType; +import com.lz.common.constant.CacheConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.core.*; +import org.springframework.stereotype.Component; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.TimeUnit; + + +/** + * @author yuzhong + * @date 2017-12-20 11:07 AM + */ +@Component("redisCacheUtil") +public class RedisCacheUtil { + + protected static Logger logger = LoggerFactory.getLogger(RedisCacheUtil.class); + + public static boolean RISK_CACHE_SWITCH = true;//风控缓存开关,true:打开(即使用缓存) false:关闭(即不使用缓存) + + private static final String KEY_SEPARATOR = "_"; + + final Random random = new Random(); + + + enum KeyPre { + + TABLE_KEY("table_"), + TARGET_LT_KEY("target_lt_"); + + private String key; + + KeyPre(String key) { + this.key = key; + } + + public String getKey() { + return key; + } + + } + + @Autowired + private RedisTemplate redisTemplate; + + @Autowired + private ValueOperations valueOperations; + + @Autowired + private HashOperations hashOperations; + + @Autowired + private ListOperations listOperations; + + @Autowired + private SetOperations setOperations; + + @Autowired + private ZSetOperations zSetOperations; + + /** + * 保存到缓存,过期时间为默认过期时间 + * + * @param key 缓存key + * @param obj 缓存数据 + */ + public void saveObject(final String key, final Object obj) { + this.saveObject(key, obj, CacheConstants.DEFAULT_EXPIRE_SECOND); + } + + + /** + * 保存到缓存,并设定过期时间 + * + * @param key 缓存key + * @param obj 缓存数据 + * @param expire 过期时间 + */ + public void saveObject(final String key, final Object obj, final long expire) { + if (!RISK_CACHE_SWITCH || StringUtil.isBlank(key) || obj == null) { + return; + } + try { + redisTemplate.opsForValue().set(key, obj, expire, TimeUnit.SECONDS); + } catch (Exception e) { + logger.error("saveObject", e); + } + } + + + /** + * 保存到缓存,并设定过期时间 + * + * @param key 缓存key + * @param + * @param expire 过期时间 + */ + public void saveStr(final String key, final String str, final long expire) { + if (!RISK_CACHE_SWITCH || StringUtil.isBlank(key) || str == null) { + return; + } + try { + redisTemplate.opsForValue().set(key, str, expire, TimeUnit.SECONDS); + } catch (Exception e) { + logger.error("saveObject", e); + } + } + + + /** + * 调用set后的返回值 + */ + public static final String OK = "OK"; + + public Object getHashValue(final String key, String hashKey) { + if (!RISK_CACHE_SWITCH || StringUtil.isEmpty(key) || StringUtil.isEmpty(hashKey)) { + return null; + } + return hashOperations.get(key, hashKey); + } + + /** + * 重试 获取锁 + * + * @param key + * @param lockTime ,获得锁以后的锁定时间 + * @return + */ + public boolean lockTryTimes(final String key, final Long tryTimes, final Long lockTime) { + final String value = "xx"; + boolean flag = false; + try { + // 请求锁超时时间,毫秒 + long timeout = tryTimes * 1000; + // 系统当前时间,毫秒 + long nowTime = System.currentTimeMillis(); + while ((System.currentTimeMillis() - nowTime) < timeout) { + if (set(key, value)) { + flag = true; + break; + } + // 每次请求等待一段时间 + seleep(10, 50000); + } + if (flag) { + redisTemplate.execute(new RedisCallback() { + @Override + public Boolean doInRedis(RedisConnection connection) throws DataAccessException { + return connection.expire(redisTemplate.getStringSerializer().serialize(key), lockTime); + } + }); + } + } catch (Exception e) { + logger.error("getLock error", e); + } + return flag; + } + + public static void main(String[] args) { + long a = System.currentTimeMillis(); + System.out.println(a); + } + + /** + * @param millis 毫秒 + * @param nanos 纳秒 + * @Title: seleep + * @Description: 线程等待时间 + * @author yuhao.wang + */ + private void seleep(long millis, int nanos) { + try { + Thread.sleep(millis, random.nextInt(nanos)); + } catch (InterruptedException e) { + logger.info("获取分布式锁休眠被中断:", e); + } + } + + + /** + * 立即获取锁 + * + * @param key + * @param lockTime ,获得锁以后的锁定时间 + * @return + */ + public boolean lock(final String key, final Long lockTime) { + final String value = "xx"; + try { + Boolean flag = set(key, value); + if (flag) { + redisTemplate.execute(new RedisCallback() { + @Override + public Boolean doInRedis(RedisConnection connection) throws DataAccessException { + return connection.expire(redisTemplate.getStringSerializer().serialize(key), lockTime); + } + }); + } + return flag; + } catch (Exception e) { + logger.error("getLock error", e); + return false; + } + } + + + private Boolean set(String key, String value) { + return (Boolean) redisTemplate.execute(new RedisCallback() { + @Override + public Boolean doInRedis(RedisConnection connection) throws DataAccessException { + return connection.setNX(redisTemplate.getStringSerializer().serialize(key), value.getBytes()); + } + }); + } + + /** + * 锁住某个key值30S,需要解锁时删除即可 + * + * @param key + * @param key + * @return + */ + public boolean lock30Second(final String key) { + final String value = "xx"; + try { + Boolean flag = set(key, value); + if (flag) { + redisTemplate.execute(new RedisCallback() { + @Override + public Boolean doInRedis(RedisConnection connection) throws DataAccessException { + return connection.expire(redisTemplate.getStringSerializer().serialize(key), Constant.SECOND_OF_THREE); + } + }); + } + return flag; + } catch (Exception e) { + logger.error("getLock error", e); + return false; + } + } + + + /** + * 锁住某个key值30S,需要解锁时删除即可 + * + * @param key + * @param key + * @return + */ + public boolean lock60Second(final String key) { + final String value = "xx"; + try { + Boolean flag = set(key, value); + if (flag) { + redisTemplate.execute(new RedisCallback() { + @Override + public Boolean doInRedis(RedisConnection connection) throws DataAccessException { + return connection.expire(redisTemplate.getStringSerializer().serialize(key), Constant.SECOND_OF_SIXTY); + } + }); + } + return flag; + } catch (Exception e) { + logger.error("getLock error", e); + return false; + } + } + + + /** + * 锁住某个key值30S,需要解锁时删除即可 + * + * @param key + * @param key + * @return + */ + public boolean lock5Minite(final String key) { + final String value = "xx"; + try { + Boolean flag = set(key, value); + if (flag) { + redisTemplate.execute(new RedisCallback() { + @Override + public Boolean doInRedis(RedisConnection connection) throws DataAccessException { + return connection.expire(redisTemplate.getStringSerializer().serialize(key), Constant.SECOND_OF_5_MINITE); + } + }); + } + return flag; + } catch (Exception e) { + logger.error("getLock error", e); + return false; + } + } + + /** + * 锁住某个key值,需要解锁时删除即可 + * + * @param key + * @param value + * @return + */ + public boolean getLock(final String key, final String value) { + try { + return (Boolean) redisTemplate.execute(new RedisCallback() { + @Override + public Boolean doInRedis(RedisConnection connection) throws DataAccessException { + return connection.setNX(redisTemplate.getStringSerializer().serialize(key), value.getBytes()); + } + }); + } catch (Exception e) { + logger.error("getLock error", e); + return false; + } + } + + + /** + * 删除缓存 + * + * @param key 需要删除缓存的id + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public void unLock(final String key) { + //如果为空 + if (StringUtil.isBlank(key)) { + return; + } + try { + redisTemplate.execute(new RedisCallback() { + @Override + public Long doInRedis(RedisConnection connection) throws DataAccessException { + return connection.del(redisTemplate.getStringSerializer().serialize(key)); + } + }); + } catch (Exception e) { + logger.error("delCache error", e); + } + } + + + /** + * 删除缓存 + * + * @param key 需要删除缓存的id + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public void delCache(final String key) { + try { + redisTemplate.execute(new RedisCallback() { + @Override + public Long doInRedis(RedisConnection connection) throws DataAccessException { + return connection.del(redisTemplate.getStringSerializer().serialize(key)); + } + }); + } catch (Exception e) { + logger.error("delCache error", e); + + } + } + + + public void saveTableObjectViaHash(final String consumerNo, String table, Map tableFields) { + if (StringUtil.isEmpty(consumerNo) || StringUtil.isEmpty(table)) { + return; + } + String hashKey = KeyPre.TABLE_KEY.getKey() + consumerNo + KEY_SEPARATOR + table; + hashOperations.putAll(hashKey, tableFields); + hashOperations.getOperations().expire(hashKey, CacheConstants.SECOND_OF_ONE_WEEK, TimeUnit.SECONDS); + } + + public void saveTargetValueViaHash(final String queryKey, Map targets) { + if (!RISK_CACHE_SWITCH || StringUtil.isEmpty(queryKey) || targets == null) { + return; + } + String hashKey = KeyPre.TARGET_LT_KEY.getKey() + queryKey; + hashOperations.putAll(hashKey, targets); + hashOperations.getOperations().expire(hashKey, CacheConstants.SECOND_OF_TWO_WEEK, TimeUnit.SECONDS); + } + + public Object getTargetValueViaHash(final String phone, final String targetCode) { + if (!RISK_CACHE_SWITCH || StringUtil.isBlank(phone) || StringUtil.isBlank(targetCode)) { + return null; + } + return hashOperations.get(KeyPre.TARGET_LT_KEY.getKey() + phone, targetCode); + } + + public Object getTableValueViaHash(final String consumerNo, final String table, final String column) { + if (!RISK_CACHE_SWITCH || StringUtil.isBlank(consumerNo)) { + return null; + } + return hashOperations.get(KeyPre.TABLE_KEY.getKey() + consumerNo + KEY_SEPARATOR + table, column); + } + + public Object getRuleResultValueViaHash(final String consumerNo, final String ruleId) { + if (!RISK_CACHE_SWITCH || StringUtil.isBlank(consumerNo)) { + return null; + } + String cacheKey = String.format(CacheConstants.HASH_KEY_RULE_RESULT.getKey(), consumerNo); + return hashOperations.get(cacheKey, ruleId); + } + + /** + * 保存到缓存,永不过期 + * + * @param key 缓存key + * @param obj 缓存数据 + */ + public void saveObjectForever(final String key, final Object obj) { + if (!RISK_CACHE_SWITCH || StringUtil.isBlank(key) || obj == null) { + return; + } + try { + redisTemplate.opsForValue().set(key, obj); + } catch (Exception e) { + logger.error("saveObject", e); + } + } + + /** + * 获取缓存对象 + * + * @param key 缓存key + * @return + */ + public T getObject(final String key, Class objClass) { + if (!RISK_CACHE_SWITCH || StringUtil.isBlank(key)) { + return null; + } + try { + return (T) redisTemplate.opsForValue().get(key); + } catch (Exception e) { + logger.error("getObject error", e); + return null; + } + } + + /** + * 获取缓存对象 + * + * @param key 缓存key + * @return + */ + public Object getObject(final String key) { + if (!RISK_CACHE_SWITCH || StringUtil.isBlank(key)) { + return null; + } + try { + return redisTemplate.opsForValue().get(key); + } catch (Exception e) { + logger.error("getObject error", e); + return null; + } + } + + + /** + * 获取缓存对象 + * + * @param key 缓存key + * @param javaType Jackson JavaType + * @return + */ + public T getObject(final String key, JavaType javaType) { + if (!RISK_CACHE_SWITCH || StringUtil.isBlank(key)) { + return null; + } + try { + return (T) redisTemplate.opsForValue().get(key); + } catch (Exception e) { + logger.error("getObject error", e); + return null; + } + } + + + /** + * 返回int类型缓存值,null或者""则返回默认值 + * + * @param key 缓存key + * @param defaultValue 默认值 + * @return + */ + public int getInt(String key, int defaultValue) { + String value = getObject(key, String.class); + if (StringUtil.isEmpty(value)) { + return defaultValue; + } + return NumberUtil.getInt(value.trim()); + } + + + /** + * 返回double类型缓存值,null或者""则返回默认值 + * + * @param key 缓存key + * @param defaultValue 默认值 + * @return + */ + public double getDouble(String key, double defaultValue) { + String value = getObject(key, String.class); + if (StringUtil.isEmpty(value)) { + return defaultValue; + } + return NumberUtil.getDouble(value.trim()); + } + + + /** + * 返回String类型缓存值,null则返回默认值 + * + * @param key 缓存key + * @param defaultValue 默认值 + * @return + */ + public String getValue(String key, String defaultValue) { + String value = getObject(key, String.class); + if (StringUtil.isEmpty(value)) { + return defaultValue; + } + return StringUtil.isNull(value); + } + + + /** + * 缓存续期,单位秒,使用CacheConstants定义的时间 + * + * @param key + * @param expire + */ + public void expire(final String key, final long expire) { + if (!RISK_CACHE_SWITCH || StringUtil.isBlank(key)) { + return; + } + try { + redisTemplate.expire(key, expire, TimeUnit.SECONDS); + } catch (Exception e) { + logger.error("expire error", e); + } + } + + /** + * 以key删除缓存 + * + * @param key + */ + public void delete(final String key) { + if (!RISK_CACHE_SWITCH || StringUtil.isBlank(key)) { + return; + } + try { + redisTemplate.delete(key); + } catch (Exception e) { + logger.error("redis delete key error", e); + } + } + + /** + * 删除用户所有缓存 + * + * @param consumerNo + */ + public void deleteByCNo(String consumerNo) { + try { + deleteByPrefix(KeyPre.TABLE_KEY.getKey() + consumerNo + KEY_SEPARATOR); + deleteByPrefix(String.format(CacheConstants.HASH_KEY_RULE_RESULT.getKey(), consumerNo)); + logger.info("【删除redis缓存】consumerNo:" + consumerNo); + } catch (Exception e) { + logger.error("redis delete key, consumerNo:" + consumerNo + ",error:", e); + } + } + + + /** + * 以前缀删除缓存 + * + * @param prefix + */ + public void deleteByPrefix(String prefix) { + if (!RISK_CACHE_SWITCH || StringUtil.isBlank(prefix)) { + return; + } + try { + Set keys = redisTemplate.keys(prefix + "*"); + redisTemplate.delete(keys); + } catch (Exception e) { + logger.error("redis delete prefix key error", e); + } + } + + /** + * 以后缀删除缓存 + * + * @param suffix + */ + public void deleteBySuffix(String suffix) { + if (!RISK_CACHE_SWITCH || StringUtil.isBlank(suffix)) { + return; + } + try { + Set keys = redisTemplate.keys("*" + suffix); + redisTemplate.delete(keys); + } catch (Exception e) { + logger.error("redis delete suffix key error", e); + } + } + + /** + * 以keys删除缓存 + * + * @param keys + */ + public void deleteByKeys(String... keys) { + if (!RISK_CACHE_SWITCH || keys == null) { + return; + } + try { + redisTemplate.delete(Arrays.asList(keys)); + } catch (Exception e) { + logger.error("redis delete keys error", e); + } + } + + +} diff --git a/src/main/java/com/lz/config/RedisConfig.java b/src/main/java/com/lz/config/RedisConfig.java index daccde19..550253ca 100644 --- a/src/main/java/com/lz/config/RedisConfig.java +++ b/src/main/java/com/lz/config/RedisConfig.java @@ -9,10 +9,15 @@ package com.lz.config; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.interceptor.KeyGenerator; +import org.springframework.cache.interceptor.SimpleKeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.*; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; /** @@ -22,20 +27,23 @@ import org.springframework.data.redis.serializer.StringRedisSerializer; */ @Configuration public class RedisConfig { - @Autowired - private RedisConnectionFactory factory; + @Value("${redis.cache.expiration:3600}") + private Long expiration; @Bean - public RedisTemplate redisTemplate() { + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate redisTemplate = new RedisTemplate<>(); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); - redisTemplate.setHashValueSerializer(new StringRedisSerializer()); - redisTemplate.setValueSerializer(new StringRedisSerializer()); - redisTemplate.setConnectionFactory(factory); + redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); + redisTemplate.setConnectionFactory(redisConnectionFactory); + redisTemplate.afterPropertiesSet(); return redisTemplate; } + + @Bean public HashOperations hashOperations(RedisTemplate redisTemplate) { return redisTemplate.opsForHash(); @@ -60,4 +68,16 @@ public class RedisConfig { public ZSetOperations zSetOperations(RedisTemplate redisTemplate) { return redisTemplate.opsForZSet(); } + + + /** + * 显示声明缓存key生成器 + * + * @return + */ + @Bean + public KeyGenerator keyGenerator() { + + return new SimpleKeyGenerator(); + } } diff --git a/src/main/java/com/lz/modules/app/controller/ResultRecordController.java b/src/main/java/com/lz/modules/app/controller/ResultRecordController.java index 884cdd66..6e7aee21 100644 --- a/src/main/java/com/lz/modules/app/controller/ResultRecordController.java +++ b/src/main/java/com/lz/modules/app/controller/ResultRecordController.java @@ -1,6 +1,5 @@ package com.lz.modules.app.controller; -import com.alibaba.fastjson.JSONObject; import com.lz.common.emun.WorkMsgTypeEnum; import com.lz.common.utils.*; import com.lz.modules.app.dto.DepartmentsDto; @@ -18,13 +17,11 @@ import com.lz.modules.flow.entity.RecordAuth; import com.lz.modules.flow.entity.RecordFile; import com.lz.modules.flow.entity.StaffRole; import com.lz.modules.flow.model.Auth; -import com.lz.modules.flow.model.StaffRoleDto; import com.lz.modules.flow.req.ResultDetailReq; import com.lz.modules.flow.service.FlowRecordService; import com.lz.modules.flow.service.RecordAuthService; import com.lz.modules.flow.service.RecordFileService; import com.lz.modules.flow.service.StaffRoleService; -import com.lz.modules.job.business.DingtalkBusiness; import com.lz.modules.sys.controller.AbstractController; import com.lz.modules.sys.entity.SysUserEntity; import com.lz.modules.sys.entity.app.ResultComment; @@ -33,18 +30,17 @@ import com.lz.modules.sys.entity.app.ResultRecord; import com.lz.modules.sys.service.app.ResultCommentService; import com.lz.modules.sys.service.app.ResultDetailService; import com.lz.modules.sys.service.app.ResultRecordService; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.math.BigDecimal; -import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; @@ -59,6 +55,7 @@ import java.util.stream.Collectors; */ @RestController @RequestMapping("user/lzresultrecord") +@Slf4j public class ResultRecordController extends AbstractController { @Autowired private ResultRecordService lzResultRecordService; @@ -83,18 +80,15 @@ public class ResultRecordController extends AbstractController { @Autowired private RecordFileService recordFileService; - @Autowired - private DingtalkBusiness dingtalkBusiness; - @Value("${dingtalk.appid}") - private String appid; - @Value("${domain.main}") - private String domain; @Autowired private StaffRoleService staffRoleService; + @Autowired + private RedisCacheUtil redisCacheUtil; + /** * 列表 */ @@ -138,6 +132,7 @@ public class ResultRecordController extends AbstractController { } } } + PageUtils page = lzResultRecordService.queryPage(req, user); return R.ok().put("page", page) .put("departmentList1", departmentList1) @@ -249,7 +244,6 @@ public class ResultRecordController extends AbstractController { list.add(resultDetailService.getWenHuaJiaZhiGuaResult1(sumWenHuaJiaZhiGuan)); list.add(resultDetailService.getWenHuaJiaZhiGuaResult2()); list.add(resultDetailService.getLastResult(resultRecord.getLastScore())); - List comments = resultCommentService.selectByRecordId(resultRecord.getId()); if (CollectionUtils.isNotEmpty(comments)) { ResultDetailResp header = new ResultDetailResp(); @@ -295,84 +289,25 @@ public class ResultRecordController extends AbstractController { @RequestMapping("/commitApproval") public R commitApproval(ResultRecordReq req) { - R r = null; - int status = 1; - if (req.getStatus() == 2) { - r = resultRecordService.approval(req.getRecordResultId(), getUserId()); - } else if (req.getStatus() == 3) { //侍提交 - ResultRecord resultRecord = resultRecordService.selectResultRecordById(req.getRecordResultId()); - resultRecord.setStatus(Constant.STATUS_3); - resultRecordService.updateResultRecordById(resultRecord); - } else if (req.getStatus() == 5) { // 驳回 - status = 5; - List flowRecords = flowRecordService.selectFlowRecordByResultRecordIdFlowId(req.getRecordResultId()); - ResultRecord resultRecord = resultRecordService.selectResultRecordById(req.getRecordResultId()); - if (flowRecords.size() >= 2) { - FlowRecord secondFlowRecord = flowRecords.get(flowRecords.size() - 2); - resultRecord.setFlowStaffIdRole(secondFlowRecord.getFlowStaffIdRole()); - resultRecord.setStatus(req.getStatus()); - List list = JSONObject.parseArray(resultRecord.getFlowStaffIdRole(), StaffRoleDto.class); - if (CollectionUtils.isNotEmpty(list)) { - StaffRoleDto staffRoleDto = list.get(0); - StaffEntity approvalStaff = staffService.selectStaffById(staffRoleDto.getStaffId()); - resultRecord.setCurrentApprovalStaffId(approvalStaff != null ? approvalStaff.getId() : null); - resultRecord.setCurrentApprovalStaffName(approvalStaff != null ? approvalStaff.getName() : null); - } - resultRecordService.updateResultRecordById(resultRecord); - - FlowRecord lastFlowRecord = flowRecords.get(flowRecords.size() - 1); - lastFlowRecord.setStatus(1); - flowRecordService.updateFlowRecordById(lastFlowRecord); - - // 可能会被删除 - FlowRecord lastUsedFlowRecord = flowRecordService.selectLastFlowRecordByRecordId(req.getRecordResultId()); - lastUsedFlowRecord.setId(null); - lastUsedFlowRecord.setGmtCreate(new Date()); - lastUsedFlowRecord.setGmtModified(new Date()); - flowRecordService.insertFlowRecord(lastUsedFlowRecord);// 新插入一条提交记录 - - StaffEntity mySelf = staffService.selectStaffById(resultRecord.getStaffId()); - r = R.ok("成功") - .put("from", mySelf) - .put("to", mySelf) - .put("type", WorkMsgTypeEnum.REJECT); + String key = req.getRecordResultId() + "_$commitApproval"; + Object o = redisCacheUtil.getObject(key); + log.info(" commitApproval start value :" + o); + if (o == null) { + try { + redisCacheUtil.saveObject(key, 1, Constant.SECOND_OF_SIXTY); + o = redisCacheUtil.getObject(key); + log.info(" commitApproval running value :" + o); + return resultRecordService.commitApproval(req, getUserId()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + redisCacheUtil.delete(key); + log.info(" commitApproval delete value "); } } - resultCommentService.addOrUpdateComment(req, getUserId(), status); - - if(r != null){//下面推送消息 - if(r.isSuccess()){ - StaffEntity mySelf = (StaffEntity)r.get("from"); - StaffEntity toSelf = (StaffEntity)r.get("to"); - WorkMsgTypeEnum workMsgTypeEnum = (WorkMsgTypeEnum)r.get("type"); - sendWorkMSG(mySelf, toSelf, workMsgTypeEnum, req.getRecordResultId(), 1); - return R.ok("成功"); - } - return r; - - } - - return R.ok("成功"); - //return r != null ? r : R.ok("成功"); + return R.error("正在处理中,请勿重复提交"); } - private void sendWorkMSG(StaffEntity mySelf, StaffEntity toSelf, WorkMsgTypeEnum workMsgTypeEnum - , Long recordResultId, int count){ - String url = domain + "/management/dingtalklogin?url=";//免登接口 - String jump; - if(count == 1){//一个提交 - logger.info("单个提交推送消息"); - jump = domain + "/management/recorddetail?id=" + recordResultId - + "&recordType=3" ;//跳转接口 - }else{//批量提交 - logger.info("批量提交推送消息"); - jump = domain + "/management/result-record-lzresultrecordapp";//跳转接口 - } - - jump = URLEncoder.encode(jump); - String msg = dingtalkBusiness.sendWorkMSGByEntity(appid, mySelf, toSelf, workMsgTypeEnum, url + jump); - logger.info("发送钉钉工作消息{}", msg); - } /** * 信息 @@ -384,9 +319,6 @@ public class ResultRecordController extends AbstractController { return R.ok().put("lzResultRecord", lzResultRecord); } - - - /** * 信息 */ @@ -460,12 +392,11 @@ public class ResultRecordController extends AbstractController { return r; } } - if (r != null && r.isSuccess()) {//批量提交 StaffEntity mySelf = (StaffEntity) r.get("from"); StaffEntity toSelf = (StaffEntity) r.get("to"); WorkMsgTypeEnum workMsgTypeEnum = (WorkMsgTypeEnum) r.get("type"); - sendWorkMSG(mySelf, toSelf, workMsgTypeEnum, 0L, 2); + resultRecordService.sendWorkMSG(mySelf, toSelf, workMsgTypeEnum, 0L, 2); } return R.ok("批量提交成功"); diff --git a/src/main/java/com/lz/modules/app/resp/ResultRecordResp.java b/src/main/java/com/lz/modules/app/resp/ResultRecordResp.java index 1a8d6412..a44e20af 100644 --- a/src/main/java/com/lz/modules/app/resp/ResultRecordResp.java +++ b/src/main/java/com/lz/modules/app/resp/ResultRecordResp.java @@ -38,4 +38,9 @@ public class ResultRecordResp { private String monthTimeStr; + //当前审批的员工 id + private Long currentApprovalStaffId; + //当前审批的员工名,以逗号隔开 + private String currentApprovalStaffName; + } diff --git a/src/main/java/com/lz/modules/sys/service/app/ResultRecordService.java b/src/main/java/com/lz/modules/sys/service/app/ResultRecordService.java index 74149367..51ab1c0b 100644 --- a/src/main/java/com/lz/modules/sys/service/app/ResultRecordService.java +++ b/src/main/java/com/lz/modules/sys/service/app/ResultRecordService.java @@ -1,8 +1,10 @@ package com.lz.modules.sys.service.app; import com.baomidou.mybatisplus.extension.service.IService; +import com.lz.common.emun.WorkMsgTypeEnum; import com.lz.common.utils.PageUtils; import com.lz.common.utils.R; +import com.lz.modules.app.entity.StaffEntity; import com.lz.modules.app.req.ResultRecordReq; import com.lz.modules.app.utils.t.TwoTuple; import com.lz.modules.flow.entity.Flow; @@ -60,4 +62,9 @@ public interface ResultRecordService extends IService { R checkApproval(Long recordId); int getDepartmentLevelIndex(List list, int flowIndex); + + R commitApproval(ResultRecordReq req,Long userId); + + void sendWorkMSG(StaffEntity mySelf, StaffEntity toSelf, WorkMsgTypeEnum workMsgTypeEnum + , Long recordResultId, int count); } \ No newline at end of file diff --git a/src/main/java/com/lz/modules/sys/service/app/impl/ResultDetailServiceImpl.java b/src/main/java/com/lz/modules/sys/service/app/impl/ResultDetailServiceImpl.java index 26d846e2..0fabed64 100644 --- a/src/main/java/com/lz/modules/sys/service/app/impl/ResultDetailServiceImpl.java +++ b/src/main/java/com/lz/modules/sys/service/app/impl/ResultDetailServiceImpl.java @@ -264,7 +264,7 @@ public class ResultDetailServiceImpl extends ServiceImpl staffRoleMap = recordAuthService.selectRoleIdByStaffRoleInfo(resultRecord.getFlowStaffIdRole()); - if (resp.getStatus().equals(1) && staffRoleMap.get(user.getUserId()) == null) { - resp.setStatus(2); // 如果不是自己审批,说明自己己经审批完成 - } else if (resp.getStatus().equals(5) && staffRoleMap.get(user.getUserId()) == null) { + if (resp.getStatus().equals(5) && staffRoleMap.get(user.getUserId()) == null) { resp.setStatus(1); // 如果不是自己审批,说明自己己经审批完成 } resp.setMonthTimeStr(df.format(resultRecord.getMonthTime())); @@ -383,8 +398,6 @@ public class ResultRecordServiceImpl extends ServiceImpl staffRoleDtos = new ArrayList<>(); Long roleId = flows.get(flowIndex - 1).getRoleId(); @@ -402,11 +415,17 @@ public class ResultRecordServiceImpl extends ServiceImpl flowRecords = flowRecordService.selectFlowRecordByResultRecordIdFlowId(req.getRecordResultId()); + if (flowRecords.size() >= 2) { + FlowRecord secondFlowRecord = flowRecords.get(flowRecords.size() - 2); + resultRecord.setFlowStaffIdRole(secondFlowRecord.getFlowStaffIdRole()); + resultRecord.setStatus(req.getStatus()); + List list = JSONObject.parseArray(resultRecord.getFlowStaffIdRole(), StaffRoleDto.class); + if (CollectionUtils.isNotEmpty(list)) { + StaffRoleDto staffRoleDto = list.get(0); + StaffEntity approvalStaff = staffService.selectStaffById(staffRoleDto.getStaffId()); + resultRecord.setCurrentApprovalStaffId(approvalStaff != null ? approvalStaff.getId() : null); + resultRecord.setCurrentApprovalStaffName(approvalStaff != null ? approvalStaff.getName() : null); + } + resultRecordService.updateResultRecordById(resultRecord); + + FlowRecord lastFlowRecord = flowRecords.get(flowRecords.size() - 1); + lastFlowRecord.setStatus(1); + flowRecordService.updateFlowRecordById(lastFlowRecord); + + // 可能会被删除 + FlowRecord lastUsedFlowRecord = flowRecordService.selectLastFlowRecordByRecordId(req.getRecordResultId()); + lastUsedFlowRecord.setId(null); + lastUsedFlowRecord.setGmtCreate(new Date()); + lastUsedFlowRecord.setGmtModified(new Date()); + flowRecordService.insertFlowRecord(lastUsedFlowRecord);// 新插入一条提交记录 + + StaffEntity mySelf = staffService.selectStaffById(resultRecord.getStaffId()); + r = R.ok("成功") + .put("from", mySelf) + .put("to", mySelf) + .put("type", WorkMsgTypeEnum.REJECT); + } + } + resultCommentService.addOrUpdateComment(req, userId, status); + if(r != null){//下面推送消息 + if(r.isSuccess()){ + StaffEntity mySelf = (StaffEntity)r.get("from"); + StaffEntity toSelf = (StaffEntity)r.get("to"); + WorkMsgTypeEnum workMsgTypeEnum = (WorkMsgTypeEnum)r.get("type"); + sendWorkMSG(mySelf, toSelf, workMsgTypeEnum, req.getRecordResultId(), 1); + return R.ok("成功"); + } + return r; + } + return R.ok("成功"); + } + + public void sendWorkMSG(StaffEntity mySelf, StaffEntity toSelf, WorkMsgTypeEnum workMsgTypeEnum + , Long recordResultId, int count){ + String url = domain + "/management/dingtalklogin?url=";//免登接口 + String jump; + if(count == 1){//一个提交 + log.info("单个提交推送消息"); + jump = domain + "/management/recorddetail?id=" + recordResultId + + "&recordType=3" ;//跳转接口 + }else{//批量提交 + log.info("批量提交推送消息"); + jump = domain + "/management/result-record-lzresultrecordapp";//跳转接口 + } + + jump = URLEncoder.encode(jump); + String msg = dingtalkBusiness.sendWorkMSGByEntity(appid, mySelf, toSelf, workMsgTypeEnum, url + jump); + log.info("发送钉钉工作消息{}", msg); + } } diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml index be50f689..6552c314 100644 --- a/src/main/resources/application-test.yml +++ b/src/main/resources/application-test.yml @@ -35,6 +35,8 @@ dingtalk: domain: main: "http:/localhost" + + ##多数据源的配置 #dynamic: # datasource: diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 3af7ff2c..8d93bfa5 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -23,9 +23,8 @@ spring: max-request-size: 100MB enabled: true redis: - open: false # 是否开启redis缓存 true开启 false关闭 database: 0 - host: localhost + host: 172.16.157.239 port: 6379 password: # 密码(默认为空) timeout: 6000ms # 连接超时时长(毫秒)