详解java之redis篇(spring-data-redis整合)

1,利用spring-data-redis整合

项目使用的pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.x.redis</groupId>

<artifactId>Spring_redis</artifactId>

<version>1.0-SNAPSHOT</version>

<packaging>jar</packaging>

<name>Spring_redis</name>

<url>http://maven.apache.org</url>

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

</properties>

<dependencies>

<dependency>

<groupId>org.springframework.data</groupId>

<artifactId>spring-data-redis</artifactId>

<version>1.0.2.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-core</artifactId>

<version>3.1.2.RELEASE</version>

</dependency>

<dependency>

<groupId>redis.clients</groupId>

<artifactId>jedis</artifactId>

<version>2.1.0</version>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.8.2</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<version>1.6.1</version>

</dependency>

<!-- 将现有的jakarta commons logging的调用转换成lsf4j的调用。 -->

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>jcl-over-slf4j</artifactId>

<version>1.6.1</version>

</dependency>

<!-- Hack:确保commons-logging的jar包不被引入,否则将和jcl-over-slf4j冲突 -->

<dependency>

<groupId>commons-logging</groupId>

<artifactId>commons-logging</artifactId>

<version>1.1.1</version>

<scope>provided</scope>

</dependency>

<!-- slf4j的实现:logback,用来取代log4j。更快、更强! -->

<dependency>

<groupId>ch.qos.logback</groupId>

<artifactId>logback-classic</artifactId>

<version>0.9.24</version>

<scope>runtime</scope>

</dependency>

</dependencies>

</project>

除了log部分,只有一个spring core 和 spring-data-redis了

项目文件目录结构:

applicationContext.xml:

1,context:property-placeholder 标签用来导入properties文件。从而替换${redis.maxIdle}这样的变量。

2,context:component-scan 是为了在com.x.redis.dao报下的类能够实用spring的注解注入的方式。

3,事实上我们只需要把JedisPoolConfig配数来就好了,接下来就是spring的封装了。所以直接看UserDAOImpl的实现就明白了。

<?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:p="http://www.springframework.org/schema/p"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"

xmlns:aop="http://www.springframework.org/schema/aop"

xsi:schemaLocation="

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<context:property-placeholder location="classpath:redis.properties" />

<context:component-scan base-package="com.x.redis.dao">

</context:component-scan>

<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">

<property name="maxIdle" value="${redis.maxIdle}" />

<property name="maxActive" value="${redis.maxActive}" />

<property name="maxWait" value="${redis.maxWait}" />

<property name="testOnBorrow" value="${redis.testOnBorrow}" />

</bean>

<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"

p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:pool-config-ref="poolConfig"/>

<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">

<property name="connectionFactory" ref="connectionFactory" />

</bean>

<bean id="userDAO" class="com.x.redis.dao.impl.UserDAOImpl" />

</beans>

redis.properties:

# Redis settings

#redis.host=192.168.20.101

#redis.port=6380

#redis.pass=foobared

redis.host=127.0.0.1

redis.port=6379

redis.pass=

redis.maxIdle=300

redis.maxActive=600

redis.maxWait=1000

redis.testOnBorrow=true

UserDAOImpl:

1,spring对dao层的封装很多用了类似于下面代码的模板方式。

2,RedisTemplate就是spring对redis的一个封装而已。

public class UserDAOImpl implements UserDAO {

@Autowired

protected RedisTemplate<Serializable, Serializable> redisTemplate;

public void saveUser(final User user) {

redisTemplate.execute(new RedisCallback<Object>() {

@Override

public Object doInRedis(RedisConnection connection) throws DataAccessException {

connection.set(redisTemplate.getStringSerializer().serialize("user.uid." + user.getId()),

redisTemplate.getStringSerializer().serialize(user.getName()));

return null;

}

});

}

@Override

public User getUser(final long id) {

return redisTemplate.execute(new RedisCallback<User>() {

@Override

public User doInRedis(RedisConnection connection) throws DataAccessException {

byte[] key = redisTemplate.getStringSerializer().serialize("user.uid." + id);

if (connection.exists(key)) {

byte[] value = connection.get(key);

String name = redisTemplate.getStringSerializer().deserialize(value);

User user = new User();

user.setName(name);

user.setId(id);

return user;

}

return null;

}

});

}

}

其他:

User:

public class User {

private long id;

private String name;

public long getId() {

return id;

}

public void setId(long id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

测试代码:

public static void main(String[] args) {

ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:/applicationContext.xml");

UserDAO userDAO = (UserDAO)ac.getBean("userDAO");

User user1 = new User();

user1.setId(1);

user1.setName("obama");

userDAO.saveUser(user1);

User user2 = userDAO.getUser(1);

System.out.println(user2.getName());

}

2,不利用spring-data-redis整合

个人觉得这样整合灵活度更大,能够更加明了的完成任务。

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.d.work</groupId>

<artifactId>Redis_Templete</artifactId>

<version>1.0-SNAPSHOT</version>

<packaging>jar</packaging>

<name>Redis_Templete</name>

<url>http://maven.apache.org</url>

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

</properties>

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>3.8.1</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>redis.clients</groupId>

<artifactId>jedis</artifactId>

<version>2.1.0</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-core</artifactId>

<version>3.1.2.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-beans</artifactId>

<version>3.1.2.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context</artifactId>

<version>3.1.2.RELEASE</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<version>1.6.1</version>

</dependency>

<!-- 将现有的jakarta commons logging的调用转换成lsf4j的调用。 -->

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>jcl-over-slf4j</artifactId>

<version>1.6.1</version>

</dependency>

<!-- Hack:确保commons-logging的jar包不被引入,否则将和jcl-over-slf4j冲突 -->

<dependency>

<groupId>commons-logging</groupId>

<artifactId>commons-logging</artifactId>

<version>1.1.1</version>

<scope>provided</scope>

</dependency>

<!-- slf4j的实现:logback,用来取代log4j。更快、更强! -->

<dependency>

<groupId>ch.qos.logback</groupId>

<artifactId>logback-classic</artifactId>

<version>0.9.24</version>

<scope>runtime</scope>

</dependency>

</dependencies>

</project>

目录结构:

data-source.xml

1,context:property-placeholder 和 context:component-scan 前面解释过啦。

2,配置了一个ShardedJedisPool,在jdeis里 还有个JedisPool。这两个的区别:

一个是分片形式,可以连接有主备的redis服务端,一个是单个的。详细后续学习

3,因为不使用spring-data-redis的封装,所以自己要自己封装一个

<?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:p="http://www.springframework.org/schema/p"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"

xmlns:aop="http://www.springframework.org/schema/aop"

xsi:schemaLocation="

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<context:property-placeholder location="classpath:redis.properties" />

<context:component-scan base-package="com.d.work.main">

</context:component-scan>

<context:component-scan base-package="com.d.work.redis">

</context:component-scan>

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">

<property name="maxActive" value="50" />

<property name="maxIdle" value="8" />

<property name="maxWait" value="1000" />

<property name="testOnBorrow" value="true"/>

<property name="testOnReturn" value="true"/>

<!-- <property name="testWhileIdle" value="true"/> -->

</bean>

<bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool" scope="singleton">

<constructor-arg index="0" ref="jedisPoolConfig" />

<constructor-arg index="1">

<list>

<bean class="redis.clients.jedis.JedisShardInfo">

<constructor-arg name="host" value="${redis.host}" />

<constructor-arg name="port" value="${redis.port}" />

<constructor-arg name="timeout" value="${redis.timeout}" />

<constructor-arg name="weight" value="1" />

</bean>

</list>

</constructor-arg>

</bean>

</beans>

RedisDataSource:定义三个方法

public interface RedisDataSource {

public abstract ShardedJedis getRedisClient();

public void returnResource(ShardedJedis shardedJedis);

public void returnResource(ShardedJedis shardedJedis,boolean broken);

}

实现redisDataSource:

1, 注入配置好的ShardedJedisPool,这三个方法的作用:

  •  getRedisClient() : 取得redis的客户端,可以执行命令了。
  • returnResource(ShardedJedis shardedJedis) : 将资源返还给pool
  • returnResource(ShardedJedis shardedJedis, boolean broken) : 出现异常后,将资源返还给pool (其实不需要第二个方法)

@Repository("redisDataSource")

public class RedisDataSourceImpl implements RedisDataSource {

private static final Logger log = LoggerFactory.getLogger(RedisDataSourceImpl.class);

@Autowired

private ShardedJedisPool shardedJedisPool;

public ShardedJedis getRedisClient() {

try {

ShardedJedis shardJedis = shardedJedisPool.getResource();

return shardJedis;

} catch (Exception e) {

log.error("getRedisClent error", e);

}

return null;

}

public void returnResource(ShardedJedis shardedJedis) {

shardedJedisPool.returnResource(shardedJedis);

}

public void returnResource(ShardedJedis shardedJedis, boolean broken) {

if (broken) {

shardedJedisPool.returnBrokenResource(shardedJedis);

} else {

shardedJedisPool.returnResource(shardedJedis);

}

}

}

第二层的封装:RedisClientTemplate,例子实现了放值和取值。最后代码提供了全部命令的实现。

代码就是映射性质的又一次调用jedis的方法而已,用了个broken来做标示符,决定返还资源的方式。

这一层的目的主要也是让再上层的调用不需要关心pool中链接的取得和返还问题了。

@Repository("redisClientTemplate")

public class RedisClientTemplate {

private static final Logger log = LoggerFactory.getLogger(RedisClientTemplate.class);

@Autowired

private RedisDataSource redisDataSource;

public void disconnect() {

ShardedJedis shardedJedis = redisDataSource.getRedisClient();

shardedJedis.disconnect();

}

/**

* 设置单个值

*

* @param key

* @param value

* @return

*/

public String set(String key, String value) {

String result = null;

ShardedJedis shardedJedis = redisDataSource.getRedisClient();

if (shardedJedis == null) {

return result;

}

boolean broken = false;

try {

result = shardedJedis.set(key, value);

} catch (Exception e) {

log.error(e.getMessage(), e);

broken = true;

} finally {

redisDataSource.returnResource(shardedJedis, broken);

}

return result;

}

/**

* 获取单个值

*

* @param key

* @return

*/

public String get(String key) {

String result = null;

ShardedJedis shardedJedis = redisDataSource.getRedisClient();

if (shardedJedis == null) {

return result;

}

boolean broken = false;

try {

result = shardedJedis.get(key);

} catch (Exception e) {

log.error(e.getMessage(), e);

broken = true;

} finally {

redisDataSource.returnResource(shardedJedis, broken);

}

return result;

}

}

测试代码:

public static void main(String[] args) {

ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:/data-source.xml");

RedisClientTemplate redisClient = (RedisClientTemplate)ac.getBean("redisClientTemplate");

redisClient.set("a", "abc");

System.out.println(redisClient.get("a"));

}

附上RedisClientTemplate全部实现:

RedisClientTemplate代码太多,附上下载地址:http://xiazai./201701/yuanma/RedisClientTemplate_.rar

 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是 详解java之redis篇(spring-data-redis整合) 的全部内容, 来源链接: utcz.com/p/211013.html

回到顶部