基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖集成Redis(九)
作者:mmseoamin日期:2023-12-13

Redis结合店铺营业状态设计

    • 1.在Java中操作Redis
      • 1.1 Redis的Java客户端
      • 1.2 Spring Data Redis使用方式
        • 1.2.1 介绍
        • 1.2.2 环境搭建
        • 1.2.3 操作常见类型数据
        • 2. 店铺营业状态设置
          • 2.1 需求分析和设计
            • 2.1.1 产品原型
            • 2.1.2 接口设计
            • 2.1.3 营业状态存储方式
            • 2.2 代码开发
              • 2.2.1 设置营业状态
              • 2.2.2 管理端查询营业状态
              • 2.2.3 用户端查询营业状态
              • 2.3 功能测试

                1.在Java中操作Redis

                1.1 Redis的Java客户端

                Redis 的 Java 客户端很多,常用的几种:

                • Jedis
                • Lettuce
                • Spring Data Redis

                  Spring 对 Redis 客户端进行了整合,提供了 Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即 spring-boot-starter-data-redis。

                  1.2 Spring Data Redis使用方式

                  1.2.1 介绍

                  Spring Data Redis 是 Spring 的一部分,提供了在 Spring 应用中通过简单的配置就可以访问 Redis 服务,对 Redis 底层开发包进行了高度封装。在 Spring 项目中,可以使用Spring Data Redis来简化 Redis 操作

                  网址:https://spring.io/projects/spring-data-redis

                  基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖集成Redis(九),在这里插入图片描述,第1张

                  Spring Boot提供了对应的Starter,maven坐标:

                  
                  	org.springframework.boot
                  	spring-boot-starter-data-redis
                  
                  

                  Spring Data Redis中提供了一个高度封装的类:RedisTemplate,对相关api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:

                  • ValueOperations:string数据操作
                  • SetOperations:set类型数据操作
                  • ZSetOperations:zset类型数据操作
                  • HashOperations:hash类型的数据操作
                  • ListOperations:list类型的数据操作
                    1.2.2 环境搭建

                    进入到sky-server模块

                    1). 导入Spring Data Redis的maven坐标

                    
                         org.springframework.boot
                         spring-boot-starter-data-redis
                    
                    

                    2). 配置Redis数据源

                    在application-dev.yml中添加

                    sky:
                      redis:
                        host: localhost
                        port: 6379
                        password: 123456
                        database: 10
                    

                    解释说明:

                    database:指定使用Redis的哪个数据库,Redis服务启动后默认有16个数据库,编号分别是从0到15。

                    可以通过修改Redis配置文件来指定数据库的数量。

                    在application.yml中添加读取application-dev.yml中的相关Redis配置

                    spring:
                      profiles:
                        active: dev
                      redis:
                        host: ${sky.redis.host}
                        port: ${sky.redis.port}
                        password: ${sky.redis.password}
                        database: ${sky.redis.database}
                    

                    3). 编写配置类,创建RedisTemplate对象

                    package com.sky.config;
                    @Configuration
                    @Slf4j
                    public class RedisConfiguration {
                        @Bean
                        public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
                            log.info("开始创建redis模板对象...");
                            RedisTemplate redisTemplate = new RedisTemplate();
                            //设置redis的连接工厂对象
                            redisTemplate.setConnectionFactory(redisConnectionFactory);
                            //设置redis key的序列化器
                            redisTemplate.setKeySerializer(new StringRedisSerializer());
                            return redisTemplate;
                        }
                    }
                    

                    解释说明:

                    当前配置类不是必须的,因为 Spring Boot 框架会自动装配 RedisTemplate 对象,但是默认的key序列化器为

                    JdkSerializationRedisSerializer,导致我们存到Redis中后的数据和原始数据有差别,故设置为

                    StringRedisSerializer序列化器。

                    4). 通过RedisTemplate对象操作Redis

                    在test下新建测试类

                    package com.sky.test;
                    @SpringBootTest
                    public class SpringDataRedisTest {
                        @Autowired
                        private RedisTemplate redisTemplate;
                        @Test
                        public void testRedisTemplate(){
                            System.out.println(redisTemplate);
                            //string数据操作
                            ValueOperations valueOperations = redisTemplate.opsForValue();
                            //hash类型的数据操作
                            HashOperations hashOperations = redisTemplate.opsForHash();
                            //list类型的数据操作
                            ListOperations listOperations = redisTemplate.opsForList();
                            //set类型数据操作
                            SetOperations setOperations = redisTemplate.opsForSet();
                            //zset类型数据操作
                            ZSetOperations zSetOperations = redisTemplate.opsForZSet();
                        }
                    }
                    

                    测试:

                    基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖集成Redis(九),在这里插入图片描述,第2张

                    说明RedisTemplate对象注入成功,并且通过该RedisTemplate对象获取操作5种数据类型相关对象。

                    1.2.3 操作常见类型数据

                    1). 操作字符串类型数据

                    	/**
                         * 操作字符串类型的数据
                         */
                        @Test
                        public void testString(){
                            // set get setex setnx
                            redisTemplate.opsForValue().set("name","小明");
                            String city = (String) redisTemplate.opsForValue().get("name");
                            System.out.println(city);
                            redisTemplate.opsForValue().set("code","1234",3, TimeUnit.MINUTES);
                            redisTemplate.opsForValue().setIfAbsent("lock","1");
                            redisTemplate.opsForValue().setIfAbsent("lock","2");
                        }
                    

                    2). 操作哈希类型数据

                    	/**
                         * 操作哈希类型的数据
                         */
                        @Test
                        public void testHash(){
                            //hset hget hdel hkeys hvals
                            HashOperations hashOperations = redisTemplate.opsForHash();
                            hashOperations.put("100","name","tom");
                            hashOperations.put("100","age","20");
                            String name = (String) hashOperations.get("100", "name");
                            System.out.println(name);
                            Set keys = hashOperations.keys("100");
                            System.out.println(keys);
                            List values = hashOperations.values("100");
                            System.out.println(values);
                            hashOperations.delete("100","age");
                        }
                    

                    3). 操作列表类型数据

                    	/**
                         * 操作列表类型的数据
                         */
                        @Test
                        public void testList(){
                            //lpush lrange rpop llen
                            ListOperations listOperations = redisTemplate.opsForList();
                            listOperations.leftPushAll("mylist","a","b","c");
                            listOperations.leftPush("mylist","d");
                            List mylist = listOperations.range("mylist", 0, -1);
                            System.out.println(mylist);
                            listOperations.rightPop("mylist");
                            Long size = listOperations.size("mylist");
                            System.out.println(size);
                        }
                    

                    4). 操作集合类型数据

                    	/**
                         * 操作集合类型的数据
                         */
                        @Test
                        public void testSet(){
                            //sadd smembers scard sinter sunion srem
                            SetOperations setOperations = redisTemplate.opsForSet();
                            setOperations.add("set1","a","b","c","d");
                            setOperations.add("set2","a","b","x","y");
                            Set members = setOperations.members("set1");
                            System.out.println(members);
                            Long size = setOperations.size("set1");
                            System.out.println(size);
                            Set intersect = setOperations.intersect("set1", "set2");
                            System.out.println(intersect);
                            Set union = setOperations.union("set1", "set2");
                            System.out.println(union);
                            setOperations.remove("set1","a","b");
                        }
                    

                    5). 操作有序集合类型数据

                    	/**
                         * 操作有序集合类型的数据
                         */
                        @Test
                        public void testZset(){
                            //zadd zrange zincrby zrem
                            ZSetOperations zSetOperations = redisTemplate.opsForZSet();
                            zSetOperations.add("zset1","a",10);
                            zSetOperations.add("zset1","b",12);
                            zSetOperations.add("zset1","c",9);
                            Set zset1 = zSetOperations.range("zset1", 0, -1);
                            System.out.println(zset1);
                            zSetOperations.incrementScore("zset1","c",10);
                            zSetOperations.remove("zset1","a","b");
                        }
                    

                    6). 通用命令操作

                    	/**
                         * 通用命令操作
                         */
                        @Test
                        public void testCommon(){
                            //keys exists type del
                            Set keys = redisTemplate.keys("*");
                            System.out.println(keys);
                            Boolean name = redisTemplate.hasKey("name");
                            Boolean set1 = redisTemplate.hasKey("set1");
                            for (Object key : keys) {
                                DataType type = redisTemplate.type(key);
                                System.out.println(type.name());
                            }
                            redisTemplate.delete("mylist");
                        }
                    

                    2. 店铺营业状态设置

                    2.1 需求分析和设计

                    2.1.1 产品原型

                    进到苍穹外卖后台,显示餐厅的营业状态,营业状态分为营业中和打烊中,若当前餐厅处于营业状态,自动接收任何订单,客户可在小程序进行下单操作;若当前餐厅处于打烊状态,不接受任何订单,客户便无法在小程序进行下单操作。

                    基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖集成Redis(九),在这里插入图片描述,第3张

                    状态说明:

                    基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖集成Redis(九),在这里插入图片描述,第4张

                    2.1.2 接口设计

                    根据上述原型图设计接口,共包含3个接口。

                    接口设计:

                    • 设置营业状态
                    • 管理端查询营业状态
                    • 用户端查询营业状态

                      注:从技术层面分析,其实管理端和用户端查询营业状态时,可通过一个接口去实现即可。因为营业状态是一致的。但是,本项目约定:

                      • 管理端发出的请求,统一使用/admin作为前缀。
                      • 用户端发出的请求,统一使用/user作为前缀。

                        因为访问路径不一致,故分为两个接口实现。

                        1). 设置营业状态

                        基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖集成Redis(九),在这里插入图片描述,第5张

                        2). 管理端营业状态

                        基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖集成Redis(九),在这里插入图片描述,第6张

                        3). 用户端营业状态

                        基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖集成Redis(九),在这里插入图片描述,第7张

                        2.1.3 营业状态存储方式

                        虽然,可以通过一张表来存储营业状态数据,但整个表中只有一个字段,所以意义不大。

                        营业状态数据存储方式:基于Redis的字符串来进行存储

                        基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖集成Redis(九),在这里插入图片描述,第8张

                        约定:1表示营业 0表示打烊

                        2.2 代码开发

                        2.2.1 设置营业状态

                        在sky-server模块中,创建ShopController.java

                        根据接口定义创建ShopController的setStatus设置营业状态方法:

                        package com.sky.controller.admin;
                        @RestController("adminShopController")
                        @RequestMapping("/admin/shop")
                        @Api(tags = "店铺相关接口")
                        @Slf4j
                        public class ShopController {
                            public static final String KEY = "SHOP_STATUS";
                            @Autowired
                            private RedisTemplate redisTemplate;
                            /**
                             * 设置店铺的营业状态
                             * @param status
                             * @return
                             */
                            @PutMapping("/{status}")
                            @ApiOperation("设置店铺的营业状态")
                            public Result setStatus(@PathVariable Integer status){
                                log.info("设置店铺的营业状态为:{}",status == 1 ? "营业中" : "打烊中");
                                redisTemplate.opsForValue().set(KEY,status);
                                return Result.success();
                            }
                        }
                        
                        2.2.2 管理端查询营业状态

                        根据接口定义创建ShopController的getStatus查询营业状态方法:

                        	/**
                             * 获取店铺的营业状态
                             * @return
                             */
                            @GetMapping("/status")
                            @ApiOperation("获取店铺的营业状态")
                            public Result getStatus(){
                                Integer status = (Integer) redisTemplate.opsForValue().get(KEY);
                                log.info("获取到店铺的营业状态为:{}",status == 1 ? "营业中" : "打烊中");
                                return Result.success(status);
                            }
                        
                        2.2.3 用户端查询营业状态

                        创建com.sky.controller.user包,在该包下创建ShopController.java

                        根据接口定义创建ShopController的getStatus查询营业状态方法:

                        package com.sky.controller.user;
                        @RestController("userShopController")
                        @RequestMapping("/user/shop")
                        @Api(tags = "店铺相关接口")
                        @Slf4j
                        public class ShopController {
                            public static final String KEY = "SHOP_STATUS";
                            @Autowired
                            private RedisTemplate redisTemplate;
                            /**
                             * 获取店铺的营业状态
                             * @return
                             */
                            @GetMapping("/status")
                            @ApiOperation("获取店铺的营业状态")
                            public Result getStatus(){
                                Integer status = (Integer) redisTemplate.opsForValue().get(KEY);
                                log.info("获取到店铺的营业状态为:{}",status == 1 ? "营业中" : "打烊中");
                                return Result.success(status);
                            }
                        }
                        

                        2.3 功能测试

                        设置状态,查看Idea控制台日志;

                        基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖集成Redis(九),在这里插入图片描述,第9张

                        查看Redis中数据;

                        基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖集成Redis(九),在这里插入图片描述,第10张

                        后记

                        👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹