您的位置:首页 > 数据库 > Redis

redis做缓存的简单实例

2017-04-19 08:46 281 查看
由于之前对redis有了一个系统的研究,在公司的多个项目中使用redis当做数据缓存;所以趁着这些天晚上的时间,自己写了一个demo;这里仅供自己后期学习笔记参考,若有不对的地方,请轻拍砖!

redis 官网推荐给java 使用的客户端很多:Jedis、Redisson、JRedis、JDBC-Redis 等,当然首推是jedis;可以参考redis客户端官网查看。

接下来来讲下我的这个demo,我这个案例不是通过spring进行整合的redis,这个将会在之后的demo中讲到的。

(1).创建一个maven 功臣,在工程的pom 中引入jedis客户端;还有要依赖spring管理,所以也要引入spring相关jar包。

[html] view
plain copy

<span style="white-space:pre"> </span><dependency>

<groupId>redis.clients</groupId>

<artifactId>jedis</artifactId>

<version>${jedis-version}</version>

</dependency>

<dependency>

(2).一般一个(系统)项目所用的redis服务器 多节点的集群服务器,所以会自己对(jedis)redis客户端进行封装,由于本例我自己写的是单节点,但是我还是按多节点的思路对客户端进行了封装。

redisClient类

[java] view
plain copy

/**

* redis 客户端封装

* @author leo

*

*/

public class RedisClient {

/**

* 日志记录

*/

private static final Log LOG = LogFactory.getLog(RedisClient.class);

/**

* redis 连接池

*/

private JedisPool pool;

public void setPool(JedisPool pool) {

this.pool = pool;

}

/**

* 获取jedis

* @return

*/

public Jedis getResource(){

Jedis jedis =null;

try {

jedis =pool.getResource();

} catch (Exception e) {

LOG.info("can't get the redis resource");

}

return jedis;

}

/**

* 关闭连接

* @param jedis

*/

public void disconnect(Jedis jedis){

jedis.disconnect();

}

/**

* 将jedis 返还连接池

* @param jedis

*/

public void returnResource(Jedis jedis){

if(null != jedis){

try {

pool.returnResource(jedis);

} catch (Exception e) {

LOG.info("can't return jedis to jedisPool");

}

}

}

/**

* 无法返还jedispool,释放jedis客户端对象,

* @param jedis

*/

public void brokenResource(Jedis jedis){

if (jedis!=null) {

try {

pool.returnBrokenResource(jedis);

} catch (Exception e) {

LOG.info("can't release jedis Object");

}

}

}

}

然后 通过spring的bean.xml 来管理 连接池,和连接池参数配置,以及redisClient 的依赖注入。

[html] view
plain copy

<!-- jedis 连接池配置参数: -->

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

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

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

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

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

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

</bean>

<!-- jedis 连接池 连接本地redis服务 构造器注入-->

<bean id="pool" class="redis.clients.jedis.JedisPool">

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

<constructor-arg index="1" value="10.224.68.46"/>

<constructor-arg index="2" value="6379"/>

<constructor-arg index="3" value="2000"/>

</bean>

<!-- cleint-->

<bean id="redisClient" class="com.deppon.cache.redis.RedisClient">

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

</bean>

(3).创建好redisClient 之后,我要创造一个存储器,即一个对redis操作的工具容器。由于是公共容器,所以我创建接口是的容器接口就不该是封闭的,应该是开封的,保证存入数据库中对象类型的多态性。

存储器接口:

[java] view
plain copy

/**

*

* @author leo

*缓存存储接口

* @param <K> key

* @param <V> value

*/

public interface RedisCacheStorage<K, V> {

/**

* 在redis数据库中插入 key 和value

* @param key

* @param value

* @return

*/

boolean set(K key,V value);

/**

* 在redis数据库中插入 key 和value 并且设置过期时间

* @param key

* @param value

* @param exp 过期时间 s

* @return

*/

boolean set(K key, V value, int exp);

/**

* 根据key 去redis 中获取value

* @param key

* @return

*/

V get(K key);

/**

* 删除redis库中的数据

* @param key

* @return

*/

boolean remove(K key);

/**

* 设置哈希类型数据到redis 数据库

* @param cacheKey 可以看做一张表

* @param key 表字段

* @param value

* @return

*/

boolean hset(String cacheKey,K key,V value);

/**

* 获取哈希表数据类型的值

* @param cacheKey

* @param key

* @return

*/

V hget(String cacheKey,K key);

/**

* 获取哈希类型的数据

* @param cacheKey

* @return

*/

Map<K,V> hget(String cacheKey);

以及存储实现类:

[java] view
plain copy

/**

* redis 缓存存储器实现

* @author leo

*

* @param <V>

*/

public class RedisCacheStorageImpl<V> implements RedisCacheStorage<String, V> {

/**

* 日志记录

*/

public static final Log LOG = LogFactory.getLog(RedisCacheStorageImpl.class);

/**

* redis 客户端

*/

private RedisClient redisClient;

/**

* 默认过时时间

*/

private static final int EXPRIE_TIME =3600*24;

public void setRedisClient(RedisClient redisClient) {

this.redisClient = redisClient;

}

/**

* 在redis数据库中插入 key 和value

* @param key

* @param value

* @return

*/

@Override

public boolean set(String key, V value) {

//设置默认过时时间

return set(key, value, EXPRIE_TIME);

}

/**

* 在redis数据库中插入 key 和value 并且设置过期时间

* @param key

* @param value

* @param exp 过期时间 s

* @return

*/

@SuppressWarnings("finally")

@Override

public boolean set(String key, V value, int exp) {

Jedis jedis =null;

//将key 和value 转换成 json 对象

String jKey =CacheUtils.toJsonString(key);

String jValue =CacheUtils.toJsonString(value);

//操作是否成功

boolean isSucess =true;

if(StringUtils.isNotEmpty(jKey)){

LOG.info("key is empty");

return false;

}

try {

//获取客户端对象

jedis =redisClient.getResource();

//执行插入

jedis.setex(jKey, exp, jValue);

} catch (JedisException e) {

LOG.info("client can't connect server");

isSucess =false;

if(null !=jedis){

//释放jedis对象

redisClient.brokenResource(jedis);

}

return false;

}finally{

if(isSucess){

//返还连接池

redisClient.returnResource(jedis);

}

return true;

}

}

/**

* 根据key 去redis 中获取value

* @param key

* @return

*/

@SuppressWarnings("unchecked")

@Override

public V get(String key) {

Jedis jedis =null;

//将key 和value 转换成 json 对象

String jKey =CacheUtils.toJsonString(key);

V jValue =null;

//key 不能为空

if(StringUtils.isEmpty(jKey)){

LOG.info("key is empty");

return null;

}

try {

//获取客户端对象

jedis =redisClient.getResource();

//执行查询

String value = jedis.get(jKey);

//判断值是否非空

if(StringUtils.isEmpty(value)){

return null;

}else{

jValue= (V) CacheUtils.jsonParseObject(value);

}

//返还连接池

redisClient.returnResource(jedis);

} catch (JedisException e) {

LOG.info("client can't connect server");

if(null !=jedis){

//释放jedis 对象

redisClient.brokenResource(jedis);

}

}

return jValue;

}

/**

* 删除redis库中的数据

* @param key

* @return

*/

@SuppressWarnings("finally")

@Override

public boolean remove(String key) {

Jedis jedis =null;

//将key 和value 转换成 json 对象

String jKey =CacheUtils.toJsonString(key);

//操作是否成功

boolean isSucess =true;

if(StringUtils.isEmpty(jKey)){

LOG.info("key is empty");

return false;

}

try {

jedis =redisClient.getResource();

//执行删除

jedis.del(jKey);

} catch (JedisException e) {

LOG.info("client can't connect server");

isSucess =false;

if(null !=jedis){

//释放jedis 对象

redisClient.brokenResource(jedis);

}

return false;

}finally{

if (isSucess) {

//返还连接池

redisClient.returnResource(jedis);

}

return true;

}

}

/**

* 设置哈希类型数据到redis 数据库

* @param cacheKey 可以看做一张表

* @param key 表字段

* @param value

* @return

*/

@SuppressWarnings("finally")

@Override

public boolean hset(String cacheKey, String key, V value) {

Jedis jedis =null;

//将key 和value 转换成 json 对象

String jKey =CacheUtils.toJsonString(key);

String jCacheKey =CacheUtils.toJsonString(cacheKey);

String jValue =CacheUtils.toJsonString(value);

//操作是否成功

boolean isSucess =true;

if(StringUtils.isEmpty(jCacheKey)){

LOG.info("cacheKey is empty");

return false;

}

try {

jedis =redisClient.getResource();

//执行插入哈希

jedis.hset(jCacheKey, jKey, jValue);

} catch (JedisException e) {

LOG.info("client can't connect server");

isSucess =false;

if(null !=jedis){

//释放jedis 对象

redisClient.brokenResource(jedis);

}

return false;

}finally{

if (isSucess) {

//返还连接池

redisClient.returnResource(jedis);

}

return true;

}

}

/**

* 获取哈希表数据类型的值

* @param cacheKey

* @param key

* @return

*/

@SuppressWarnings("unchecked")

@Override

public V hget(String cacheKey, String key) {

Jedis jedis =null;

//将key 和value 转换成 json 对象

String jKey =CacheUtils.toJsonString(key);

String jCacheKey =CacheUtils.toJsonString(cacheKey);

V jValue =null;

if(StringUtils.isEmpty(jCacheKey)){

LOG.info("cacheKey is empty");

return null;

}

try {

//获取客户端对象

jedis =redisClient.getResource();

//执行查询

String value = jedis.hget(jCacheKey, jKey);

//判断值是否非空

if(StringUtils.isEmpty(value)){

return null;

}else{

jValue= (V) CacheUtils.jsonParseObject(value);

}

//返还连接池

redisClient.returnResource(jedis);

} catch (JedisException e) {

LOG.info("client can't connect server");

if(null !=jedis){

//释放jedis 对象

redisClient.brokenResource(jedis);

}

}

return jValue;

}

/**

* 获取哈希类型的数据

* @param cacheKey

* @return

*/

@Override

public Map<String, V> hget(String cacheKey) {

String jCacheKey =CacheUtils.toJsonString(cacheKey);

//非空校验

if(StringUtils.isEmpty(jCacheKey)){

LOG.info("cacheKey is empty!");

return null;

}

Jedis jedis =null;

Map<String,V> result =null;

try {

jedis =redisClient.getResource();

//获取列表集合

Map<String,String> map = jedis.hgetAll(jCacheKey);

if(null !=map){

for(Map.Entry<String, String> entry : map.entrySet()){

if(result ==null){

result =new HashMap<String,V>();

}

result.put((String) CacheUtils.jsonParseObject(entry.getKey()), (V)CacheUtils.jsonParseObject(entry.getValue()));

}

}

} catch (JedisException e) {

LOG.info("client can't connect server");

if(null !=jedis){

//释放jedis 对象

redisClient.brokenResource(jedis);

}

}

return result;

}

}

(4),接下来要把写个具体的业务UserService,来测试redis的存储器在具体业务中的使用,即实现(非关系型数据库的持久化操作)。本例中的例子是经常项目中对user的操作

创建UserEntity实体类:

[java] view
plain copy

/**

* 用户实体类

* @author leo

*

*/

public class UserEntity {

//用户id

private String userId;

//用户账号

private String EmpCode;

//用户名称

private String EmpName;

//用户角色

private String role;

//职位

private String title;

public String getUserId() {

return userId;

}

public void setUserId(String userId) {

this.userId = userId;

}

public String getEmpCode() {

return EmpCode;

}

public void setEmpCode(String empCode) {

EmpCode = empCode;

}

public String getEmpName() {

return EmpName;

}

public void setEmpName(String empName) {

EmpName = empName;

}

public String getRole() {

return role;

}

public void setRole(String role) {

this.role = role;

}

public String getTitle() {

return title;

}

public void setTitle(String title) {

this.title = title;

}

然后创建用户操作的业务层Service;由于这里主要是测试NOSQL的数据持久化,所以就忽略了对数据库持久化层(DAO)的操作。

userServiceImpl类:

[java] view
plain copy

/**

* 业务层接口实现

* @author leo

*

*/

public class UserServiceImpl implements IUserService {

private static final String cacheKey ="userEntity";

/**

* 缓存存储

*/

private RedisCacheStorageImpl<UserEntity> storageCache;

public void setStorageCache(RedisCacheStorageImpl<UserEntity> storageCache) {

this.storageCache = storageCache;

}

/**

* 新增

* @param entity

* @return

*/

@Override

public boolean addUserEntity(UserEntity entity) {

//非空

if(entity ==null || StringUtils.isEmpty(entity.getUserId())){

return false;

}

/**

* 做数据库持久化,这里就无需再申明了

*/

System.out.println("先插入数据库中,.........");

//然后接下来做非关系型数据库持久化

return storageCache.hset(cacheKey, entity.getUserId(), entity);

}

@Override

public boolean deleteUserEntity(UserEntity entity) {

return false;

}

/**

* 根据id 查询

* @return

*/

@Override

public UserEntity queryUserEntityByUserId(UserEntity userEntity) {

//非空

if(userEntity ==null || StringUtils.isEmpty(userEntity.getUserId())){

return null;

}

//先去缓存中查询 是否存在,不存在在查询

UserEntity reslut = storageCache.hget(cacheKey, userEntity.getUserId());

if(reslut!=null){

return reslut;

}else{

//查询数据库

System.out.println("查询数据库");

}

return null;

}

}

以及spring-bean.xml的配置对业务层的管理:

[html] view
plain copy

<!-- storge Cache 存储器-->

<bean id="storageCache" class="com.deppon.cache.storage.impl.RedisCacheStorageImpl">

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

</bean>

<bean id="userServiceImpl" class="com.deppon.cache.service.impl.UserServiceImpl">

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

</bean>

(6).最后写个junit 测下,查看是否有没有插入到redis库中

[html] view
plain copy

public class TestUserServiceImpl {

/**

* 用户接口

*/

private IUserService userServiceImpl;

public void setUserServiceImpl(IUserService userServiceImpl) {

this.userServiceImpl = userServiceImpl;

}

@Before

public void setUp() throws Exception {

userServiceImpl = (IUserService) SpringTestHelper.get().getBeanByClass(UserServiceImpl.class);

}

@After

public void tearDown() throws Exception {

}

@Test

public void testAdd(){

UserEntity entity = new UserEntity();

entity.setUserId("000001");

entity.setEmpCode("130566");

entity.setEmpName("leonardo-zeng");

entity.setRole("Java Development Engineer");

entity.setTitle("PM");

boolean isTrue =userServiceImpl.addUserEntity(entity);

Assert.assertTrue(isTrue);

}

@Test

public void testQueryById(){

UserEntity entity = new UserEntity();

entity.setUserId("000001");

UserEntity userEntity =userServiceImpl.queryUserEntityByUserId(entity);

System.out.println(userEntity);

}

}

连接redis库,查询出来的确值在库中存在

redis 127.0.0.1:6379> hkeys "\"userEntity\""

1) "\"000001\""

redis 127.0.0.1:6379> hget "\"userEntity\"" "\"000001\""

"{\"@type\":\"com.deppon.cache.entity.UserEntity\",\"empCode\":\"130566\",\"empN

ame\":\"leonardo-zeng\",\"role\":\"Java Development Engineer\",\"title\":\"PM\",

\"userId\":\"000001\"}"

redis 127.0.0.1:6379>

整个demo就这样了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: