瑞吉外卖项目

简介: 1.手机验证码登录在开发代码之前,需要梳理一下登录时前端页面和服务端的交互过程:1、在登录页面(front/page/login.html)输入手机号,点击【获取验证码】按钮,页面发送ajax请求,在服务端调用短信服务API给指定手机号发送验证码短信2、在登录页面输入验证码,点击【登录】按钮,发送ajax请求,在服务端处理登录请求开发手机验证码登录功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。

1.手机验证码登录

在开发代码之前,需要梳理一下登录时前端页面和服务端的交互过程:

1、在登录页面(front/page/login.html)输入手机号,点击【获取验证码】按钮,页面发送ajax请求,在服务端调用短信服务API给指定手机号发送验证码短信

2、在登录页面输入验证码,点击【登录】按钮,发送ajax请求,在服务端处理登录请求

开发手机验证码登录功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。

使用阿里云短信服务发送短信,可以参照官方提供的文档即可。

具体开发步骤:

1、导入maven坐标

  <dependency>
           <groupId>com.aliyun</groupId>
           <artifactId>aliyun-java-sdk-core</artifactId>
           <version>4.5.16</version>
       </dependency>
       <dependency>
       <groupId>com.aliyun</groupId>
       <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
       <version>2.1.0</version>
       </dependency>

2、调用API

在开发业务功能前,先将需要用到的类和接口基本结构创建好:

实体类User

package com.itheima.reggie.entity;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
/**
 * 用户信息
 */
@Data
public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private Long id;
    //姓名
    private String name;
    //手机号
    private String phone;
    //性别 0 女 1 男
    private String sex;
    //身份证号
    private String idNumber;
    //头像
    private String avatar;
    //状态 0:禁用,1:正常
    private Integer status;
}

Mapper接口UserMapper

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.reggie.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}

业务层接口UserService

import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.reggie.entity.User;
public interface UserService extends IService<User> {
}

业务层实现类UserServicelmpl

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

控制层UserController

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
    @Autowired
   private UserService userService;
    //发送手机验证码
@PostMapping("/sendMsg")
private R<String> sendMsg(@RequestBody User user, HttpSession session){
//获取手机号
String phone=user.getPhone();
if (StringUtils.isNotEmpty(phone)){
    //生成随机4位验证码
    String code = ValidateCodeUtils.generateValidateCode(4).toString();
    log.info("code={}",code);
    //调用阿里云的短信服务apl完成发送短信
    //SMSUtils.sendMessage("瑞吉外卖","SMS_273795337","17807941605",code);
    //需要将生成的验证码保存到session中
session.setAttribute(phone,code);
    return R.success("手机验证码短信发送成功");
}
return R.error("短信发送失败");
}
//移动端用户登录
    @PostMapping("/login")
    private R<User> login(@RequestBody Map map, HttpSession session){
log.info(map.toString());
//获取手机号
        String phone = map.get("phone").toString();
        //获取验证码
        String code = map.get("code").toString();
        //从session获取保存的验证码
        Object codeInSession = session.getAttribute(phone);
        //进行验证码的比对(页面提交的验证码和session中保存的验证码比对)
if (codeInSession!=null && codeInSession.equals(code)){
        //如果能够比对成功,说明登录成功
    LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>();
    queryWrapper.eq(User::getPhone,phone);
    User user = userService.getOne(queryWrapper);
    //判断当前手机号对应的用户是为新用户,如果是新用户自动完成登录
    if (user==null){
       user=new User();
       user.setPhone(phone);
       user.setStatus(1);
       userService.save(user);
   }
    session.setAttribute("user",user.getId());
return R.success(user);
}
        return R.error("登录失败");
    }

工具类SMSutils、ValidateCodeutils

package com.itheima.reggie.utils;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
/**
 * 短信发送工具类
 */
public class SMSUtils {
  /**
   * 发送短信
   * @param signName 签名
   * @param templateCode 模板
   * @param phoneNumbers 手机号
   * @param param 参数
   */
  public static void sendMessage(String signName, String templateCode,String phoneNumbers,String param){
    DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "", "");
    IAcsClient client = new DefaultAcsClient(profile);
    SendSmsRequest request = new SendSmsRequest();
    request.setSysRegionId("cn-hangzhou");
    request.setPhoneNumbers(phoneNumbers);
    request.setSignName(signName);
    request.setTemplateCode(templateCode);
    request.setTemplateParam("{\"code\":\""+param+"\"}");
    try {
      SendSmsResponse response = client.getAcsResponse(request);
      System.out.println("短信发送成功");
    }catch (ClientException e) {
      e.printStackTrace();
    }
  }
}
package com.itheima.reggie.utils;
import java.util.Random;
/**
 * 随机生成验证码工具类
 */
public class ValidateCodeUtils {
    /**
     * 随机生成验证码
     * @param length 长度为4位或者6位
     * @return
     */
    public static Integer generateValidateCode(int length){
        Integer code =null;
        if(length == 4){
            code = new Random().nextInt(9999);//生成随机数,最大为9999
            if(code < 1000){
                code = code + 1000;//保证随机数为4位数字
            }
        }else if(length == 6){
            code = new Random().nextInt(999999);//生成随机数,最大为999999
            if(code < 100000){
                code = code + 100000;//保证随机数为6位数字
            }
        }else{
            throw new RuntimeException("只能生成4位或6位数字验证码");
        }
        return code;
    }
    /**
     * 随机生成指定长度字符串验证码
     * @param length 长度
     * @return
     */
    public static String generateValidateCode4String(int length){
        Random rdm = new Random();
        String hash1 = Integer.toHexString(rdm.nextInt());
        String capstr = hash1.substring(0, length);
        return capstr;
    }
}

2.导入用户地址簿

实体类AddressBook

package com.itheima.reggie.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
 * 地址簿
 */
@Data
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;
    //创建时间
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    //更新时间
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
    //创建人
    @TableField(fill = FieldFill.INSERT)
    private Long createUser;
    //修改人
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;
    //是否删除
    private Integer isDeleted;
}

Mapper接口AddressBookMapper

@Mapper
public interface AddressBookMapper extends BaseMapper<AddressBook> {
}

业务层接口AddressBookService

public interface AddressBookService extends IService<AddressBook> {
}

业务层实现类AddressBookServicelmpl

@Service
public class AddressBookServiceImpl extends ServiceImpl<AddressBookMapper, AddressBook> implements AddressBookService {
}

控制层AddressBookController

/**
 * 地址簿管理
 */
@Slf4j
@RestController
@RequestMapping("/addressBook")
public class AddressBookController {
    @Autowired
    private AddressBookService addressBookService;
    /**
     * 新增
     */
    @PostMapping
    public R<AddressBook> save(@RequestBody AddressBook addressBook) {
        addressBook.setUserId(BaseContext.getCurrentId());
        log.info("addressBook:{}", addressBook);
        addressBookService.save(addressBook);
        return R.success(addressBook);
    }
    /**
     * 设置默认地址
     */
    @PutMapping("default")
    public R<AddressBook> setDefault(@RequestBody AddressBook addressBook) {
        log.info("addressBook:{}", addressBook);
        LambdaUpdateWrapper<AddressBook> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(AddressBook::getUserId, BaseContext.getCurrentId());
        wrapper.set(AddressBook::getIsDefault, 0);
        //SQL:update address_book set is_default = 0 where user_id = ?
        addressBookService.update(wrapper);
        addressBook.setIsDefault(1);
        //SQL:update address_book set is_default = 1 where id = ?
        addressBookService.updateById(addressBook);
        return R.success(addressBook);
    }
    /**
     * 根据id查询地址
     */
    @GetMapping("/{id}")
    public R get(@PathVariable Long id) {
        AddressBook addressBook = addressBookService.getById(id);
        if (addressBook != null) {
            return R.success(addressBook);
        } else {
            return R.error("没有找到该对象");
        }
    }
    /**
     * 查询默认地址
     */
    @GetMapping("default")
    public R<AddressBook> getDefault() {
        LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AddressBook::getUserId, BaseContext.getCurrentId());
        queryWrapper.eq(AddressBook::getIsDefault, 1);
        //SQL:select * from address_book where user_id = ? and is_default = 1
        AddressBook addressBook = addressBookService.getOne(queryWrapper);
        if (null == addressBook) {
            return R.error("没有找到该对象");
        } else {
            return R.success(addressBook);
        }
    }
    /**
     * 查询指定用户的全部地址
     */
    @GetMapping("/list")
    public R<List<AddressBook>> list(AddressBook addressBook) {
        addressBook.setUserId(BaseContext.getCurrentId());
        log.info("addressBook:{}", addressBook);
        //条件构造器
        LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(null != addressBook.getUserId(), AddressBook::getUserId, addressBook.getUserId());
        queryWrapper.orderByDesc(AddressBook::getUpdateTime);
        //SQL:select * from address_book where user_id = ? order by update_time desc
        return R.success(addressBookService.list(queryWrapper));
    }
}

3.菜品展示

在开发代码之前,需要梳理一下前端页面和服务端的交互过程:

1、页面(front/index.html)发送ajax请求,获取分类数据(菜品分类和套餐分类)

2、页面发送ajax请求,获取第一个分类下的菜品或者套餐

开发菜品展示功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。

注意:首页加载完成后,还发送了一次ajax请求用于加载购物车数据,此处可以将这次请求的地址暂时修改一下,从静态json文件获取数据,等后续开发购物车功能时再修改回来,如下:

b496df301f5843a0b992ef5e94b9329f.png

在SetmealController中写list方法

    /**
     * 根据条件查询套餐数据
     * @param setmeal
     * @return
     */
    @GetMapping("/list")
    public R<List<Setmeal>> list(Setmeal setmeal){
        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(setmeal.getCategoryId() != null,Setmeal::getCategoryId,setmeal.getCategoryId());
        queryWrapper.eq(setmeal.getStatus() != null,Setmeal::getStatus,setmeal.getStatus());
        queryWrapper.orderByDesc(Setmeal::getUpdateTime);
        List<Setmeal> list = setmealService.list(queryWrapper);
        return R.success(list);
    }

修改 dishController中的list方法

 @GetMapping("/list")
    public R<List<DishDto>> list(Dish dish){
        //构造查询对象
        LambdaQueryWrapper<Dish> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());
        //查询状态为1的
        queryWrapper.eq(Dish::getStatus,1);
        //添加排序条件
        queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
        List<Dish> list = dishService.list(queryWrapper);
        List<DishDto> dishDtoList=list.stream().map(item->{
            DishDto dishDto=new DishDto();
            BeanUtils.copyProperties(item,dishDto);
            Long categoryId= item.getCategoryId();//分类id
            //根据id查询分类对象
            Category category = categoryService.getById(categoryId);
            if (category!=null){
                String categoryName = category.getName();
                dishDto.setCategoryName(categoryName);
            }
            //当前菜品id
            Long dishId = item.getId();
            LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper=new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(DishFlavor::getDishId,dishId);
List<DishFlavor> dishFlavorList=dishFlavorService.list(lambdaQueryWrapper);
dishDto.setFlavors(dishFlavorList);
            return dishDto;
        }).collect(Collectors.toList());
        return R.success(dishDtoList);
    }

4.购物车

在开发代码之前,需要梳理一下购物车操作时前端页面和服务端的交互过程:

1、点击加入购物车或者+按钮,页面发送ajax请求,请求服务端,将菜品或者套餐添加到购物车

2、点击购物车图标,页面发送ajax请求,请求服务端查询购物车中的菜品和套餐

3、点击清空购物车按钮,页面发送ajax请求,请求服务端来执行清空购物车操作

开发购物车功能,其实就是在服务端编写代码去处理前端页面发送的这3次请求即可。

在开发业务功能前,先将需要用到的类和接口基本结构创建好:

实体类ShopplingCart

package com.itheima.reggie.entity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
 * 购物车
 */
@Data
public class ShoppingCart implements Serializable {
    private static final long serialVersionUID = 1L;
    private Long id;
    //名称
    private String name;
    //用户id
    private Long userId;
    //菜品id
    private Long dishId;
    //套餐id
    private Long setmealId;
    //口味
    private String dishFlavor;
    //数量
    private Integer number;
    //金额
    private BigDecimal amount;
    //图片
    private String image;
    private LocalDateTime createTime;
}

Mapper接口ShoppingCartMapper

@Mapper
public interface ShoppingCartMapper extends BaseMapper<ShoppingCart> {
}

业务层接口ShoppingCartService

public interface ShoppingCartService extends IService<ShoppingCart> {
}

业务层实现类ShoppingCartServicelmpl

@Service
public class ShoppingCartServiceImpl extends ServiceImpl<ShoppingCartMapper, ShoppingCart> implements ShoppingCartService {
}

控制层ShoppingCartController

//购物车
@Slf4j
@RestController
@RequestMapping("/shoppingCart")
public class ShoppingCartController {
    @Autowired
    private ShoppingCartService shoppingCartService;
//添加购物车
    @PostMapping("/add")
    public R<ShoppingCart> add(@RequestBody ShoppingCart shoppingCart){
        log.info("购物车:{}",shoppingCart);
//设置用户id,指定当前是那个用户的购物车数据
        Long currentId = BaseContext.getCurrentId();
        shoppingCart.setUserId(currentId);
        //查询当前菜品或者套餐是否在购物车中
        Long dishId = shoppingCart.getDishId();
        LambdaQueryWrapper<ShoppingCart> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(ShoppingCart::getUserId,currentId);
       if (dishId!=null){
           //添加到购物车的是菜品
         queryWrapper.eq(ShoppingCart::getDishId,dishId);
       }else {
           //添加到购物车的套餐
           queryWrapper.eq(ShoppingCart::getSetmealId,shoppingCart.getSetmealId());
       }
        //查询当前菜品或者套餐是否在购物车中
        ShoppingCart cartServiceOne = shoppingCartService.getOne(queryWrapper);
      if (cartServiceOne!=null){
          //如果已经存在,就原来数量的基础上加1
          Integer number = cartServiceOne.getNumber();
          cartServiceOne.setNumber(number+1);
          shoppingCartService.updateById(cartServiceOne);
      }else {
          //如果不存在就添加到购物车,数量默认为1
          shoppingCart.setNumber(1);
          shoppingCart.setCreateTime(LocalDateTime.now());
          shoppingCartService.save(shoppingCart);
          cartServiceOne=shoppingCart;
      }
     return R.success(cartServiceOne);
    }
//购物车减少
    @PostMapping("/sub")
    @Transactional
    public R<ShoppingCart> sub(@RequestBody ShoppingCart shoppingCart){
        Long dishId = shoppingCart.getDishId();
        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
        //代表数量减少的是菜品数量
        if (dishId != null){
            //通过dishId查出购物车对象
            queryWrapper.eq(ShoppingCart::getDishId,dishId);
            //这里必须要加两个条件,否则会出现用户互相修改对方与自己购物车中相同套餐或者是菜品的数量
            queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());
            ShoppingCart cart1 = shoppingCartService.getOne(queryWrapper);
            cart1.setNumber(cart1.getNumber()-1);
            Integer LatestNumber = cart1.getNumber();
            if (LatestNumber > 0){
                //对数据进行更新操作
                shoppingCartService.updateById(cart1);
            }else if(LatestNumber == 0){
                //如果购物车的菜品数量减为0,那么就把菜品从购物车删除
                shoppingCartService.removeById(cart1.getId());
            }else if (LatestNumber < 0){
                return R.error("操作异常");
            }
            return R.success(cart1);
        }
        Long setmealId = shoppingCart.getSetmealId();
        if (setmealId != null){
            //代表是套餐数量减少
            queryWrapper.eq(ShoppingCart::getSetmealId,setmealId).eq(ShoppingCart::getUserId,BaseContext.getCurrentId());
            ShoppingCart cart2 = shoppingCartService.getOne(queryWrapper);
            cart2.setNumber(cart2.getNumber()-1);
            Integer LatestNumber = cart2.getNumber();
            if (LatestNumber > 0){
                //对数据进行更新操作
                shoppingCartService.updateById(cart2);
            }else if(LatestNumber == 0){
                //如果购物车的套餐数量减为0,那么就把套餐从购物车删除
                shoppingCartService.removeById(cart2.getId());
            }else if (LatestNumber < 0){
                return R.error("操作异常");
            }
            return R.success(cart2);
        }
        //如果两个大if判断都进不去
        return R.error("操作异常");
    }
    //查看购物车
@GetMapping("/list")
    public R<List<ShoppingCart>> list(){
log.info("查看购物车");
LambdaQueryWrapper<ShoppingCart> queryWrapper=new LambdaQueryWrapper<>();
queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());
      queryWrapper.orderByAsc(ShoppingCart::getCreateTime);
    List<ShoppingCart> list = shoppingCartService.list(queryWrapper);
    return R.success(list);
    }
    //清空购物车
@DeleteMapping("/clean")
    public R<String> clean(){
        LambdaQueryWrapper<ShoppingCart> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());
        shoppingCartService.remove(queryWrapper);
return R.success("清空购物车成功");
}

5.用户下单

在开发业务功能前,先将需要用到的类和接口基本结构创建好:

实体类Orders、OrderDetail

package com.itheima.reggie.entity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
 * 订单
 */
@Data
public class Orders implements Serializable {
    private static final long serialVersionUID = 1L;
    private Long id;
    //订单号
    private String number;
    //订单状态 1待付款,2待派送,3已派送,4已完成,5已取消
    private Integer status;
    //下单用户id
    private Long userId;
    //地址id
    private Long addressBookId;
    //下单时间
    private LocalDateTime orderTime;
    //结账时间
    private LocalDateTime checkoutTime;
    //支付方式 1微信,2支付宝
    private Integer payMethod;
    //实收金额
    private BigDecimal amount;
    //备注
    private String remark;
    //用户名
    private String userName;
    //手机号
    private String phone;
    //地址
    private String address;
    //收货人
    private String consignee;
}
package com.itheima.reggie.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
 * 订单明细
 */
@Data
public class OrderDetail implements Serializable {
    private static final long serialVersionUID = 1L;
    private Long id;
    //名称
    private String name;
    //订单id
    private Long orderId;
    //菜品id
    private Long dishId;
    //套餐id
    private Long setmealId;
    //口味
    private String dishFlavor;
    //数量
    private Integer number;
    //金额
    private BigDecimal amount;
    //图片
    private String image;
}

Mapper接口OrderMapper、OrderDetailMapper

@Mapper
public interface OrderMapper extends BaseMapper<Orders> {
}
@Mapper
public interface OrderDetaiMapper extends BaseMapper<OrderDetail> {
}

业务层接口OrderService、OrderDetailService

public interface OrderService extends IService<Orders> {
//用户下单
    public void submit(Orders orders);
}
public interface OrderDetailService extends IService<OrderDetail> {
}

业务层实现类OrderServicelmpl、OrderDetailServicelmpl

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService {
   @Autowired
    private ShoppingCartService shoppingCartService;
@Autowired
private UserService userService;
@Autowired
private AddressBookService addressBookService;
@Autowired
private OrderDetailService orderDetailService;
    //用户下单
    @Override
    @Transactional
    public void submit(Orders orders) {
//获得当前用户id
        Long userId = BaseContext.getCurrentId();
//查询当前用户的购物车数据
        LambdaQueryWrapper<ShoppingCart> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(ShoppingCart::getUserId,userId);
        List<ShoppingCart> shoppingCarts = shoppingCartService.list(wrapper);
        if (shoppingCarts==null || shoppingCarts.size()==0){
            throw new CustomException("购物车为空,不能下单");
        }
        //查询用户数据
        User user = userService.getById(userId);
        //查询地址数据
        Long addressBookId = orders.getAddressBookId();
        AddressBook addressBook = addressBookService.getById(addressBookId);
        if (addressBook==null){
            throw new CustomException("地址信息有误");
        }
        //订单号
        long orderId = IdWorker.getId();
        AtomicInteger amount=new AtomicInteger(0);
     List<OrderDetail> orderDetails= shoppingCarts.stream().map((item)->{
     OrderDetail orderDetail=new OrderDetail();
     orderDetail.setOrderId(orderId);
     orderDetail.setNumber(item.getNumber());
     orderDetail.setDishFlavor(item.getDishFlavor());
     orderDetail.setDishId(item.getDishId());
     orderDetail.setSetmealId(item.getSetmealId());
     orderDetail.setName(item.getName());
     orderDetail.setImage(item.getImage());
     orderDetail.setAmount(item.getAmount());
     amount.addAndGet(item.getAmount().multiply(new BigDecimal(item.getNumber())).intValue());
     return orderDetail;
      }).collect(Collectors.toList());
        orders.setOrderTime(LocalDateTime.now());
        orders.setCheckoutTime(LocalDateTime.now());
        orders.setStatus(2);
        orders.setAmount(new BigDecimal(amount.get()));
        orders.setUserId(userId);
        orders.setNumber(String.valueOf(orderId));
        orders.setUserName(user.getName());
        orders.setConsignee(addressBook.getConsignee());
        orders.setPhone(addressBook.getPhone());
        orders.setAddress((addressBook.getProvinceName()==null?"":addressBook.getProvinceName())
        +(addressBook.getCityName()==null?"":addressBook.getCityName())
        +(addressBook.getDistrictName()==null?"":addressBook.getDistrictName())
        +(addressBook.getDetail()==null?"":addressBook.getDetail()));
        //向订单表插入数据,一条数据
this.save(orders);
        //向订单明细表插入数据,多条
orderDetailService.saveBatch(orderDetails);
        //清空购物车数据
  shoppingCartService.remove(wrapper);
    }
}
@Service
public class OrderDateilServiceImpl extends ServiceImpl<OrderDetaiMapper, OrderDetail> implements OrderDetailService {
}

控制层OrderController、OrderDetailController

@RestController
@Slf4j
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private OrderService orderService;
//用户下单
    @PostMapping("/submit")
public R<String> submit(@RequestBody Orders orders){
log.info("订单数据:{}",orders);
        orderService.submit(orders);
        return R.success("下单成功");
    }
}
@RequestMapping("/orderDetail")
@RestController
@Slf4j
public class OrderDetailController {
    @Autowired
    private OrderDetailService orderDetailService;
}

美好的一天,到此结束,下次继续努力!

相关文章
|
5天前
|
存储 小程序 算法
东郊到家预约系统开发|源码案例|小程序
区块链的最重要特性是去中心化,它不依赖于任何中心机构或第三方信任
|
9月前
|
开发框架 小程序 前端开发
东郊到家丨家政服务丨预约上门丨系统开发稳定版,家政服务丨预约上门丨东郊到家系统开发(开发案例)及源码技术
 随着人们对家政服务的需求不断增加,家政服务行业也变得越来越受欢迎。家政服务小程序和家政服务系统是两种常见的家政服务解决方案,它们可以为人们提供更加便捷和高效的家政服务体验。下面将详细介绍这两种解决方案。
|
5天前
|
安全 Java 数据库连接
首次面试经历(忘指导)当我在简历上写了苍穹外卖,瑞吉外卖时……
首次面试经历(忘指导)当我在简历上写了苍穹外卖,瑞吉外卖时……
351 1
|
8月前
|
负载均衡 Java 数据库连接
瑞吉外卖项目
瑞吉外卖项目
61 0
|
SQL 缓存 JSON
瑞吉外卖笔记
这是一份写给自己的笔记,主要记录瑞吉外卖项目中自己没有了解过的知识点。我将按照功能来分别解析
668 1
|
11月前
|
前端开发
瑞吉外卖项目(超详细)
新增套餐 在开发业务功能前,先将需要用到的类和接口基本结构创建好: 实体类SetmealDish
|
11月前
|
Java 数据库连接 mybatis
瑞吉外卖项目(超详细)
公共字段自动填充 Mybatis Plus公共字段自动填充,也就是在插入或者更新的时候为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,避免了重复代码。 实现步骤: 1、在实体类的属性上加入@TableField注解,指定自动填充的策略 2、按照框架要求编写元数据对象处理器,在此类中统一为公共字段赋值,此类需要实现MetaObjectHandler接口
|
11月前
|
SQL 前端开发 Java
学习瑞吉外卖项目
以当前热门的外卖点餐为业务基础,业务真实、实用、广泛。基于流行的Spring Boot、mybatis plus等技术框架进行开发。 第一天: 设计产品原型。 新建数据库,导入sql文件。
|
XML 前端开发 JavaScript
点餐项目实现(二)
点餐项目实现(二)
166 0
点餐项目实现(二)