【框架整合】四、整合redis



一、首先要下载一个redis服务器(Windows版)

1.下载安装

下载地址  : https://github.com/MSOpenTech/redis/releases

下载好之后直接解压文件  绿色免安装

推荐把redis路径设在path中

这样打开cmd 界面就可以直接打开了,不用每次都要输入路径了


自己遇到一个问题就是必须要把redis.windows.conf文件拷贝到自己系统的根路径中,很郁闷

redis.windows.conf放到C:\Users\82745 下

否则直接使用下面的命令无法启动   报错:加载不到redis.windows.conf文件


这里也可以安装 RedisDesktopManager,启动Redis服务之后,可以直接使用此redis桌面管理工具
连接redis服务端
方便操作


2.启动基本命令

启动服务命令 redis-server.exe redis.windows.conf

后面的redis.windows.conf 即为redis的配置文件



出现如上界面表示redis服务端启动成功,保持此界面不要关闭,(这里没有修改配置文件,可修改为后台运行)

重新打开一个命令窗口


输入命令redis-cli 打开客户端 命令 如下

如果在conf中设立了redis密码,则可使用auth 密码登录,不设置也可以正常使用



现在可以简单的先测试一下redis 

放入一个值 set myKey xiazhang(最简单的存命令为 set key value)

然后取出  get myKey   结构为 xiazhang,

redis安装测试成功



二、spring框架集成redis


1.导入jar包

我开始使用的是下面两个版本

jedis-2.2.0.jar   最后使用的是jedis-2.6.0

spring-data-jedis.1.4.1.jar


2. 配置redis

a. 配置redis.properties文件

#redis server ip
redis.host=127.0.0.1
redis.port=6379
redis.password=xiazhang

#redis.database=3
redis.maxIdle=300
redis.maxActive=600
redis.maxWait=1000
redis.testOnBorrow=true

并记得在spring         applicationContext.xml文件中引入该配置文件

<!-- 引入本地配置文件 -->
	<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:jdbc.properties</value>
				<value>classpath:redis.properties</value>
			</list>
		</property>
	</bean>


b. 在applicationContext-datasource.xml文件中配置redis

这里为最终的正确配置

当然也可以单独在特定文件中配置如applicationContext-redis.xml,但是个人感觉这个配置不是很多所以放到一个文件中,方便管理

<!-- redis 配置开始 -->
	
	<!-- redis连接池 -->
	<beans:bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<!-- 最大空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连接将被标记为不可用,然后被释放。设为0表示无限制。 -->  
        <beans:property name="maxIdle" value="${redis.maxIdle}" />  
        <!-- 连接池的最大数据库连接数。设为0表示无限制 -->
		<beans:property name="maxTotal" value="${redis.maxActive}" />
        <!-- 最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制 --> 
        <beans:property name="maxWaitMillis" value="${redis.maxWait}" />
        <!-- 在borrow一个jedis实例时,是否提前进行alidate操作;如果为true,则得到的jedis实例均是可用的  -->
        <beans:property name="testOnBorrow" value="${redis.testOnBorrow}" />  
    </beans:bean>
	<!-- redis 连接工厂 -->
	<bean id="redisConnectionFactory"
            class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
	    <property name="hostName" value="${redis.host}"/>
	    <property name="port" value="${redis.port}"/>
	    <property name="password" value="${redis.password}"/>
	    <property name="timeout" value="15000"/>
	    <!-- <beans:property name="database" value="${redis.database}"/> -->
	    <property name="poolConfig" ref="jedisPoolConfig"/>
	</bean>
	
	<!-- redis操作模板,这里采用尽量面向对象的模板 -->
	<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
		<property name="connectionFactory" ref="redisConnectionFactory"/>
		<!-- 如果不配置Serializer,那么存储的时候只能使用String,如果用对象类型存储,那么会提示错误 can't cast to String -->
		<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="hashKeySerializer">
			<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
		</property>
		<property name="hashValueSerializer">
			<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
		</property>
	</bean>
	<!-- redis 配置结束 -->

配置结束


3.从开始遇到的问题

报错:

java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig 

(高版本jedis需要使用commons-pool2 ),缺少jar包:导入commons-pool2 jar包


继续启动工程

 
错误 java.lang.VerifyError: (class: org/springframework/data/redis/connection/jedis/JedisConnectionFactory, method: createRedisPool signature: ()Lredis/clients/util/Pool;) Incompatible argument to function


jedis 和 spring-data-jedis jar包 冲突  更换jedis.jar 版本

注意 : 这里有一个大坑

jar包冲突所以更换jar包  于是找了一个最新的jedis-2.9.0.jar  
于是报错
nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'maxActive' of bean class [redis.clients.jedis.JedisPoolConfig]: Bean property 'maxActive' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?

   
  提示JedisPoolConfig没有maxActive属性
  查看源码
  
  package redis.clients.jedis;
  import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
  public class JedisPoolConfig extends GenericObjectPoolConfig {
    public JedisPoolConfig() {
   // defaults to make your life with connection pool easier :)
   setTestWhileIdle(true);
   setMinEvictableIdleTimeMillis(60000);
   setTimeBetweenEvictionRunsMillis(30000);
   setNumTestsPerEvictionRun(-1);
    }
  }


 再继续查看GenericObjectPoolConfig类所在的jar包,果然没有





jedis包括2.4.1,2.5.1等高版本的JedisPoolConfig没有maxActive属性,不能按照网上那些方式去配置Redis了,网上大部分搜索出来的redis配置都是基于旧版本的jedis,在jedis新版本,JedisPoolConfig没有maxActive属性,JedisPoolConfig没有maxWait属性,以及被替换成其他的命名。


其实高版本的jedis使用了org.apache.commons.pool2.impl.GenericObjectPoolConfig。dbcp的修改日志显示:change "maxActive" -> "maxTotal" and "maxWait" -> "maxWaitMillis" in all examples.所以高版本jedis配置JedisPoolConfig的maxActive,maxWait应该为:
 
  原<beans:property name="maxActive" value="${redis.maxActive}" />
          <beans:property name="maxWait" value="${redis.maxWait}" />
  
  改为
  <property name="maxTotal" value="${redis.pool.maxActive}"/>
  <property name="maxWaitMillis" value="${redis.pool.maxWait}"/>


然后启动工程还是报错  不过已经跳过了刚刚的 
  
  Error creating bean with name 'redisConnectionFactory' defined in class path resource [applicationContext-datasource.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'pool' of bean class [org.springframework.data.redis.connection.jedis.JedisConnectionFactory]:Bean property 'pool' is not writable or has an invalid setter method. Did you mean 'port'?
 
  <property name="pool" ref="poolConfig"/>
这里错误
  
  查看JedisConnectionFactory源码 发现又改动了 你大爷


  private Pool<Jedis> pool;
  private JedisPoolConfig poolConfig = new JedisPoolConfig();

  
  pool 已经不是那个pool了 然而poolConfig 还是那个JedisPoolConfig 所以应该使用 poolConfig替换pool


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

应改为

<property name="poolConfig" ref="jedisPoolConfig"/>



continue!!!
  
于是又报错了
Caused by: java.lang.NoSuchMethodError: redis.clients.jedis.JedisShardInfo.setTimeout(I)V

(你大爷的  算了 等会出去吃饭吧)
源码中 timeout 是有默认值的 private int timeout = Protocol.DEFAULT_TIMEOUT;

肯定不是配置错误
难道是我用的jedis版本是最新的吗  jedis-2.9.0.jar  换成 jedis-2.6.0 果然好了 这里几个错误折腾了好久


4.测试


激动人心的时候到了 
启动redis 服务器 测试一下


新建RedisService接口

package com.mvc.redis.service;

/**
 * redis 操作接口层
 * 
 * @author xiazhang
 * @date   2017-6-16
 */
public interface RedisService {

	/**
     * 通过key删除
     * 
     * @param key
     */
    public abstract long del(String... keys);

    /**
     * 添加key value 并且设置存活时间(byte)
     * 
     * @param key
     * @param value
     * @param liveTime
     */
    public abstract void set(byte[] key, byte[] value, long liveTime);

    /**
     * 添加key value 并且设置存活时间
     * 
     * @param key
     * @param value
     * @param liveTime
     *            单位秒
     */
    public abstract void set(String key, String value, long liveTime);

    /**
     * 添加key value
     * 
     * @param key
     * @param value
     */
    public abstract void set(String key, String value);

    /**
     * 添加key value (字节)(序列化)
     * 
     * @param key
     * @param value
     */
    public abstract void set(byte[] key, byte[] value);

    /**
     * 获取redis value (String)
     * 
     * @param key
     * @return
     */
    public abstract String get(String key);

    /**
     * 通过正则匹配keys
     * 
     * @param pattern
     * @return 
     * @return
     */
//    public abstract Setkeys(String pattern);

    /**
     * 检查key是否已经存在
     * 
     * @param key
     * @return
     */
    public abstract boolean exists(String key);

    /**
     * 清空redis 所有数据
     * 
     * @return
     */
    public abstract String flushDB();

    /**
     * 查看redis里有多少数据
     */
    public abstract long dbSize();

    /**
     * 检查是否连接成功
     * 
     * @return
     */
    public abstract String ping();
}




接口实现类 RedisServerImpl


package com.mvc.redis.service.impl;

import java.io.UnsupportedEncodingException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import com.mvc.redis.service.RedisService;

@Service(value="redisService")
public class RedisServiceImpl implements RedisService{

	private static String redisCode = "utf-8";

	@Autowired
    private RedisTemplate redisTemplate;
    /**
     * @param key
     */
    public long del(final String... keys) {
        return redisTemplate.execute(new RedisCallback() {
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                long result = 0;
                for (int i = 0; i < keys.length; i++) {
                    result = connection.del(keys[i].getBytes());
                }
                return result;
            }
        });
    }

    /**
     * @param key
     * @param value
     * @param liveTime
     */
    public void set(final byte[] key, final byte[] value, final long liveTime) {
        redisTemplate.execute(new RedisCallback() {
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                connection.set(key, value);
                if (liveTime > 0) {
                    connection.expire(key, liveTime);
                }
                return 1L;
            }
        });
    }

    /**
     * @param key
     * @param value
     * @param liveTime
     */
    public void set(String key, String value, long liveTime) {
        this.set(key.getBytes(), value.getBytes(), liveTime);
    }

    /**
     * @param key
     * @param value
     */
    public void set(String key, String value) {
        this.set(key, value, 0L);
    }

    /**
     * @param key
     * @param value
     */
    public void set(byte[] key, byte[] value) {
        this.set(key, value, 0L);
    }

    /**
     * @param key
     * @return
     */
    public String get(final String key) {
        return redisTemplate.execute(new RedisCallback() {
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                try {
                    return new String(connection.get(key.getBytes()), redisCode);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                return "";
            }
        });
    }

    /**
     * @param pattern
     * @return
     */
//    public Setkeys(String pattern) {
//        return redisTemplate.keys(pattern);
//
//    }

    /**
     * @param key
     * @return
     */
    public boolean exists(final String key) {
        return redisTemplate.execute(new RedisCallback() {
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.exists(key.getBytes());
            }
        });
    }

    /**
     * @return
     */
    public String flushDB() {
        return redisTemplate.execute(new RedisCallback() {
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                connection.flushDb();
                return "ok";
            }
        });
    }

    /**
     * @return
     */
    public long dbSize() {
        return redisTemplate.execute(new RedisCallback() {
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.dbSize();
            }
        });
    }

    /**
     * @return
     */
    public String ping() {
        return redisTemplate.execute(new RedisCallback() {
            public String doInRedis(RedisConnection connection) throws DataAccessException {

                return connection.ping();
            }
        });
    }

    private RedisServiceImpl() {

    }


}



新建测试类


package com.mvc.redis;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.mvc.redis.service.RedisService;

/**
 * redis 测试
 * 
 * @author xiazhang
 * @date   2017-6-15
 */
public class RedisTest{

    ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    RedisService redisService = (RedisService) app.getBean("redisService");


	
    @Test
    public void del() {
        redisService.set("xia", "xia");
        long result = redisService.del("xia");
        Assert.assertEquals(1L, result);
    }

    @Before
    @Test
    public void set() {
        redisService.set("zhang", "zhang");
        
    }

    @After
    @Test
    public void get() {
    	
        Assert.assertEquals("zhang", redisService.get("zhang"));
    }
	
	

	
}


最终的结构为



测试成功





  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值