SpringMVC集成Redis集群的应用,使用了

log4j,@value,@Configuration,@Bean,jackson工具类

SpringMVC集成Redis集群 github

resources目录下配置文件

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsd"><!-- @Value --><!-- 将多个配置文件位置放到列表中 --><bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"><property name="locations"><list><value>classpath*:redis.properties</value></list></property></bean><!-- 将配置文件读取到容器中,交给Spring管理 --><bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer"><property name="properties" ref="configProperties"/></bean><beans><!--定义包扫描路径--><context:component-scan base-package="com.diy.sigmund"/><!--与com.diy.sigmund.conifg.BeansConfig作用相同@Configuration,@Bean(initMethod = "initJedisCluster")-->
<!--        <bean id="redisUtil" class="com.diy.sigmund.redis.RedisUtil" init-method="initJedisCluster">-->
<!--            <constructor-arg ref="redisClusterConfig"/>-->
<!--        </bean>--></beans>
</beans>

log4j. properties

### 设置###
log4j.rootLogger=debug,stdout,D,E
### 输出信息到控制抬,仅输出INFO级别以上 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.Threshold=INFO
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=F:/project/knight/github/logs/app.log ###
log4j.appender.D=org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File=F:/project/knight/github/logs/app.log
log4j.appender.D.Append=true
log4j.appender.D.Threshold=DEBUG
log4j.appender.D.layout=org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
### 输出ERROR 级别以上的日志到=F:/project/knight/github/logs/error.log ###
log4j.appender.E=org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File=F:/project/knight/github/logs/error.log
log4j.appender.E.Append=true
log4j.appender.E.Threshold=ERROR
log4j.appender.E.layout=org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

redis.properties

redis.cluster.nodes=192.168.92.100:8000,192.168.92.100:8001,192.168.92.100:8002,192.168.92.100:8003,192.168.92.100:8004,192.168.92.100:8005
redis.cluster.pwd=123456

工具类

JsonUtil

package com.diy.sigmund.redis;import java.util.Objects;
import java.util.function.Supplier;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;/*** @author ylm-sigmund* @since 2020/11/21 13:16*/
public class JsonUtil {/*** 对象映射器*/private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();/*** 日志*/private static final Logger LOGGER = LoggerFactory.getLogger(JsonUtil.class);/*** 序列化对象为字符串* * OBJECT_MAPPER.writerWithDefaultPrettyPrinter() 漂亮打印机* * @param value*            value* @return String*/public static String toJson(Object value) {if (Objects.isNull(value)) {return "";}String jsonString = "";try {jsonString = OBJECT_MAPPER.writeValueAsString(value);} catch (Exception e) {LOGGER.error("toJson error, value is {}", value);}return jsonString;}/*** 反序列化对象* * 例如:JsonUtil.toObject(mapJson, () -> new TypeReference<Map<Integer, String>>() {});* * @param content*            content* @param supplier*            supplier* @param <T>*            <T>* @return 结果信息*/public static <T> T toObject(String content, Supplier<TypeReference<T>> supplier) {T object = null;try {final TypeReference<T> valueType = supplier.get();object = OBJECT_MAPPER.readValue(content, valueType);} catch (Exception e) {LOGGER.error("toObject error, content is {}", content);}return object;}
}

RedisClusterConfig

package com.diy.sigmund.redis;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;/*** @author ylm-sigmund* @since 2020/11/20 20:43*/
@Component
public class RedisClusterConfig {@Value("${redis.cluster.nodes}")private String nodes;@Value("${redis.cluster.pwd}")private String pwd;public String getNodes() {return nodes;}public String getPwd() {return pwd;}
}

RedisUtil

package com.diy.sigmund.redis;import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;import com.fasterxml.jackson.core.type.TypeReference;import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;/*** @author ylm-sigmund* @since 2020/11/20 20:43*/
@Component
public class RedisUtil {private static JedisCluster jedisCluster;private RedisClusterConfig redisClusterConfig;public RedisUtil(RedisClusterConfig redisClusterConfig) {this.redisClusterConfig = redisClusterConfig;}/*** 日志*/private static final Logger LOGGER = LoggerFactory.getLogger(RedisUtil.class);/*** 解析redis机器的ip+port* * @param nodes*            nodes* @return node*/private Set<HostAndPort> parseHostAndPort(String nodes) {Set<HostAndPort> node = new HashSet<>();String[] hostAndPorts = nodes.split(",");for (String hostAndPort : hostAndPorts) {String host = hostAndPort.split(":")[0];int port = Integer.parseInt(hostAndPort.split(":")[1]);HostAndPort hap = new HostAndPort(host, port);node.add(hap);}return node;}/*** 初始化 JedisCluster*/private void initJedisCluster() {Set<HostAndPort> node = parseHostAndPort(redisClusterConfig.getNodes());JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();// 注意:这里超时时间不要太短,他会有超时重试机制。而且其他像httpclient、dubbo等RPC框架也要注意这点jedisCluster = new JedisCluster(node, 1000, 1000, 1, redisClusterConfig.getPwd(), jedisPoolConfig);}/*** 将键 key 的值设置为 value , 并将键 key 的生存时间设置为 seconds 秒钟。** 如果键 key 已经存在, 那么 SETEX 命令将覆盖已有的值。* * @param key*            key* @param value*            value* @param timeout*            超时时间* @param timeUnit*            时间单位 SECONDS(秒),MINUTES(分),HOURS(时),DAYS(天),* @return 成功true或者失败false*/public static boolean setex(String key, Object value, int timeout, TimeUnit timeUnit) {try {int seconds = (int)timeUnit.toSeconds(timeout);jedisCluster.setex(key, seconds, JsonUtil.toJson(value));return true;} catch (Exception e) {LOGGER.error("Redis setex key {} value {} timeout {} timeUnit {}", key, value, timeout, timeUnit);return false;}}/*** 返回与键 key 相关联的值(已将字符串处理为对象)。* * 例如:RedisUtil.get(key1, () -> new TypeReference<User>() {});** @param key*            key* @param supplier*            supplier* @param <T>*            <T>* @return return*/public static <T> T get(String key, Supplier<TypeReference<T>> supplier) {try {final String json = jedisCluster.get(key);return JsonUtil.toObject(json, supplier);} catch (Exception e) {LOGGER.error("Redis get key {}", key);return null;}}/*** Redis Expire 命令用于设置 key 的过期时间。key 过期后将不再可用。若 key 存在,则会覆盖过期时间* * @param key*            key* @param timeout*            timeout* @param timeUnit*            timeUnit* @return Long*/public static Long expire(String key, int timeout, TimeUnit timeUnit) {try {int seconds = (int)timeUnit.toSeconds(timeout);return jedisCluster.expire(key, seconds);} catch (Exception e) {LOGGER.error("Redis expire key {}", key);return null;}}/*** Redis EXISTS 命令用于检查给定 key 是否存在。* * @param key*            key* @return Boolean*/public static Boolean exists(String key) {try {return jedisCluster.exists(key);} catch (Exception e) {LOGGER.error("Redis exists key {}", key);return false;}}/*** Redis TTL 命令以秒为单位返回 key 的剩余过期时间。* * @param key*            key* @return Long*/public static Long ttl(String key) {try {return jedisCluster.ttl(key);} catch (Exception e) {LOGGER.error("Redis ttl key {}", key);return null;}}/*** Redis DEL 命令用于删除已存在的键。不存在的 key 会被忽略。* * @param key*            key* @return Long*/public static Long del(String key) {try {return jedisCluster.del(key);} catch (Exception e) {LOGGER.error("Redis del key {}", key);return null;}}
}

配置类

BeansConfig

package com.diy.sigmund.conifg;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;import com.diy.sigmund.redis.RedisClusterConfig;
import com.diy.sigmund.redis.RedisUtil;/*** @author ylm-sigmund* @since 2020/11/22 12:34*/
@Configuration
@ComponentScan("com.diy.sigmund")
public class BeansConfig {public RedisClusterConfig redisClusterConfig() {return new RedisClusterConfig();}@Bean(initMethod = "initJedisCluster")public RedisUtil redisUtil(RedisClusterConfig redisClusterConfig) {return new RedisUtil(redisClusterConfig);}
}

pom文件

    <dependencies><!--Spring AOP--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.6.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.0.6.RELEASE</version></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.2.0</version></dependency><!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.11.2</version></dependency><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency><dependency><groupId>commons-collections</groupId><artifactId>commons-collections</artifactId><version>3.2.2</version></dependency><!--slf4j只是一个日志标准,并不是日志系统的具体实现--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.30</version></dependency><!--slf4j-simple是slf4j的具体实现-->
<!--        <dependency>-->
<!--            <groupId>org.slf4j</groupId>-->
<!--            <artifactId>slf4j-simple</artifactId>-->
<!--            <version>1.7.30</version>-->
<!--            <scope>test</scope>-->
<!--        </dependency>--><!--log4j并不直接实现slf4j,但是有专门的一层桥接slf4j-log4j12来实现slf4j--><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.30</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.0.6.RELEASE</version><scope>provided</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency></dependencies>

单元测试

package com.diy.sigmund.redis;import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.diy.sigmund.entity.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;/*** @author ylm-sigmund* @since 2020/11/20 20:50*/
// @ComponentScan("com.diy.sigmund")//该注解在单元测试下无效
@RunWith(SpringJUnit4ClassRunner.class)
// @ContextConfiguration属性locations和classes只能取一个,否则会报错configure one or the other, but not both.
// @ContextConfiguration(locations = {"classpath:applicationContext.xml"},classes = BeansConfig.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class RedisClusterConfigTest {/*** 日志*/private static final Logger LOGGER = LoggerFactory.getLogger(RedisClusterConfigTest.class);@Autowiredprivate RedisClusterConfig redisClusterConfig;@Testpublic void setex() {final User user = new User();user.setId(1234);user.setName("jackson包");String key1 = "qqq";LOGGER.info("key1 是否存在 {}", RedisUtil.exists(key1));final boolean setex = RedisUtil.setex(key1, user, 1, TimeUnit.MINUTES);LOGGER.info("setex key1 是否成功 {}", setex);LOGGER.info("key1 过期时间 {} 秒", RedisUtil.ttl(key1));final Long expire = RedisUtil.expire(key1, 1, TimeUnit.HOURS);LOGGER.info("expire key1 设置过期时间 {}", expire);LOGGER.info("key1 过期时间 {} 秒", RedisUtil.ttl(key1));final User user1 = RedisUtil.get(key1, () -> new TypeReference<User>() {});LOGGER.info("get key1 {}", Objects.requireNonNull(user1).toString());final Long del = RedisUtil.del(key1);LOGGER.info("del key1 {}", del);LOGGER.info("key1 是否存在 {}", RedisUtil.exists(key1));final Long expire1 = RedisUtil.expire(key1, 1, TimeUnit.MINUTES);LOGGER.info("expire key1 设置过期时间 {}", expire1);LOGGER.info("key1 过期时间 {} 秒", RedisUtil.ttl(key1));}/*** 测试序列化和反序列化* * @throws JsonProcessingException*             JsonProcessingException*/@Testpublic void testJackson() throws JsonProcessingException {LOGGER.info("key1 是否存在 {}", RedisUtil.exists("key1"));// 对象final User user = new User();user.setId(1234);user.setName("jackson包");// 序列化final String json = JsonUtil.toJson(user);LOGGER.info("user is {}", json);// 反序列化final User user1 = JsonUtil.toObject(json, () -> new TypeReference<User>() {});LOGGER.info(user1.toString());// mapfinal Map<Integer, String> map = new HashMap<Integer, String>();map.put(2234, "jackson包");// 序列化final String mapJson = JsonUtil.toJson(map);LOGGER.info(mapJson);// 反序列化final Map<Integer, String> hashMap =JsonUtil.toObject(mapJson, () -> new TypeReference<Map<Integer, String>>() {});LOGGER.info(hashMap.toString());// listfinal List<User> collect = Stream.of(user).collect(Collectors.toList());// 序列化final String listJson = JsonUtil.toJson(collect);LOGGER.info(listJson);// 反序列化final List<User> arrayList = JsonUtil.toObject(listJson, () -> new TypeReference<List<User>>() {});LOGGER.info(arrayList.toString());}}

资料参考

  • Jackson 的 基本用法

  • jackson学习之三:常用API操作

  • Redis TTL 命令

  • SETEX key seconds value

  • Spring 集成Redis Cluster模式

  • log4j.properties配置文件详解

  • log4j.properties 详解与配置步骤

  • spring @Bean注解的使用

  • Spring中配置和读取多个Properties文件–转

  • JedisPool资源池优化

  • 掌握JedisPoolConfig参数配置,学会调优技能

SpringMVC集成Redis集群相关推荐

  1. 超完整!Springboot整合redis集群(Sentine),spring boot自动配置集成redis集群(Sentine)

    1.添加maven依赖 注意maven版本依赖,版本要相互匹配,如不知道如何查看相对应的版本时,可进入博主主页查看博主上一篇博文. <parent><groupId>org.s ...

  2. Spring集成Redis集群(含spring集成redis代码)

    代码地址如下: http://www.demodashi.com/demo/11458.html 一.准备工作 安装 Redis 集群 安装参考: http://blog.csdn.net/zk673 ...

  3. 什么是slot槽节点、Springboot集成Redis集群

    一. 什么是slot槽节点 slots:槽,用于装数据,主节点有,从节点没有 1.怎么分配slot? --平均分配 需要注意的是,槽节点是分配给master节点的,slave节点没有.  2.槽slo ...

  4. springboot集成redis集群实现集群拓扑动态刷新

    一个redis-cluster的三主三从集群,在其中一个master节点挂了之后,springboot集成redis集群配置信息没有及时刷新,出现读取操作报错.下面聊聊如何实现springboot集成 ...

  5. java集成redis集群_spring集成redis cluster详解

    客户端采用最新的jedis 2.7 1.maven依赖: redis.clients jedis 2.7.3 2.增加spring 配置 classpath:connect-redis.propert ...

  6. 丹丹丹学妹哭着对我说:学长,SpringBoot集成Redis集群

    aaasdass[注]:装箱.拆箱的开销是Java泛型慢的重要原因.也成为今天Valhalla项目要重点解决的问题之一. aa aasdas②.运行期无法取到泛型类型信息.会让一些代码变得相当啰嗦.比 ...

  7. Redis集群架构搭建和原理

    Redis集群架构教程 Redis常见的架构有主从.哨兵.高可用集群,接下来的文章分四章分别介绍linux安装redis.主从架构搭建.哨兵模式搭建.集群架构搭建 第一章 Redis的安装 我的cen ...

  8. 如何从0到1构建一个稳定、高性能的Redis集群?(附16张图解)

    阅读本文大约需要 13 分钟. 大家好,我是 Kaito. 这篇文章我想和你聊一聊 Redis 的架构演化之路. 现如今 Redis 变得越来越流行,几乎在很多项目中都要被用到,不知道你在使用 Red ...

  9. 一次搞定:分布式缓存 Redis 集群搭建!

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | Esofar 来源 | cnblogs.com ...

最新文章

  1. 【短视频SDK - 参数解析】对焦模式、裁剪模式、视频质量、分辨率、视频比例、帧率、关键帧间隔等参数解析...
  2. iOS9的新特性以及适配方案
  3. spring-boot的access日志格式修改
  4. c++ 预处理命令 预定义变量用法
  5. DestroyJavaVM
  6. python两个装饰器执行顺序_python中多个装饰器的执行顺序详解
  7. java swing 禁用鼠标事件_Java学习笔记:swing中树控件,设置树节点的图标,按钮美化,鼠标事件,禁止鼠标双击...
  8. 我的第一个REST客户端程序!
  9. [sh]shift参数左移用法
  10. Picasso源码阅读笔记三
  11. eXtremeComponents 使用总结
  12. Linux学习之dpkg错误:另外一个进程已为dpkg状态库加锁
  13. 2022年计算机二级WPS Office高级应用与设计复习题及答案
  14. Python编程:从入门到实践.pdf :Python 基础笔记,最基本的 Python语法,快速上手入门 Python
  15. android手机短信诈骗原理,安卓系统均存短信欺诈漏洞 专家:系统先天不足
  16. 所有能反演SIF的卫星以及下载链接
  17. JavaScript在表格中实现九九乘法表
  18. 记一次Oracle 11g xe 导出导入使用过程
  19. J2EE重要的技术架构图
  20. 《白帽子讲web安全》读书笔记_2021年7月16日(2)_第3篇 服务器端应用安全

热门文章

  1. 如何看待自己的第一份工作
  2. Neo4j 基础简介一
  3. mysql 多表联查
  4. CDR插件开发之Addon插件003 - 认识解决方案(sln)和项目(csproj)文件
  5. 新 年 祝 福 三 则 群 聊 版
  6. 笔记本运行php的快捷键是啥,电脑的窗口切换快捷键是什么
  7. 关于MES与设备集成方式及注意项目
  8. XM外汇平台:句句箴言!外汇投资交易市场的九大生存准则
  9. 长安“战疫”网络安全卫士守护赛_crypto_复现
  10. fofa网络资产检索