项目日志苍穹外卖企业级开发项目《苍穹外卖》(二)
何平安设置店铺营业状态
先去我之前写的博客“Redis数据库学习笔记”学习Redis的基本操作。
在config层下创建Redis的配置类,里面编写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Configuration @Slf4j public class RedisConfiguration {
@Bean public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){ log.info("开始创建redis对象:{}",redisConnectionFactory); RedisTemplate redisTemplate = new RedisTemplate(); redisTemplate.setConnectionFactory(redisConnectionFactory); redisTemplate.setKeySerializer(new StringRedisSerializer()); return redisTemplate; } }
|
然后再在controller层里面创建shop店铺管理的类,里面编写设置店铺状态和查询店铺状态的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @RestController("adminShopController") @Slf4j @Api(tags = "店铺管理") @RequestMapping("/admin/shop") public class ShopController {
@Autowired private RedisTemplate redisTemplate;
@PutMapping("/{status}") @ApiOperation("设置店铺营业状态") public Result setStaus(@PathVariable Integer status){ log.info("设置店铺营业状态:{}",status ==1 ?"营业中": "打烊中"); redisTemplate.opsForValue().set("SHOP_STATUS",status); return Result.success(); }
@GetMapping("/status") @ApiOperation("获取店铺营业状态") public Result<Integer> getStatus(){ Integer shopStatus = (Integer) redisTemplate.opsForValue().get("SHOP_STATUS"); log.info("获取店铺营业状态:{}",shopStatus ==1 ?"营业中": "打烊中"); return Result.success(shopStatus); } }
|
记得在yml和的-dev yml里面配置redis的用户连接信息:
1 2 3 4 5
| redis: host: localhost port: 6379 password: 123456 database: 1
|
接口管理分开管理端和用户端
· 在WebMvcConfiguration里面复制一个bean注解下的代码,并在new Docket下编写.groupName(“管理端接口/用户端接口”),具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
@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; }
|
这样在项目接口文档里面就可以区分开这两个端了。
微信小程序开发
下载微信开发者工具,然后将资料里面的前端文件导入进来,输入自己的openid(openid和小程序appid和secret自己去网上搜),微信小程序开发我博客之前也写过。
将资料里面的用户端文件导入进对应server文件夹里
Spring Cache
maven坐标:
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
|
常用注解:

在苍穹外卖项目中的应用:用于缓存套餐数据,只需在启动类上加入@EnableCaching注解,在admin的SetmealController里面的删改和启动禁用上加上@CacheEvict(cacheNames = “setmealCache”,allEntries = true)注解,增加套餐上添加@CacheEvict(cacheNames = “setmealCache”,key=”#setmealDTO.categoryId”)注解。在user的SetmealController的根据id查询套餐上添加@Cacheable(cacheNames =”setmealCache”,key=”#categoryId”)
购物车管理
后面的购物车管理就跟之前的差不多了,直接上impl的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| @Autowired private ShoppingCartMapper shoppingCartMapper; @Autowired private SetmealMapper setmealMapper; @Autowired private DishMapper dishMapper;
public void addShoppingCart(ShoppingCartDTO shoppingCartDTO) { ShoppingCart shoppingCart=new ShoppingCart(); BeanUtils.copyProperties(shoppingCartDTO,shoppingCart); Long userId= BaseContext.getCurrentId(); shoppingCart.setUserId(userId);
List<ShoppingCart> list =shoppingCartMapper.list(shoppingCart); if (list !=null&& list.size()>0){ ShoppingCart cart=list.get(0); cart.setNumber(cart.getNumber()+1); shoppingCartMapper.updateById(cart); }else { Long dishId = shoppingCart.getDishId(); if (dishId !=null){ Dish dish=dishMapper.getById(dishId); shoppingCart.setName(dish.getName()); shoppingCart.setImage(dish.getImage()); shoppingCart.setAmount(dish.getPrice());
shoppingCart.setNumber(1); shoppingCart.setCreateTime(LocalDateTime.now());
}else { Long setmealId=shoppingCart.getSetmealId(); Setmeal setmeal=setmealMapper.pageById(setmealId); shoppingCart.setName(setmeal.getName()); shoppingCart.setImage(setmeal.getImage()); shoppingCart.setAmount(setmeal.getPrice());
shoppingCart.setNumber(1); shoppingCart.setCreateTime(LocalDateTime.now());
} shoppingCartMapper.insert(shoppingCart); }
}
|
导入收货地址接口(AdressBook)和用户下单接口代码(Order),代码的话就自己去下载看看吧,没啥新技术。
除了用户下单的 ServiceImpl的代码有点难:其他的还将就
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
@Transactional public OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) { AddressBook addressBook = addressBookMapper.getById(ordersSubmitDTO.getAddressBookId()); if (addressBook == null) { throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL); }
Long userId = BaseContext.getCurrentId(); ShoppingCart shoppingCart = new ShoppingCart(); shoppingCart.setUserId(userId);
List<ShoppingCart> shoppingCartList = shoppingCartMapper.list(shoppingCart); if (shoppingCartList == null || shoppingCartList.size() == 0) { throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL); }
Orders order = new Orders(); BeanUtils.copyProperties(ordersSubmitDTO,order); order.setPhone(addressBook.getPhone()); order.setAddress(addressBook.getDetail()); order.setConsignee(addressBook.getConsignee()); order.setNumber(String.valueOf(System.currentTimeMillis())); order.setUserId(userId); order.setStatus(Orders.PENDING_PAYMENT); order.setPayStatus(Orders.UN_PAID); order.setOrderTime(LocalDateTime.now());
orderMapper.insert(order);
List<OrderDetail> orderDetailList = new ArrayList<>(); for (ShoppingCart cart : shoppingCartList) { OrderDetail orderDetail = new OrderDetail(); BeanUtils.copyProperties(cart, orderDetail); orderDetail.setOrderId(order.getId()); orderDetailList.add(orderDetail); }
orderDetailMapper.insertBatch(orderDetailList);
shoppingCartMapper.deleteByUserId(userId);
OrderSubmitVO orderSubmitVO = OrderSubmitVO.builder() .id(order.getId()) .orderNumber(order.getNumber()) .orderAmount(order.getAmount()) .orderTime(order.getOrderTime()) .build();
return orderSubmitVO; }
|
这里就顺便补充下@Transactional注解:
事务处理translational
概念:指一组原子性的操作序列,这些操作要么全部执行,要么全部不执行
特性:原子性、一致性、隔离性和持久性
应用场景:当一组操作需要同时执行时。–金融行业、电商平台、物流行业
开发流程:在需要事务管理的方法上加注解:@Transactional()
rollbackFor属性:回滚指定类型的异常:@Transactional(rollbackFor =
Exception.class)
Propagation属性 :
事务传播:当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制。
REQUIRED – 【默认值】需要事务,有则加入,无则创建新事务
REQUIRES_NEW –总是创建新事务
内网穿透
封面图就是内网穿透的原理图:

进入临时域名的使用网站:https://dashboard.cpolar.com/,注册一个账户登进去选择免费的临时域名,下载cpolar的安装exe,按照步骤安装好就行。然后回到cpolar网站选择验证,复制你的Authtoken,然后运行刚刚安装好的cpolar.exe,输入cpolar.exe authtoken 【刚刚复制的】 ,再输入cpolar.exe http 8080然后回车,这时您的公网域名就创建好了,别人的电脑和手机就可以访问你的苍穹外卖了。可以输入https://xxxx/doc.html访问你的接口文档。
其他的接口就参考day9的资料吧:

微信小程序备案上线


剩下的催单接口和表格输出就自己去看黑马的吧~
苍穹外卖,完结!