说明:
- 此项目演示Redis与Spring集成, Redis轻量级集群即分片模式
- Redis与Spring集成代码:JedisPoolSpring.java; Redis轻量级集群代码:ShardedJedisPoolSpring.java
- 代码中注释有具体的使用说明等讲解。
项目结构图==
代码如下====
====>>>> JedisPoolSpring.java
/**
* 本地环境Redis连接池JedisPool集成Spring:
* Spring环境中使用JedisPool
* 即JedisPool与Spring集成
*
* @author 拈花为何不一笑
*
*/
public class JedisPoolSpring {
private JedisPool jedisPool;
//初始化Spring容器
public void initSpringContainer(){
//构建Spring容器通过applicationContext-jedis.xml配置文件,联想一下Struts2的容器
//容器的作用:提供AOP,DI即bean的注册和依赖注入等功能
//Struts2的容器Container/ContainerImple构造函数为default只能在同类或同包下才能使用,可以看出该容器是Struts2内部专用的容器
//Spring的容器是ApplicationContext是public构造函数,可以提供对内和对外都能使用。但是容器中的bean的访问是有限制条件的,这个条件如下:
//通俗点说就是:new 出来的bean是不能使用Spring容器中的bean,new出来的bean是Spring容器外的bean,不归Spring容器管理。
//即Spring bean提供被访问的前提是Spring容器中的bean相互访问,容器外的bean是不能"直接"访问容器内的bean,因为容器外的bean不是由Spring进行管理的。
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext-jedis.xml");
System.out.println("=====>>>连接Redis服务器成功,并初始Spring容器和注册JedisPool..");
jedisPool = (JedisPool) ctx.getBean("jedisPool");
}
//从JedisPool中获取一个Jedis实例
public Jedis getJedis(){
return jedisPool.getResource();
}
//释放Jedis,并未真正关闭连接,而是返回到连接池中
public void freeJedis(Jedis jedis){
if(null != jedis){
jedis.close();
}
}
//使用jedis操作String数据结构
public void setString(String key ,String value){
//从JedisPool池中获取一个Jedis实例
Jedis jedis = getJedis();
//使用Jedis
jedis.set(key, value);
//释放jedis连接,返回到连接池中
freeJedis(jedis);
}
//从Redis服务器中获取String结构类型数据
public String getValueStr(String key){
//从JedisPool池中获取一个Jedis实例
Jedis jedis = getJedis();
//使用Jedis
String value = jedis.get(key);
//释放jedis连接,返回到连接池中
freeJedis(jedis);
return value;
}
/**
* 单元测试
* @param args
* 遇到异常:
* Caused by: java.lang.ClassNotFoundException:
* org.springframework.expression.PropertyAccessor
* 解决方案:因为使用了expression即spring表达式,加入spring-expression.jar
* 类似异常还依赖commons-logging.jar
*
*/
public static void main(String[] args) {
JedisPoolSpring jedisPoolSpring = new JedisPoolSpring();
//初始化Spring容器
jedisPoolSpring.initSpringContainer();
//这个首次运行机制后main方法后,注释掉再运行main方法查询str-key数据看看结果
//jedisPoolSpring.setString("str-key", "baby,i love you!");//相同的key对应的value会被覆盖,跟Map特性类似
System.out.println("从Redis中获取数据:" + jedisPoolSpring.getValueStr("str-key"));
}
}
====>>>> ShardedJedisPoolSpring.java
package com.it.util;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
/**
* ShardedJedis分布式集群(即分片模式,属性轻量级集群)
*
* @author 拈花为何不一笑
* 说明:java通过jedis客户端操作redis主要三种模式:
* 单机模式(JedisPool)、
* 分片模式(ShardedJedis)、
* 集群模式(BinaryJedisCluster),分片模式是一种轻量级集群
*/
public class ShardedJedisPoolSpring {
private ShardedJedisPool shardedJedisPool;
//初始化Spring容器
public void initSpringContainer(){
//构建Spring容器通过applicationContext-jedis.xml配置文件,联想一下Struts2的容器
//容器的作用:提供AOP,DI即bean的注册和依赖注入等功能
//Struts2的容器Container/ContainerImple构造函数为default只能在同类或同包下才能使用,可以看出该容器是Struts2内部专用的容器
//Spring的容器是ApplicationContext是public构造函数,可以提供对内和对外都能使用。但是容器中的bean的访问是有限制条件的,这个条件如下:
//通俗点说就是:new 出来的bean是不能使用Spring容器中的bean,new出来的bean是Spring容器外的bean,不归Spring容器管理。
//即Spring bean提供被访问的前提是Spring容器中的bean相互访问,容器外的bean是不能"直接"访问容器内的bean,因为容器外的bean不是由Spring进行管理的。
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext-shardedJedis.xml");
System.out.println("=====>>>连接Redis服务器成功,并初始Spring容器和注册shardedJedisPool..");
shardedJedisPool = (ShardedJedisPool) ctx.getBean("shardedJedisPool");
}
//从shardedJedisPool中获取一个ShardedJedis实例
public ShardedJedis getShardedJedis(){
return shardedJedisPool.getResource();
}
//释放ShardedJedis,并未真正关闭连接,而是返回到连接池中
public void freeShardedJedis(ShardedJedis shardedJedis){
if(null != shardedJedis){
shardedJedis.close();
}
}
//使用ShardedJedis操作String数据结构
public void setString(String key ,String value){
//从shardedJedisPool池中获取一个ShardedJedis实例
ShardedJedis shardedJedis = getShardedJedis();
//使用ShardedJedis
shardedJedis.set(key, value);
//释放jedis连接,返回到连接池中
freeShardedJedis(shardedJedis);
}
//从Redis服务器中获取String结构类型数据
public String getValueStr(String key){
//从shardedJedisPool池中获取一个ShardedJedis实例
ShardedJedis shardedJedis = getShardedJedis();
//使用ShardedJedis
String value = shardedJedis.get(key);
//释放jedis连接,返回到连接池中
freeShardedJedis(shardedJedis);
return value;
}
/**
* 单元测试
* @param args
*
*/
public static void main(String[] args) {
ShardedJedisPoolSpring sharedJedisPoolSpring = new ShardedJedisPoolSpring();
//初始化Spring容器
sharedJedisPoolSpring.initSpringContainer();
//这个首次运行机制后main方法后,注释掉再运行main方法查询str-bb数据看看结果
//sharedJedisPoolSpring.setString("str-bb", "i am sharedJedis!");
System.out.println("从Redis中获取数据:" + sharedJedisPoolSpring.getValueStr("str-bb"));
}
}
配置代码如下====
====>>>>redis.properties
#最大分配的对象数
redis.pool.maxActive=200
#最大能够保持idel状态的对象数
redis.pool.maxIdle=50
redis.pool.minIdle=10
redis.pool.maxWaitMillis=20000
#当池内没有返回对象时,最大等待时间
redis.pool.maxWait=300
#语法格式:redis://:[密码]@[服务器地址]:[端口]/[db index]
redis.uri=redis://:foo666k@127.0.0.1:6379/0
#对比一下java连接mysql数据库使用jdbc协议,jdbc:mysql://localhost:3306/dbname
#对比一下java连接oracle数据库使用jdbc协议,jdbc:oracle:thin:@127.0.0.1:1521:orcl
redis.host=127.0.0.1
redis.port=6379
redis.timeout=30000
#这个密码是启动Redis服务器指定加载配置文件中配置的密码
#比如笔者加载这个redis.windows.conf配置文件,那么密码配置在此文件中,对应项为requirepass
redis.password=foo666k
#连接并使用Redis的数据库0,Redis数据库名称用数字表示0,1,2...
redis.database=0
====>>>> applicationContext-jedis.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/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!-- 引入jedis的properties配置文件 -->
<!--如果你有多个数据源且不愿意放在一个配置文件里,那么一定要加上ignore-unresolvable="true"-->
<context:property-placeholder location="classpath:properties/redis.properties" ignore-unresolvable="true" />
<!-- Spring注册bean:JedisPoolConfig -->
<!-- Jedis连接池的相关配置-->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!--新版是maxTotal,旧版是maxActive-->
<property name="maxTotal">
<value>${redis.pool.maxActive}</value>
</property>
<property name="maxIdle">
<value>${redis.pool.maxIdle}</value>
</property>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
</bean>
<!-- 使用constructor-arg构造器方式进行注入 -->
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="poolConfig" ref="jedisPoolConfig" />
<constructor-arg name="host" value="${redis.host}" />
<constructor-arg name="port" value="${redis.port}" type="int" />
<constructor-arg name="timeout" value="${redis.timeout}" type="int" />
<constructor-arg name="password" value="${redis.password}" />
<constructor-arg name="database" value="${redis.database}" type="int" />
</bean>
<!-- JedisPool构造器
public JedisPool(final GenericObjectPoolConfig poolConfig,
final String host, int port, int timeout,
final String password, final int database) {
}
-->
</beans>
====>>>> applicationContext-shardedJedis.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/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!-- 引入redis.properties配置文件 -->
<context:property-placeholder location="classpath:properties/redis.properties" ignore-unresolvable="true" />
<!--JedisPoolConfig配置,这个就相当于Spring中常用的DataSource加载jdbc.properties配置文件的bean的注册-->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.pool.maxActive}" />
<property name="maxIdle" value="${redis.pool.maxIdle}" />
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
</bean>
<!--ShardedJedisPool配置,使用Spring构造器进行bean:ShardedJedisPool的创建并进行jedisPoolConfig的注入 -->
<bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool" scope="singleton">
<constructor-arg index="0" ref="jedisPoolConfig" />
<constructor-arg index="1">
<!-- 天生的集群配置,看到没?list意思就是告诉你要配置多个JedisSahredInfo,多个集中起来不就是集群了
有多个Redis服务器,就配置多个JedisDataSource bean就OK了。现在就一台Redis就配置一个。
当然一个完整集群的环境必须有负载均衡Nginx + tomcat + Linux之类的组合等等,这个在这就不演示了。
-->
<list>
<bean class="redis.clients.jedis.JedisShardInfo">
<constructor-arg name="host" value="${redis.uri}" />
</bean>
</list>
</constructor-arg>
</bean>
<!-- ShardedJedisPool构造器如下:
public ShardedJedisPool(final GenericObjectPoolConfig poolConfig, List<JedisShardInfo> shards) {
this(poolConfig, shards, Hashing.MURMUR_HASH);
}
-->
</beans>
@author 拈花为何不一笑
关于与Spring集成使用注解的方式,有需要的可以联系,可以单独发源码。这里就不贴代码了。谢谢大家阅读。