瑞吉外卖 - 新增菜品功能(16)

news2025/1/8 5:11:08

某马瑞吉外卖单体架构项目完整开发文档,基于 Spring Boot 2.7.11 + JDK 11。预计 5 月 20 日前更新完成,有需要的胖友记得一键三连,关注主页 “瑞吉外卖” 专栏获取最新文章。
相关资料:https://pan.baidu.com/s/1rO1Vytcp67mcw-PDe_7uIg?pwd=x548
提取码:x548

文章目录

    • 1.需求分析
    • 2.数据模型
    • 3.代码开发
      • 3.1 搭建代码框架
      • 3.2 梳理交互过程
      • 3.3 代码实现
    • 4.功能测试

1.需求分析

后台系统中可以管理菜品信息,通过新增功能来添加一个新的菜品,在添加菜品时需要选择当前菜品所属的菜品分类,并且需要上传菜品图片,在移动端会按照菜品分类来展示对应的菜品信息。

2.数据模型

新增菜品,其实就是将新增页面录入的菜品信息插入到 dish 表,如果添加了口味做法,还需要向 dish_flavor 表插入数据。所以在新增菜品时,涉及以下两个表:

dish:菜品表

dish_flavor:菜品口味表

3.代码开发

3.1 搭建代码框架

在开发业务功能前,先将需要用到的类和接口基本结构创建好,流程与之前一样。

实体类 DishDishFlavor 直接从下载资料中导入即可,Dish 实体前面已经导入过了,DishFlavor 实体类完整代码如下:

package cn.javgo.reggie_take_out.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 DishFlavor implements Serializable {
    // 序列化版本号
    private static final long serialVersionUID = 1L;
    
    //主键
    private Long id;
    
    //菜品id
    private Long dishId;
    
    //口味名称
    private String name;
    
    //口味数据 list
    private String value;
    
    @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 接口 DishFlavorMapper 相关代码如下:

package cn.javgo.reggie_take_out.mapper;

import cn.javgo.reggie_take_out.entity.DishFlavor;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface DishFlavorMapper extends BaseMapper<DishFlavor> {
}

业务层接口 DishFlavorService 相关代码如下:

package cn.javgo.reggie_take_out.service;

import cn.javgo.reggie_take_out.entity.DishFlavor;
import com.baomidou.mybatisplus.extension.service.IService;

public interface DishFlavorService extends IService<DishFlavor> {
}

业务层实现类 DishFlavorServicelmpl 相关代码如下:

package cn.javgo.reggie_take_out.service.impl;

import cn.javgo.reggie_take_out.entity.DishFlavor;
import cn.javgo.reggie_take_out.mapper.DishFlavorMapper;
import cn.javgo.reggie_take_out.service.DishFlavorService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

@Service
public class DishFlavorServicelmpl extends ServiceImpl<DishFlavorMapper, DishFlavor> implements DishFlavorService {
}

控制层 DishController 相关代码如下:

package cn.javgo.reggie_take_out.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 菜品控制器
 */
@RestController
@RequestMapping("/dish")
public class DishController {
    @Resource
    private DishService dishService;
    
    @Resource
    private DishFlavorService dishFlavorService;
    
    @Resource
    private CategoryService categoryService;
}

3.2 梳理交互过程

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

  1. 页面(backend/page/food/add.html)发送 ajax 请求,请求服务端获取菜品分类数据并展示到下拉框中;
  2. 页面发送请求进行图片上传,请求服务端将图片保存到服务器;
  3. 页面发送请求进行图片下载,将上传的图片进行回显;
  4. 点击保存按钮,发送 ajax 请求,将菜品相关数据以 json 形式提交到服务端。

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

展示分类列表的请求:

上传图片的请求:(已实现)

下载图片的请求:(已实现)

保存菜品信息的请求:

3.3 代码实现

CategoryController 中对应的处理分类列表的方法如下:

@RestController
@RequestMapping("/category")
public class CategoryController {
    /**
     * 根据条件查询分类列表
     * @param category 分类实体
     * @return R
     */
    @GetMapping("/list")
    public R<List<Category>> list(Category category){
        // 1.构造查询条件
        QueryWrapper<Category> queryWrapper = new QueryWrapper<>();
        // 2.添加查询条件(根据分类类型查询)
        queryWrapper.eq("type",category.getType());
        // 3.添加排序条件(先根据 sort 字段进行排序,再根据更新时间进行排序)
        queryWrapper.orderByAsc("sort").orderByDesc("update_time");
        // 4.执行查询
        List<Category> list = categoryService.list(queryWrapper);
        // 5.返回结果
        return R.success(list);
    }
    
    // 省略其他方法
}

在开发处理保存菜品信息方法是我们需要先关注一个问题,方法参数直接封装为 Dish 吗?不妨我们先来看看在发送请求时都携带了哪些 json 数据:

从其中圈出的口味可以看出 json 数据中还携带了关于口味的信息,但是该属性在 Dish 实体类里面是没有的。这种情况下我们可以使用 DTO,全称为 Data Transfer Object,即数据传输对象,一般用于显示层与服务层之间的数据传输。对此我们可以提供一个 dto/DishDto.java 用于封装页面提交的数据。

资料位置:瑞吉外卖\瑞吉外卖项目\资料\dto

该目录下有三个 Dto 类,我们可以一次全部复制到项目的 dto 目录下,以免后续重复导入。

完整代码如下:

package cn.javgo.reggie_take_out.dto;

import cn.javgo.reggie_take_out.entity.Dish;
import cn.javgo.reggie_take_out.entity.DishFlavor;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;

@Data
public class DishDto extends Dish {
    // 菜品口味,接收前端传来的数据
    private List<DishFlavor> flavors = new ArrayList<>();
    // 菜品分类名称
    private String categoryName;

    private Integer copies;
}

其中的 flavors 属性就是用来处理请求携带的 json 数据中的 flavors 口味数据的,同时该类继承了 Dish 实体类,拥有 Dish 的属性。这样我们就可以在相应的处理方法中提供 DishDto 作为方法参数进行封装了。

DishController 中对应的处理保存菜品信息方法如下:

@RestController
@RequestMapping("/dish")
public class DishController {
    @Resource
    private DishService dishService;

    /**
     * 新增菜品
     * @param dishDto 自定义的 DTO 对象,用于接收前端传递的数据
     * @return R
     */
    @PostMapping
    public R<String> save(@RequestBody DishDto dishDto){
        // 调用菜品业务层自定义的新增菜品方法
        dishService.saveWithFlavor(dishDto);
        return R.success("新增菜品成功");
    }
    
    // 省略其他方法
}

由于保存操作要同时操作 dish 和 dish_flavor 表两张表,因此我们需要自定义 saveWithFlavor 保存方法,DishService 中对应的抽象方法如下:

package cn.javgo.reggie_take_out.service;

import cn.javgo.reggie_take_out.dto.DishDto;
import cn.javgo.reggie_take_out.entity.Dish;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * @author: JavGo
 * @description: TODO
 * @date: 2023/5/17 20:38
 */
public interface DishService extends IService<Dish> {
    /**
     * 新增菜品,同时新增菜品口味(需要操作两张表)
     * @param dishDto 自定义的 DTO 对象,用于接收前端传递的数据
     */
    public void saveWithFlavor(DishDto dishDto);
}

然后在 DishServiceImpl 中进行具体实现,完整代码如下:

package cn.javgo.reggie_take_out.service.impl;

import cn.javgo.reggie_take_out.dto.DishDto;
import cn.javgo.reggie_take_out.entity.Dish;
import cn.javgo.reggie_take_out.entity.DishFlavor;
import cn.javgo.reggie_take_out.mapper.DishMapper;
import cn.javgo.reggie_take_out.service.DishFlavorService;
import cn.javgo.reggie_take_out.service.DishService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;

/**
 * @author: JavGo
 * @description: TODO
 * @date: 2023/5/17 20:39
 */
@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {
    @Resource
    private DishFlavorService dishFlavorService;

    /**
     * 新增菜品,同时新增菜品口味(需要操作两张表)
     * @param dishDto 自定义的 DTO 对象,用于接收前端传递的数据
     */
    @Transactional
    @Override
    public void saveWithFlavor(DishDto dishDto) {
        // 1.保存菜品的基本信息到菜品表
        this.save(dishDto);
        // 2.获取菜品的 id
        Long dishId = dishDto.getId();
        // 3.获取菜品口味
        List<DishFlavor> flavors = dishDto.getFlavors();
        // 4.遍历菜品口味,设置菜品 id
        flavors.forEach(flavor -> flavor.setDishId(dishId));
        // 5.批量保存菜品口味
        dishFlavorService.saveBatch(flavors);
    }
}

4.功能测试

重启应用,进行新建菜品功能测试:

查看数据库,添加成功:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/541995.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(十)Spring源码阅读:finishBeanFactoryInitialization方法

一、概述 该方法是实例化bean的主要方法&#xff0c;它实现的主要流程如下图所示。 这是方法执行的主要流程图。 具体执行流程如下图&#xff0c;我们将按照具体执行流程一个个介绍具体的方法。 二、主要方法 finishBeanFactoryInitialization内部调用了getBean方法。 getBea…

AIGC+机器人=具身智能?硅谷最酷的两个男人不谋而合预演“下个浪潮”

收集整理|小鱼新的AI题材层出不穷&#xff0c;这次轮到“机器人AI"融合而成的具身智能概念。 “硅谷钢铁侠"马斯克和热爱黑色皮衣的"显卡教父”黄仁勋均作出积极表态&#xff0c;可谓不谋而合。 当地时间5月16日&#xff0c;特斯拉2023年年度股东大会召开&…

unity DoTween动画插件的使用(最全)

DOTween是最常用的动画插件之一,比使用Unity自带脚本写动画,方便很多。 插件获取 untiy商店插件地址 https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676 DOTween商城地址,开发文档 http://dotween.demigiant.com 导入和设置 DOTween首次使…

离散数学_九章:关系 —— 拓扑排序

拓扑排序 背景知识相容一个引理什么是拓扑排序 拓扑排序算法&#xff08;伪代码&#xff09;几个实例例1例2 假设一个项目由20个不同的任务构成。某些任务只能在其他任务结束之后完成。如何找到关于这些任务的顺序&#xff1f; 为了对这个问题建模&#xff0c;我们在任务的集合…

mysql强制修改mysql数据库密码(无需原密码)

1.创建新记事本new_password.txt 定位到记事本绝对路径&#xff0c;我直接放桌面 C:\Users\bao123\Desktop 为用户为 root 新密码 123456为例 ALTER user rootlocalhost identified by 123456; 为用户为 mytest 新密码 88888888为例 ALTER user mytestlocalhost identifi…

opencv_c++学习(十三)

一、创建滑动条 createTrackbar(const String & trackbarname, const String & winname, int* value, int count, onChange , TrackbarCallback 0, void * userdata 0)trackbarname:滑动条的名称。 winname:创建滑动条窗口的名称。 value:指向整数变量的指针&#xff0…

Harbor在arm架构下亲测编译成功

先安装好Docker,docker-compose 华为云arm架构安装Docker arm架构安装docker-compose Harbor官网: https://github.com/goharbor/harbor/releases Harbor官方没有提供arm架构的包,需要自己编译,我编译好的版本是:harbor-1.9.1 大家可以按我的博客,自己去编译,或评论留言给…

Vivado 下 LED 流水灯实验

目录 Vivado 下 LED 流水灯实验 1、实验简介 2、实验环境 3、实验原理 3.1、LED硬件电路 3.2、程序设计 4、Vivado 工程 4.1、创建工程 4.2、编写流水灯的 verilog代码 1. 点击 Project Manager 下的 Add Sources 图标&#xff08;或者使用快捷键 AltA&#xff09;。…

基于协同过滤的推荐算法

基于协同过滤的推荐算法 基于协同过滤&#xff08;CF&#xff09;的推荐基于近邻的协同过滤基于用户的协同过滤&#xff08;User-CF&#xff09;基于物品的协同过滤&#xff08;Item-CF&#xff09;User-CF 和 Item-CF 的比较基于协同过滤的推荐优缺点基于模型的协同过滤隐语义…

WoW 游戏软件

访问【WRITE-BUG数字空间】_[内附完整源码和文档] 我们选择Tcp协议进行传输&#xff0c;之所以采用tcp,首先是因为tcp传输稳定&#xff0c;相比于udp不稳定的传输&#xff0c;tcp能确保消息一定传输出去。然后是tcp有服务器&#xff0c;相比于 p2p 无服务器模型&#xff0c;tc…

RocketMQ 下载安装

一、下载地址 https://rocketmq.apache.org/download/ 下载完成解压即可 二、安装 2.1 系统环境变量配置 1、右键我的电脑–>属性 ​ 2、高级系统设置–环境变量 ​ 3、系统变量中–>新建 2.2 启动NAMESERVER cmd命令框执行进入至‘MQ文件夹\bin’下 start mqnames…

【教学类-33-02】食物加加加2.0版(3、4、5、10、15、20以内数字加法,随机抽数)

作品展示 3以内点数加法&#xff1a;加法最大值6 4以内点数加法&#xff1a;加法最大值8 背景需求&#xff1a; 幼儿在完成“5以内加法21题、5以内减法21题”时&#xff0c;有两个特点&#xff1a; 1、50%幼儿口算、另外50%不会做的孩子虽然画圈划圈&#xff0c;但更多还是习…

数据结构_图

目录 1. 图的基本概念 1.1 图的定义 1.1.1 有向图 1.1.2 无向图 1.1.3 简单图、多重图 1.1.4 完全图&#xff08;也称简单完全图&#xff09; 1.1.5 子图 1.1.6 连通、连通图和连通分量 1.1.7 强连通图、强连通分量 1.1.8 生成树、生成森林 1.1.9 顶点的度、入度和出…

MapReduce【自定义InputFormat】

MapReduce在处理小文件时效率很低&#xff0c;但面对大量的小文件又不可避免&#xff0c;这个时候就需要相应的解决方案。 默认的输入格式为TextInputFormat&#xff0c;对于小文件&#xff0c;它是按照它的父类FileInputFormat的切片机制来切片的&#xff0c;也就是不管一个文…

Java基础学习(17)网络编程

Java基础学习 一、 网络编程1.1 什么是网络编程1.2 常见的软件架构&#xff1a;1.3 网络编程的三要素1.4 IP1.4.1 InetAddress用法 1.5 端口号1.6 协议1.6.1 UDP协议1.6.1.1 UDP的三种通信方式 1.6.2 TCP协议1.6.2.1 TCP底层原理 一、 网络编程 1.1 什么是网络编程 解释&…

C++常用的支持中文的GUI库Qt 6之一:下载、安装与使用

C常用的支持中文的GUI库Qt 6之一&#xff1a;下载、安装与使用 因为Qt发展变化较快&#xff0c;网上许多介绍Qt的下载、安装与使用已过时&#xff0c;初学者常因行不通而受挫&#xff0c;故此发布本文&#xff0c;以Qt 6.2.4开源版在Windows 10安装与使用为例介绍。 C好用的GU…

DM8:达梦数据库宕机版本记录汇总(持续更新中)

DM8:达梦数据库宕机版本记录汇总&#xff08;持续更新中&#xff09; 环境介绍1 SQL引起的数据库故障1.1 SQL引起的数据库故障汇总表1.2 gdb dmserver core 调试得到数据库崩溃时的内存信息1.3 优化参数解决故障 环境介绍 在测试环境或生产环境&#xff0c;特别情况下会遇到数…

go tool pprof 参数 ‘-base‘ 和 ‘-diff_base‘ 之间的区别

go tool pprof 工具是用于分析由 runtime/pprof包 或 net/http/pprof包产生的profile数据&#xff0c;完整的帮助文档在 https://github.com/google/pprof/blob/main/doc/README.md &#xff0c;pprof 工具支持的参数很多&#xff0c;可以用命令 go tool pprof --help来查看全部…

DJ5-4 交换局域网(第一节课)

目录 一、局域网概述 1、LAN 的特点和分类 2、常见的网络拓扑结构 二、计算机与局域网的连接 三、局域网体系结构 四、链路层寻址地址 1、MAC 地址分配 2、MAC 地址识别 五、ARP 地址解析协议 1、ARP 地址解析协议 2、ARP&#xff1a;两个主机位于同一个局域网 3、…

网络计算模式复习(六)

什么是CDN CDN的全称是Content Delivery Network&#xff0c;即内容分发网络。 其目的通过在现有的Internet中增加一层新的网络架构&#xff0c;将网站的内容发布到最接近用户的网络“边缘”&#xff0c;使用户可以就近取得所需的内容&#xff0c;解决Internet网络拥挤的状况&…