校园外卖点餐系统——Day04【菜品管理业务开发】

❤ 作者主页:欢迎来到我的技术博客😎
❀ 个人介绍:大家好,本人热衷于Java后端开发,欢迎来交流学习哦!( ̄▽ ̄)~*
🍊 如果文章对您有帮助,记得关注点赞收藏评论⭐️⭐️⭐️
📣 您的支持将是我创作的动力,让我们一起加油进步吧!!!🎉🎉

一、文件上传下载

1. 文件上传介绍

文件上传,也称为upload,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程。文件上传在项目中应用非常广泛,我们经常发微博、发微信朋友圈都用到了文件上传功能。

文件上传时,对页面的form表单有如下要求:
在这里插入图片描述

目前一些前端组件库也提供了相应的上传组件,但是底层原理还是基于form表单的文件上传。例如ElementUI中提供的upload上传组件:
在这里插入图片描述
服务端要接收客户端页面上传的文件,通常都会使用Apache的两个组件:

  • commons-fileupload
  • commons-io

Spring框架在spring-web包中对文件上传进行了封装,大大简化了服务端代码,我们只需要在Controller的方法中声明一个MultipartFile类型的参数即可接收上传的文件。


2. 文件下载介绍

文件下载,也称为download,是指将文件从服务器传输到本地计算机的过程。
通过浏览器进行文件下载,通常有两种表现形式:

  • 以附件形式下载,弹出保存对话框,将文件保存到指定磁盘目录
  • 直接在浏览器中打开

通过浏览器进行文件下载,本质上就是服务端将文件以流的形式写回浏览器的过程。


3. 文件上传代码实现

文件上传,页面端可以使用ElementuI提供的上传组件。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>文件上传</title><!-- 引入样式 --><link rel="stylesheet" href="../../plugins/element-ui/index.css" /><link rel="stylesheet" href="../../styles/common.css" /><link rel="stylesheet" href="../../styles/page.css" /><link rel="shortcut icon" href="../../favicon.ico">
</head>
<body><div class="addBrand-container" id="food-add-app"><div class="container"><el-upload class="avatar-uploader"action="/common/upload":show-file-list="false":on-success="handleAvatarSuccess":before-upload="beforeUpload"ref="upload"><img v-if="imageUrl" :src="imageUrl" class="avatar"></img><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload></div></div><!-- 开发环境版本,包含了有帮助的命令行警告 --><script src="../../plugins/vue/vue.js"></script><!-- 引入组件库 --><script src="../../plugins/element-ui/index.js"></script><!-- 引入axios --><script src="../../plugins/axios/axios.min.js"></script><script src="../../js/index.js"></script><script>new Vue({el: '#food-add-app',data() {return {imageUrl: ''}},methods: {handleAvatarSuccess (response, file, fileList) {this.imageUrl = `/common/download?name=${response.data}`},beforeUpload (file) {if(file){const suffix = file.name.split('.')[1]const size = file.size / 1024 / 1024 < 2if(['png','jpeg','jpg'].indexOf(suffix) < 0){this.$message.error('上传图片只支持 png、jpeg、jpg 格式!')this.$refs.upload.clearFiles()return false}if(!size){this.$message.error('上传文件大小不能超过 2MB!')return false}return file}}}})</script>
</body>
</html>

添加CommonController,负责文件上传与下载:

@Slf4j
@RestController
@RequestMapping("common")
public class CommonController {//文件上传@PostMapping("/upload")public R<String> upload(MultipartFile file) {//file 是一个临时文件,需要转存到指定位置,否则请求完成后临时文件会删除log.info("file:{}",file.toString());return null;}
}

MultipartFile定义的file变量必须与name保持一致
在这里插入图片描述


完整代码:

@Slf4j
@RestController
@RequestMapping("common")
public class CommonController {@Value("reggie.path")private String basePath;//文件上传@PostMapping("/upload")public R<String> upload(MultipartFile file) {//file 是一个临时文件,需要转存到指定位置,否则请求完成后临时文件会删除log.info("file:{}",file.toString());//原始文件名String originalFilename = file.getOriginalFilename();String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));//使用UUID随机生成文件名,防止因为文件名相同造成文件覆盖String fileName = UUID.randomUUID().toString() + suffix;//创建一个目录对象File dir = new File(basePath);//判断当前目录是否存在if(!dir.exists()){//目录不存在dir.mkdirs();}try {//将临时文件转存到指定位置file.transferTo(new File(basePath+fileName));} catch (IOException e) {e.printStackTrace();}return R.success(fileName);}}

4. 文件下载代码实现

文件下载,页面端可以使用 < img > 标签展示下载的图片。
在这里插入图片描述
代码如下:

   //文件下载@GetMapping("/download")public void download(String name, HttpServletResponse response){try {//输入流,通过输入流读取文件内容FileInputStream fileInputStream = new FileInputStream(new File(basePath + name));//输出流,通过输出流将文件写回浏览器,在浏览器中展示图片ServletOutputStream outputStream = response.getOutputStream();int len = 0;byte[] bytes = new byte[1024];while ((len = fileInputStream.read(bytes)) != -1){outputStream.write(bytes,0, len);outputStream.flush();}outputStream.close();fileInputStream.close();} catch (Exception e) {e.printStackTrace();}}

二、新增菜品

1. 需求分析

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

在这里插入图片描述


2. 数据模型

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

  • dish(菜品表)
    在这里插入图片描述
  • dish_flavor(菜品口味表)
    在这里插入图片描述

3. 代码开发——准备工作

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

  • 实体类DishFlavor

    @Data
    public class DishFlavor implements Serializable {private static final long serialVersionUID = 1L;private Long id;//菜品idprivate Long dishId;//口味名称private String name;//口味数据listprivate 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

    @Mapper
    public interface DishFlavorMapper extends BaseMapper<DishFlavor> {
    }
    
  • 业务层接口DishFlavorService

    public interface DishFlavorService extends IService<DishFlavor> {
    }
    
  • 业务层实现类 DishFlavorServicelmpl

    @Service
    public class DishFlavorServiceImpl extends ServiceImpl<DishFlavorMapper, DishFlavor> implements DishFlavorService {
    }
    
  • 控制层 DishController

    @Slf4j
    @RestController
    @RequestMapping("/dish")
    public class DishController {@Autowiredprivate DishService dishService;@Autowiredprivate DishFlavorService dishFlavorService;
    }
    

4. 代码开发梳理——交互过程

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

1、页面(backend/page/food/add.html)发送ajax请求,请求服务端获取菜品分类数据并展示到下拉框中;

2、页面发送请求进行图片上传,请求服务端将图片保存到服务器;

3、页面发送请求进行图片下载,将上传的图片进行回显;

4、点击保存按钮,发送ajax请求,将菜品相关数据以json形式提交到服务端。

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


菜品分类下拉框:在 CategoryController 添加

	//根据条件查询分类数据@GetMapping("/list")public R<List<Category>> list(Category category) {//条件构造器LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();//添加条件lambdaQueryWrapper.eq(category.getType() != null, Category::getType, category.getType());//添加排序条件lambdaQueryWrapper.orderByAsc(Category::getSort).orderByAsc(Category::getUpdateTime);List<Category> list = categoryService.list(lambdaQueryWrapper);return R.success(list);}

导入 DishDto,用于封装页面提交的数据:

@Data
public class DishDto extends Dish {private List<DishFlavor> flavors = new ArrayList<>();private String categoryName;private Integer copies;
}

注意: DTO,全称为 Data Transfer object,即数据传输对象,一般用于展示层与服务层之间的数据传输。

新增菜品同时插入菜品对应的口味数据,需要操作两张表:dish、dishflavor

控制层 DishController

	@PostMappingpublic R<String> save(@RequestBody DishDto dishDto) {dishService.saveWithFlavor(dishDto);return R.success("新增菜品成功");}

业务层实现类 DishServiceImpl:

	@Override@Transactionalpublic void saveWithFlavor(DishDto dishDto) {//保存菜品的基本信息到菜品表dishthis.save(dishDto);Long dishId = dishDto.getId(); //菜品id//菜品口味List<DishFlavor> flavors = dishDto.getFlavors();flavors = flavors.stream().map((item) -> {item.setDishId(dishId);return item;}).collect(Collectors.toList());//保存菜品口味数据到口味表dish_flavordishFlavorService.saveBatch(flavors);}

由于以上代码涉及多表操作,在启动类上开启事务支持添加@EnableTransactionManagement注解,该注解应该是默认开启的,故没有添加。


三、菜品信息分页查询

1. 需求分析

系统中的菜品数据很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看,所以一般的系统中都会以分页的方式来展示列表数据。
在这里插入图片描述


2. 代码开发

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

1、页面(backend/page/food/list.html)发送ajax请求,将分页查询参数(page、pageSize、name)提交到服务端,获取分页数据;

2、页面发送请求,请求服务端进行图片下载,用于页面图片展示。

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

 //菜品信息分页查询@GetMapping("/page")public R<Page> page(int page, int pageSize, String name) {//构造分页构造器Page<Dish> pageInfo = new Page<>(page, pageSize);Page<DishDto> dishDtoPage = new Page<>();//构造条件构造器LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();//添加过滤条件queryWrapper.like(!StringUtils.isEmpty(name), Dish::getName, name);//添加排序条件queryWrapper.orderByDesc(Dish::getUpdateTime);//进行分页查询dishService.page(pageInfo, queryWrapper);//对象拷贝BeanUtils.copyProperties(pageInfo, dishDtoPage, "records");List<Dish> records = pageInfo.getRecords();List<DishDto> list=records.stream().map((item)->{DishDto dishDto=new DishDto();BeanUtils.copyProperties(item,dishDto);Long categoryId = item.getCategoryId();//根据id查分类对象Category category = categoryService.getById(categoryId);if(category!=null){String categoryName = category.getName();dishDto.setCategoryName(categoryName);}return dishDto;}).collect(Collectors.toList());dishDtoPage.setRecords(list);return R.success(dishDtoPage);}

四、修改菜品

1. 需求分析

在菜品管理列表页面点击修改按钮,跳转到修改菜品页面,在修改页面回显菜品相关信息并进行修改,最后点击确定按钮完成修改操作。
在这里插入图片描述


2. 代码开发

在开发代码之前,需要梳理一下修改菜品时前端页面( add.html)和服务端的交互过程:

1、页面发送ajax请求,请求服务端获取分类数据,用于菜品分类下拉框中数据展示

2、页面发送ajax请求,请求服务端,根据id查询当前菜品信息,用于菜品信息回显

  • DishController处理Get请求
        //根据id查询菜品信息与对应的口味信息@GetMapping("/{id}")public R<DishDto> getById(@PathVariable Long id) {DishDto dishDto = dishService.getByIdWithFlavor(id);return R.success(dishDto);}
    
  • 在DishServiceImpl添加getByIdWithFlavor方法
    @Transactional@Overridepublic DishDto getByIdWithFlavor(Long id) {//查询菜品基本信息Dish dish = this.getById(id);DishDto dishDto = new DishDto();BeanUtils.copyProperties(dish, dishDto);//查询菜品口味信息LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(DishFlavor::getDishId, dish.getId());List<DishFlavor> list = dishFlavorService.list(queryWrapper);dishDto.setFlavors(list);return dishDto;}
    

在这里插入图片描述

3、页面发送请求,请求服务端进行图片下载,用于页图片回显

4、点击保存按钮,页面发送ajax请求,将修改后的菜品相关数据以json形式提交到服务端

  • 在DishController添加put方法
      //修改菜品@PutMappingpublic R<String> update(@RequestBody DishDto dishDto){dishService.updateWithFlavor(dishDto);return R.success("修改菜品成功");}
    
  • 在DishServiceImpl添加updateWithFlavor方法
     @Overridepublic void updateWithFlavor(DishDto dishDto) {//更新dish表基本信息this.updateById(dishDto);//更新dish_flavor表信息delete操作LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(DishFlavor::getDishId, dishDto.getId());dishFlavorService.remove(queryWrapper);//更新dish_flavor表信息insert操作List<DishFlavor> flavors = dishDto.getFlavors();flavors = flavors.stream().map((item) -> {item.setDishId(dishDto.getId());return item;}).collect(Collectors.toList());dishFlavorService.saveBatch(flavors);}
    

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


五、停售/起售菜品,删除菜品

1. 需求分析

在商品买卖过程中,商品停售,起售可以更加方便的让用户知道店家还有什么类型的商品在卖。删除方法也更方便的管理菜品。

2. 代码实现

在DishController添加sale方法与delete方法,通过数组保存ids,批量起售停售、删除都能生效

	//停售起售菜品@PostMapping("/status/{status}")public R<String> sale(@PathVariable int status, String[] ids) {for(String id : ids) {Dish dish = dishService.getById(id);dish.setStatus(status);dishService.updateById(dish);}return R.success("修改成功");}//删除菜品@DeleteMappingpublic R<String> delete(String[] ids) {for (String id : ids) {dishService.removeById(id);}return R.success("删除成功");}

创作不易,如果有帮助到你,请给文章点个赞和收藏,让更多的人看到!!!
关注博主不迷路,内容持续更新中。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小饭馆拓客营销流程,小饭馆宣传推广方案

基于目前持续回暖的餐饮行业&#xff0c;小饭馆起死回生&#xff0c;业绩翻倍&#xff0c;关键在于营销推广。那么如何进行小饭馆的推广&#xff1f;今天我们就和各位聊聊小饭馆引流推广应该如何做&#xff01; 小饭馆营销推广流程 小饭馆引流推广方案主要包含如下&#xff1a…

基于python Django 餐馆点菜管理系统

问题描述&#xff1a; 随着网络的迅速发展&#xff0c;越来越多的人开始接受甚至时依赖了网络营业的这种交易形式&#xff0c;传统的点菜模式不仅浪费时间&#xff0c;效率低下&#xff0c;而且特别耗费成本与人力&#xff0c;因此不少商家开始使用网上点菜系统。网上点菜系统是…

软件测试项目实战,一比一还原可以写进简历的

项目一&#xff1a;ShopNC商城 项目概况&#xff1a; ShopNC商城是一个电子商务B2C电商平台系统&#xff0c;功能强大&#xff0c;安全便捷。适合企业及个人快速构建个性化网上商城。 包含PCIOS客户端Adroid客户端微商城&#xff0c;系统PC后台是基于ThinkPHP MVC构架开发的跨…

软件测试【个人简历】展示模板

个人简历 就职目标&#xff1a;软件测试工程师 简历是我们求职的第一步&#xff0c;也是非常重要的一步。 如果你简历写的一塌糊涂&#xff0c;那么你瞬间就会被淘汰&#xff0c;那么一份好的简历应该怎么写呢&#xff1f; 一般分为如下几部分内容&#xff1a; 1、个人基本…

软件测试电商项目实战(写进简历没问题)

前言 说实话&#xff0c;在找项目的过程中&#xff0c;我下载过&#xff08;甚至付费下载过&#xff09;N多个项目、联系过很多项目的作者&#xff0c;但是绝大部分项目&#xff0c;在我看来&#xff0c;并不适合你拿来练习&#xff0c;它们或多或少都存在着“问题”&#xff…

如何介绍简历中的项目呢?请看软件测试老师的分享

项目经验与工作经验是相辅相成的&#xff0c;但较之于工作经验&#xff0c;项目经验更侧重于表现求职者在某个专业领域内的技能水平&#xff08;技能水平决定了工资水平&#xff09;。因而&#xff0c;技术类岗招聘的时候&#xff0c;更注重项目经验。项目介绍是有套路的&#…

软件测试的简历里面,项目介绍要怎么写好呢

一、如果你是做功能测试&#xff08;项目介绍可以这样&#xff09; 项目一&#xff1a;2019/4-至今 项目简介&#xff1a;该项目是题库/考勤APP&#xff0c;主要的功能有题库、考勤、用户信息系统、直播视频、社区板块。迭代了多少次xxx,目前正在正常运营xxx. 负责模块&#…

详解9个写进简历的数据分析项目

核心知识点覆盖 Excel、Python、SQL、Pandas、Numpy、Matplotlib、Power BI、PyEcharts可视化、数据指标、波士顿矩阵、数据建模、AARRR模型、漏斗模型、RFM模型、A\BTest、逻辑回归、线性回归、预测分析、K近邻算法、网络爬虫、数据化运营、用户画像体系构建 9大企业项目实战 …

可以写进简历的软件测试项目实战经验(包含电商、银行、app等)

目录 目录 前言&#xff1a; 1、项目名称: 家电购 2、项目名称: 瑞德商城 3、项目名称:随意读(APP) 4、项目&#xff1a;东海农村商行 总结 前言&#xff1a; 今天给大家带来几个软件测试项目的实战总结及经验&#xff0c;适合想自学、转行或者面试的朋友&#xff0c;可…

postmessage通信

在业务中&#xff0c;有一种开发形式为&#xff1a;多个子系统集成为一个父系统。每个系统之间都管理着不同的业务与逻辑&#xff0c;他们是互不干涉的。 那么&#xff0c;我们如何在父系统页面中操作子系统中的内容呢&#xff1f; 首先通过vite初始化两个项目。 父系统端口…

微软历史上的12个Windows操作系统版本排名

作为全球最流行的操作系统之一&#xff0c;Windows 操作系统的发布对世界产生了深远的影响。Windows 操作系统的发布历程可以追溯到 1985 年&#xff0c;当时微软推出了第一个版本的 Windows。随着时间的推移&#xff0c;Windows 不断升级和改进&#xff0c;推出了多个版本&…

独立开发变现周刊(第86期):月收入4000美元的日程规划器

分享独立开发、产品变现相关内容&#xff0c;每周五发布。 目录 1、NotionReads: 在Notion中管理你的阅读书籍2、Zaap.ai: 面向创作者的一站式工具3、microfeed: 开源的可自我托管的轻量级内容管理系统(CMS)4、Reactive Resume&#xff1a;一个免费的开源简历生成器5、一个月收…

苹果的 Vision Pro 会重蹈谷歌眼镜的覆辙吗?

本文作者认为&#xff0c;一款成功的AR头戴式设备需要考虑以下几方面&#xff1a;成本高&#xff0c;回报低&#xff1b;安全与隐私问题&#xff1b;时机与市场&#xff1b;4、设计与社会接受度。 原文链接&#xff1a;https://uxdesign.cc/can-apples-vision-pro-succeed-wher…

chatgpt赋能python:Python描述性统计分析:基础概念、应用和实例分析

Python描述性统计分析&#xff1a;基础概念、应用和实例分析 作为一种高效、可扩展和易于学习的编程语言&#xff0c;Python在文本处理、数据挖掘、机器学习、数据可视化等方面已经得到了广泛应用。在数据分析领域&#xff0c;Python拥有强大的描述性统计分析库&#xff0c;可…

AIGC:Google Bard VS ChatGPT 简介及对比分析

文章目录 [toc]前言一、Bard和ChatGPT二、应用场景三、时效性小结其他 前言 自从 OpenAI 向公众发布ChatGPT以来的过去几个月里&#xff0c;我们都见证了围绕 ChatGPT 的各种测评&#xff0c;并为它带来的效果感到惊艳。昨晚Google开放了自家研发的AI聊天机器人Bard的测评入口…

R语言利用wordcloud2绘制词云

本次的重点绘制词云&#xff0c;所以并不太重视其他分析方面的论述。 本机环境&#xff1a; window 10 R x64 3.3.0 R包&#xff1a; tmcn&#xff1a;词频统计 wordcloud2&#xff1a;绘制词云 Rwordseg&#xff1a;分词 由于tmcn和Rwordseg包在R3.3.0的版本中没有可以…

同一界面画出多个QQ图(R语言)

题目&#xff1a;一名研究者用光子吸收法测量了妇女骨骼中无机物含量&#xff0c;对三根骨头主侧和非主侧记录了测量值&#xff0c;数据框“T1bones.txt”中的第2至第7列记录了相应数据。对各个变量做qq图&#xff0c;在同一个界面画出所有的qq图&#xff0c;不同的qq图用不同颜…

R语言各个包里面的数据集

关注微信公共号&#xff1a;小程在线 关注CSDN博客&#xff1a;程志伟的博客 Package Item Title csv docdatasetsAirPassengersMonthly Airline Passenger Numbers 1949-1960CSVDOCdatasetsBJsalesSales Data with Leading IndicatorCSVDOCdatasetsBODBiochemical Oxygen Dema…

R语言 聊天词云图

准备聊天记录 建议使用QQ聊天记录&#xff0c;导出txt格式 进行文本分词并可视化 install.packages("wordcloud2") install.packages("jiebaR") install.packages("jiebaRD") library(wordcloud2) library(jiebaRD) library(jiebaR) enginew…

巧用R语言实现各种常用的数据输入与输出

将数据输入或加载到R工作空间中&#xff0c;是使用R进行数据分析的第一步。R语言支持读取众多格式的数据文件&#xff0c;excel文件&#xff0c;csv文件&#xff0c;txt文件和数据库&#xff08;MYSQL数据库&#xff09;等&#xff1b;其中&#xff0c;excel和csv是我们最常遇到…