spring-data-redis实例应用

[b]spring-data-redis实例应用[/b]

1.对Redis的Key-Value数据存储操作提供了更高层次的抽象,类似于Spring Framework对JDBC支持一样。
2.如果不用这个你就要自己进行redis连接的连接与关闭操作,这个要小心的进行关闭,因为不关闭连接
就会太多,甚至用完(连接池方式)不能连接
3.RedisTemplate是线程安全的(spring-data-redis的操作接口)
4.ObjectMapper是线程安全的(外部序列化用到的)


[b]spring-data-redis Operations[/b]
spring-data-redis针对jedis提供了如下功能:
1. 连接池自动管理,提供了一个高度封装的“RedisTemplate”类
2. 针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口
ValueOperations:简单K-V操作
SetOperations:set类型数据操作
ZSetOperations:zset类型数据操作
HashOperations:针对map类型的数据操作
ListOperations:针对list类型的数据操作
3. 提供了对key的“bound”(绑定)便捷化操作API,可以通过bound封装指定的key,然后进行一系列的操作而无须“显式”的再次指定Key.
BoundValueOperations
BoundSetOperations
BoundListOperations
BoundSetOperations
BoundHashOperations

两者区别是一个进行set时要写key值(里面可以进行多个key的操作),一个不用(里面只可以进行一个key的操作)

ValueOperations<String, User> valueOper = redisTemplate.opsForValue(); //取得一个新的ValueOperations



[b]Spring-data-redis: serializer(序列化方式)[/b]
设置序列化方式(可以用内置的,也可以用别的)

spring-data-redis提供了多种serializer策略,这对使用jedis的开发者而言,实在是非常便捷。sdr提供了4种内置的serializer:
1.JdkSerializationRedisSerializer:使用JDK的序列化手段(serializable接口,ObjectInputStrean,ObjectOutputStream),数据以字节流存储
2.StringRedisSerializer:字符串编码,数据以string存储
3.JacksonJsonRedisSerializer:json格式存储
4.OxmSerializer:xml格式存储

[b]注意:[/b]
1.其中JdkSerializationRedisSerializer和StringRedisSerializer是最基础的序列化策略。
2.其中“JacksonJsonRedisSerializer”与“OxmSerializer”都是基于stirng存储,因此它们是较为“高级”的序列化(最终还是使用string解析以及构建java对象)。


RedisTemplate中需要声明4种serializer,默认为“JdkSerializationRedisSerializer”:
1) keySerializer :对于普通K-V操作时,key采取的序列化策略
2) valueSerializer:value采取的序列化策略
3) hashKeySerializer: 在hash数据结构中,hash-key的序列化策略
4) hashValueSerializer:hash-value的序列化策略

[b]注意:[/b]无论如何,建议key/hashKey采用StringRedisSerializer。


[b]例子:[/b]
redis.properties
# Redis settings
redis.host=127.0.0.1
redis.port=6379
redis.pass=

redis.maxIdle=300
redis.maxTotal=600
redis.maxWaitMillis=1000
redis.testOnBorrow=true



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: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:annotation-config />
<!-- <task:annotation-driven /> -->
<context:component-scan base-package="com.*" />

<context:property-placeholder location="classpath:redis.properties" />
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxTotal" value="${redis.maxTotal}" />
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
<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" />
<property name="keySerializer">
<bean
class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer">
<bean
class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
</property>
<!-- <property name="enableTransactionSupport" value="true" /> -->

</bean>
</beans>



User.java
package com.redis;
import java.io.Serializable;

public class User implements Serializable{
private static final long serialVersionUID = 1L;
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;
}

@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}

public User(long id, String name) {
super();
this.id = id;
this.name = name;
}

public User() {
super();
// TODO Auto-generated constructor stub
}
}



[b]使用内部JdkSerializationRedisSerializer工具进行序列化[/b]
main
package com.redis;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

public class SpringDataRedisTest {
public static void main(String[] args) throws InterruptedException {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/applicationContext.xml");

RedisTemplate redisTemplate = (RedisTemplate) applicationContext.getBean("redisTemplate");
System.out.println("redisTemplate == " + redisTemplate);

ValueOperations<String, User> valueOper = redisTemplate.opsForValue();
User u1 = new User(10, "zhangsan");
User u2 = new User(11, "lisi");
valueOper.set("u:u1", u1);
valueOper.set("u:u2", u2);

User User = valueOper.get("u:u1");
System.out.println("User == " + User.toString());
User User2 = valueOper.get("u:u2");
System.out.println("User2 == " + User2.toString());
}
}



[b]使用外部jackson工具进行序列化[/b]
1.因为使用内部的序列化工具创建ValueOperations时要指定对象的ClassType,用外部序列化工具可以全部基于String(接口统一),如
ValueOperations<String, User> valueOper = redisTemplate.opsForValue(); //取得一个新的ValueOperations,要指定User


main
package com.redis;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringDataRedisOtherJsonTest {
public static void main(String[] args) throws InterruptedException {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/applicationContext.xml");

RedisClientTest redisClientTest = (RedisClientTest) applicationContext.getBean("redisClientTest");
System.out.println("redisClientTest == " + redisClientTest);

User user1 = new User();
user1.setId(21);
user1.setName("obama21");
redisClientTest.insertUser(user1);
System.out.println("insertUser");

User user2 = redisClientTest.getUser(21);
System.out.println("user2 == " + user2.toString());

}
}


JsonRedisSeriaziler.java
package com.redis;
import java.io.IOException;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.stereotype.Service;

@Service("jsonRedisSeriaziler")
public class JsonRedisSeriaziler {
private ObjectMapper objectMapper = new ObjectMapper();

/**
* java-object as json-string
*
* @param object
* @return
*/
public String seriazileAsString(Object object) {
if (object == null) {
return null;
}

try {
return this.objectMapper.writeValueAsString(object);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

/**
* json-string to java-object
*
* @param str
* @return
*/
public <T> T deserializeAsObject(String str, Class<T> clazz) {
if (str == null || clazz == null) {
return null;
}
try {
return this.objectMapper.readValue(str, clazz);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

return null;
}
}


RedisClientTest.java
package com.redis;
import javax.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

@Service("redisClientTest")
public class RedisClientTest {

@Resource(name = "jsonRedisSeriaziler")
private JsonRedisSeriaziler seriaziler;

@Resource(name = "redisTemplate")
private RedisTemplate redisTemplate;

public void insertUser(User user) {
ValueOperations<String, String> operations = redisTemplate.opsForValue();
operations.set("user:" + user.getId(), seriaziler.seriazileAsString(user));
}

public User getUser(long id) {
ValueOperations<String, String> operations = redisTemplate.opsForValue();
String json = operations.get("user:" + id);
System.out.println("json ==" + json);
return seriaziler.deserializeAsObject(json, User.class);
}
}


参考原文:[url]http://shift-alt-ctrl.iteye.com/blog/1886831[/url]


[b]Spring-data-redis事务[/b]
1.enableTransactionSupport:是否启用事务支持。要在XML文件中进行配置(StringRedisTemplate的属性)
2.enableTransactionSupport为true时,系统自动帮我们拿到了事务中绑定的连接。可以在一个方法的多次对Redis增删该查中,始终使用同一个连接。
但是,即使使用了同样的连接,没有进行connection.multi()和connection.exec(),依然是无法启用事务的。
3.sdr提供SessionCallback接口用于同线程的多操作执行。(同一个连接)

非连接池环境下,事务操作;对于sdr而言,每次操作(例如,get,set)都有会从pool中获取connection;
因此在连接池环境下,使用事务需要注意。
public void saveNoPoolUser(final User user) {
redisTemplate.watch("user:" + user.getId());
redisTemplate.multi();
ValueOperations<String, String> tvo = redisTemplate.opsForValue();
tvo.set("user:" + user.getId(), seriaziler.seriazileAsString(user));
redisTemplate.exec();
}


在连接池环境中,需要借助sessionCallback来绑定connection
public void savePoolUser(final User user) {
SessionCallback<User> sessionCallback = new SessionCallback<User>() {
@Override
public User execute(RedisOperations operations) throws DataAccessException {
operations.multi();
String key = "user:" + user.getId();
ValueOperations<String, String> oper = operations.opsForValue();
oper.set(key,seriaziler.seriazileAsString(user));
operations.exec();
return user;
}
};
redisTemplate.execute(sessionCallback);
}


SpringDataRedisTransactional.java
package com.redis;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringDataRedisTransactional {
public static void main(String[] args) throws InterruptedException {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/applicationContext.xml");

RedisClientTest redisClientTest = (RedisClientTest) applicationContext.getBean("redisClientTest");
System.out.println("redisClientTest == " + redisClientTest);

User user1 = new User();
user1.setId(33);
user1.setName("obama31 55");
redisClientTest.savePoolUser(user1);
System.out.println("insertUser");

User user2 = redisClientTest.getUser(33);
System.out.println("user2 == " + user2.toString());

}
}


RedisClientTest.java
package com.redis;
import javax.annotation.Resource;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("redisClientTest")
public class RedisClientTest {

@Resource(name = "jsonRedisSeriaziler")
private JsonRedisSeriaziler seriaziler;

@Resource(name = "redisTemplate")
private RedisTemplate redisTemplate;

public void insertUser(User user) {
ValueOperations<String, String> operations = redisTemplate.opsForValue();
operations.set("user:" + user.getId(), seriaziler.seriazileAsString(user));
}

public User getUser(long id) {
ValueOperations<String, String> operations = redisTemplate.opsForValue();
String json = operations.get("user:" + id);
System.out.println("json ==" + json);
return seriaziler.deserializeAsObject(json, User.class);
}

public void savePoolUser(final User user) {
SessionCallback<User> sessionCallback = new SessionCallback<User>() {
@Override
public User execute(RedisOperations operations) throws DataAccessException {
operations.multi();
String key = "user:" + user.getId();
ValueOperations<String, String> oper = operations.opsForValue();
oper.set(key, seriaziler.seriazileAsString(user));
operations.exec();
return user;
}
};
redisTemplate.execute(sessionCallback);
}

public void saveNoPoolUser(final User user) {
redisTemplate.watch("user:" + user.getId());
redisTemplate.multi();
ValueOperations<String, String> tvo = redisTemplate.opsForValue();
tvo.set("user:" + user.getId(), seriaziler.seriazileAsString(user));
redisTemplate.exec();
}
}



[b]Pipeline[/b]
1.就是先将命令缓存起来,到时一次打包发送到redis服务器进行处理
2.通过pipeline方式当有大批量的操作时候,我们可以节省很多原来浪费在网络延迟的时间,需要注意到是用pipeline方式打包命令发送,
redis必须在处理完所有命令前先缓存起所有命令的处理结果。打包的命令越多,缓存消耗内存也越多。所以并不是打包的命令越多越好。


[b]如果存储的是数字(当然值的序列化方式要先用StringRedisSerializer否则不能用increment)[/b]
package com.redis;

import java.io.Serializable;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

public class SpringDataRedisTestLong {
public static void main(String[] args) throws InterruptedException {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/applicationContext.xml");

RedisTemplate redisTemplate = (RedisTemplate) applicationContext.getBean("redisTemplate");
System.out.println("redisTemplate == " + redisTemplate);

ValueOperations<String, Serializable> valueOper = redisTemplate.opsForValue();
long i = 10245;
valueOper.set("u:u53", String.valueOf(i));

System.out.println("redisTemplate == 100");
valueOper.increment("u:u53", 3L);//负数实现减操作
System.out.println("redisTemplate == 100");

String User = (String) valueOper.get("u:u53");
System.out.println("User == " + User);

long j =Long.parseLong(User);
System.out.println("j == " + j);
}
}


参考原文:[url]http://www.cnblogs.com/luochengqiuse/p/4640932.html[/b][/url]
参考原文:[url]http://shift-alt-ctrl.iteye.com/blog/1887370[/url]
参考原文:[url]http://shift-alt-ctrl.iteye.com/blog/1886831[/url]
参考原文(性能对比):[url]http://blog.csdn.net/u010739551/article/details/48165063[/url]

[b]所用到的jar包如下:[/b]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jie310600

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值