店铺营业状态设置与查询
注意,先把测试类最上面的SpringBootTest注解注释掉,否则每次启动项目都会自动帮你测试一遍,导致项目启动变慢。
其次,该项目没有设置相应拦截器对付以下情况:用户使用过程中商家突然暂停营业,需要先通过拦截器拦截user的请求,prehandle里先查询店铺状态,如果为0则拦截请求。
业务分析与接口设计
因为无论是查询还是设置,都只有一个字段,那就是营业状态为0或为1.那么为了这单个字段在mysql中创建一张表是很浪费的,而且店铺营业状态每天都需要查询或更新,所以属于热数据,所以我们直接存储到redis里面。
店铺营业状态设置与查询
管理端
在sky-server模块中,创建ShopController.java
package com.sky.controller.admin;
import com.sky.result.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@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();
}
/**
* 获取店铺的营业状态
* @return
*/
@GetMapping("/status")
@ApiOperation("获取店铺的营业状态")
public Result<Integer> getStatus(){
Integer status = (Integer) redisTemplate.opsForValue().get(KEY);
log.info("获取到店铺的营业状态为:{}",status == 1 ? "营业中" : "打烊中");
return Result.success(status);
}
}
代码解释:
1、这里将常量抽取出来但并不封装为常量类是因为这个常量只会用在修改或查询店铺营业状态的时候,不会用在其他地方。所以单独定义在这里就已经够了。
2、在@RestController里额外将该类的bean名称定义为adminShopController,是因为用户端那里也会有个相同的ShopController类,所以要额外重定义bean名称,否则运行会报错。
用户端
创建com.sky.controller.user包,在该包下创建ShopController.java
package com.sky.controller.user;
import com.sky.result.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
@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<Integer> getStatus(){
Integer status = (Integer) redisTemplate.opsForValue().get(KEY);
log.info("获取到店铺的营业状态为:{}",status == 1 ? "营业中" : "打烊中");
return Result.success(status);
}
}
优化接口文档
因为我们开始涉及到第二个端,用户端的接口设计。那么接口文档将所有端的接口放在一起的做法就需要优化改进了。
我们需要在WebMvcConfiguration.java中,指定其分别扫描"com.sky.controller.admin"和"com.sky.controller.user"这两个包。
@Bean
public Docket docket1(){
log.info("准备生成接口文档...");
ApiInfo apiInfo = new ApiInfoBuilder()
.title("苍穹外卖项目接口文档")
.version("2.0")
.description("苍穹外卖项目接口文档")
.build();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.groupName("管理端接口")
.apiInfo(apiInfo)
.select()
//指定生成接口需要扫描的包
.apis(RequestHandlerSelectors.basePackage("com.sky.controller.admin"))
.paths(PathSelectors.any())
.build();
return docket;
}
@Bean
public Docket docket2(){
log.info("准备生成接口文档...");
ApiInfo apiInfo = new ApiInfoBuilder()
.title("苍穹外卖项目接口文档")
.version("2.0")
.description("苍穹外卖项目接口文档")
.build();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.groupName("用户端接口")
.apiInfo(apiInfo)
.select()
//指定生成接口需要扫描的包
.apis(RequestHandlerSelectors.basePackage("com.sky.controller.user"))
.paths(PathSelectors.any())
.build();
return docket;
}
代码解释:
直接生成两个Docket,然后在docket里新增属性叫groupName,分别为端的名字。
重启服务后需要重新输入接口文档的地址:http://localhost:8080/doc.html#/home
然后发现我们由原来的default分组下所有端接口混在一起,变成了可选择用户端或管理端进行查看接口。