当前位置: 首页 > news >正文

JavaWeb合集12-Redis

十二、Redis

1、Redis 入门

Redis是一个基于内存的key-valule 结构数据库。

特点:基于内存存储,读写性能高

场景:适合存储热点数据(热点商品、资讯、新闻)

Redis安装包分为Windows版和Linux版:

Windows版 下载地址: https://github.com/microsoftarchive/redis/releases

Linux版 下载地址: https://download.redis.io/releases/

Redis操作工具:https://gitee.com/qishibo/AnotherRedisDesktopManager/releases

Redis的Windows版属于绿色软件,直接解压即可使用,解压后目录结构如下:

在这里插入图片描述

Redis启动命令(cmd):服务名 配置文件名

redis-server.exe redis.windows.conf

在这里插入图片描述

启动客户端(cmd操作,可对其存取数据):

redis-cli.exe

可通过配置文件中参数的设置密码,如:requirepass 123456

2、Redis 数据类型

Redis存储的是key-value结构的数据,其中key是字符串类型,value有5种常用的数据类型。

5种常用数据类型:字符串string、哈希hash、列表list、集合set、有序集合sorted set/ zset

在这里插入图片描述

  • 字符串(string):普通字符串,Redis中最简单的数据类型。
  • 哈希(hash):也叫散列,类似于Java中的HashMap结构。可以用来存对象
  • 列表(list):按照插入顺序排序,可以有重复元素,类似于Java中的LinkedList,可以永来存有顺序的数据
  • 集合(set):无序集合,没有重复元素,类似于Java中的HashSet,可以进行集合间的计算(交集、并集)
  • 有序集合(sorted set / zset):集合中每个元素关联一个分数(score)根据分数升序排序,没有重复元素

3、Redis常用命令

3.1 字符串操作命令
set key value  //设置指定key的值(如果存在key,那么就修改value) 如:set name  小明  get key       //获取指定key的值 如:get  namesetex key seconds value //设置指定key的值,并将key的过期时间设为seconds秒,如:setex code 2 123setnx  key value     //只有在key不存在时设置key的值(如果存在key不能修改value)  setnx sex 男
3.2 哈希操作命令

Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象,常用命令:

在这里插入图片描述

hset key field value  //将哈希表key中的字段field的值设为value
//如:hset 100 name 小明    hset 100 set 男hget key field    //获取存储在哈希表中指定字段的值
//如:hget  100 name   获取属性name的value值:小明hkeys key    //获取哈希表中所有字段
//如:hkeys 100   结果为:name、sethvals key    //获取哈希表中所有值
//如:hvals 100  结果为:小明、男hdel key field   //删除存储在哈希表中的指定字段
//如:hdel  100  sex  删除set属性
3.3 列表操作命令

Redis列表(list)是简单的字符串列表,按照插入顺序排序,常用命令

在这里插入图片描述

lpush key value1 [value2]  //将一个或多个值插入到列表头部(left左边插入)rpush key value1 [value2]  //将一个或多个值插入到列表头部(right右边插入)lrange key start stop   //获取列表指定范围内的元素(下标从0开始)
//lrange key 0 -1  可返回列表里的全部数据 rpop  key    //移除并获取列表最后一个元素lpop  key    //移除并获取列表最前面一个元素llen  key    //获取列表长度
3.4 集合操作命令

Redis set是string类型的无序集合。集合成员是唯大-的,集合中不能出现重复的数据,常用命令:

在这里插入图片描述

sadd key member1 [member2]   //向集合添加一个或多个成员smembers  key                //返回集合中的所有成员scard  key                   //获取集合的成员数sinter  key1 [key2]         //返回给定所有集合的交集sunion key1 [key2]            //返回所有给定集合的并集srem  key member1 [member2]  //删除集合中一个或多个成员
3.5 有序集合操作命令

Redis有序集合是string类型元素的集合(zset),且不允许有重复成员。每个元素都会关联一个double类型的分数。通过关联一个double类型的分数来对集合进行排序, 常用命令:

在这里插入图片描述

zadd key score1 member1 [score2 member2]     //向有序集合添加一个或多个成员zrange key start stop [WITHSCORES]          //通过索引区间返回有序集合中指定区间内的成员
//加上WITHSCORES 可以输出对应的member,zrange key 0 -1 输出全部的scorezincrby key increment member      //有序集合中对指定成员的分数加上增量ZREM key member [member ...]                //移除有序集合中的一个或多个成员
3.6 通用命令

Redis的通用命令是不分数据类型的,都可以使用的命令:

keys pattern    //查找所有符合给定模式(pattern)的key(正则表达式)exists key       //检查给定key是否存在type key         //返回key所储存的值的类型del key1 [key2]          //该命令用于在key存在时删除key 

4、在java中如何操作Redis

4.1 Redis的java客户端

Redis的Java客户端很多,常用的几种:Jedis(官方推荐的)、Lettuce、Spring Data Redis。

Spring Data Redis是Spring的一部分,对Redis底层开发包进行了高度封装。在Spring项目中,可以使用Spring Data Redis来简化操作。

4.2 Spring Date Redis使用方式

操作步骤:

  1. 导入Spring Data Redis的maven坐标

    <dependency>
    <groupId>org.springframework.boot</ groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
  2. 配置Redis数据源

    spring:data:redis:host: localhostport: 6379password: 123456
    
  3. 编写配置类,创建Redis Template对象

    // redis配置类
    @Configuration
    @Slf4j
    public class RedisConfiguration {// 配置redisTemplate@Beanpublic RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){log.info("redisTemplate初始化中...");RedisTemplate redisTemplate = new RedisTemplate();// 设置redis的连接工厂对象redisTemplate.setConnectionFactory(redisConnectionFactory);// 设置redis字符串类型的key的序列化器StringRedisSerializer stringSerializer = new StringRedisSerializer();redisTemplate.setKeySerializer(stringSerializer);   //字符串类型的key设置为StringredisTemplate.setHashKeySerializer(stringSerializer); //哈希类型的key设置为String// 设置Redis中value的序列化器(对象类型)Jackson2JsonRedisSerializer<Object> jacksonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);redisTemplate.setValueSerializer(jacksonSerializer);  redisTemplate.setHashValueSerializer(jacksonSerializer);// 触发 afterPropertiesSet 方法redisTemplate.afterPropertiesSet();return redisTemplate;}
    }
    
  4. 通过Redis Template对象操作Redis

    @SpringBootTest
    public class RedisTest {@Autowiredprivate RedisTemplate redisTemplate;@Testvoid testRedis() {//创建一个字符串类型的redis操作对象ValueOperations valueOperations = redisTemplate.opsForValue();// 创建一个哈希类型的redis操作对象HashOperations hashOperations = redisTemplate.opsForHash();// 创建一个列表类型的redis操作对象ListOperations listOperations = redisTemplate.opsForList();//创建一个集合类型的redis操作对象SetOperations setOperations = redisTemplate.opsForSet();//创建一个有序集合类型的redis操作对象ZSetOperations zSetOperations = redisTemplate.opsForZSet();}}
    
4.2.1 Redis字符存取串类型操作
   @Testvoid stringRedis(){/*** String类型Redis:set、get、setnx、setex*///创建一个字符串类型的redis操作对象ValueOperations valueOperations =redisTemplate.opsForValue();// 设置值valueOperations.set("name","yzhy");// 获取值String name =(String) valueOperations.get("name");System.out.println(name);// 设置值并设置过期时间(10分钟)valueOperations.set("code","12345",10, TimeUnit.MINUTES);// 设置值,如果key不存在,则设置值valueOperations.setIfAbsent("code", "4321");}
4.2.2 Redis操作Hash类型存取操作
    @Testvoid   ridisHash(){/*** Hash类型Redis:hset、hget、hkeys、hvals、hlen、hdel*/// 创建一个哈希类型的redis操作对象HashOperations hashOperations =redisTemplate.opsForHash();// 设置值hashOperations.put("user","name","yhzy");hashOperations.put("user","age","18");hashOperations.put("user","sex","男");//取值String age = (String) hashOperations.get("user","age");System.out.println(age);// 取keys的集合Set keys = hashOperations.keys("user");for (Object key : keys) {System.out.println(key);}//取values的集合List values = hashOperations.values("user");for(Object value : values){System.out.println(value);}// 取hash的长度Long size = hashOperations.size("user");System.out.println(size);// 删除hashOperations.delete("user","age");}
}
4.2.3 Redis操作List数据类型
    @Testvoid redisList(){/*** List类型Redis:lpush、rpush、lpop、rpop、lrange、lrem、lset、lindex、llen*/ListOperations listOperations = redisTemplate.opsForList();listOperations.rightPush("list","小明");listOperations.rightPush("list","小梅");listOperations.leftPushAll("list","小红","小刚");String name = (String) listOperations.index("list",0);System.out.println(name);List<String> list =listOperations.range("list",0,-1);for (String s : list) {System.out.println(s);}Long size = listOperations.size("list");System.out.println(size);listOperations.leftPop("list");}
}
4.2.4 Redis操作Set集合数据类型
   @Testvoid redisSet(){/*** Set类型Redis:sadd、srem、smembers、scard、sismember、srandmember、sinter、sunion*/// 创建一个集合类型的redis操作对象SetOperations setOper=  redisTemplate.opsForSet();setOper.add("fruitName1","苹果","香蕉","橘子");setOper.add("fruitName2","苹果","草莓","葡萄");Set<String> fruitNames= setOper.members("fruitName1");for (String fruitName : fruitNames){System.out.println(fruitName);}System.out.println(setOper.size("fruitName1"));// 判断是否包含System.out.println(setOper.isMember("fruitName1","香蕉"));//   求交集Set<String> fruitIntersect = setOper.intersect("fruitName1","fruitName2");for (String fruit : fruitIntersect){System.out.println(fruit);}System.out.println("=====================");// 求并集Set<String> fruitUnion = setOper.union("fruitName1","fruitName2");for (String fruit : fruitUnion){System.out.println(fruit);}}
4.2.5 Redis有序集合数据类型操作
   @Testvoid redisZSet(){/*** ZSet类型Redis:zadd、zrem、zrange、zrevrange、zcard、zscore、zrank、zrevrank、zcount、zrangebyscore、zremrangebyrank、zremrangebyscore*/// 创建一个有序集合类型的redis操作对象ZSetOperations zSetOper= redisTemplate.opsForZSet();zSetOper.add("scors","小明",100);zSetOper.add("scors","小红",90);zSetOper.add("scors","小刚",98);System.out.println(zSetOper.size("scors"));System.out.println(zSetOper.score("scors","小刚"));//默认升序排序Set  scors =  zSetOper.range("scors",0,-1);for (Object o : scors){System.out.println(o);}System.out.println("======================");// 倒序Set  scors1 =  zSetOper.reverseRange("scors",0,-1);for (Object o : scors1){System.out.println(o);}// 删除zSetOper.remove("scors","小刚","小红");}
4.2.6 Redis通用命令
    @Testvoid redisCommon(){/*** Redis通用操作:keys、etits、type、del*/// 获取所有的key(正则表达式)Set<String> keys = redisTemplate.keys("*");for (String key : keys) {System.out.print(redisTemplate.type(key)+" ");System.out.println(key);}// 判断key是否存在Boolean isExist = redisTemplate.hasKey("name");System.out.println(isExist);// 删除对应keyredisTemplate.delete("name");}

5、场景运用设计

5.1 存储营业状态

外卖商家,右自己的外卖管理端,可以添加菜品对外售卖,售卖前,需要将店铺的营业状态从打样中设置为营业中,其中这个状态,是保存到Redis中的。(0代表:打样中;1代表:营业中)

@RestController
@RequestMapping("/admin/shop")
public class ShopController {private static final String KEY="SHOP_STATUS_KEY";@Autowiredprivate RedisTemplate redisTemplate;/*** 设置店铺状态* @param status* @return*/@Operation(summary = "设置店铺状态")@PutMapping("/{status}")public Result setShopStatus(@PathVariable Integer status) {redisTemplate.opsForValue().set(KEY,status);return Result.success("设置成功",status);}/*** 获取店铺状态* @return*/@Operation(summary = "获取店铺状态")@GetMapping("/status")public Result getShopStatus(){Integer status =(Integer) redisTemplate.opsForValue().get(KEY);return Result.success("获取成功",status);}
}
5.2 存储和清除菜品数据

菜品分类喝套餐分类进行存储,其中分类ID作为存储的key,分类里面包含的数据作为value,来存储。

每当通过菜品分类id或者套餐分类id,来对数据进行查询时,进行先查询Redis里面是否有对应的数据,如果没有才查询数据库,从数据库里面查询出来的结果,再缓存到Redis中。

如果,对菜品,或者套装进行增删改操作时,就会将Redis中对应的一组key进行清除,如(dish_*、setmeal_*)

//查询数据@RestController("userDishController")
@RequestMapping("/user/dish")
public class DishController {@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate DishService  dishService;@Operation(summary = "根据分类ID菜品列表")@GetMapping("/list")public Result list(Long categoryId){//1、构建KeyString key = "dish_"+categoryId;//2、查询Redis缓存List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(key);//3、判断缓存是否存在,存在就获取缓存,并返回if(list!=null && list.size()>0){return Result.success(list);}//4、缓存不存在,查询数据库Dish dish = new Dish();dish.setCategoryId(categoryId);list = dishService.getDishWithFlavorListByCategoryId(dish);//5、将查询结果保存到Redis缓存中(存什么类型的数据,就用什么类型的变量接收)redisTemplate.opsForValue().set(key,list);return Result.success(list);}
}
//清除缓存
@RestController
@RequestMapping("/admin/dish")
@Slf4j
public class DishController {@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate DishService  dishService;/*** 添加菜品* @param dishDto* @return*/@Operation(summary = "添加菜品")@PostMappingpublic Result addDish(@RequestBody DishDTO dishDto) {int insert = dishService.addDish(dishDto);if (insert==0) {return Result.error("添加菜品失败");}//单独清除对应key的缓存String key="dish_"+dishDto.getCategoryId();clearCache(key);return Result.success();}/*** 批量删除菜品* @param ids* @return*/@Operation(summary = "批量删除菜品")@DeleteMappingpublic Result deleteDish(@RequestParam List<Long> ids) {int delete =  dishService.deleteBatch(ids);if (delete==0){return Result.error("删除失败");}//清理全部key以dish_开头缓存clearCache("dish_*");return Result.success();}@Operation(summary = "修改菜品")@PutMappingpublic  Result updateDishWithFlavor(@RequestBody DishDTO dishDto){log.info("修改菜品:"+dishDto.toString());int updateNum=dishService.updateDishWithFlavor(dishDto);if (updateNum==0){return Result.error("修改失败");}//清理全部key以dish_开头缓存clearCache("dish_*");return Result.success();}/*** 清理缓存* @param pattern*/private void clearCache(String pattern){//1、查询出要清理对应缓存的keys,keys方法的参数可以匹配一个通配符,如:dish_*Set<String> keys = redisTemplate.keys(pattern);//2、清理缓存(可以传入一个集合)redisTemplate.delete(keys);}
}

6、Spring Cache

Spring Cache是一个框架, 实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。

Spring Cache提供了一层抽象, 底层可以切换不同的缓存实现,例如:EHCache、Caffeine、Redis。

它会自动识别你所使用的缓存,只需要你导入对应缓存的jar包,如果你想使用Redis,做为缓存工具的话,你就导入Redis的jar包;如果你想使用EHCache作为缓存的话,你就导入 EHCache 的jar包。

<!--Spring Cache-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>2.7.3</version>
</dependency>
Spring Cache提供的注解说明
@EnableCaching开启缓存注解功能,通常加再启动类上面
@Cacheable通常加到方法上,在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据;如果没有缓存数据,则调用方法并将方法返回值放到缓存中。
@CachePut加到方法上,将方法的放回值放到缓存中,只放不取
@CacheEvict将一条或多条数据从缓存中删除

具体的实现思路如下:

  1. 导入Spring Cache和Redis相关maven坐标。
  2. 在启动类上加入@EnableCaching注解, 开启缓存注解功能。
  3. 在Controller层的查询方法上加上注解@Cacheable。
  4. 在Controller层的保存、删除、更新等方法上加上注解@CacheEvict。
6.1 @CachePut 注解

加到方法上,将方法的放回值放到缓存中,只放不取;使用步骤,及其注意事项

格式: @CachePut(cacheName="userCache",key="#user.id")

cacheName:就是Redis(或其他缓存工具)的key的前半部分,可以任意字符串,通常是:类名+Cache

key:就是Redis(或其他缓存工具)的key的后半部分,是动态的,这里使用的是Spring表达式来获取到对象的id属性,作为后半部分。#表示Spring表达式;user表示,形参里的user对象;id表示将数据添加到数据库后,返回到形参中user对象里id属性的值。

完整的key,中间由双冒号分隔如:userCache::1、userCache::2

  1. 在导入对应jar包后,在启动类上加上注解:@EnableCaching

    @SpringBootApplication
    @EnableCaching //开启缓存注解功能
    public class SkyServerApplication {public static void main(String[] args) {SpringApplication.run(SkyServerApplication.class, args);}
    }
    
  2. Mapper层

    @Mapper
    public interface UserMapper {@Insert("insert into user(name,sex,age) values(#{name},#{sex},#{age})")@Options(useGenteratedKeys=true,keyProperty="id")  //插入数据完成后将id返回到对象中void addUser(User user);
    }
    
  3. Service层不变,以前怎么写现在就怎么写

    @Service
    public UserServiceImpl implements UserService {@AutoWriteprivate UserMapper  userMapper;@Overridepublic User addUser(User user){userMapper.addUser(user); return;  }
    }
    
  4. Controller层

    将注解加入到Controller成的方法上

    @RestController
    @RequestMapping("/user")
    public class UserController {@Autowiredprivate UserService userService;/**
    cacheName:就是Redis(或其他缓存工具)的key的前半部分,可以任意字符串,通常是:类名+Cache
    key:就是Redis(或其他缓存工具)的key的后半部分,是动态的,这里使用的是Spring表达式来获取到对象的id属性,作为后半部分。#表示Spring表达式;user表示,形参里的user;id表示将数据添加到数据库后,返回到user对象里id属性的值。
    完整的key,中间由双冒号分隔如:userCache::1、userCache::2*/@PostMapping@CachePut(cacheName="userCache",key="#user.id")  //最常使用//@CachePut(cacheName="userCache",key="#result.id") //表示返回结果中的user对象的id//@CachePut(cacheName="userCache",key="#p0.id") //表示形参中的第一个参数中的id//@CachePut(cacheName="userCache",key="#a0.id") //表示形参中的第一个参数中的idpublic Result adduser(@RequesBody User user){userService.addUser(user)return Result.success(user);}}
    
6.2 @Cacheable注解

在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据;如果没有缓存数据,则调用方法并将方法返回值放到缓存中。

格式: @CachePut(cacheName="userCache",key="#id") ,key的值要根据形参来变化,保证与存储的key所对应。

  1. Controller层
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@GetMapping// //如果有缓存就获取对应key的缓存,如果没有就执行方法,获取数据库数据存入缓存@Cacheable(cacheName="userCache",key="#id")  //生成的key如:userCache::2public Result getUserById(Long id){User user= userService.getUserById(id)return Result.success(user);}}
6.3 @CacheEvict注解

将一条或多条数据从缓存中删除

  1. Controller层

    @RestController
    @RequestMapping("/user")
    public class UserController {@Autowiredprivate UserService userService;/**删除指定key的缓存数据*/@DeleteMapping// 将对应key的缓存进行清除@CacheEvict(cacheName="userCache",key="#id")  //生成的key如:userCache::2public Result deleteUserById(Long id){User user= userService.deleteUserById(id)return Result.success();}/**删除以某某key开头的全部缓存数据,这里是以:userCache开头的全部数据*/@DeleteMapping@CacheEvict(cacheName="userCache",allEntries=true)  //生成的key如:userCache::*public Result deleteAllUser(){User user= userService.deleteAllUser()return Result.success();}}
    
http://www.lryc.cn/news/467827.html

相关文章:

  • 【C++】在Windows中使用Boost库——实现TCP、UDP通信
  • 怎么提取pdf的某一页?批量提取pdf的某一页的简单方法
  • Github优质项目推荐(第八期)
  • 快读快写模板
  • make_blobs函数
  • 特斯拉Optimus:展望智能生活新篇章
  • 基于Leaflet和SpringBoot的全球国家综合检索WebGIS可视化
  • 【Linux】/usr/share目录
  • Java中如何应用序列化 serialVersionUID 版本号呢?
  • 面部识别技术:AI 如何识别人脸
  • 全面解析文档对象模型(DOM)及其操作(DOM的概念与结构、操作DOM节点、描述DOM树的形成过程、用DOMParser解析字符串为DOM对象)
  • 字符串使用方法:
  • 想让前后端交互更轻松?alovajs了解一下?
  • E/MicroMsg.SDK.WXMediaMessage:checkArgs fail,thumbData is invalid 图片资源太大导致分享失败
  • No.21 笔记 | WEB安全 - 任意文件绕过详解 part 3
  • 咸鱼自动发货 免费无需授权
  • Netty核心组件
  • Windows中如何安装SSH
  • 在linux上部署ollama+open-webu,且局域网访问教程
  • 基于大模型的招聘智能体:从创意到MVP
  • STM32F1+HAL库+FreeTOTS学习19——软件定时器
  • @RequestBody的详解和使用
  • VMware介绍及常见使用方法
  • Deepinteraction 深度交互:通过模态交互的3D对象检测
  • 开展物业满意度调查的策略与注意事项
  • 如何使用 Maven 不同环境使用不同资源文件 提升项目安全性
  • QT 如何置顶窗口并激活
  • 嵌入式面试刷题(day19)
  • Robot Framework命令和Tag运用
  • 软件分享丨PDF Shaper