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;
	}
}
原文地址:https://www.cnblogs.com/sxpy-lj/p/7290466.html