苍穹外卖资源点整理+个人错误解析-Day05-Redis、店铺营业状态设置
一.Redis入门
简介
是基于内存的key-value的结构数据库

优势:
基于内存读取,读写性能高
适合存储热点数据(热点商品、资讯、新闻)
企业应用广泛
如何打开redis
1.找到redis安装文件夹
2.在该文件夹打开cmd
3.输入指令:redis-serve+tab键+空格+redis.window+tab键.
想关闭crtl+c
4.新建一个cmd,输入redis-cli+tab键
想退出客户端直接输入exit
想连接其他接口的redis: redis-cli.exe -h localhost -p 端口号
给redis设置密码
1.打开该配置文件

2.使用crtl+f打开搜索,搜索pass

3.设置密码,将#删除,将foobared改成自己设置的密码

4.设置密码后进入redis:
redis-cli.exe -h localhost -p 端口号 -a 设置的密码
二.Redis数据类型
一共有五种常用的数据类型

大致特点

字符串string
普通字符串,最简单的数据类型

哈希hash
也叫散列,类似于java中的HashMap结构,比较适合存储一些对象

列表list
类似于一个队列,按照插入顺序排序,可以有重复元素,类似于java中的LinkedList

集合set
无序集合没有重复元素,类似于java中的hashset

有序集合sorted set/zset
集合中每个元素关联一个分数(score),根据分数升序排序,无重复元素

三.Redis常用命令
在redis中,不同的数据类型有不同的操作命令。
字符串操作命令

在redis客户端进行演示:
打开redis控制台:

进行数据添加:set key value

点击name,可以看见插入的数据

进行数据查询:get key

进行数据添加并制定过期的时间(单位为秒):setex key seconds value

30s一过,会显示不存在
只有在key不存在时设置key的值:setnx key value

点击key1发现里面的值为id:

哈希操作命令

将哈希表 key 中的字段 field 的值设为 value
hset key field value

获取存储在哈希表中指定字段的值
hget key field

删除存储在哈希表中的指定字段
hdel key field

获取哈希表中所有字段
hkeys key

获取哈希表中所有值
hvals key

列表操作命令


将一个或多个值插入到列表头部
lpush key value1[value2],注意的是lpush中的l指的是left而不是list


注意顺序,发现d在最上面
如果我再插入一个元素e:


获取列表指定范围内的元素
lrange key start stop

从0到-1指全部返回:
0表示列表的第一个元素(头部元素)。-1表示列表的最后一个元素(尾部元素)。
移除并获取列表最后一个元素
rpop key


获取列表长度
llen key

集合操作命令


向集合添加一个或多个成员
sadd key member1[member2],sadd的s指的是set


顺序和插入的顺序无关,是无序的

并且不能有重复元素
返回集合中的所有成员
smembers key

获取集合的成员数
scard key

返回给定所有集合的交集
sinter key1[key2]
![]()

返回所有给定集合的并集
sunion key1[key2]

删除集合中一个或多个成员
srem key member1[member2]


成功删除a
有序集合操作命令


向有序集合添加一个或多个成员
zadd key score1 member1[score2 member2] 这个z指的是zset,即有序集合


通过索引区间返回有序集合中指定区间内的成员
zrange key start stop[withscores]


有序集合中对指定成员的分数加上增量 increment
zincrby key increment member

移除有序集合中的一个或多个成员
zrem key member [member]


通用命令

查找所有符合给定模式 (pattern) 的 key
keys pattern

这是查找以set开头的
检查给定 key 是否存在
exists key

返回 key 所储存的值的类型
type key

该命令用于在 key 存在时删除 key
del key

四.在java中操作Redis
redis的java客户端

spring data redis使用方式


① 导入 Spring Data Redis 的 maven 坐标
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
② 配置 Redis 数据源
redis:host: localhostport: 6379 # 这个是管理数据库,redis默认提供了16个数据库,0~15选择一个,每个库数据不相通,不配置的话默认使用0database: 1
但不推荐直接放在application.yml文件中,一般放在application-dev.yml文件中


③ 编写配置类,创建 RedisTemplate 对象

@Configuration
@Slf4j
public class RedisConfiguration {@Beanpublic RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){log.info("开始创建redis模板对象……");RedisTemplate redisTemplate = new RedisTemplate();//设置redis的连接工厂对象redisTemplate.setConnectionFactory(redisConnectionFactory);//设置redis key的序列化器redisTemplate.setKeySerializer(new StringRedisSerializer()) ;return redisTemplate;}
}通过测试类说明配置成功:
测试类代码:
@SpringBootTest
public class SpringDateRedisTest {@Autowiredprivate RedisTemplate redisTemplate;@Testpublic void testRedisTemplate(){System.out.println(redisTemplate);ValueOperations valueOperations=redisTemplate.opsForValue();HashOperations hashOperations=redisTemplate.opsForHash();ListOperations listOperations = redisTemplate.opsForList();SetOperations setOperations = redisTemplate.opsForSet();ZSetOperations zSetOperations = redisTemplate.opsForZSet();}
}
④ 通过 RedisTemplate 对象操作 Redis
操纵string类型数据
@Test
//操作字符串类型数据
public void testString(){//set get setex(设置有效期) setnx(不存在则创建)//setredisTemplate.opsForValue().set("city","bj");String city = (String) redisTemplate.opsForValue().get("city");System.out.println(city);//setex(设置有效期)redisTemplate.opsForValue().set("code","1234",3, TimeUnit.MINUTES);//发现此处setIfAbsent()传入的key与value是object类型,而在redis中存储的是string类型//为什么会是object类型呢,因为redis中的string类型与java中的string不完全一致//setnx(不存在则创建)redisTemplate.opsForValue().setIfAbsent("lock","1");redisTemplate.opsForValue().setIfAbsent("lock","2");
}打开redis进入DB1,发现数据成功存储:

但是数据与java程序中输入的不一样,是乱码:

原因是因为:在通过java程序进行插入数据时会对数据进行了序列化,序列化之后就如图所示。
但是key的值不被序列化,这是因为在配置类我们写了序列化器,不写的话也会出现类似乱码的效果。
//设置redis key的序列化器 redisTemplate.setKeySerializer(new StringRedisSerializer()) ;
但事实上value值被序列化并不影响使用,只是在redis客户端查看有点影响。
不设置key的序列化器就会如图所示:

操作哈希数据类型
//操作哈希类型数据
@Test
public void testHash(){//Hset Hget Hdel Hkeys HvalsHashOperations hashOperations = redisTemplate.opsForHash();hashOperations.put("100","name","tom");hashOperations.put("100","age","20");//获取,hgetString name = (String) hashOperations.get("100","name");System.out.println(name);//获取所有key,hkeysSet keys = hashOperations.keys("100");System.out.println(keys);//获取所有value,hvalsList values = hashOperations.values("100");System.out.println(values);//删除,hdelhashOperations.delete("100","age");
}
五.店铺营业状态设置
1.分析
产品原型:

而
此处就是修改的对象。

首先,修改这个状态需要一个接口。
其次,能在前端看到状态,说明需要一个查询类的接口。并且在小程序与商家端都需要查询营业停业状态,理论可以写成一个接口,但本次设计成两个接口,因为约定限制了必须要两个接口:


设置营业状态-修改接口

管理端查询

用户端查询

就为了一个数据存一张表没什么意义,可以使用redis。

2.代码
设置店铺营业状态,前端进行选择营业还是打烊,从而决定status传给后端的是1还是0,然后存到redis数据库中
@RestController
@RequestMapping("/admin/shop")
@Api(tags = "店铺相关接口")
@Slf4j
public class ShopController {@Autowiredprivate RedisTemplate redisTemplate;//状态修改@PutMapping("/{status}")@ApiOperation("设置店铺营业状态")public Result setStatus(@PathVariable Integer status){log.info("设置店铺营业状:{}",status==1?"营业中":"打烊中");
redisTemplate.opsForValue().set("SHOP_STATUS",status);return Result.success();}//商家查看店铺@GetMapping("/status")@ApiOperation("获取店铺营业状态")public Result<Integer> getStatus(){//获取status为0还是1Integer status = (Integer) redisTemplate.opsForValue().get("SHOP_STATUS");log.info("获取店铺营业状态:{}",status==1 ?"营业中":"打烊中");return Result.success(status);}
}然后在用户端:
public class ShopController {@Autowiredprivate RedisTemplate redisTemplate;//商家查看店铺@GetMapping("/status")@ApiOperation("获取店铺营业状态")public Result<Integer> getStatus(){//获取status为0还是1Integer status = (Integer) redisTemplate.opsForValue().get("SHOP_STATUS");log.info("获取店铺营业状态:{}",status==1 ?"营业中":"打烊中");return Result.success(status);}
}但是有一点需要注意:

如图所示在admin包和user包中都有一个ShopController类,如果运行的话会报错,bean的名称会相同,所以需要修改bean类名:


