ToB企服应用市场:ToB评测及商务社交产业平台

标题: 瑞吉外卖day4 [打印本页]

作者: 王國慶    时间: 2023-5-13 15:56
标题: 瑞吉外卖day4
菜品管理业务开发

文件上传与下载

文件上传

介绍

 服务端要接收客户端页面上传的文件,通常都会使用Apache的两个组件
1.commons-file upload
2.commons-io
Spring框架在spring-web包中对文件上传进行了封装。只需要在Controller的方法中声明一个MultipartFile类型的参数即可接受上传的文件
代码实现
  1. @Value("${reggie.path}")
  2.     private String basePath;
  3.     @PostMapping("/upload")
  4.     public R<String> upload(MultipartFile file){
  5.         //file是一个临时文件,需要把他转存到指定文件,否则本次请求完成后会被删除
  6.         log.info("上传的文件{}",file.toString());
  7.         //原始文件名
  8.         String originalFilename = file.getOriginalFilename();
  9.         String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
  10.         //使用uuid重新生成文件名,防止文件名重复造成文件被覆盖
  11.         String fileName = UUID.randomUUID().toString()+suffix;
  12.         //创建一个目录对象
  13.         File dir = new File(basePath);
  14.         //判断当前目录是否存在
  15.         if (!dir.exists()){
  16.             //目录不存在  创建目录
  17.             dir.mkdirs();
  18.         }
  19.         try {
  20.             file.transferTo(new File(basePath+fileName));
  21.         } catch (IOException e) {
  22.             throw new RuntimeException(e);
  23.         }
  24.         return R.success(fileName);
  25.     }
复制代码
upload方法里的形参名要保证与前端提交的表单名一致
在yml配置文件中定义路径变量path
文件下载


 代码实现
 
  1. @GetMapping("/download")
  2.     public void download(String name, HttpServletResponse response){
  3.         try {
  4.             //输入流  通过输入流读取文件内容
  5.             FileInputStream fileInputStream = new FileInputStream(new File(basePath+name));
  6.             //输出流  通过输出流将文件写回浏览器  在浏览器展示图片
  7.             ServletOutputStream outputStream = response.getOutputStream();
  8.             response.setContentType("image/jpeg");//设置文件写入类型
  9.             int len = 0;
  10.             byte[] bytes = new byte[1024];
  11.             while ((len=fileInputStream.read(bytes))!=-1){//len:m每次读取的有效字节数当len=-1表示读取到文件末尾
  12.                 outputStream.write(bytes,0,len);//**写出指定长度字节数组**:`write(byte[] b, int off, int len)` ,每次写出从off索引开始,len个字节,
  13.                 outputStream.flush();
  14.             }
  15.             outputStream.close();
  16.             fileInputStream.close();
  17.         } catch (FileNotFoundException e) {
  18.             throw new RuntimeException(e);
  19.         } catch (IOException e) {
  20.             throw new RuntimeException(e);
  21.         }
  22.     }
复制代码
新增菜品功能

需求分析

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


 代码开发

准备工作:
实体类DishFlavor
Mapper接口DishFlavorMapper
业务层接口DishFlavorService
业务层实现类 DishFlavorServicelmpl控制层 DishController
交互过程:
1、页面(backend/page/food/ add.html)发送ajax请求,请求服务端获取菜品分类数据并展示到下拉框中
  1.   /**
  2.      *
  3.      * @param category
  4.      * @return
  5.      */
  6.     @GetMapping("/list")
  7.     public R<List<Category>>  list(Category category){
  8.         //条件构造器
  9.         LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
  10.         queryWrapper.eq(category.getType()!=null,Category::getType,category.getType());
  11.         queryWrapper.orderByAsc(Category::getSort).orderByDesc(Category::getUpdateTime);
  12.         List<Category> list = categoryService.list(queryWrapper);
  13.         return R.success(list);
  14.     }
复制代码
 
2、页面发送请求进行图片上传,请求服务端将图片保存到服务器
3、页面发送请求进行图片下载,将上传的图片进行回显
4、点击保存按钮,发送ajax请求,将菜品相关数据以json形式提交到服务端
前端提交的json数据与dish实体类不是一一对应,需要定义dishDao类来接受数据
DTO:全称为Data Transfer Object,即数据传输对象,一般用于展示层和服务层之间的数据传输
  1. @Data
  2. public class DishDto extends Dish {
  3.     private List<DishFlavor> flavors = new ArrayList<>();
  4.     private String categoryName;
  5.     private Integer copies;
  6. }
复制代码
 菜品信息分页查询

代码开发-梳理交互

 


1、页面(backend/page/food/list.html)发送ajax请求,将分页查询参数(page、pageSize,name)
提交到服务端,获取分页数据
2、页面发送请求,请求服务端进行图片下载,用于页面图片展示
代码实现
  1. /**
  2. * 菜品分页查询
  3. * @param page
  4. * @param pageSize
  5. * @param name
  6. * @return
  7. */
  8. @GetMapping("/page")
  9. public R<Page> page(int page,int pageSize,String name){
  10. //构造分页构造器对象
  11. Page<Dish> pageInfo = new Page<>(page,pageSize);
  12. Page<DishDto> dishDtoPage = new Page<>();
  13. //构造查询构造器对象
  14. LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
  15. queryWrapper.like(name!=null,Dish::getName,name);
  16. queryWrapper.orderByDesc(Dish::getUpdateTime);
  17. dishService.page(pageInfo,queryWrapper);
  18. //对象拷贝
  19. BeanUtils.copyProperties(pageInfo,dishDtoPage,"records");
  20. List<Dish> records = pageInfo.getRecords();
  21. List<DishDto> list= records.stream().map((item)->{
  22. DishDto dishDto = new DishDto();
  23. BeanUtils.copyProperties(item,dishDto);
  24. Long categoryId = item.getCategoryId();
  25. //根据id查询分类对象
  26. Category category=categoryService.getById(categoryId);
  27. if (category!=null){
  28. String categoryName = category.getName();
  29. dishDto.setCategoryName(categoryName);
  30. }
  31. return dishDto;
  32. }).collect(Collectors.toList());
  33. dishDtoPage.setRecords(list);
  34. return R.success(dishDtoPage);
  35. }
复制代码
前端渲染页面需要categoryName参数。实体类dish中无对应属性,所以不能直接将获取到的pageInfo响应给客户端。再声明泛型为DishDao的Page对象。将pageInfo中的属性拷贝到dishDaoPage中返回给客户端,但由于pageInfo中的records属性中寸的是dish对象,需要单独处理,将records中的dish对象转换为dishDao对象存到新集合中。最后将dishDaoPage返回给前端。
修改菜品

需求分析

在菜品管理列表页面点击修改按钮,跳转到修改菜品页面,在修改页面回显菜品相关信息并进行修改,点击确定按钮完成相关操作

 代码实现

页面的回显信息中包含菜品口味,因此服务端应向客户端返回dishDto类型的数据,在dishService中声明getByIdWithFlavor方法,根据id查询菜品信息以及菜品口味信息封装成dishDto对象,返回
  1.   @Override
  2.     public DishDto getByIdWithFlavor(Long id) {
  3.         Dish dish = this.getById(id);
  4.         DishDto dishDto = new DishDto();
  5.         BeanUtils.copyProperties(dish,dishDto);
  6.         //查询当前菜品的口味信息
  7.         LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
  8.         queryWrapper.eq(DishFlavor::getDishId,dish.getId());
  9.         List<DishFlavor> list = dishFlavorService.list(queryWrapper);
  10.         dishDto.setFlavors(list);
  11.         return dishDto;
  12.     }
复制代码
调用dishSer中的getByIdWithFlavor方法,将返回值响应给客户端,实现数据回显
  1. @GetMapping("/{id}")
  2.     public R<DishDto> get(@PathVariable Long id){
  3.         DishDto byIdWithFlavor = dishService.getByIdWithFlavor(id);
  4.         return R.success(byIdWithFlavor);
  5.     }
复制代码
将修改后的数据保存到数据库中,需要分别更新菜品表和菜品口味表。
菜品口味表的更新分两步,第一步先将当前口味表中对应的数据删除,再添加客户端提交过来的数据实现数据更新
  1.   @Override
  2.     public void updateWithFlavor(DishDto dishDto) {
  3.         //更新dish表基本信息
  4.         this.updateById(dishDto);
  5.         //清理当前菜品口味对应数据-----dishFlavor表对应的删除操作
  6.         LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
  7.         queryWrapper.eq(DishFlavor::getDishId,dishDto.getId());
  8.         dishFlavorService.remove(queryWrapper);
  9.         //添加提交过来的口味数据
  10.         List<DishFlavor> flavors = dishDto.getFlavors();
  11.         flavors = flavors.stream().map((item)->{
  12.             item.setDishId(dishDto.getId());
  13.             return item;
  14.         }).collect(Collectors.toList());
  15.         dishFlavorService.saveBatch(flavors);
  16.     }
复制代码
  1. /**
  2.      * 修改菜品
  3.      * @param dishDto
  4.      * @return
  5.      */
  6.     @PutMapping
  7.     public R<String> update(@RequestBody DishDto dishDto){
  8.         log.info(dishDto.toString());
  9.         dishService.updateWithFlavor(dishDto);
  10.         return R.success("修改菜品成功");
  11.     }
复制代码
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4