Bootstrap

苍穹外卖学习 Day08

前言

该篇博客用于记录苍穹外卖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>

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;