前言
该篇博客用于记录苍穹外卖Day08地址、用户下单、订单支付的学习记录
(订单支付部分这里简化了逻辑)
地址
课程中这个模块的代码是直接导入的,这里我来从0开始敲一遍,思路大多通过注释写出
要完成地址功能的开发,涉及到以下接口设计:
- 查询当前登录用户的所有地址信息
- 新增地址
- 根据id查询地址
- 根据id修改地址
- 查询默认地址
- 根据id删除地址
- 设置默认地址
注意:
- 1.代码全由我自己开发,可能与提供的资料有所不同,但功能实现都没问题,仅做参考
- 2.接口文档有一个小错误。在设置默认地址接口,接口文档中的参数是id,这里要是AddressBook,不然无法接收到参数
- 3.在设置默认地址接口中,资料提供的方法我认为较麻烦,我这里是直接先根据默认地址is_default=1的性质将其变为0,再根据id将我们要变更的默认地址的is_default设为1
接下来正式开始开发:
- AddressBookController
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 lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.io.ResolverUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@Slf4j
@Api(tags = "地址薄功能开发")
@RequestMapping("/user/addressBook")
public class AddressController {
@Autowired
private AddressBookService addressBookService;
@GetMapping("/list")
@ApiOperation("查询当前登录用户的所有地址信息")
public Result<List<AddressBook>> list(){
log.info("查询当前登录用户的所有地址信息");
AddressBook addressBook=new AddressBook();
Long userId= BaseContext.getCurrentId();
addressBook.setUserId(userId);
List<AddressBook> list=addressBookService.list(addressBook);
return Result.success(list);
}
@PostMapping
@ApiOperation("新增地址")
public Result add(@RequestBody AddressBook addressBook){
log.info("新增地址:{}",addressBook);
addressBookService.add(addressBook);
return Result.success();
}
@GetMapping("/{id}")
@ApiOperation("根据id查询地址")
public Result<AddressBook> getById(@PathVariable Long id){
log.info("根据id查询地址:{}",id);
AddressBook addressBook=addressBookService.getById(id);
return Result.success(addressBook);
}
@PutMapping
@ApiOperation("根据id修改地址")
public Result update(@RequestBody AddressBook addressBook){
log.info("根据id修改地址:{}",addressBook);
Long userId= BaseContext.getCurrentId();
addressBook.setUserId(userId);
addressBookService.update(addressBook);
return Result.success();
}
@PutMapping("/default")
@ApiOperation("设置默认地址")
public Result setDefault(@RequestBody AddressBook addressBook){
addressBookService.setDefault(addressBook);
return Result.success();
}
@DeleteMapping
@ApiOperation("根据id删除地址")
public Result delete(Long id){
log.info("根据id删除地址:{}",id);
addressBookService.deleteById(id);
return Result.success();
}
@GetMapping("/default")
@ApiOperation("查询默认地址")
public Result<AddressBook> getDefault(){
log.info("查询默认地址");
AddressBook addressBook=addressBookService.getDefault();
return Result.success(addressBook);
}
}
- AddressBookService
package com.sky.service;
import com.sky.entity.AddressBook;
import java.util.List;
public interface AddressBookService {
List<AddressBook> list(AddressBook addressBook);
void add(AddressBook addressBook);
AddressBook getById(Long id);
void update(AddressBook addressBook);
void setDefault(AddressBook addressBook);
void deleteById(Long id);
AddressBook getDefault();
}
- AddressBookServiceImpl
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;
//查询当前登录用户的所有地址信息
public List<AddressBook> list(AddressBook addressBook) {
List<AddressBook> list=addressBookMapper.list(addressBook);
return list;
}
//新增地址
@Override
public void add(AddressBook addressBook) {
Long userId= BaseContext.getCurrentId();
addressBook.setUserId(userId);
addressBook.setIsDefault(0);
addressBookMapper.add(addressBook);
}
//根据id查询地址
@Override
public AddressBook getById(Long id) {
AddressBook addressBook=new AddressBook();
Long userId= BaseContext.getCurrentId();
addressBook.setUserId(userId);
addressBook.setId(id);
AddressBook addressBook1=addressBookMapper.getById(addressBook);
return addressBook1;
}
//根据id修改地址
@Override
public void update(AddressBook addressBook) {
addressBookMapper.update(addressBook);
}
//设置默认地址
@Override
public void setDefault(AddressBook addressBook) {
//先将默认地址取消
addressBookMapper.doDefault();
//根据id将该地址设为默认地址
addressBookMapper.setDefault(addressBook.getId());
}
//根据id删除地址
@Override
public void deleteById(Long id) {
addressBookMapper.deleteById(id);
}
//查询默认地址
@Override
public AddressBook getDefault() {
AddressBook addressBook=addressBookMapper.getDefault();
return addressBook;
}
}
- AddressBookMapper
package com.sky.mapper;
import com.sky.entity.AddressBook;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface AddressBookMapper {
List<AddressBook> list(AddressBook addressBook);
@Insert("insert into 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 add(AddressBook addressBook);
@Select("select * from address_book where id=#{id} and user_id=#{userId}")
AddressBook getById(AddressBook addressBook);
void update(AddressBook addressBook);
@Update("update address_book set is_default=0 where is_default=1")
void doDefault();
@Update("update address_book set is_default=1 where id=#{id}")
void setDefault(Long id);
@Delete("delete from address_book where id=#{id}")
void deleteById(Long id);
@Select("select * from address_book where is_default=1")
AddressBook getDefault();
}
- AddressBookMapper.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">
<update id="update" parameterType="addressBook">
update 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>
<select id="list" parameterType="AddressBook" resultType="AddressBook">
select * from 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>
</mapper>
用户下单
在该接口,我只分析一下OrderServiceImpl层的代码。完成用户下单功能开发有以下步骤:
- 要向订单表和订单明细表插入数据之前,先要对异常情况进行处理(地址薄为空、购物车为空)
- 封装好Orders对象来进行数据库操作
- 向订单表和订单明细表插入数据
- 订单完成,清空购物车
- 封装OrderSubmitVO,返回给前端
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private OrderDetailMapper orderDetailMapper;
@Autowired
private ShoppingCartMapper shoppingCartMapper;
@Autowired
private AddressBookMapper addressBookMapper;
//用户下单
@Override
public OrderSubmitVO submit(OrdersSubmitDTO ordersSubmitDTO) {
//先处理各种业务异常(地址薄为空、购物车为空)
AddressBook addressBook=addressBookMapper.getById1(ordersSubmitDTO.getAddressBookId());
if(addressBook==null){
throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
}
ShoppingCart shoppingCart=new ShoppingCart();
shoppingCart.setUserId(BaseContext.getCurrentId());
List<ShoppingCart> shoppingCarts=shoppingCartMapper.list(shoppingCart);
if(shoppingCarts==null||shoppingCarts.size()==0){
throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
}
//封装好Orders对象
Orders orders=new Orders();
BeanUtils.copyProperties(ordersSubmitDTO,orders);
orders.setUserId(BaseContext.getCurrentId());
orders.setOrderTime(LocalDateTime.now());
orders.setPayStatus(Orders.UN_PAID);//未支付
orders.setStatus(Orders.PENDING_PAYMENT);//待付款
orders.setNumber(String.valueOf(System.currentTimeMillis()));
orders.setPhone(addressBook.getPhone());
orders.setConsignee(addressBook.getConsignee());
//向订单表插入数据(1条)
orderMapper.insert(orders);
//获取订单明细表的orderId
Long id= orders.getId();
//向订单明细表插入数据(n条),获取购物车中的数据插进订单明细表
List<OrderDetail> detailList=new ArrayList<>();
for (ShoppingCart cart : shoppingCarts) {
OrderDetail orderDetail=new OrderDetail();
orderDetail.setOrderId(id);
BeanUtils.copyProperties(cart,orderDetail);
detailList.add(orderDetail);
}
orderDetailMapper.insertBatch(detailList);
//订单完成,清空购物车
shoppingCartMapper.delete(shoppingCart);
//封装OrderSubmitVO,返回给前端
OrderSubmitVO orderSubmitVO=new OrderSubmitVO();
orderSubmitVO.setId(orders.getId());
orderSubmitVO.setOrderTime(orders.getOrderTime());
orderSubmitVO.setOrderAmount(orders.getAmount());
orderSubmitVO.setOrderNumber(orders.getNumber());
return orderSubmitVO;
}
}
订单支付
在该模块你可以按照老师的操作申请各种东西来做,原谅我这里为了简化逻辑,点击支付我就直接修改订单状态了。
- OrderController
@PutMapping("/payment")
@ApiOperation("订单支付")
public Result<OrderPaymentVO> payment(@RequestBody OrdersPaymentDTO ordersPaymentDTO) throws Exception {
log.info("订单支付:{}", ordersPaymentDTO);
orderService.paySuccess(ordersPaymentDTO.getOrderNumber());
return Result.success();
}
- OrderServiceImpl
//支付成功,修改订单数据
public void paySuccess(String outTradeNo) {
// 根据订单号查询订单
Orders ordersDB = orderMapper.getByNumber(outTradeNo);
// 根据订单id更新订单的状态、支付方式、支付状态、结账时间
Orders orders = Orders.builder()
.id(ordersDB.getId())
.status(Orders.TO_BE_CONFIRMED)
.payStatus(Orders.PAID)
.checkoutTime(LocalDateTime.now())
.build();
orderMapper.update(orders);
}
- OrderMapper
//根据订单号查询订单
@Select("select * from orders where number = #{orderNumber}")
Orders getByNumber(String orderNumber);
//修改订单信息
void update(Orders orders);
- OrderMapper.xml
<update id="update" parameterType="com.sky.entity.Orders">
update orders
<set>
<if test="cancelReason != null and cancelReason!='' ">
cancel_reason=#{cancelReason},
</if>
<if test="rejectionReason != null and rejectionReason!='' ">
rejection_reason=#{rejectionReason},
</if>
<if test="cancelTime != null">
cancel_time=#{cancelTime},
</if>
<if test="payStatus != null">
pay_status=#{payStatus},
</if>
<if test="payMethod != null">
pay_method=#{payMethod},
</if>
<if test="checkoutTime != null">
checkout_time=#{checkoutTime},
</if>
<if test="status != null">
status = #{status},
</if>
<if test="deliveryTime != null">
delivery_time = #{deliveryTime}
</if>
</set>
where id = #{id}
</update>