欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SSM框架上集合Redis技术

程序员文章站 2022-05-19 14:46:01
...

为了完成毕业设计,将之前做的电商网站进行整改,目前需要整合上Redis,说明一下步骤,为到时候答辩做个笔记

前言:Redis简介(简单概述)

  • key-value存储系统
  • 支持string,list链表,set集合,hash表
  • 符合原子性(成功则提交,失败则回滚),要么就完成,要么就不完成,当作什么都没做,就是一定要完成一整套的操作,不可中途退出
  • 无需考虑多线程的并发问题
  • 缓存在内存中

以上是一些简述,我只用到这些,用到哪些写哪些,没用过的就没有写,(写上也不一定会用,额,到时候再补充)

第一步:下载Redis(跟没说一样,但是这里有关于Redis闪退的问题)

安装好Redis后,打开Redis服务有时会发现弹出一个窗口就闪退;

  • 目前已知的原因只发现一个:已经有Redis进程在启动

       解决方案:任务管理器  ----->  找到Redis进程 -----> 结束关闭它  ----->  再次重启

  • 还有一种情况闪退,有解决方案,但是还没弄清问题产生的原因,所以先放上解决方案:

    更改redis文件夹中的 redis.windows.conf

    #bind 127.0.0.1 去掉#

    然后重启Redis,或者CMD上 cd 到 Redis存储路径  执行  redis-server.exe redis.windows.conf

    有的时候还是会报错,讲道理,这里真不知道为什么!!(百度了好久,看来还是不够认真)

    如果还有错,那就这样:

    redis-cli.exe  ----->   shutdown   ----->    exit  ----->   edis-server.exe redis.windows.conf

    依次执行命令行,难受(希望有人告诉我),额,继续整合步骤!

第二步:编写Redis配置文件(redis.properties、spring-redis.xml)

这里说明一下redis.properties。后续会有SpringBoot的更换,换成yml的格式,先说一下,以免到时候忘掉

还有,我的配置文件目录形式如下:

SSM框架上集合Redis技术

将spring的配置文件放入spring文件夹中,方便管理,在spring-dao.xml中,这里加载了redis.properites的配置:

<bean class="com.zhaoyu.shop.util.EncryptPropertyPlaceholderConfigurer">
	<property name="locations">
		<list>
			<value>classpath:jdbc.properties</value>
			<value>classpath:redis.properties</value>
		</list>
	</property>
	<property name="fileEncoding" value="UTF-8" />
</bean>

这里一个是jdbc的配置,一个是redis的配置;

  • redis.properties的编写:
redis.hostname=127.0.0.1
redis.port=6379
redis.database=0
redis.pool.maxActive=600
redis.pool.maxIdle=300
redis.pool.maxWait=3000
redis.pool.testOnBorrow=true

这里不做过多的说明了,强调一下默认端口号 6379 (之前被问过,竟然忘了。。)

这个properties的编写和数据库连接(jdbc.properties)的一样

  • spring-redis.xml的编写
  • <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    	<!-- Redis连接池的设置 -->
    	<bean id="jedisPoolConfig"
    		class="redis.clients.jedis.JedisPoolConfig">
    		<!-- 控制一个pool可分配多少个Jedis实例 -->
    		<property name="maxTotal" value="${redis.pool.maxActive}" />
    		<!-- 连接池中最多可空闲maxIdle个连接,这里取值为20,表示即使没有数据库连接时依然可以保持20个空闲的连接,而不被清除,随时处于待命状态 -->
    		<property name="maxIdle" value="${redis.pool.maxIdle}" />
    		<!-- 最大连接时间,当没有可用连接时 -->
    		<property name="maxWaitMillis" value="${redis.pool.maxWait}" />
    		<!-- 在获取连接时检查有效性 -->
    		<property name="testOnBorrow"
    			value="${redis.pool.testOnBorrow}" />
    	</bean>
    	<!-- 创建Redis连接池,并作相关配置 -->
    	<bean id="jedisWritePool"
    		class="com.zhaoyu.shop.cache.JedisPoolWriper"
    		depends-on="jedisPoolConfig">
    		<constructor-arg index="0" ref="jedisPoolConfig" />
    		<constructor-arg index="1" value="${redis.hostname}" />
    		<constructor-arg index="2" value="${redis.port}"
    			type="int" />
    	</bean>
    	<bean id="jedisKeys" class="com.zhaoyu.shop.cache.JedisUtil$Keys"
    		scope="singleton">
    		<constructor-arg ref="jedisUtil"></constructor-arg>
    	</bean>
    	<bean id="jedisStrings"
    		class="com.zhaoyu.shop.cache.JedisUtil$Strings" scope="singleton">
    		<constructor-arg ref="jedisUtil"></constructor-arg>
    	</bean>
    	<bean id="jedisLists"
    		class="com.zhaoyu.shop.cache.JedisUtil$Lists" scope="singleton">
    		<constructor-arg ref="jedisUtil"></constructor-arg>
    	</bean>
    	<bean id="jedisSets" class="com.zhaoyu.shop.cache.JedisUtil$Sets"
    		scope="singleton">
    		<constructor-arg ref="jedisUtil"></constructor-arg>
    	</bean>
    	<bean id="jedisHash" class="com.zhaoyu.shop.cache.JedisUtil$Hash"
    		scope="singleton">
    		<constructor-arg ref="jedisUtil"></constructor-arg>
    	</bean>
    	<!-- 创建Redis工具类,封装好Redis的连接并进行相关操作 -->
    	<bean id="jedisUtil" class="com.zhaoyu.shop.cache.JedisUtil"
    		scope="singleton">
    		<property name="jedisPool">
    			<ref bean="jedisWritePool" />
    		</property>
    	</bean>
    </beans>    

 

     说明一下上述的配置文件:

  • 首先设置Redis连接池
<!-- Redis连接池的设置 -->
	<bean id="jedisPoolConfig"
		class="redis.clients.jedis.JedisPoolConfig">
		<!-- 控制一个pool可分配多少个Jedis实例 -->
		<property name="maxTotal" value="${redis.pool.maxActive}" />
		<!-- 连接池中最多可空闲maxIdle个连接,这里取值为20,表示即使没有数据库连接时依然可以保持20个空闲的连接,而不被清除,随时处于待命状态 -->
		<property name="maxIdle" value="${redis.pool.maxIdle}" />
		<!-- 最大连接时间,当没有可用连接时 -->
		<property name="maxWaitMillis" value="${redis.pool.maxWait}" />
		<!-- 在获取连接时检查有效性 -->
		<property name="testOnBorrow"
			value="${redis.pool.testOnBorrow}" />
	</bean>

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

           这里有个value,和jdbc的连接池一样,动态获取redis.properties中的对应值

  • 创建Redis连接池,配置其属性
<!-- 创建Redis连接池,并作相关配置 -->
	<bean id="jedisWritePool"
		class="com.zhaoyu.shop.cache.JedisPoolWriper"
		depends-on="jedisPoolConfig">
		<constructor-arg index="0" ref="jedisPoolConfig" />
		<constructor-arg index="1" value="${redis.hostname}" />
		<constructor-arg index="2" value="${redis.port}"
			type="int" />
	</bean>

            <constructor-arg index="2" value="${redis.port}"  type="int" />

            这里的value和上面一样

  • 创建Redis工具类,封装好Redis的连接并进行相关操作
<!-- 创建Redis工具类,封装好Redis的连接并进行相关操作 -->
	<bean id="jedisUtil" class="com.zhaoyu.shop.cache.JedisUtil"
		scope="singleton">
		<property name="jedisPool">
			<ref bean="jedisWritePool" />
		</property>
	</bean>
<bean id="jedisKeys" class="com.zhaoyu.shop.cache.JedisUtil$Keys"
		scope="singleton">
		<constructor-arg ref="jedisUtil"></constructor-arg>
	</bean>

	<bean id="jedisStrings"
		class="com.zhaoyu.shop.cache.JedisUtil$Strings" scope="singleton">
		<constructor-arg ref="jedisUtil"></constructor-arg>
	</bean>

	<bean id="jedisLists"
		class="com.zhaoyu.shop.cache.JedisUtil$Lists" scope="singleton">
		<constructor-arg ref="jedisUtil"></constructor-arg>
	</bean>

	<bean id="jedisSets" class="com.zhaoyu.shop.cache.JedisUtil$Sets"
		scope="singleton">
		<constructor-arg ref="jedisUtil"></constructor-arg>
	</bean>

	<bean id="jedisHash" class="com.zhaoyu.shop.cache.JedisUtil$Hash"
		scope="singleton">
		<constructor-arg ref="jedisUtil"></constructor-arg>
	</bean>

这块的配置就是对于Redis的相关操作,分别为key,String,List,set,hash

现在配置文件就完成了;

第三步:编写redis连接池类(jedisWritePool)管理连接

这里说到了jedis,我的理解就是jedis就是集成了redis的一些命令操作,封装了redis的java客户端。提供了连接池管理;

话句话说,jedis就是redis的客户端;

jedisWritePool.java代码如下:

/**
 * 强指定redis的JedisPool接口构造函数,这样才能在centos成功创建jedispool
 * 
 * @author xiangze
 *
 */
public class JedisPoolWriper {
	/**
	 * redis连接池对象
	 */
	private JedisPool jedisPool;

	public JedisPoolWriper(final JedisPoolConfig poolConfig, final String host,
			final int port) {
		try {
			jedisPool = new JedisPool(poolConfig, host, port);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 获取	redis连接池对象
	 * @return
	 */
	public JedisPool getJedisPool() {
		return jedisPool;
	}
	/**
	 * 注入redis连接池对象
	 * @param jedisPool
	 */
	public void setJedisPool(JedisPool jedisPool) {
		this.jedisPool = jedisPool;
	}

}

这里就是实现构造方法,传参连接池配置信息,host地址,port端口号,然后通过get和set方法,实现对连接池的获取和注入

第四步:编写redis操作类(JedisUtil)操作Redis数据库

JedisUtil.java:代码如下

public class JedisUtil {
	/** 操作Key的方法 */
	public Keys KEYS;
	/** 对存储结构为String类型的操作 */
	public Strings STRINGS;
	/** 对存储结构为List类型的操作 */
	public Lists LISTS;
	/** 对存储结构为Set类型的操作 */
	public Sets SETS;
	/** 对存储结构为HashMap类型的操作 */
	public Hash HASH;

	private JedisPool jedisPool;
	/**
	 * 从Jedis连接池中获取redis连接池
	 * @return
	 */
	public JedisPool getJedisPool() {
		return jedisPool;
	}
    /**
	 * 设置redis连接池
	 * @param jedisPoolWriper
	 */
	public void setJedisPool(JedisPoolWriper jedisPoolWriper) {
		this.jedisPool = jedisPoolWriper.getJedisPool();
	}
    /**
	 * 从jedis连接池中获取获取jedis对象
	 * 
	 * @return
	 */
	public Jedis getJedis() {
		return jedisPool.getResource();
	}
}

这就是一个简易的Jedis连接池工具类,比如像缓存生存时间等一些其他功能没有设置。。。

第五步:Redis缓存技术实现

这里就简述一个我的商品类别一览信息获取的redis缓存技术

public class ShopCategoryServiceImpl implements ShopCategoryService {
	@Autowired
	private JedisUtil.Strings jedisStrings;
	@Autowired
	private JedisUtil.Keys jedisKeys;
	@Autowired
	private ShopCategoryDao shopCategoryDao;
	
	private static String SCLISTKEY = "shopcategorylist";

	@Override
	public List<ShopCategory> getFirstLevelShopCategoryList()
			throws IOException {
		//定义redis的key前缀
		String key = SCLISTKEY;
		//定义接受对象
		List<ShopCategory> shopCategoryList = null;
		//定义jackson数据转换操作类
		ObjectMapper mapper = new ObjectMapper();
		if (!jedisKeys.exists(key)) {
			ShopCategory shopCategoryCondition = new ShopCategory();
			// 当shopCategoryId不为空的时候,查询的条件会变为 where parent_id is null
			shopCategoryCondition.setShopCategoryId(-1L);
			shopCategoryList = shopCategoryDao
					.queryShopCategory(shopCategoryCondition);
			String jsonString = mapper.writeValueAsString(shopCategoryList);
			jedisStrings.set(key, jsonString);
		} else {
			String jsonString = jedisStrings.get(key);
			JavaType javaType = mapper.getTypeFactory()
					.constructParametricType(ArrayList.class,
							ShopCategory.class);
			shopCategoryList = mapper.readValue(jsonString, javaType);
		}
		return shopCategoryList;
	}
}
  • 首先,注入JedisUtil工具类中的String,key字段属性
  • 定义一个key 为 SCLISTKEY,值是shopcategorylist
  • 判断redis中是否有需要的数据,若为true,则查询出数据,通过ObjectMapper类将ArrayList对象转换成ShopCategory(商品类别)类的对象
  • 若redis中没有相关数据,则从数据库中查询,并将其准换成(查出的数据是list)string,然后set到redis中对应的key值