学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
Python实战微信订餐小程序 | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 |
Python量化交易实战 | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |
该系列将记录一份完整的实战项目的完成过程,该篇属于第四天
案例来自B站黑马程序员Java项目实战《瑞吉外卖》,请结合课程资料阅读以下内容
该篇我们将完成以下内容:
由于是第一次接触文件上传下载,我们分为五个小阶段讲解
文件上传,也称为upload,是指将本地图片,视频,音频等文件上传到服务器上,可以供其他用户浏览下载的过程
首先我们介绍文件上传对前端的要求:
尽管前端组件库提供了相应的上传组件,但这些组件底层仍旧采用上述要求的格式构造
然后我们介绍文件上传在后端的实现:
目前我们的Spring框架在Spring-web包下对文件上传进行了封装,简化了服务端代码
我们只需要在Controller中的方法声明一个MultipartFile类型的参数即可接收上传的数据
文件下载,也称为download,是指将文件从服务器传输到本地计算机的过程
通过浏览器进行文件下载,通常有两种表现形式:
通过浏览器进行文件下载,本质上就是服务端将文件以流的形式写回浏览器的过程
测试用例:
我们先来思考一下文件上传的逻辑:
接下来我们正式开始文件上传代码的实现:
package com.qiuluo.reggie.controller;
import com.qiuluo.reggie.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.CoyoteOutputStream;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.UUID;
@Slf4j
@RestController
@RequestMapping("/common")
public class CommonController {
/**
* 下载操作
* @param MultipartFile file 是文件上传的唯一必备代码,代表上传的数据
* 注意:file只是一个临时文件,当我们的request请求结束时,file也会消失,所以我们需要将它保存起来
* @return
*/
@PostMapping("/upload")
public Result upload(MultipartFile file){
// 我们可以直接记录日志查看是否收集到file
log.info(file.toString());
}
}
package com.qiuluo.reggie.controller;
import com.qiuluo.reggie.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.CoyoteOutputStream;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.UUID;
@Slf4j
@RestController
@RequestMapping("/common")
public class CommonController {
@Value("${reggie.path}")
private String BasePath;
/**
* 下载操作
* @param file 注意需要与前端传来的数据名一致
* @return
*/
@PostMapping("/upload")
public Result upload(MultipartFile file){
// 由于我们的file是临时文件,我们需要将该文件保存在计算机上
try {
// 这个方法可以转载文件到指定目录
file.transferTo(new File("D:/hello.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
// 注意:我们需要返回文件名,因为我们还需要让图片回显,回显就需要再次传入文件名来查询文件
return Result.success(fileName);
}
}
# 我们定义了一个reggie.path的参数来存放我们存放文件的地址
reggie:
path: E:\imgs\
package com.qiuluo.reggie.controller;
import com.qiuluo.reggie.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.CoyoteOutputStream;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.UUID;
/*
目前我们的文件存放已经有了固定的位置
但是我们的文件名以及后缀文件名还没有获得,我们将把它们变为动态的
*/
@Slf4j
@RestController
@RequestMapping("/common")
public class CommonController {
// 定义主路径
@Value("${reggie.path}")
private String BasePath;
/**
* 下载操作
* @param file 注意需要与前端传来的数据名一致
* @return
*/
@PostMapping("/upload")
public Result upload(MultipartFile file){
// 注意:file只是一个临时文件,当我们的request请求结束时,file也会消失,所以我们需要将它保存起来
// 这个方法可以获得文件的原名称,但不推荐设置为文件名保存(因为可能出现重复名称导致文件覆盖)
String originalFilename = file.getOriginalFilename();
// 将原始文件的后缀截取下来
String substring = originalFilename.substring(originalFilename.lastIndexOf("."));
// UUID生成随机名称,文件名设置为 UUID随机值+源文件后缀
String fileName = UUID.randomUUID().toString() + substring;
// 判断文件夹是否存在,若不存在需创建一个
File dir = new File(BasePath);
if (!dir.exists()){
dir.mkdirs();
}
// 这个方法可以转载文件到指定目录
try {
file.transferTo(new File(BasePath + fileName));
} catch (IOException e) {
e.printStackTrace();
}
return Result.success(fileName);
}
}
同样我们来思考一下文件下载的逻辑:
我们的文件下载同时在CommonController中实现:
package com.qiuluo.reggie.controller;
import com.qiuluo.reggie.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.CoyoteOutputStream;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.UUID;
@Slf4j
@RestController
@RequestMapping("/common")
public class CommonController {
@Value("${reggie.path}")
private String BasePath;
/**
*
* @param name
* @param response
* @return
*/
@GetMapping("/download")
public void download(String name, HttpServletResponse response){
// 我们将在里面实现,读取文件,再返回文件的操作
}
}
package com.qiuluo.reggie.controller;
import com.qiuluo.reggie.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.CoyoteOutputStream;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.UUID;
@Slf4j
@RestController
@RequestMapping("/common")
public class CommonController {
@Value("${reggie.path}")
private String BasePath;
/**
* 文件下载
* @param name
* @param response
* @return
*/
@GetMapping("/download")
public void download(String name, HttpServletResponse response){
try {
// 输入流获得数据
FileInputStream fileInputStream = new FileInputStream(new File(BasePath + name));
// 输出流写出数据
ServletOutputStream outputStream = response.getOutputStream();
// 设置文件类型(可设可不设)
response.setContentType("image/jpeg");
// 转载数据
int len = 0;
byte[] bytes = new byte[1024];
while ((len = fileInputStream.read(bytes)) != -1){
outputStream.write(bytes,0,len);
outputStream.flush();
}
// 关闭数据
fileInputStream.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
我们打开之前转载过来的upload.html页面,传进照片后照片显示在页面中即为成功
我们的功能开发通常分为三部分
当我们点击页面的菜品的新添时,会弹出页面,我们根据这个页面进行分析:
我们需要注意,这里还有一个菜品分类的下拉框,其中菜品分类的数据是通过请求到后台最后到数据库查询所得到的:
此外我们点击保存时,还会将一个菜品的相关信息请求返回后台:
我们需要注意的是:这里返回的并不仅仅只有菜品Dish的数据表,还包括了调料Dish Flavor的数据表
所以我们得到数据时不能采用Dish来获得数据
这里我们提出一个新的概念:
这是一种设计模式之间传输数据的软件应用系统,它用于储存一些不属于同一个数据库中的一些信息
我们会新创一种DishDto实体类来继承Dish实体类并且新添一些关于DishFlavor的属性或方法来接收整个数据
在最后我们简单查看一下Dish和DishFlavor的数据表:
其中category_id表示所属分类的id
其中dish_id表示该调味的菜的id
首先我们来实现一个简单的功能,获得菜品分类并返回前端页面:
package com.qiuluo.reggie.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Category;
import com.qiuluo.reggie.service.impl.CategoryServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/category")
public class CategoryController {
@Autowired
private CategoryServiceImpl categoryService;
/**
* 返回所有分类名称
*/
@GetMapping("/list")
public Result> list(Category category){
// 创造一个LambdaQueryWrapper来判断Type=1并设置排序顺序
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper();
queryWrapper.eq(category.getType() != null,Category::getType,category.getType());
queryWrapper.orderByAsc(Category::getSort).orderByDesc(Category::getUpdateTime);
// 查询信息
List list = categoryService.list(queryWrapper);
// 返回信息
return Result.success(list);
}
}
接下来我们来实现存储双数据表到数据库的操作:
# 首先我们来完成一些基本准备(我们的DishFlavor的操作也会放在DishController中实现)
实体类DishFlavor
数据层DishFlavorMapper
业务层接口DishFlavorService
业务层DishFlavorServiceImpl
服务层DishController
// 我们通常单独创建一个包dto来装在DTO类
package com.qiuluo.reggie.dto;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.domain.DishFlavor;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class DishDto extends Dish {
// 在里面设置了List flavors 来装载 flavors
private List flavors = new ArrayList<>();
// categoryName 表示属于的分类名
private String categoryName;
private Integer copies;
}
package com.qiuluo.reggie.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.domain.DishFlavor;
import com.qiuluo.reggie.dto.DishDto;
public interface DishService extends IService {
// 由于当前的默认方法无法满足我们的需求,我们创建新的方法来实现该操作
//新增菜品,同时插入菜品对应的口味数据,需要操作两张表:dish、dish\_flavor
public void saveWithFlavor(DishDto dishDto);
}
package com.qiuluo.reggie.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.domain.DishFlavor;
import com.qiuluo.reggie.dto.DishDto;
import com.qiuluo.reggie.mapper.DishMapper;
import com.qiuluo.reggie.service.DishService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class DishServiceImpl extends ServiceImpl implements DishService {
// 调入dishFlavor的业务层实现类
@Autowired
private DishFlavorServiceImpl dishFlavorService;
public void saveWithFlavor(DishDto dishDto){
// 1. 将菜品数据导入
this.save(dishDto);
// 2. 将Flavor导入(注意:Flavor传入时没有传入dishID,需要我们手动设置)
List flavors = dishDto.getFlavors();
for (DishFlavor flavor:flavors) {
flavor.setDishId(dishDto.getId());
}
dishFlavorService.saveBatch(flavors);
}
}
package com.qiuluo.reggie.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Category;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.dto.DishDto;
import com.qiuluo.reggie.service.impl.CategoryServiceImpl;
import com.qiuluo.reggie.service.impl.DishServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {
@Autowired
private DishServiceImpl dishService;
/**
* 新增菜品
* @param dishDto
* @return
*/
@PostMapping
public Result save(@RequestBody DishDto dishDto){
dishService.saveWithFlavor(dishDto);
return Result.success("新创成功");
}
}
点击打开新建菜品,填写数据点击后数据库出现相关菜品即可
我们的功能开发通常分为三部分
系统中菜品很多时,我们需要采用分页查询,使菜品多批出现防止拥挤导致页面阅读不方便
这里我们先给出完成操作后的图片:
我们需要注意的是这里的菜品分类直接出了分类的名称
但是我们的Dish中只给出了菜品分类的id,所以我们还需要借用id去查出所属分类的名称并重新赋值
首先我们来完成简单的分页查询操作:
package com.qiuluo.reggie.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Category;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.dto.DishDto;
import com.qiuluo.reggie.service.impl.CategoryServiceImpl;
import com.qiuluo.reggie.service.impl.DishServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {
@Autowired
private DishServiceImpl dishService;
@Autowired
private CategoryServiceImpl categoryService;
/**
* 分页查询
* @param page
* @param pageSize
* @param name
* @return
*/
@GetMapping("/page")
public Result page(int page,int pageSize,String name){
// 构造基本Page
Page pageImpl = new Page<>(page,pageSize);
// 进行查询
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper();
queryWrapper.eq(name != null,Dish::getName,name);
queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
// 查询赋值,此时pageImpl里有值
dishService.page(pageImpl,queryWrapper);
return Result.success(pageImpl);
}
}
此时我们出来的页面中是无法查看到分类所属的:
所以我们需要设置包含有菜品分类名称的实体类作为Page的实现类参数才可以将菜品分类的名称传递到前端
我们只需要到前端代码中查看就可以注意到,商品分类这行上的数据属性名称为categoryName,所以我们采用DishDto来完成操作
我们将对代码进行修改:
package com.qiuluo.reggie.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Category;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.dto.DishDto;
import com.qiuluo.reggie.service.impl.CategoryServiceImpl;
import com.qiuluo.reggie.service.impl.DishServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {
@Autowired
private DishServiceImpl dishService;
@Autowired
private CategoryServiceImpl categoryService;
/**
* 分页查询
* @param page
* @param pageSize
* @param name
* @return
*/
@GetMapping("/page")
public Result page(int page,int pageSize,String name){
// 构造基本Page
Page pageImpl = new Page<>(page,pageSize);
// 因为返回类型中多了一个categoryName,我们还需要构造一个DishDto类型的Page
Page dishDtoPage = new Page<>();
// 进行查询
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper();
queryWrapper.eq(name != null,Dish::getName,name);
queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
// 查询赋值,此时pageImpl里有值
dishService.page(pageImpl,queryWrapper);
// 但是我们需要返回DishDto类型的Page,我们将pageImpl的值赋值到dishDtoPage中(不要赋值records,这个值是数据,我们需要单独处理)
// 我们借助工具类实现
BeanUtils.copyProperties(pageImpl,dishDtoPage,"records");
// 然后我们来处理dishDtoPage中的records值,我们首先将pageImpl的records提取出来
List records = pageImpl.getRecords();
// 将该值除了CategoryName全都赋值给dishDtoPage的records(我们这里使用stream流进行局内单个赋值,采用foreach方法也相同)
List dishDtoList = records.stream().map((item) -> {
// 创建一个新dishDto作为返回实体
DishDto dishDto = new DishDto();
// 将正常属性赋值进去
BeanUtils.copyProperties(item,dishDto);
// 将CategoryName复制进去
Long categoryId = item.getCategoryId();
Category category = categoryService.getById(categoryId);
if(category != null){
String categoryName = category.getName();
dishDto.setCategoryName(categoryName);
}
return dishDto;
}).collect(Collectors.toList());
// 完成dishDtoPage的results的内容封装
dishDtoPage.setRecords(dishDtoList);
return Result.success(dishDtoPage);
}
}
当我们打开页面时,所有数据均出现在页面即为代码实现成功
我们的功能开发通常分为三部分
首先我们会发现我们的菜品数据会展现在页面中,这是因为在打开时页面就发送了一个请求来获得该菜品的相关信息并回显:
然后我们会发现菜品分类下拉框的数据又出来了,这里我们在前面的新填菜品中已经实现了
我们这次需要实现两个流程
首先我们来实现根据id返回数据的代码实现:
package com.qiuluo.reggie.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.domain.DishFlavor;
import com.qiuluo.reggie.dto.DishDto;
public interface DishService extends IService {
//查询菜品,并查询对应口味
public DishDto getByIdWithFlavors(Long id);
}
package com.qiuluo.reggie.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.domain.DishFlavor;
import com.qiuluo.reggie.dto.DishDto;
import com.qiuluo.reggie.mapper.DishMapper;
import com.qiuluo.reggie.service.DishService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class DishServiceImpl extends ServiceImpl implements DishService {
// 调入dishFlavor的业务层实现类
@Autowired
private DishFlavorServiceImpl dishFlavorService;
/**
* 查询菜品,并查询对应口味
* @param id
* @return
*/
public DishDto getByIdWithFlavors(Long id){
// 创造返回对象
DishDto dishDto = new DishDto();
// 首先根据id获得菜品信息
Dish dish = this.getById(id);
// 根据id获得调料信息
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DishFlavor::getDishId,id);
List list = dishFlavorService.list(queryWrapper);
// 将数据传入
BeanUtils.copyProperties(dish,dishDto);
dishDto.setFlavors(list);
return dishDto;
}
}
package com.qiuluo.reggie.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Category;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.dto.DishDto;
import com.qiuluo.reggie.service.impl.CategoryServiceImpl;
import com.qiuluo.reggie.service.impl.DishServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {
@Autowired
private DishServiceImpl dishService;
/**
* 得到数据
* @param id
* @return
*/
@GetMapping("/{id}")
public Result get(@PathVariable Long id){
DishDto dishDto = dishService.getByIdWithFlavors(id);
return Result.success(dishDto);
}
}
接下来我们来实现修改操作:
package com.qiuluo.reggie.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.domain.DishFlavor;
import com.qiuluo.reggie.dto.DishDto;
public interface DishService extends IService {
// 修改菜品
public void updateWithFlavor(DishDto dishDto);
}
package com.qiuluo.reggie.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.domain.DishFlavor;
import com.qiuluo.reggie.dto.DishDto;
import com.qiuluo.reggie.mapper.DishMapper;
import com.qiuluo.reggie.service.DishService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class DishServiceImpl extends ServiceImpl implements DishService {
// 调入dishFlavor的业务层实现类
@Autowired
private DishFlavorServiceImpl dishFlavorService;
// 修改菜品
public void updateWithFlavor(DishDto dishDto){
// Dish修改
this.updateById(dishDto);
// Flavor修改(我们先全部删除,再全部重新添加)
// 删除操作
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DishFlavor::getDishId,dishDto.getId());
dishFlavorService.remove(queryWrapper);
// 添加操作
List flavors = dishDto.getFlavors();
flavors = flavors.stream().map((item) -> {
item.setDishId(dishDto.getId());
return item;
}).collect(Collectors.toList());
}
}
package com.qiuluo.reggie.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Category;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.dto.DishDto;
import com.qiuluo.reggie.service.impl.CategoryServiceImpl;
import com.qiuluo.reggie.service.impl.DishServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {
@Autowired
private DishServiceImpl dishService;
@Autowired
private CategoryServiceImpl categoryService;
/**
* 修改数据
* @param
* @return
*/
@PutMapping
public Result update(@RequestBody DishDto dishDto){
dishService.updateWithFlavor(dishDto);
return Result.success("修改完成");
}
}
回到菜品页面,修改相关信息点击修改,若修改成功,代码即为成功
我们的功能开发通常分为三部分
该节属于视频未提及的简单操作,只需要调用简单的业务层函数处理即可
我们需要完成批量删除,批量启售,批量停售,我们点击相关菜品后,依次点击方法,F12查看url以及传递的参数:
# 批量删除
url:http://localhost:8080/dish?ids=1583025958761824258
Method:DELETE
# 批量启售
url:http://localhost:8080/dish/status/1?ids=1413384757047271425,1413385247889891330
Method:POST
# 批量停售
url:http://localhost:8080/dish/status/0?ids=1413384757047271425,1413385247889891330
Method:POST
我们直接给出代码展示:
package com.qiuluo.reggie.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Category;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.dto.DishDto;
import com.qiuluo.reggie.service.impl.CategoryServiceImpl;
import com.qiuluo.reggie.service.impl.DishServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {
@Autowired
private DishServiceImpl dishService;
/**
* 批量删除
* @param ids
* @return
*/
@DeleteMapping
public Result deleteByIds(Long[] ids){
for (Long id:ids
) {
dishService.removeById(id);
}
return Result.success("删除成功");
}
/**
* 批量启售
* @param ids
* @return
*/
@PostMapping("/status/1")
public Result openStatus(Long[] ids) {
for (Long id : ids
) {
Dish dish = dishService.getById(id);
dish.setStatus(1);
dishService.updateById(dish);
}
return Result.success("修改成功");
}
/**
* 批量停售
* @param ids
* @return
*/
@PostMapping("/status/0")
public Result closeStatus(Long[] ids) {
for (Long id : ids
) {
Dish dish = dishService.getById(id);
dish.setStatus(0);
dishService.updateById(dish);
}
return Result.success("修改成功");
}
}
返回菜品页面,点击若干菜品,进行三个方法的测试,实现即可
在这里我们会点出该项目目前容易出错的位置
我们在这里重新强调一下DTO:
DTO的作用我们在实例中已经很清楚了:
DTO的原理实际上很简单:
总而言之DTO在我们的实际开发中是很有用的哦~
我们在前面的文章中基本都是借助SpringBoot和MyBaits所提供的方法来进行开发
但在实际业务中,我们遇到的查询语法或查询条件或者需要操作的步骤不是简单的方法所能实现的
这时我们就需要采用原始的方法重新进行业务层的方法实现:
首先在业务层接口声明该方法,在这时要想要返回的类型,想要需要什么参数
这里主要负责方法的实现,我们要根据自己的逻辑思路来一步一步完成方法
到了这层基本就是直接调用业务层实现的方法即可
该篇内容到这里就结束了,希望能为你带来帮助~
该文章属于学习内容,具体参考B站黑马程序员的Java项目实战《瑞吉外卖》
这里附上视频链接:业务开发Day4-01-本章内容介绍_哔哩哔哩_bilibili