1 地址簿模块
地址簿实体对象:
package com.sky.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 地址簿
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AddressBook implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
//用户id
private Long userId;
//收货人
private String consignee;
//手机号
private String phone;
//性别 0 女 1 男
private String sex;
//省级区划编号
private String provinceCode;
//省级名称
private String provinceName;
//市级区划编号
private String cityCode;
//市级名称
private String cityName;
//区级区划编号
private String districtCode;
//区级名称
private String districtName;
//详细地址
private String detail;
//标签
private String label;
//是否默认 0否 1是
private Integer isDefault;
}
数据库地址簿表
1.1 Path 和 Method 设计
1.2 实现
controller
package com.sky.controller.user;
import com.sky.context.BaseContext;
import com.sky.entity.AddressBook;
import com.sky.result.Result;
import com.sky.service.AddressBookService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/user/addressBook")
@Api(tags = "地址簿相关代码")
public class AddressBookController {
@Autowired
private AddressBookService addressBookService;
/**
* 新增地址
*
* @param addressBook
* @return
*/
@ApiOperation("新增地址")
@PostMapping
public Result save(@RequestBody AddressBook addressBook) {
// 这里要进行处理:
// 1.设置 userId,因为传过来的addressBook无法拿到用户 id
addressBook.setUserId(BaseContext.getCurrentId());
// 2.设置默认状态为 0,因为在新增地址模块不能先设置默认地址
addressBook.setIsDefault(0);
addressBookService.save(addressBook);
return Result.success();
}
/**
* 查询地址
*
* @return
*/
@ApiOperation("查询地址")
@GetMapping("/list")
public Result<List<AddressBook>> list() {
List<AddressBook> list = addressBookService.list();
return Result.success(list);
}
/**
* 查询默认地址
*
* @return
*/
@ApiOperation("查询默认地址")
@GetMapping("/default")
public Result<AddressBook> getDefault() {
AddressBook addressBook = addressBookService.getDefault();
return Result.success(addressBook);
}
/**
* 修改地址
*
* @return
*/
@PutMapping
@ApiOperation("修改地址")
public Result update(@RequestBody AddressBook addressBook) {
addressBookService.update(addressBook);
return Result.success();
}
/**
* 根据id删除地址
*
* @param id
* @return
*/
@DeleteMapping
@ApiOperation("根据id删除地址")
public Result deleteById(Long id) {
addressBookService.deleteById(id);
return Result.success();
}
/**
* 根据id查询地址
*
* @param id
* @return
*/
@GetMapping("/{id}")
@ApiOperation("根据id查询地址")
public Result<AddressBook> getById(@PathVariable Long id) {
AddressBook addressBook = addressBookService.getById(id);
return Result.success(addressBook);
}
/**
* 设置默认地址
*
* @param addressBook
* @return
*/
@PutMapping("/default")
@ApiOperation("设置默认地址")
public Result setDefault(@RequestBody AddressBook addressBook) {
addressBookService.setDefault(addressBook);
return Result.success();
}
}
service
package com.sky.service.impl;
import com.sky.context.BaseContext;
import com.sky.entity.AddressBook;
import com.sky.mapper.AddressBookMapper;
import com.sky.service.AddressBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class AddressBookServiceImpl implements AddressBookService {
@Autowired
private AddressBookMapper addressBookMapper;
/**
* 新增地址
*/
@Override
public void save(AddressBook addressBook) {
addressBookMapper.save(addressBook);
}
/**
* 查询地址
*
* @return
*/
@Override
public List<AddressBook> list() {
List<AddressBook> list = addressBookMapper.list();
return list;
}
/**
* 查询默认地址
*
* @return
*/
@Override
public AddressBook getDefault() {
return addressBookMapper.getDefault();
}
/**
* 修改地址
*
* @param addressBook
*/
@Override
public void update(AddressBook addressBook) {
addressBookMapper.update(addressBook);
}
/**
* 根据id删除地址
*
* @param id
*/
@Override
public void deleteById(Long id) {
addressBookMapper.deleteById(id);
}
/**
* 根据id查询地址
*
* @param id
* @return
*/
@Override
public AddressBook getById(Long id) {
AddressBook addressBook = addressBookMapper.getById(id);
return addressBook;
}
/**
* 设置默认地址
*
* @param addressBook
*/
@Override
public void setDefault(AddressBook addressBook) {
//1、将当前用户的所有地址修改为非默认地址 update address_book set is_default = ? where user_id = ?
addressBook.setIsDefault(0);
addressBook.setUserId(BaseContext.getCurrentId());
addressBookMapper.updateIsDefaultByUserId(addressBook);
//2、将当前地址改为默认地址 update address_book set is_default = ? where id = ?
addressBook.setIsDefault(1);
addressBookMapper.update(addressBook);
}
}
mapper
package com.sky.mapper;
import com.sky.entity.AddressBook;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface AddressBookMapper {
/**
* 新增地址
*
* @param addressBook
*/
@Insert("insert into sky_take_out.address_book" +
"(user_id, consignee, sex, phone, province_code, province_name, city_code, city_name, district_code, district_name, detail, label,is_default)" +
"values " +
"(#{userId}, #{consignee}, #{sex},#{phone}, #{provinceCode}, #{provinceName}, #{cityCode}, #{cityName}, #{districtCode}, #{districtName}, #{detail}, #{label}, #{isDefault})")
void save(AddressBook addressBook);
/**
* 查询地址
*
* @return
*/
// 这里应该条件查询,代码复用
// @Select("select * from sky_take_out.address_book")
List<AddressBook> list();
/**
* 查询默认地址
*
* @return
*/
@Select("select * from sky_take_out.address_book where is_default = 1")
AddressBook getDefault();
/**
* 修改地址
*
* @param addressBook
*/
void update(AddressBook addressBook);
/**
* 根据id删除地址
*
* @param id
*/
@Delete("delete from sky_take_out.address_book where id = #{id}")
void deleteById(Long id);
/**
* 根据id查询地址
*
* @param id
* @return
*/
@Select("select * from sky_take_out.address_book where id = #{id}")
AddressBook getById(Long id);
/**
* 根据 用户id修改 是否默认地址
*
* @param addressBook
*/
@Update("update sky_take_out.address_book set is_default = #{isDefault} where user_id = #{userId}")
void updateIsDefaultByUserId(AddressBook addressBook);
}
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.AddressBookMapper">
<select id="list" parameterType="AddressBook" resultType="AddressBook">
select * from sky_take_out.address_book
<where>
<if test="userId != null">and user_id = #{userId}</if>
<if test="phone != null">and phone = #{phone}</if>
<if test="isDefault != null">and is_default = #{isDefault}</if>
</where>
</select>
<update id="update" parameterType="addressBook">
update sky_take_out.address_book
<set>
<if test="consignee != null">consignee = #{consignee},</if>
<if test="sex != null">sex = #{sex},</if>
<if test="phone != null">phone = #{phone},</if>
<if test="detail != null">detail = #{detail},</if>
<if test="label != null">label = #{label},</if>
<if test="isDefault != null">is_default = #{isDefault},</if>
</set>
where id = #{id}
</update>
</mapper>
1.3 测试
2 下单
为什么两张表:
订单表 是描述订单的
订单明细表 是描述订单里面的商品
2.1 实现
controller
service
package com.sky.service.impl;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.OrdersSubmitDTO;
import com.sky.entity.AddressBook;
import com.sky.entity.OrderDetail;
import com.sky.entity.Orders;
import com.sky.entity.ShoppingCart;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.ShoppingCartBusinessException;
import com.sky.mapper.AddressBookMapper;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.ShoppingCartMapper;
import com.sky.service.OrderService;
import com.sky.vo.OrderSubmitVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private OrderDetailMapper orderDetailMapper;
@Autowired
private AddressBookMapper addressBookMapper;
@Autowired
private ShoppingCartMapper shoppingCartMapper;
/**
* 用户下单
*
* @param ordersSubmitDTO
* @return
*/
public OrderSubmitVO submit(OrdersSubmitDTO ordersSubmitDTO) {
// 处理异常(地址簿为空、购物车为空)
AddressBook addressBook = addressBookMapper.getById(ordersSubmitDTO.getAddressBookId());
if (addressBook == null) {
throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
}
ShoppingCart shoppingCart = new ShoppingCart();
shoppingCart.setUserId(BaseContext.getCurrentId());
List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
if (list == null || list.isEmpty()) {
throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
}
// 订单表插入1条数据
Orders order = new Orders();
BeanUtils.copyProperties(ordersSubmitDTO, order);
order.setOrderTime(LocalDateTime.now());
order.setPayStatus(Orders.UN_PAID);
order.setStatus(Orders.PENDING_PAYMENT);
order.setNumber(String.valueOf(System.currentTimeMillis()));
order.setPhone(addressBook.getPhone());
order.setConsignee(addressBook.getConsignee());
order.setUserId(BaseContext.getCurrentId());
orderMapper.insert(order);
// 订单明细表插入n条数据
for (ShoppingCart cart :
list) {
OrderDetail orderDetail = new OrderDetail();
BeanUtils.copyProperties(cart, orderDetail);
orderDetail.setOrderId(order.getId()); // useGeneratedKeys="true" keyProperty="id"才可以获得主键值
orderDetailMapper.insert(orderDetail);
}
// 清空购物车
shoppingCartMapper.clean();
// 封装VO返回
OrderSubmitVO orderSubmitVO = OrderSubmitVO.builder()
.id(order.getId())
.orderNumber(order.getNumber())
.orderAmount(order.getAmount())
.orderTime(order.getOrderTime())
.build();
return orderSubmitVO;
}
}
mapper 略
2.2 测试
3 订单定时处理
3.1 定时处理 - - - Spring Task
Spring Task 是 spring 框架提供的任务调度工具,可以按照约定的时间 自动执行某个代码逻辑
cron 表达式 是一个字符串,通过 cron 表达式可以定义任务触发的时间,构成规则:分为 6 或 7 个域,由空格分隔开,每个域代表一个含义
每个域的含义分别为:秒、分钟、小时、日、月、周、年(可选)
使用时,在启动类上加
@EnableScheduling 注解
然后在定时任务类上加注解
@Scheduled(cron = " ")
在控制台每一秒输出当前时间
对于订单超时任务,每一分钟检查一次,如果超时则自动取消订单
4 WebSocket //Todo
(回过头再看)
WebSocket 是基于 TCP 的一种新的 网络协议。它实现了 浏览器 与 服务器 全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建 持久性 的连接,并进行 双向数据传输。
来单提醒: