Redis中在程序中的应用

1、导入redis的配置文件,因为要交给web容器管理,所以直接命名为ApplicationContext-redis.xml,具体配置如下:

  

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

	<!-- 构建连接池配置信息 -->
	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<!-- 最大连接数 -->
		<property name="maxTotal" value="${redis.maxTotal}" />
	</bean>
    
	<bean id="jedisShardInfo1" class="redis.clients.jedis.JedisShardInfo">
		<constructor-arg index="0" value="${redis.node1.ip}" />
		<constructor-arg index="1" value="${redis.node1.port}"
			type="int" />
	</bean>

	<bean id="jedisShardInfo2" class="redis.clients.jedis.JedisShardInfo">
		<constructor-arg index="0" value="${redis.node2.ip}" />
		<constructor-arg index="1" value="${redis.node2.port}"
			type="int" /> <!-- 端口必须为int类型,如果不写的话,默认是字符串类型,这是时候不起作用,所以端口就是默认端口,会造成分片失败 -->
	</bean>

	<bean id="jedisShardInfo3" class="redis.clients.jedis.JedisShardInfo">
		<constructor-arg index="0" value="${redis.node3.ip}" />
		<constructor-arg index="1" value="${redis.node3.port}"
			type="int" />
	</bean>

	<!-- 定义集群连接池 -->
	<bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool"
		destroy-method="close">
		<constructor-arg index="0" ref="jedisPoolConfig" />
		<constructor-arg index="1">
			<list>
				<ref bean="jedisShardInfo1" />
				<ref bean="jedisShardInfo2" />
				<ref bean="jedisShardInfo3"/>
			</list>
		</constructor-arg>
	</bean>

</beans>

  需要说明的是,这里是通过jedis进行操作的(jedis即java版的redis)

2、写伪service工具类

  伪service--封装一个新的技术,融合进业务,而不是真正的业务层需要,但是本质还是service,目的是为了在controller中注入方便。经过伪service封装可以屏蔽掉底层的api

  

package com.jt.common.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;

@Service
public class RedisService {

	//有的工程需要,有的工程不需要。设置required=false,有就注入,没有就不注入。
    @Autowired(required = false)
    private ShardedJedisPool shardedJedisPool;

    private <T> T execute(Function<ShardedJedis, T> function) {
        ShardedJedis shardedJedis = null;
        try {
            // 从连接池中获取到jedis分片对象
            shardedJedis = shardedJedisPool.getResource();
            return function.execute(shardedJedis);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != shardedJedis) {
                // 关闭,检测连接是否有效,有效则放回到连接池中,无效则重置状态
                shardedJedis.close();
            }
        }
        return null;
    }

    /**
     * 保存数据到redis中
     *
     * @param key
     * @param value
     * @return
     */
    public String set(final String key, final String value) {
        return this.execute(new Function<ShardedJedis, String>() {
            @Override
            public String execute(ShardedJedis shardedJedis) {
                return shardedJedis.set(key, value);
            }

        });
    }

    /**
     * 保存数据到redis中,生存时间单位是:秒
     *
     * @param key
     * @param value
     * @param seconds
     * @return
     */
    public String set(final String key, final String value, final Integer seconds) {
        return this.execute(new Function<ShardedJedis, String>() {
            @Override
            public String execute(ShardedJedis shardedJedis) {
                String result = shardedJedis.set(key, value);
                shardedJedis.expire(key, seconds);//设置生存时间
                return result;
            }

        });
    }

    /**
     * 从redis中获取数据
     *
     * @param key
     * @return
     */
    public String get(final String key) {
        return this.execute(new Function<ShardedJedis, String>() {
            @Override
            public String execute(ShardedJedis shardedJedis) {
                return shardedJedis.get(key);
            }

        });
    }

    /**
     * 设置key生存时间,单位:秒
     *
     * @param key
     * @param seconds
     * @return
     */
    public Long expire(final String key, final Integer seconds) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.expire(key, seconds);
            }

        });
    }

    /**
     * 从redis中删除数据
     *
     * @param key
     * @return
     */
    public Long del(final String key) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.del(key);
            }
        });
    }

}

 3、在对应的执行业务的service中添加缓存方法

  我这里因为是要做的查询的一个三级树目录,通过点击前台页面的父选项,传递父ID给后台,查询对应的子类,并将子类集合返回

  原代码如下:

  

package com.jt.manage.service;

import java.io.IOException;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jt.common.service.BaseService;
import com.jt.common.service.RedisService;
import com.jt.manage.mapper.ItemCatMapper;
import com.jt.manage.pojo.ItemCat;

@Service
public class ItemCatService extends BaseService<ItemCat> {
	@Autowired
	private ItemCatMapper itemCatMapper;

	public List<ItemCat> findItemCarList(Long parentId) {
          itemCat.setParentId(parentId);
<!--这里采用的是JPA的方式,自动构建sql语句,查询的时候如果传入的是对象,那么会根据对象的属性当做where条件进行对应的匹配-->
          return   itemCatMapper.select(itemCat);

}

修改后的代码如下:

  

package com.jt.manage.service;

import java.io.IOException;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jt.common.service.BaseService;
import com.jt.common.service.RedisService;
import com.jt.manage.mapper.ItemCatMapper;
import com.jt.manage.pojo.ItemCat;

@Service
public class ItemCatService extends BaseService<ItemCat> {
	@Autowired
	private ItemCatMapper itemCatMapper;

	@Autowired
	private RedisService redisService;

	private static final ObjectMapper MAPPER = new ObjectMapper();

	public List<ItemCat> findItemCarList(Long parentId) {

		/*
		 * 如果传入的是对象,查询时就会根据对象的属性值添加where条件 写null表示不需要where条件
		 */
		ItemCat itemCat = new ItemCat();

		/*
		 * 1、在执行业务前判断缓存总是否所有数据,如果有数据,就获取数据,直接返回结果
		 * 2、如果没有数据,继续执行业务,访问数据库,获取返回的值
		 * 3、再返回业务之前,把获取的数据在缓存中存放一份,然后再返回
		 * 4、放缓存:kv(String) 把java对象变成json字符串
		 * 5、拿缓存:把字符串转换成java对象List<ItemCat>
		 */
		itemCat.setParentId(parentId);
		// 判断缓存中有无数据
		// 定义键
		String ITEM_CAT_KEY = "ITEM_CAT_" + parentId;
		// 根据键获取数据
		String jsonData = redisService.get(ITEM_CAT_KEY);
		if (StringUtils.isNotEmpty(jsonData)) { // 缓存中有数据
			try {
				// 直接从缓存中获取数据,把json串转换为java对象
				JsonNode jsonNode = MAPPER.readTree(jsonData);

				Object obj = null;
				if (jsonNode.isArray() && jsonNode.size() > 0) {
					obj = MAPPER.readValue(jsonNode.traverse(),
							MAPPER.getTypeFactory().constructCollectionType(List.class, ItemCat.class));
				return (List<ItemCat>) obj;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else {//如果缓存中没有数据,执行业务
			try {
			//从数据库中获取数据
			List<ItemCat> itemCatList = itemCatMapper.select(itemCat);
			//将数据保存一份在缓存中
				//将数据转换成json对象
				String json = MAPPER.writeValueAsString(itemCatList);
				//将对象保存进缓存
				redisService.set(ITEM_CAT_KEY, json);
			//返回需要的对象
			return itemCatList;
			} catch (JsonProcessingException e) {
				e.printStackTrace();
			}
		}
		return null;
	}
}
时间: 2024-11-05 13:41:25

Redis中在程序中的应用的相关文章

redis总结(一) -- php中redis的使用

经常用到redis,但基本上都是基于集成开发环境,redis的连接也是基于框架自身,总感觉缺点什么,恰好在ubuntu系统中apt-get并不直接提供php的redis扩展,借此机会总结了下redis对php的支持 如果想想要在程序中使用redis,那么要有两个先决条件,第一要安装redis程序,第二要使redis支持php 这里主要谈一下redis对php的支持,我们常见的有两种 1.phpredis(实现方式:php扩展,c语言) 特点:需要我们在开发环境中安装php扩展,使用比较方便,缺点

redis在asp.net 中的应用

1.redis介绍 Nosql数据库作为关系型数据库的补充,在互联网公司已经得到广泛的运用.redis便是其中的代表之一,redis是一种(key,value)基于内存的数据库,并支持多种数据结构,如List,HashSet,string等,并能够支持的数据的持久化存储,redis如何做内存数据到磁盘的同步将分单独的章节讲解.既然redis是基于内存的数据库,那么它将应用在对性能要求高的场合,如做数据缓存,可以减少数据库访问的压力.同时redis可以应用在统计分析类的Web应用,统计分析类Web

redis入门指南书中概要

一.简介 1.redis是一个开源的.高性能的.基于键值对的缓存和存储系统,通过提供多种键值数据类型适应不同场景下的缓存和存储需求,同时redis高级功能能胜任消息队列.任务队列等不同角色. 2.内存存储与持久化:redis中所有数据都存储在内存中.但有问题,程序退出的时候内存中的数据会丢失,不过redis提供对持久化的支持,即将内存中的数据异步写入到硬盘中,不影响提供服务. 3.redis可以为每个键设置生存时间,到期后会自动删除,这一功能让redis成为了出色的缓存系统.作为缓存系统,red

Redis在WEB开发中的应用与实践

一.Redis概述: Redis是一个功能强大.性能高效的开源数据结构服务器,Redis最典型的应用是NoSQL.但事实上Redis除了作为NoSQL数据库使用之外,还能广泛应用消息队列,数据堆栈以及数据缓存等众多场合.Redis与Memcached相类似,都是以键值对(key-value)存放数据的,但是Redis支持的数据类型及特性远比Memcached丰富. 在缓存应用方面,Redis同样也是一个内存数据库,拥有Memcached的快速.稳定等特性,并且支持数据快照功能,开发人员可以通过配

三分钟学会Redis在.NET Core中做缓存中间件

原文:三分钟学会Redis在.NET Core中做缓存中间件 大家好,今天给大家说明如何在.NET Core中使用Redis,我们在想要辩论程序的好与坏,都想需要一个可视化工具,我经常使用的是一位国内大牛开发的免费工具,其Github地址为: https://github.com/qishibo/AnotherRedisDesktopManager/releases ,它真的很给力,Redis的安装在 https://github.com/MicrosoftArchive/redis/relea

在Android程序中使用已有的SQLite数据库

已经将这篇文章迁移至 Code问答,你也能够到这里查看这篇文章,请多多关注我的新技术博客CodeWenDa.com 在中文搜索中,没有找到一篇比較好的关于怎样在Android应用中使用自己事先创建好的数据库的文章,于是在谷歌上找到这篇英文文章,依照它的步骤,測试成功.决定把这篇文章大致的翻译一下,想看原文的能够点击这里:http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/ .

如何给程序中的变量起个好名字

新手程序员总是把大量的时间用在学习编程语言上,学习语法,技术和开发工具,他们认为如果掌握了这些就是一个优秀的程序员.但是,实际的编程不仅是要精通技术和工具,关键是要对某个特定领域的问题给出解决方案,而且通常要和其他程序员一起合作完成.因此,很重要的一点就是,程序员要用代码准确的表达出自己的思想,从而让其他人明白程序的含义. 编程大师Robert C. Martin在<Clean Code>中说道:“使用注释是为了弥补我们代码表意上的不足.”这句话就意味着如果你的代码需要添加注释,就说明你的代码

C程序中让两个不同版本的库共存

原文连接:http://blog.gotocoding.com/archives/875 今天有同学提出,如何在一个C程序中让两个不同版本的库共存. 首先想到的方案是,把其中一个版本的库函数全部重命名,比如把每一个函数名都加一个_v2的后缀. 人工替换到没什么,但是如果函数个数超过10个,就有点不拿人当人使了. 而使有工具去替换就会遇到一些棘手的问题,如何识别哪些是函数,哪些是系统函数(系统函数不需要添加后缀)等. 随后想到的另一个解决方案是C++的方案,为其中一个版本库中的所有文件添加命名空间

C#中的程序集和命名空间

C#中的程序集和命名空间 如果说命名空间是类库的逻辑组织形式,那么程序集就是类库的物理组织形式.只有同时指定类型所在的命名空间及实现该类型的程序集,才能完全限定该类型.<精通.NET核心技术--原理与架构> 程序集和命名空间不存在必然联系,一个程序集可以包含多个命名空间,同一个命名空间也可以分放在几个程序集. 程序集是应用程序的部署单元..NET应用程序包含一个或多个程序集.通常扩展名是EXE或DLL 的.NET可执行程序称为程序集..NET程序集包含元数据,这些元数据描述了程序集中定义的所有