赞
踩
server:
port: 8082
spring:
application:
name: order-nacos
redis:
host: 127.0.0.1
password: 123456
database: 0
logging:
level:
root: info
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.11</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83_noneautotype</version> </dependency>
package com.test.order.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; 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.cache.RedisCacheWriter; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.listener.ChannelTopic; import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; 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 javax.annotation.Resource; import java.time.Duration; import static java.util.Collections.singletonMap; /** * 开启缓存支持 * * @author xqf * @Return: */ @Slf4j @EnableCaching @Configuration public class RedisConfig extends CachingConfigurerSupport { @Resource private LettuceConnectionFactory lettuceConnectionFactory; /** * RedisTemplate配置 * * @param lettuceConnectionFactory * @return */ @Bean public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) { log.info(" --- redis config init --- "); Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = jacksonSerializer(); RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>(); redisTemplate.setConnectionFactory(lettuceConnectionFactory); RedisSerializer<String> stringSerializer = new StringRedisSerializer(); // key序列化 redisTemplate.setKeySerializer(stringSerializer); // value序列化 redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); // Hash key序列化 redisTemplate.setHashKeySerializer(stringSerializer); // Hash value序列化 redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; } /** * 缓存配置管理器 * * @param factory * @return */ @Bean public CacheManager cacheManager(LettuceConnectionFactory factory) { Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = jacksonSerializer(); // 配置序列化(解决乱码的问题),并且配置缓存默认有效期 6小时 RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(6)); RedisCacheConfiguration redisCacheConfiguration = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)); //.disableCachingNullValues(); // 以锁写入的方式创建RedisCacheWriter对象 //update-begin-author:taoyan date:20210316 for:注解CacheEvict根据key删除redis支持通配符* RedisCacheWriter writer = new JeecgRedisCacheWriter(factory, Duration.ofMillis(50L)); //RedisCacheWriter.lockingRedisCacheWriter(factory); // 创建默认缓存配置对象 /* 默认配置,设置缓存有效期 1小时*/ //RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1)); // 自定义配置test:demo 的超时时间为 5分钟 RedisCacheManager cacheManager = RedisCacheManager.builder(writer).cacheDefaults(redisCacheConfiguration) .withInitialCacheConfigurations(singletonMap(CacheConstant.SYS_DICT_TABLE_CACHE, RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)).disableCachingNullValues() .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)))) .withInitialCacheConfigurations(singletonMap(CacheConstant.TEST_DEMO_CACHE, RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(5)).disableCachingNullValues())) .withInitialCacheConfigurations(singletonMap(CacheConstant.PLUGIN_MALL_RANKING, RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(24)).disableCachingNullValues())) .withInitialCacheConfigurations(singletonMap(CacheConstant.PLUGIN_MALL_PAGE_LIST, RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(24)).disableCachingNullValues())) .transactionAware().build(); //update-end-author:taoyan date:20210316 for:注解CacheEvict根据key删除redis支持通配符* return cacheManager; } /** * redis 监听配置 * * @param redisConnectionFactory redis 配置 * @return */ @Bean public RedisMessageListenerContainer redisContainer(RedisConnectionFactory redisConnectionFactory, RedisReceiver redisReceiver, MessageListenerAdapter commonListenerAdapter) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(redisConnectionFactory); container.addMessageListener(commonListenerAdapter, new ChannelTopic(GlobalConstants.REDIS_TOPIC_NAME)); return container; } @Bean MessageListenerAdapter commonListenerAdapter(RedisReceiver redisReceiver) { MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(redisReceiver, "onMessage"); messageListenerAdapter.setSerializer(jacksonSerializer()); return messageListenerAdapter; } private Jackson2JsonRedisSerializer jacksonSerializer() { Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); return jackson2JsonRedisSerializer; } }
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package com.test.order.config; import cn.hutool.core.util.ObjectUtil; import org.springframework.stereotype.Component; @Component public class RedisReceiver { public void onMessage(BaseMap params) { Object handlerName = params.get("handlerName"); JeecgRedisListener messageListener = (JeecgRedisListener)SpringContextHolder.getHandler(handlerName.toString(), JeecgRedisListener.class); if (ObjectUtil.isNotEmpty(messageListener)) { messageListener.onMessage(params); } } public RedisReceiver() { } public boolean equals(final Object o) { if (o == this) { return true; } else if (!(o instanceof RedisReceiver)) { return false; } else { RedisReceiver other = (RedisReceiver)o; return other.canEqual(this); } } protected boolean canEqual(final Object other) { return other instanceof RedisReceiver; } public int hashCode() { //int result = true; return 1; } public String toString() { return "RedisReceiver()"; } }
package com.test.order.config; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.core.RedisTemplate; import javax.annotation.Resource; @Configuration public class JeecgRedisClient { @Resource private RedisTemplate<String, Object> redisTemplate; public JeecgRedisClient() { } public void sendMessage(String handlerName, BaseMap params) { params.put("handlerName", handlerName); this.redisTemplate.convertAndSend("jeecg_redis_topic", params); } }
package com.test.order.config;
public interface JeecgRedisListener {
void onMessage(BaseMap message);
}
package com.test.order.config; import cn.hutool.core.util.ObjectUtil; import java.math.BigDecimal; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; import org.apache.commons.beanutils.ConvertUtils; public class BaseMap extends HashMap<String, Object> { private static final long serialVersionUID = 1L; public BaseMap() { } public BaseMap(Map<String, Object> map) { this.putAll(map); } public BaseMap put(String key, Object value) { super.put(key, Optional.ofNullable(value).orElse("")); return this; } public BaseMap add(String key, Object value) { super.put(key, Optional.ofNullable(value).orElse("")); return this; } public <T> T get(String key) { Object obj = super.get(key); return ObjectUtil.isNotEmpty(obj) ? (T) obj : null; } public Boolean getBoolean(String key) { Object obj = super.get(key); return ObjectUtil.isNotEmpty(obj) ? Boolean.valueOf(obj.toString()) : false; } public Long getLong(String key) { Object v = this.get(key); return ObjectUtil.isNotEmpty(v) ? new Long(v.toString()) : null; } public Long[] getLongs(String key) { Object v = this.get(key); return ObjectUtil.isNotEmpty(v) ? (Long[])((Long[])v) : null; } public List<Long> getListLong(String key) { List<String> list = (List)this.get(key); return ObjectUtil.isNotEmpty(list) ? (List)list.stream().map((e) -> { return new Long(e); }).collect(Collectors.toList()) : null; } public Long[] getLongIds(String key) { Object ids = this.get(key); return ObjectUtil.isNotEmpty(ids) ? (Long[])((Long[])ConvertUtils.convert(ids.toString().split(","), Long.class)) : null; } public Integer getInt(String key, Integer def) { Object v = this.get(key); return ObjectUtil.isNotEmpty(v) ? Integer.parseInt(v.toString()) : def; } public Integer getInt(String key) { Object v = this.get(key); return ObjectUtil.isNotEmpty(v) ? Integer.parseInt(v.toString()) : 0; } public BigDecimal getBigDecimal(String key) { Object v = this.get(key); return ObjectUtil.isNotEmpty(v) ? new BigDecimal(v.toString()) : new BigDecimal("0"); } public <T> T get(String key, T def) { Object obj = super.get(key); return ObjectUtil.isEmpty(obj) ? def : (T) obj; } public static BaseMap toBaseMap(Map<String, Object> obj) { BaseMap map = new BaseMap(); map.putAll(obj); return map; } }
package com.test.order.config; /** * @author: huangxutao * @date: 2019-06-14 * @description: 缓存常量 */ public interface CacheConstant { /** * 字典信息缓存(含禁用的字典项) */ public static final String SYS_DICT_CACHE = "sys:cache:dict"; /** * 字典信息缓存 status为有效的 */ public static final String SYS_ENABLE_DICT_CACHE = "sys:cache:dictEnable"; /** * 表字典信息缓存 */ public static final String SYS_DICT_TABLE_CACHE = "sys:cache:dictTable"; public static final String SYS_DICT_TABLE_BY_KEYS_CACHE = SYS_DICT_TABLE_CACHE + "ByKeys"; /** * 数据权限配置缓存 */ public static final String SYS_DATA_PERMISSIONS_CACHE = "sys:cache:permission:datarules"; /** * 缓存用户信息【加密】 */ public static final String SYS_USERS_CACHE = "sys:cache:encrypt:user"; /** * 全部部门信息缓存 */ public static final String SYS_DEPARTS_CACHE = "sys:cache:depart:alldata"; /** * 全部部门ids缓存 */ public static final String SYS_DEPART_IDS_CACHE = "sys:cache:depart:allids"; /** * 测试缓存key */ public static final String TEST_DEMO_CACHE = "test:demo"; /** * 字典信息缓存 */ public static final String SYS_DYNAMICDB_CACHE = "sys:cache:dbconnect:dynamic:"; /** * gateway路由缓存 */ public static final String GATEWAY_ROUTES = "sys:cache:cloud:gateway_routes"; /** * gateway路由 reload key */ public static final String ROUTE_JVM_RELOAD_TOPIC = "gateway_jvm_route_reload_topic"; /** * TODO 冗余代码 待删除 *插件商城排行榜 */ public static final String PLUGIN_MALL_RANKING = "pluginMall::rankingList"; /** * TODO 冗余代码 待删除 *插件商城排行榜 */ public static final String PLUGIN_MALL_PAGE_LIST = "pluginMall::queryPageList"; /** * online列表页配置信息缓存key */ public static final String ONLINE_LIST = "sys:cache:online:list"; /** * online表单页配置信息缓存key */ public static final String ONLINE_FORM = "sys:cache:online:form"; /** * online报表 */ public static final String ONLINE_RP = "sys:cache:online:rp"; /** * online图表 */ public static final String ONLINE_GRAPH = "sys:cache:online:graph"; /** * 拖拽页面信息缓存 */ public static final String DRAG_PAGE_CACHE = "drag:cache:page"; }
package com.test.order.config; import java.util.List; import java.util.Map; import java.util.Set; /** * 通用api * @author: jeecg-boot */ public interface CommonAPI { /** * 1查询用户角色信息 * @param username * @return */ Set<String> queryUserRoles(String username); /** * 2查询用户权限信息 * @param userId * @return */ Set<String> queryUserAuths(String userId); /** * 6字典表的 翻译 * @param table * @param text * @param code * @param key * @return */ String translateDictFromTable(String table, String text, String code, String key); /** * 7普通字典的翻译 * @param code * @param key * @return */ String translateDict(String code, String key); }
package com.test.order.config; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class CommonConfig { /** * Spring上下文工具配置 * * @return */ @Bean //当bean为SpringContextHolder不存在时,就执行下面的方法创建bean @ConditionalOnMissingBean(SpringContextHolder.class) public SpringContextHolder springContextHolder() { SpringContextHolder holder = new SpringContextHolder(); return holder; } }
package com.test.order.config; /** * 系统通告 - 发布状态 * @Author LeeShaoQing * */ public interface CommonSendStatus { /** * 未发布 */ public static final String UNPUBLISHED_STATUS_0 = "0"; /** * 已发布 */ public static final String PUBLISHED_STATUS_1 = "1"; /** * 撤销 */ public static final String REVOKE_STATUS_2 = "2"; /** * app端推送会话标识后缀 */ public static final String APP_SESSION_SUFFIX = "_app"; /**-----【流程相关通知模板code】------------------------------------------------------------*/ /**流程催办——系统通知消息模板*/ public static final String TZMB_BPM_CUIBAN = "bpm_cuiban"; /**流程抄送——系统通知消息模板*/ public static final String TZMB_BPM_CC = "bpm_cc"; /**流程催办——邮件通知消息模板*/ public static final String TZMB_BPM_CUIBAN_EMAIL = "bpm_cuiban_email"; /**标准模板—系统消息通知*/ public static final String TZMB_SYS_TS_NOTE = "sys_ts_note"; /**流程超时提醒——系统通知消息模板*/ public static final String TZMB_BPM_CHAOSHI_TIP = "bpm_chaoshi_tip"; /**-----【流程相关通知模板code】-----------------------------------------------------------*/ /** * 系统通知拓展参数(比如:用于流程抄送和催办通知,这里额外传递流程跳转页面所需要的路由参数) */ public static final String MSG_ABSTRACT_JSON = "msg_abstract"; }
package com.test.order.config; /** * @Description: GlobalConstants * @author: scott * @date: 2020/01/01 16:01 */ public class GlobalConstants { /** * 业务处理器beanName传递参数 */ public static final String HANDLER_NAME = "handlerName"; /** * 路由刷新触发器 */ public static final String LODER_ROUDER_HANDLER = "loderRouderHandler"; /** * redis消息通道名称 */ public static final String REDIS_TOPIC_NAME="jeecg_redis_topic"; }
package com.test.order.config; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.Collections; import java.util.Optional; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Function; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.PessimisticLockingFailureException; import org.springframework.data.redis.cache.CacheStatistics; import org.springframework.data.redis.cache.CacheStatisticsCollector; import org.springframework.data.redis.cache.RedisCacheWriter; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisStringCommands.SetOption; import org.springframework.data.redis.core.types.Expiration; import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** * 该类参照 DefaultRedisCacheWriter 重写了 remove 方法实现通配符*删除 * * @author: scott * @date: 2020/01/01 16:18 */ @Slf4j public class JeecgRedisCacheWriter implements RedisCacheWriter { private final RedisConnectionFactory connectionFactory; private final Duration sleepTime; public JeecgRedisCacheWriter(RedisConnectionFactory connectionFactory) { this(connectionFactory, Duration.ZERO); } public JeecgRedisCacheWriter(RedisConnectionFactory connectionFactory, Duration sleepTime) { Assert.notNull(connectionFactory, "ConnectionFactory must not be null!"); Assert.notNull(sleepTime, "SleepTime must not be null!"); this.connectionFactory = connectionFactory; this.sleepTime = sleepTime; } @Override public void put(String name, byte[] key, byte[] value, @Nullable Duration ttl) { Assert.notNull(name, "Name must not be null!"); Assert.notNull(key, "Key must not be null!"); Assert.notNull(value, "Value must not be null!"); this.execute(name, (connection) -> { if (shouldExpireWithin(ttl)) { connection.set(key, value, Expiration.from(ttl.toMillis(), TimeUnit.MILLISECONDS), SetOption.upsert()); } else { connection.set(key, value); } return "OK"; }); } @Override public byte[] get(String name, byte[] key) { Assert.notNull(name, "Name must not be null!"); Assert.notNull(key, "Key must not be null!"); return (byte[])this.execute(name, (connection) -> { return connection.get(key); }); } @Override public byte[] putIfAbsent(String name, byte[] key, byte[] value, @Nullable Duration ttl) { Assert.notNull(name, "Name must not be null!"); Assert.notNull(key, "Key must not be null!"); Assert.notNull(value, "Value must not be null!"); return (byte[])this.execute(name, (connection) -> { if (this.isLockingCacheWriter()) { this.doLock(name, connection); } Object var7; try { boolean put; if (shouldExpireWithin(ttl)) { put = connection.set(key, value, Expiration.from(ttl), SetOption.ifAbsent()); } else { put = connection.setNX(key, value); } if (!put) { byte[] var11 = connection.get(key); return var11; } var7 = null; } finally { if (this.isLockingCacheWriter()) { this.doUnlock(name, connection); } } return (byte[])var7; }); } @Override public void remove(String name, byte[] key) { Assert.notNull(name, "Name must not be null!"); Assert.notNull(key, "Key must not be null!"); String keyString = new String(key); log.info("redis remove key:" + keyString); String keyIsAll = "*"; if(keyString!=null && keyString.endsWith(keyIsAll)){ execute(name, connection -> { // 获取某个前缀所拥有的所有的键,某个前缀开头,后面肯定是* Set<byte[]> keys = connection.keys(key); int delNum = 0; for (byte[] keyByte : keys) { delNum += connection.del(keyByte); } return delNum; }); }else{ this.execute(name, (connection) -> { return connection.del(new byte[][]{key}); }); } } @Override public void clean(String name, byte[] pattern) { Assert.notNull(name, "Name must not be null!"); Assert.notNull(pattern, "Pattern must not be null!"); this.execute(name, (connection) -> { boolean wasLocked = false; try { if (this.isLockingCacheWriter()) { this.doLock(name, connection); wasLocked = true; } byte[][] keys = (byte[][])((Set)Optional.ofNullable(connection.keys(pattern)).orElse(Collections.emptySet())).toArray(new byte[0][]); if (keys.length > 0) { connection.del(keys); } } finally { if (wasLocked && this.isLockingCacheWriter()) { this.doUnlock(name, connection); } } return "OK"; }); } void lock(String name) { this.execute(name, (connection) -> { return this.doLock(name, connection); }); } void unlock(String name) { this.executeLockFree((connection) -> { this.doUnlock(name, connection); }); } private Boolean doLock(String name, RedisConnection connection) { return connection.setNX(createCacheLockKey(name), new byte[0]); } private Long doUnlock(String name, RedisConnection connection) { return connection.del(new byte[][]{createCacheLockKey(name)}); } boolean doCheckLock(String name, RedisConnection connection) { return connection.exists(createCacheLockKey(name)); } private boolean isLockingCacheWriter() { return !this.sleepTime.isZero() && !this.sleepTime.isNegative(); } private <T> T execute(String name, Function<RedisConnection, T> callback) { RedisConnection connection = this.connectionFactory.getConnection(); try { this.checkAndPotentiallyWaitUntilUnlocked(name, connection); return callback.apply(connection); } finally { connection.close(); } } private void executeLockFree(Consumer<RedisConnection> callback) { RedisConnection connection = this.connectionFactory.getConnection(); try { callback.accept(connection); } finally { connection.close(); } } private void checkAndPotentiallyWaitUntilUnlocked(String name, RedisConnection connection) { if (this.isLockingCacheWriter()) { try { while(this.doCheckLock(name, connection)) { Thread.sleep(this.sleepTime.toMillis()); } } catch (InterruptedException var4) { Thread.currentThread().interrupt(); throw new PessimisticLockingFailureException(String.format("Interrupted while waiting to unlock cache %s", name), var4); } } } private static boolean shouldExpireWithin(@Nullable Duration ttl) { return ttl != null && !ttl.isZero() && !ttl.isNegative(); } private static byte[] createCacheLockKey(String name) { return (name + "~lock").getBytes(StandardCharsets.UTF_8); } //update-begin-author:zyf date:20220216 for:升级springboot版本到2.4.0+以后需要实现的方法* private final CacheStatisticsCollector statistics = CacheStatisticsCollector.create(); @Override public CacheStatistics getCacheStatistics(String cacheName) { return statistics.getCacheStatistics(cacheName); } @Override public void clearStatistics(String name) { } @Override public RedisCacheWriter withStatisticsCollector(CacheStatisticsCollector cacheStatisticsCollector) { return null; } //update-begin-author:zyf date:20220216 for:升级springboot版本到2.4.0+以后需要实现的方法* }
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package com.test.order.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; @Component public class RedisUtil { @Autowired private RedisTemplate<String, Object> redisTemplate; public RedisUtil() { } public boolean expire(String key, long time) { try { if (time > 0L) { this.redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Exception var5) { var5.printStackTrace(); return false; } } public long getExpire(String key) { return this.redisTemplate.getExpire(key, TimeUnit.SECONDS); } public boolean hasKey(String key) { try { return this.redisTemplate.hasKey(key); } catch (Exception var3) { var3.printStackTrace(); return false; } } public void del(String... key) { if (key != null && key.length > 0) { if (key.length == 1) { this.redisTemplate.delete(key[0]); } else { this.redisTemplate.delete(Arrays.asList(key)); } } } public Object get(String key) { return key == null ? null : this.redisTemplate.opsForValue().get(key); } public boolean set(String key, Object value) { try { this.redisTemplate.opsForValue().set(key, value); return true; } catch (Exception var4) { var4.printStackTrace(); return false; } } public boolean set(String key, Object value, long time) { try { if (time > 0L) { this.redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); } else { this.set(key, value); } return true; } catch (Exception var6) { var6.printStackTrace(); return false; } } public long incr(String key, long delta) { if (delta < 0L) { throw new RuntimeException("递增因子必须大于0"); } else { return this.redisTemplate.opsForValue().increment(key, delta); } } public long decr(String key, long delta) { if (delta < 0L) { throw new RuntimeException("递减因子必须大于0"); } else { return this.redisTemplate.opsForValue().increment(key, -delta); } } public Object hget(String key, String item) { return this.redisTemplate.opsForHash().get(key, item); } public Map<Object, Object> hmget(String key) { return this.redisTemplate.opsForHash().entries(key); } public boolean hmset(String key, Map<String, Object> map) { try { this.redisTemplate.opsForHash().putAll(key, map); return true; } catch (Exception var4) { var4.printStackTrace(); return false; } } public boolean hmset(String key, Map<String, Object> map, long time) { try { this.redisTemplate.opsForHash().putAll(key, map); if (time > 0L) { this.expire(key, time); } return true; } catch (Exception var6) { var6.printStackTrace(); return false; } } public boolean hset(String key, String item, Object value) { try { this.redisTemplate.opsForHash().put(key, item, value); return true; } catch (Exception var5) { var5.printStackTrace(); return false; } } public boolean hset(String key, String item, Object value, long time) { try { this.redisTemplate.opsForHash().put(key, item, value); if (time > 0L) { this.expire(key, time); } return true; } catch (Exception var7) { var7.printStackTrace(); return false; } } public void hdel(String key, Object... item) { this.redisTemplate.opsForHash().delete(key, item); } public boolean hHasKey(String key, String item) { return this.redisTemplate.opsForHash().hasKey(key, item); } public double hincr(String key, String item, double by) { return this.redisTemplate.opsForHash().increment(key, item, by); } public double hdecr(String key, String item, double by) { return this.redisTemplate.opsForHash().increment(key, item, -by); } public Set<Object> sGet(String key) { try { return this.redisTemplate.opsForSet().members(key); } catch (Exception var3) { var3.printStackTrace(); return null; } } public boolean sHasKey(String key, Object value) { try { return this.redisTemplate.opsForSet().isMember(key, value); } catch (Exception var4) { var4.printStackTrace(); return false; } } public long sSet(String key, Object... values) { try { return this.redisTemplate.opsForSet().add(key, values); } catch (Exception var4) { var4.printStackTrace(); return 0L; } } public long sSetAndTime(String key, long time, Object... values) { try { Long count = this.redisTemplate.opsForSet().add(key, values); if (time > 0L) { this.expire(key, time); } return count; } catch (Exception var6) { var6.printStackTrace(); return 0L; } } public long sGetSetSize(String key) { try { return this.redisTemplate.opsForSet().size(key); } catch (Exception var3) { var3.printStackTrace(); return 0L; } } public long setRemove(String key, Object... values) { try { Long count = this.redisTemplate.opsForSet().remove(key, values); return count; } catch (Exception var4) { var4.printStackTrace(); return 0L; } } public List<Object> lGet(String key, long start, long end) { try { return this.redisTemplate.opsForList().range(key, start, end); } catch (Exception var7) { var7.printStackTrace(); return null; } } public long lGetListSize(String key) { try { return this.redisTemplate.opsForList().size(key); } catch (Exception var3) { var3.printStackTrace(); return 0L; } } public Object lGetIndex(String key, long index) { try { return this.redisTemplate.opsForList().index(key, index); } catch (Exception var5) { var5.printStackTrace(); return null; } } public boolean lSet(String key, Object value) { try { this.redisTemplate.opsForList().rightPush(key, value); return true; } catch (Exception var4) { var4.printStackTrace(); return false; } } public boolean lSet(String key, Object value, long time) { try { this.redisTemplate.opsForList().rightPush(key, value); if (time > 0L) { this.expire(key, time); } return true; } catch (Exception var6) { var6.printStackTrace(); return false; } } public boolean lSet(String key, List<Object> value) { try { this.redisTemplate.opsForList().rightPushAll(key, value); return true; } catch (Exception var4) { var4.printStackTrace(); return false; } } public boolean lSet(String key, List<Object> value, long time) { try { this.redisTemplate.opsForList().rightPushAll(key, value); if (time > 0L) { this.expire(key, time); } return true; } catch (Exception var6) { var6.printStackTrace(); return false; } } public boolean lUpdateIndex(String key, long index, Object value) { try { this.redisTemplate.opsForList().set(key, index, value); return true; } catch (Exception var6) { var6.printStackTrace(); return false; } } public long lRemove(String key, long count, Object value) { try { Long remove = this.redisTemplate.opsForList().remove(key, count, value); return remove; } catch (Exception var6) { var6.printStackTrace(); return 0L; } } }
package com.test.order.config; import cn.hutool.core.util.ObjectUtil; import com.test.order.controller.OrderController; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Slf4j @Component(WebSocket.REDIS_TOPIC_NAME) public class SocketHandler implements JeecgRedisListener { @Autowired private WebSocket webSocket; @Override public void onMessage(BaseMap map) { log.info("【Redis发布订阅模式】redis Listener: {},参数:{}",WebSocket.REDIS_TOPIC_NAME, map.toString()); String userId = map.get("userId"); String message = map.get("message"); if (ObjectUtil.isNotEmpty(userId)) { //pc端消息推送具体人 webSocket.pushMessage(userId, message); //app端消息推送具体人 webSocket.pushMessage(userId+CommonSendStatus.APP_SESSION_SUFFIX, message); } else { //推送全部 webSocket.pushMessage(message); } } }
package com.test.order.config; import cn.hutool.core.util.ObjectUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; /** * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候中取出ApplicaitonContext. * * @author zyf */ @Slf4j public class SpringContextHolder implements ApplicationContextAware { private static ApplicationContext applicationContext; /** * 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量. */ @Override public void setApplicationContext(ApplicationContext applicationContext) { // NOSONAR SpringContextHolder.applicationContext = applicationContext; } /** * 取得存储在静态变量中的ApplicationContext. */ public static ApplicationContext getApplicationContext() { checkApplicationContext(); return applicationContext; } /** * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型. */ public static <T> T getBean(String name) { checkApplicationContext(); return (T) applicationContext.getBean(name); } /** * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型. */ public static <T> T getHandler(String name, Class<T> cls) { T t = null; if (ObjectUtil.isNotEmpty(name)) { checkApplicationContext(); try { t = applicationContext.getBean(name, cls); } catch (Exception e) { log.warn("Customize redis listener handle [ " + name + " ], does not exist!"); } } return t; } /** * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型. */ public static <T> T getBean(Class<T> clazz) { checkApplicationContext(); return applicationContext.getBean(clazz); } /** * 清除applicationContext静态变量. */ public static void cleanApplicationContext() { applicationContext = null; } private static void checkApplicationContext() { if (applicationContext == null) { throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder"); } } }
package com.test.order.config; /** * @Description: Websocket常量类 * @author: taoyan * @date: 2020年03月23日 */ public class WebsocketConst { /** * 消息json key:cmd */ public static final String MSG_CMD = "cmd"; /** * 消息json key:msgId */ public static final String MSG_ID = "msgId"; /** * 消息json key:msgTxt */ public static final String MSG_TXT = "msgTxt"; /** * 消息json key:userId */ public static final String MSG_USER_ID = "userId"; /** * 消息json key:chat */ public static final String MSG_CHAT = "chat"; /** * 消息类型 heartcheck */ public static final String CMD_CHECK = "heartcheck"; /** * 消息类型 user 用户消息 */ public static final String CMD_USER = "user"; /** * 消息类型 topic 系统通知 */ public static final String CMD_TOPIC = "topic"; /** * 消息类型 email */ public static final String CMD_EMAIL = "email"; /** * 消息类型 meetingsign 会议签到 */ public static final String CMD_SIGN = "sign"; /** * 消息类型 新闻发布/取消 */ public static final String NEWS_PUBLISH = "publish"; }
package com.test.order.config; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import lombok.extern.slf4j.Slf4j; /** * @Author scott * @Date 2019/11/29 9:41 * @Description: 此注解相当于设置访问URL */ @Component @Slf4j @ServerEndpoint("/websocket/{userId}") public class WebSocket { /**线程安全Map*/ private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<>(); /** * Redis触发监听名字 */ public static final String REDIS_TOPIC_NAME = "socketHandler"; @Autowired private JeecgRedisClient jeecgRedisClient; //==========【websocket接受、推送消息等方法 —— 具体服务节点推送ws消息】======================================================================================== @OnOpen public void onOpen(Session session, @PathParam(value = "userId") String userId) { try { sessionPool.put(userId, session); log.info("【系统 WebSocket】有新的连接,总数为:" + sessionPool.size()); } catch (Exception e) { } } @OnClose public void onClose(@PathParam("userId") String userId) { try { sessionPool.remove(userId); log.info("【系统 WebSocket】连接断开,总数为:" + sessionPool.size()); } catch (Exception e) { e.printStackTrace(); } } /** * ws推送消息 * * @param userId * @param message */ public void pushMessage(String userId, String message) { for (Map.Entry<String, Session> item : sessionPool.entrySet()) { //userId key值= {用户id + "_"+ 登录token的md5串} //TODO vue2未改key新规则,暂时不影响逻辑 if (item.getKey().contains(userId)) { Session session = item.getValue(); try { //update-begin-author:taoyan date:20211012 for: websocket报错 https://gitee.com/jeecg/jeecg-boot/issues/I4C0MU synchronized (session){ log.debug("【系统 WebSocket】推送单人消息:" + message); session.getBasicRemote().sendText(message); } //update-end-author:taoyan date:20211012 for: websocket报错 https://gitee.com/jeecg/jeecg-boot/issues/I4C0MU } catch (Exception e) { log.error(e.getMessage(),e); } } } } /** * ws遍历群发消息 */ public void pushMessage(String message) { try { for (Map.Entry<String, Session> item : sessionPool.entrySet()) { try { item.getValue().getAsyncRemote().sendText(message); } catch (Exception e) { log.error(e.getMessage(), e); } } log.debug("【系统 WebSocket】群发消息:" + message); } catch (Exception e) { log.error(e.getMessage(), e); } } /** * ws接受客户端消息 */ @OnMessage public void onMessage(String message, @PathParam(value = "userId") String userId) { if(!"ping".equals(message) && !WebsocketConst.CMD_CHECK.equals(message)){ log.debug("【系统 WebSocket】收到客户端消息:" + message); }else{ log.debug("【系统 WebSocket】收到客户端消息:" + message); } // //------------------------------------------------------------------------------ // JSONObject obj = new JSONObject(); // //业务类型 // obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_CHECK); // //消息内容 // obj.put(WebsocketConst.MSG_TXT, "心跳响应"); // this.pushMessage(userId, obj.toJSONString()); // //------------------------------------------------------------------------------ } /** * 配置错误信息处理 * * @param session * @param t */ @OnError public void onError(Session session, Throwable t) { log.warn("【系统 WebSocket】消息出现错误"); t.printStackTrace(); } //==========【系统 WebSocket接受、推送消息等方法 —— 具体服务节点推送ws消息】======================================================================================== //==========【采用redis发布订阅模式——推送消息】======================================================================================== /** * 后台发送消息到redis * * @param message */ public void sendMessage(String message) { //log.debug("【系统 WebSocket】广播消息:" + message); BaseMap baseMap = new BaseMap(); baseMap.put("userId", ""); baseMap.put("message", message); jeecgRedisClient.sendMessage(WebSocket.REDIS_TOPIC_NAME, baseMap); } /** * 此为单点消息 redis * * @param userId * @param message */ public void sendMessage(String userId, String message) { BaseMap baseMap = new BaseMap(); baseMap.put("userId", userId); baseMap.put("message", message); jeecgRedisClient.sendMessage(WebSocket.REDIS_TOPIC_NAME, baseMap); } /** * 此为单点消息(多人) redis * * @param userIds * @param message */ public void sendMessage(String[] userIds, String message) { for (String userId : userIds) { sendMessage(userId, message); } } //=======【采用redis发布订阅模式——推送消息】========================================================================================== }
/**
* 注入ServerEndpointExporter,
* 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
package com.test.order.controller; import com.alibaba.fastjson.JSONObject; import com.test.order.config.WebSocket; import com.test.order.config.WebsocketConst; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * @Description: * @Author: xu * @Data: 2024-2024/3/29-16 * @Version: V1.0 */ @RestController @RequestMapping("/order") public class OrderController { @Resource WebSocket webSocket; @RequestMapping("/test") public void add() { String message="message22"; JSONObject obj = new JSONObject(); obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_TOPIC); obj.put(WebsocketConst.MSG_ID, "M0001"); obj.put(WebsocketConst.MSG_TXT, message); webSocket.sendMessage(obj.toJSONString()); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。