当前位置:   article > 正文

Redis客户端之Jedis,SpringBoot中使用StringRedisTemplate,通过注解的方式简单操作以及连接池的配置

Redis客户端之Jedis,SpringBoot中使用StringRedisTemplate,通过注解的方式简单操作以及连接池的配置

简介:

其实就是一个基于java语言的redis-cli客户端。

  1. Redis是一种运行在内存当中键值数据库,而且是以字符串类型为中心的,当前它能够支持多重数据类型,包括字符串,
  2. 散列,列表,集合,有序集合,基数和地理位置等。
  3. 在Spring项目当中使用Redis:
  4. 我们需要通过连接池创建一个RedisConnectionFactory对象,通过它我们就能够创建RedisConnection接口对象,
  5. 但是当我们使用一条连接时,我们要先从RedisConnectionFactory工厂获取,然后在使用完成后还要自己去关闭。
  6. Spring为简化操作,提供RedisTemplate
  7. redisTemplate.opsForvalue().set("key1","value1");当存储这样的一对键值对时,从Redis客户端输入
  8. key*key1,得到的并不是value1。因为Redis是基于字符串存储的NoSQl,而java是基于对象的语言,对象是无法储存到
  9. Redis中的,不过java中提供了序列化机制,可以将对象转换成二进制字符串。
  10. 所以就有了Redis键序列化器,
  11. RedisSerializer stringRedisSerializer=redisTemplate.getStringSerializer;
  12. 设置后能够从复杂的编码得到简单的字符串。
  13. 在SpringBoot中使用Redis:
  14. 1.首先要在官网下载Redis,添加服务到本地,(设置开机自动启动该服务)
  15. 2.导入依赖
  16. <!--Redis-->
  17. <dependency>
  18. <groupId>org.springframework.boot</groupId>
  19. <artifactId>spring-boot-starter-data-redis</artifactId>
  20. </dependency>
  21. 3.导入依赖后,SpringBoot已将帮我把RedisTemplateFactory,RedisTemplate,StringRedisTemplate
  22. 的常用对象添加到IOC容器当中,因此我们只需要从IOC容器中获取该对象即可。
  23. 可以通过 redis-cli.exe -h 127.0.0.1 -p 6379命令查找key对应的value和设置键值对
  24. Redis的一些特殊用法:
  25. Redis除了操作那些数据类型的功能外,还能支持事务,流水线,发布订阅和Lua语等功能
  26. 在高并发的场景中,往往我们需要保证数据的一致性,这是考虑使用Redis事务,或者是利用Redis执行
  27. Lua的原子性来达到数据一致性的目的。
  28. 使用Redis事务:
  29. 在Redis中使用事务,通常的命令组合是watch,multi,exec。也就是要在一个Redis连接中执行多个命令,
  30. 这时我们可以考虑使用SessionCallBack来达到这个目的。
  31. watch:是可以监控Redis的一些键;
  32. multi:是开始事务,开启事务后,该客户端的命令不会马上立即被执行,而是存放在一个队列中,结果返回null
  33. exec:执行事务,只是他在队列命令执行前会判断被watch监控的Redis的键的数据是否发生过改变,如果他认为发生了
  34. 改变,(即使是相同的值覆盖也认为是改变)那么Redis就会取消事务。
  35. 测试代码:

1.SpringBoot中对Redis中String类型的使用

依赖:

  1. <!--添加mysql驱动-->
  2. <dependency>
  3. <groupId>mysql</groupId>
  4. <artifactId>mysql-connector-java</artifactId>
  5. <version>5.1.37</version>
  6. </dependency>
  1. <!--添加DBCP数据源-->
  2. <dependency>
  3. <groupId>org.apache.commons</groupId>
  4. <artifactId>commons-dbcp2</artifactId>
  5. </dependency>
  1. <!--Redis-->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-data-redis</artifactId>
  5. </dependency>

常用配置 :

  1. # REDIS (RedisProperties)
  2. # Redis数据库索引(默认为0)
  3. spring.redis.database=0
  4. # Redis服务器地址
  5. spring.redis.host=localhost
  6. # Redis服务器连接端口
  7. # 添加redis到服务 redis-server --service-install redis.windows.conf
  8. # 开启服务 redis-server --service-start
  9. spring.redis.port=6379
  10. # 默认无密码
  11. spring.redis.password=
  12. spring.redis.jedis.pool.max-active=10
  13. spring.redis.jedis.pool.max-idle=10
  14. spring.redis.jedis.pool.max-wait=2000ms
  15. spring.redis.jedis.pool.min-idle=5
  16. #缓存管理器配置
  17. #如果底层的缓存管理器支持创建,以逗号分隔列表缓存名称
  18. spring.cache.cache-names=redisCache
  19. #是否允许Redis缓存空值
  20. spring.cache.redis.cache-null-values=true
  21. #Redis的键前缀
  22. spring.cache.redis.key-prefix=
  23. #缓存超时时间戳,配置为0则不设置超时时间 十分钟
  24. spring.cache.redis.time-to-live=600000ms
  25. #是否启用Redis的键前缀
  26. spring.cache.redis.use-key-prefix=true
  27. # 缓存类型 默认情况下,Spring会自动根据上下文探测
  28. spring.cache.type=REDIS

控制层:

  1. @Controller
  2. @RequestMapping("/redis")
  3. public class RedisController {
  4. @Autowired
  5. private RedisTemplate redisTemplate;
  6. @Autowired
  7. private StringRedisTemplate stringRedisTemplate;
  8. @RequestMapping("/stringAndHash")
  9. @ResponseBody
  10. public Map<String,Object> testStringAndHash(){
  11. redisTemplate.opsForValue().set("key1","value1");
  12. //默认使用JDK的序列化器,所以Redis保存的不是整数,不能进行运行
  13. redisTemplate.opsForValue().set("int_key1","1");
  14. //使用运算
  15. stringRedisTemplate.opsForValue().set("int","1");
  16. //获取底层Redis连接
  17. // RedisProperties.Jedis jedis;
  18. // jedis= (RedisProperties.Jedis) stringRedisTemplate.getConnectionFactory().getConnection().getNativeConnection();
  19. // jedis.
  20. //减一操作 redisTemplate不支持
  21. Map<String,String> hash=new HashMap();
  22. hash.put("field1","value1");
  23. hash.put("field2","value2");
  24. //存入一个散列数据类形
  25. stringRedisTemplate.opsForHash().putAll("hash",hash);
  26. stringRedisTemplate.opsForHash().put("hash","field3","value3");
  27. //绑定散列操作的key,这样可以连续对一个散列数据类型进行操作
  28. BoundHashOperations hashOps= stringRedisTemplate.boundHashOps("hash");
  29. hashOps.delete("field1","field2");
  30. hashOps.put("field4","value4");
  31. Map map=new HashMap();
  32. map.put("Success",true);
  33. return map;
  34. }
  35. @Autowired
  36. private MybatisUserService mybatisUserService;
  37. @RequestMapping("/insertUser")
  38. @ResponseBody
  39. public User insertUser(){
  40. User user=new User();
  41. user.setName("redis");
  42. user.setNote("新成员");
  43. mybatisUserService.insertUser(user);
  44. return user;
  45. }
  46. @RequestMapping("/findUser")
  47. @ResponseBody
  48. public User findUser(int id)
  49. {
  50. return mybatisUserService.findUser(id);
  51. }
  52. @RequestMapping("/updateUser")
  53. @ResponseBody
  54. public User updateUser(Integer id,String name){
  55. return mybatisUserService.updateUser(id,name);
  56. }
  57. @RequestMapping("/deleteUser")
  58. @ResponseBody
  59. public int deleteUser(Integer id){
  60. return mybatisUserService.deleteUser(id);
  61. }
  62. }

组件 :

  1. @Component
  2. public class RedisComponent {
  3. //通过stringRedisTemplate进行序列化键值,这样只能支持支持字符串,并不能支持java对象的储存。
  4. //不设置时,RedisTemplate默认使用JdkSerializationRedisSerializer 进行序列化键值。存储到
  5. //服务器,这是存入的便是一个经过序列化后的特殊字符,对于我们跟踪不友好!
  6. @Autowired
  7. private StringRedisTemplate stringRedisTemplate;
  8. public void set(String key,String value){
  9. //拿到存储操作对象
  10. ValueOperations<String,String> ops=stringRedisTemplate.opsForValue();
  11. if(stringRedisTemplate.hasKey(key))
  12. {
  13. System.out.println("Key="+key+"value="+value);
  14. }
  15. else{
  16. ops.set(key, value);
  17. System.out.println("添加成功!");
  18. }
  19. }
  20. public String get(String key){
  21. return stringRedisTemplate.opsForValue().get(key);
  22. }
  23. public void delete(String key){
  24. stringRedisTemplate.delete(key);
  25. System.out.println("删除成功!");
  26. }
  27. }

业务层

  1. //插入用户,最后Mybatis会回填ID,取结果id缓存用户
  2. @Override
  3. @Transactional
  4. @CachePut(value = "redisCache",key = "'redis_user_'+#result.id")
  5. //当方法返回值为int类型时会报找不到id异常
  6. //value配置对应缓存名称redisCache 键配置:#result表示返回对象user
  7. //而且返回类型必须为User不然会报异常
  8. public User insertUser(User user) {
  9. mybatisUserDao.insertUser(user);
  10. return user;
  11. }
  12. @Override
  13. @Transactional
  14. @CachePut(value = "redisCache",key = "'redis_user_'+#result.id",condition = "#result!='null'")
  15. //如果返回结果为空,则不使用缓存
  16. public User updateUser(Integer id,String name) {
  17. User user=this.findUser(id);//该方法的缓存注解在此处会失效
  18. if(user==null)
  19. {
  20. System.out.println("查找用户失败!!!");
  21. return null;
  22. }
  23. user.setName("更改后的名字");
  24. user.setNote("更改后的身份");
  25. mybatisUserDao.updateUser(user);//不要忘了。。
  26. return user;
  27. }
  28. @Override
  29. @Transactional
  30. @Cacheable(value = "redisCache" ,key = "'redis_user_'+#id")
  31. //参数中不是User对象不能设置为#result.id
  32. public User findUser(Integer id) {
  33. return mybatisUserDao.findUser(id);
  34. }
  35. @Override
  36. @Transactional
  37. @CacheEvict(value = "redisCache",key ="'redis_user_'+#id",beforeInvocation = false)
  38. //默认值为false 表示在该方法之后移除缓存
  39. public int deleteUser(Integer id) {
  40. return mybatisUserDao.deleteUser(id);
  41. }

2.Jedis总结:

# Jedis直连

## 执行流程

1. 创建Jedis对象

Jedis jedis=new Jedis("127.0.0.1",6379);
2. 通过Jedis执行命令
3. 返回Jedis执行结果
4. 关闭Jedis连接

## 创建Jedis的方式

```java
/**
 *    @param host Redis节点所在机器的IP或域名
 *  @param port Redis服务的端口号
 *  @param connectionTimeout 客户端连接超时时间(毫秒)
 *  @param soTimeout 客户端读写超时时间(毫秒)
 */
public Jedis(String host , int port , int connectionTimeout , int soTimeout)
```

具体参考API文档http://tool.oschina.net/apidocs/apidoc?api=jedis-2.1.0

 

# Jedis连接池

## 执行流程

1. 创建一个JedisPool对象
2. 从资源池中获取一个Jedis对象
3. 通过Jedis执行命令
4. 返回Jedis执行结果
5. 关闭Jedis连接,将Jedis还给资源池

## 创建Jedis连接池的方式

```java
JedisPoolConfig config = new JedisPoolConfig();
JedisPool jedisPool = new JedisPool(config , "127.0.0.1" , 6379);
Jedis jedis = jedisPool.getResource();
jedis.close();
```

最好是使用try catch方式

 

# Jedis直连 VS Jedis连接池

|             |                             优点                             |                             缺点                             |
| :---------: | :----------------------------------------------------------: | :----------------------------------------------------------: |
|  Jedis直连  |            使用简单<br/>适用于少量长期连接的场景             | 存在每次新建/关闭TCP连接的开销<br/>资源无法控制,存在连接泄露的风险<br/>Jedis对象线程不安全 |
| Jedis连接池 | Jedis对象预先生成,降低使用开销<br/>连接池的形式保护和控制资源的使用 | 相对于直连,使用相对麻烦<br/>尤其在资源的管理上需要许多参数保证<br/>一旦参数不合理会出现很多问题 |

Jedis连接池配置

1.commons-pool资源数配置参数:

2.commons-pool借还参数

JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(10);
jedisPoolConfig.setMaxWaitMillis(1000);

JedisPool jedisPool=new JedisPool(jedisPoolConfig,"127.0.0.1",6379);

for(int i=0;i<10;i++){
    Jedis jedis=null;
    try {
        jedis=jedisPool.getResource();
        System.out.println(jedis.ping()+(i+1));
    }catch (Exception e){
        e.printStackTrace();
    }finally {
    jedis.close();
        //当我们不在finally中进行资源的关闭时,
        // 由于连接池中的jedis都在被使用,就会出现连接超时的错误
    }
}
jedisPool.getResource().ping();

复杂一点的jedis连接池配置。https://blog.csdn.net/u010473656/article/details/78838254

在springboot中配置参考上文很简单。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/152088
推荐阅读
相关标签
  

闽ICP备14008679号