redis学习第三天和四天

1    redis的 java api

在本章主要学习在java中使用redis,在java中可以轻易使用redis,或者通过spring的redisTemplate使用Redis。为了实际的工作和学习的需要,本章以spring的视角介绍在java里面如何使用redis,基础章节会以xml的配置方式为主,在实践章节会以java的配置为主介绍redis,你可以根据需要使用xml或者注解来实现你想要的功能。

1.1.1

在java程序中使用redis,在java中使用redis工具,需要下载jedis.jar包,把它加载到工程的路径中,所以首先打开网站http://mvnrepository.com/artifact/redis.clients/jedis,如图

把它导入工程路径就可以使用了,可以使用以下代码测试。

                         1-1: java连接redis

 Jedis jedis =new Jedis(“localhost”,6379); //连接Redis

 //jedis.auth(“password”);  //如果需要密码

Int i=0; //记录操作次数

try{

  long start =System.currentTimeMillis(); //开始毫秒数

  while (true) {

     Long end =system.currentTimeMillis();

     If (end - start >=1000){  //当大于等于1000毫秒(相当于1秒)时,结束操作

       Break;

}

i++;

Jedis.set(“test” + i, i + “”);

}

 

}finally{ //关闭连接

Jedis.close();

}

System.out.println(“redis每秒操作: “ + i + “次”);//打印1秒内对redis的操作次数。

这段代码主要在于测试Redis的写入性能,这是笔者使用自己电脑(使用window操作系统)测试的结果。

Redis每秒操作:23308次。

  这里每秒只操作了两万多次,而事实上Redis的速度比这个操作的速度快的多,这里慢是应为我们只是一条条的将命令发送给redis执行。如果使用流水线技术他会快的多,将可以达到10万次每秒的操作,十分有利于系统性能的提高。注意,这只是一个简单的连接,更多的时候,我们可以使用连接池去管理它,java redis 的连接池提供了类redis.clients.jedis.JedisPool 用来创建Redis的连接池对象。使用这个对象,需要使用类redis.clients.jedis.JedisPoolConfig对连接池进行配置,连接池使用redis代码如下:

                        1-2使用Redis连接池

 JedisPoolConfig poolCfg =new JedisPoolConfig();

 //最大空闲数

 poolCfg.setMaxIdle(50);

 //最大连接数

   PoolCfg.setMaxTotal(100);

   //最大等待毫秒数

   poolCfg.setMaxWaitMillis(20000);

   //使用配置创建连接池

   JedisPool pool =new JedisPool (poolCfg, “localhost”);

   //从连接池中获取单个连接

   Jedis jedis =pool.getResource();

   //如果需要密码

   //jedis.auth(“password”);

  在写代码的时候注释了解每一步的含义,对连接池进行有效的管理。

  由于redis只能提供基于字符串型的操作,而在java中使用的却已类对象为主,所以需要redis存储的字符串和java对象相互转换。如果自己编写这些规则,工作量还是比较大的,比如一个角色对象,我们没有办法直接把对象存入redis中,需要进一步进行转换,所以对操作对象而言,使用redis是比较难得,好在spring对这些进行了封装和支持,它提供了序列化的设计框架和一些序列化的类,使用后可以通过序列化把Java对象转换,使得redis能把它存储起来,并且在读取的时候,再把由序列化过的字符串转化为java对象,这样在java环境中使用redis就更加简单了,所以更多时候可以使用spring提供的RedisTemplate的机制来使用redis。

1.1.2在spring中使用redis

 上一章介绍了在没有封装的情况下使用java api 的缺点,需要自己编写规则把java对象和redis的字符串进行相互交换,而在spring中这些问题都可以轻松处理。在spring中使用redis,

除了需要Redis,除了需要jedis.Jar外,需要下载spring-data-redis.jar,打开网址http://mvnrepository.com/artifact/org.springframework.data/spring-data-redis,可以看到以下界面,如图所示

   

 这里值得注意的是jar包和spring版本兼容的问题,我使用的jar包版本是1.7.2,而spring的版本是4.3.2,如果使用其他版本可能存在不兼容的问题,从而产生异常,这是我从实际操作中得来的经验。

  把下载的jar包导入到工程环境中,这样就可以在使用spring提供的RedisTemplate操作redis了,只是在使用前,需要对spring提供的方案进行探讨,以便更好地使用它们。(关于spring Data Redis项目了解后你可以更好地理解如何使用spring操作redis。

 在大部分情况下我们都会用到连接池,于是先用spring配置一个JedisPoolConfig对象,这个配置相对而言比较简单,代码如下所示。

                  代码1-3   使用spring配置JedisPoolConfig对象

 <bean id=”poolConfig” class=”redis.clients.Jedis.JedisPoolConfig”>

   // 最大空闲数

  <property name=”maxIdle” value=”50” />

   //最大连接数

  <property name=”maxTotal” value=”100” />

   //最大等待时间

  <property name=”maxWaitMillis” value=”20000”/>

</bean>         

 

 

 这样就配置了一个连接池的配置,继续往下配置。

   在使用spring提供的RedisTemplate之前需要配置Spring所提供的的连接工厂,在spring data redis方案中它提供了4种工厂模型。

·jredisconnectionFactory。

·jedisConnectionFactory

·LettuceConnectionFactory。

·SrpConnectionFactory

虽然使用哪种实现工厂都是可以的,但是要根据环境进行测试,以验证使用哪个

方案的性能是最佳的。无论如何他们都是由接口RedisConnectionFactory的实现类,更多的时候都是通过接口定义去理解它们,所以他们是具有接口适用性的,我是使用的最为广泛的JedisConnectionFactoty为例进行详解。

例如,在spring种配置一个jedisconnectionFactory对象,代码如1-4所示

           代码  1-4 配置jedisConnectionFactory

 

          <bean id=”connectionFactory” class=”org.springframework.data.redis.connection.jedis.JedisConnectionFactory”>

   <property name=”hostname” value=localhost”/>

 <property name=”port” value=”6379”/>

  //<property name=”password” value=”password”/>

<property name=”poolConfig” ref=”poolConfig/>

</bean>

解释一下它的属性配置。

·hostname,代表的是服务器,默认值是localhost,所以如果是本机可以不配置它。

·port,代表的是接口端口,默认值是6379,所以可以使用默认的redis端口,也可以不配置他。

·password,代表的是密码,在需要密码连接redis的场合需要配置他。

·poolConfig,是连接池配置对象,可以设置连接池的属性。

  这样就完成了一个Redis连接工厂的配置,这里配置的是JedisConnectionFactory,如过需要的是LettuceConnectionFactory,可以把代码清单1-3中中的bean元素的class属性修改为org.springframework.data.redis.connection.lettuce.lettuceConnectionFactor即可,这取决于项目的需要和特殊性,有了RedisConnectionFactory工厂,就可以使用RedisTemplate了。

  普通的连接使用没有办法把java对象直接存入Redis,而需要我们自己提供方案,这时候往往就是将对象序列化,然后使用redis进行存储,而取回序列化的内容后,在通过转换变为java对象,spring模板提供了封装的方案,在它内部提供了redisSerializer接口(org.springframework.data.redis.serializer.RedisSerializer)和一些实现类,其原理如图1-11所示。

可以选择spring提供的方案去处理序列化,当然也可以去实现在spring data redis中定义的redisSerializer接口,在spring中提供了以下几种实现redisSerializer接口的序列化器。

·genericJackson2jsonredisserializer,通用的使用json2.jar包,将redis对象的序列化器。

·Jackson2jsonredisserializer<T>,通过jackson2.jar包提供的序列化进行转换。

·jdkserializationredisSerializer<T>,使用jdk的序列化器进行转换。

·Oxmserializer,使用字符串进行序列化。

 

·generictostringSerializer,通过通用的字符串序列化进行相互转换。

使用它们就能够帮助我们把对象通过序列化存储到redis中,也可以把redis存储的内容转换为java对象,为此spring提供的redisTemplate还有两个属性。

 ·keySerializer--------键序列器。

 ·valueSerializer--------值序列器。

有了上面的了解,就可以配置RedisTemplate了。假设选用StringRedisSerializer作为Redis的key的序列化器,而使用jdkSerializationRedisSerializer作为其value的序列化器,则可以按照代码清单1-5的方法来配置RedisTemplate。

           代码清单 1-5 配置Spring Redis template

<bean id=”jdkSerializationRediserializer” class=”org.springframe.data.redis.serializer.jdkSerializationRedisSerializer”/>

<bean id=”stringRedisSerializer” class=”org.springframework.data.redis.serializer.StringRedlisSerializer”/>

<bean id=”redisTemplate”  class=”org.springframe.data.redis.core.RedisTemplate”>

<property name=”connectionFactory” ref=”connectionFactory”/>

<property name=”keySerializer” ref=”stringRedisSerializer”/>

<property name=”valuSerializer” ref=”jdkSerializationRedisSerializer” />

</bean>

 

这样就配置了一个RedisTemplate对象,并且spring data redis知道会用对应的序列化器去转换redis的键值。

举个例子,新建一个角色对象,使用redis保存它的对象,如代码清单1-6所示。

      代码清单 1-6:使用redis保存角色类对象

Package com.learn.ssm.chapter17.pojo;

 

Import java.io.Serializable;

/*注意,对象要可序列化,需要实现Serizable接口,往往要重写serialVersionUID*/

Public class Role implements Serializable{

 Private static final long serialVersionUID= 6977402643848374753L;

 Private long id;

Private String roleName;

Private String note;

/*setter and getter**/

}--

  因为要序列化对象,所以需要实现Serializable接口,表面他能够序列化,而serialVersionUID代表的是序列化的版本编号。

  假设在applicationContext.xml中配置了代码清单1-3至1-5的配置,那么就可以测试保存这个Role对象了,测试代码如代码清单1-7所示。

        代码清单 1-7:使用RedisTemplate保存Role对象

 ApplicationContext applicationContext=new ClassPathXmlApplicationContext(“applicationContext.xml”);

RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);

Role role =new Role();

Role.setId(1L);

role.setRoleName(“role_name_1”);

Role.setNote(“note_1”);

redisTemplate.opsForValue.set(“role_1”,role);

Role eole1 =(Role) redisTemplate.opsForvalue().get(“role_1”);

  System.out.println(role1.getRoleName());

   

  在system.out.println(role1.getRoleName());这行打下断点,可以看到如图1-12图的测试结果。

显然这样已经成功保存和获取了一个java对象,这段代码演示的是如何使用StringRedisSerializer序列化Redis的key,而使用jdkSerializationRedisSerializer序列化Redis的value,当然也可以根据需要去选择,甚至是自定义序列化器。

  注意,以上的使用都是基于RedisTemplate,基于连接池的操作,换句话说,并不能保证每次使用RedisTemplate是操作同一个对redis的连接,比如1-7代码清单下面的代码。

redisTemplate.opsForValue.set(“role_1”,role);

Role eole1 =(Role) redisTemplate.opsForvalue().get(“role_1”);

      图1-12

Set和get方法看起来很简单,他可能就来自同一个redis连接池的不同redis连接。为了使得所有的操作都来自同一个连接,可以使用SessonCallback或者RedisCallback这两个接口,Rediscallback是比较底层的封装,其使用不是很友好,所以更多的时候会使用sessioncallback接口,通过这个接口就可以把多个命令放入到同一个redis连接中去执行,如代码清单1-8所示,它主要是实现了代码清单1-7中的功能。

                        代码清单1-8: 使用sessioncallback接口

  ApplicationContext application =new ClassPathXmlApplicationContext(“applicationContext.xml”);

  RedisTemplate    redistemplate=applicationContext.getBean(RedisTemplate.class);

  Role role=new Role();

  Role.setId(1);

  Role.setRoleName(“role_name_1”);

Role.setNote(“role_note_1”);

SessionCallback callBack =new SessionCallback<Role>(){

@override

  Public Role execute (RedisOperations ops) throws DataAccessException {

  ops.boundValueOps(“role_1”).set(role);

  Return (Role) ops.boundValueOps(“role_1”).get();

}

};

 Role  savedRole =(Role)redisTemplate.execute(callBack);

 System.out.println(savedRole.getId());

这样set和get命令就能保证在同一个连接池的同一个redis连接操作,这里使用的是使用匿名内部类的形式,而事实上如果采用java 8 的jdk版本,也可以使用lambda表达式进行编写SessionCallback的业务逻辑,这样逻辑会更为清晰明了。由于前后使用的都是同一个连接,因此对于资源损耗就比较小,在使用redis操作多个命令或者使用事务时也常常会用到他。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值