个人名片:
博主:酒徒ᝰ.
专栏:瑞吉外卖
个人简介:沉醉在酒中,借着一股酒劲,去拼搏一个未来。
本篇励志:真正的程序员不看参考手册,新手和胆小鬼才会看。
本项目基于B站黑马程序员Java项目实战《瑞吉外卖》,轻松掌握springboot + mybatis plus开发核心技术的真java实战项目。
视频链接【黑马程序员Java项目实战《瑞吉外卖》,轻松掌握springboot + mybatis
plus开发核心技术的真java实战项目】 https://www.bilibili.com/video/BV13a411q753?
点击观看
目录
- 一、页面显示
- 1.全部查询
- 2.输入框查询
- 二、新增菜品
- 1.显示页面
- 1.菜品分类
- 2.文件上传
- 2.保存
在页面显示中的输入框查询,删除与停售和起售中的批量与单个。都是在原代码基础上进行修改。不能另写代码,会报错。
因为菜品管理太多了,所有分成三部分来写了。这是第一部分。
一、页面显示
1.全部查询
分析:dish地址,GET方式,page地址,page,pageSize属性
package com.itheima.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.service.ICategoryService;
import com.itheima.reggie.service.IDishFlavorService;
import com.itheima.reggie.service.IDishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletRequest;
import javax.websocket.server.PathParam;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;/*** <p>* 菜品管理 前端控制器* </p>** @author 酒徒* @since 2022-09-04*/
@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {@Autowiredprivate IDishService dishService;@Autowiredprivate ICategoryService categoryService;/*** 页面呈现* @param page* @param pageSize* @return*/@GetMapping("/page")public R<Page> page(int page, int pageSize){Page<Dish> pageInfo = new Page<>(page, pageSize);//查询全部LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.orderByDesc(Dish::getUpdateTime);dishService.page(pageInfo, queryWrapper);return R.success(pageInfo);}
}
这是发现菜品没有图片,这是缺少文件的上传与下载。
分析:common地址,GET方式,download地址,name属性
在controller模块中新建CommonController类。写文件的上传与下载代码。
package com.itheima.reggie.controller;import com.itheima.reggie.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.server.PathParam;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;/*** <p>* 文件的上传与下载 前端控制器* </p>** @author 酒徒* @since 2022-09-04*/
@Slf4j
@RestController
@RequestMapping("/common")
public class CommonController {@Value("${reggie.path}")private String basePath;/*** 文件下载——图片在页面显示* @param name* @param response*/@GetMapping("/download")public void download(@PathParam("name") String name, HttpServletResponse response){FileInputStream fileInputStream = null;ServletOutputStream outputStream = null;try {//文件输入流 图片文件的地址fileInputStream = new FileInputStream(new File(basePath + name));//文件输出流 将本地图片文件输出到浏览器页面outputStream = response.getOutputStream();//设置输出是文件的类型response.setContentType("image/jpeg");//图片类型//输出图片文件 以读写的方式int len = 0;byte[] buff = new byte[1024];while((len = fileInputStream.read(buff)) != -1){outputStream.write(buff, 0 ,len);outputStream.flush();}} catch (IOException e) {throw new RuntimeException(e);}finally {try {outputStream.close();fileInputStream.close();} catch (IOException e) {throw new RuntimeException(e);}}}
}
完成后仍然发现一个小问题,那就是菜品分类栏不显示。查看日志发现是categoryId对应的分类名称没有查。
这里就需要结合dish表和category表同时使用,也就是DIshDto,在这个类中包括了所有的dish,也拥有categoryname。
/*** 页面呈现* @param page* @param pageSize* @return*/
@GetMapping("/page")
public R<Page> page(int page, int pageSize){Page<Dish> dishPage = new Page<>(page, pageSize);Page<DishDto> dishDtoPage = new Page<>(page, pageSize);//查询全部LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.orderByDesc(Dish::getUpdateTime);dishService.page(dishPage, queryWrapper);//获取dish的所有数据List<Dish> records = dishPage.getRecords();//将dish的所有数据拷贝到dishDto中BeanUtils.copyProperties(dishPage, dishDtoPage);//使用流的形式给每一个dishDto进行categoryname赋值List<DishDto> list = records.stream().map((item) -> {//item与dish内容相同DishDto dishDto = new DishDto();//1.拷贝dish到dishdto中BeanUtils.copyProperties(item, dishDto);//2.根据dish中categoryId在category表中查询name,在赋值给dishDto中的categoryNameLambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();wrapper.eq(Category::getId, item.getCategoryId());Category category = categoryService.getOne(wrapper);//设置dishDto中的categoryName值 先判断category是否为空if (category != null){dishDto.setCategoryName(category.getName());}else {dishDto.setCategoryName("不存在");}return dishDto;}).collect(Collectors.toList());dishDtoPage.setRecords(list);return R.success(dishDtoPage);
}
2.输入框查询
相对于全部查询来说,多了一个name属性。
比较简单,在查询中添加name是否为空的判断。添加如下内容。
if (name != null){queryWrapper.like(Dish::getName, name);
}
完整代码为:
package com.itheima.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.service.ICategoryService;
import com.itheima.reggie.service.IDishFlavorService;
import com.itheima.reggie.service.IDishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletRequest;
import javax.websocket.server.PathParam;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;/*** <p>* 菜品管理 前端控制器* </p>** @author 酒徒* @since 2022-09-04*/
@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {@Autowiredprivate IDishService dishService;@Autowiredprivate ICategoryService categoryService;/*** 页面呈现* @param page* @param pageSize* @return*/@GetMapping("/page")public R<Page> page(int page, int pageSize, String name){Page<Dish> dishPage = new Page<>(page, pageSize);Page<DishDto> dishDtoPage = new Page<>(page, pageSize);//查询全部LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();if (name != null){queryWrapper.like(Dish::getName, name);}queryWrapper.orderByDesc(Dish::getUpdateTime);dishService.page(dishPage, queryWrapper);//获取dish的所有数据List<Dish> records = dishPage.getRecords();//将dish的所有数据拷贝到dishDto中BeanUtils.copyProperties(dishPage, dishDtoPage);//使用流的形式给每一个dishDto进行categoryname赋值List<DishDto> list = records.stream().map((item) -> {//item与dish内容相同DishDto dishDto = new DishDto();//1.拷贝dish到dishdto中BeanUtils.copyProperties(item, dishDto);//2.根据dish中categoryId在category表中查询name,在赋值给dishDto中的categoryNameLambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();wrapper.eq(Category::getId, item.getCategoryId());Category category = categoryService.getOne(wrapper);//设置dishDto中的categoryName值 先判断category是否为空if (category != null){dishDto.setCategoryName(category.getName());}else {dishDto.setCategoryName("不存在");}return dishDto;}).collect(Collectors.toList());dishDtoPage.setRecords(list);return R.success(dishDtoPage);}
}
二、新增菜品
1.显示页面
分析:category地址,GET方式,list地址,type属性。
先进行测试,用以下代码进行。
@GetMapping("/list")
public R<String> list(@PathParam("type") String type){log.info("type:{}",type);return R.success("");
}
type为菜品和套餐的区分:1 菜品分类 2 套餐分类
从页面中可以分析出,需要补充的为菜品分类和文件上传
1.菜品分类
菜品分类就是categoryName属性。
/*** 页面显示——菜品分类显示* @param type* @param category* @return*/
@GetMapping("/list")
public R<List<Category>> list(@PathParam("type") String type, Category category){//log.info("type:{}",type);//查询Category表中的所有nameLambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(Category::getType, type);queryWrapper.orderByDesc(Category::getUpdateTime);List<Category> list = categoryService.list(queryWrapper);return R.success(list);
}
2.文件上传
分析:common地址,POST方式,upload地址。
/*** 文件的下载* @param file* @return*/
@PostMapping("/upload")
public R<String> upload(MultipartFile file){//1.获取文件名,生成新的名字,确保文件名具有唯一性//获取文件名String originalFilename = file.getOriginalFilename();//获取文件后缀名 .jpg类型String substring = originalFilename.substring(originalFilename.lastIndexOf("."));//生成一个新的文件名 唯一性String fileName = UUID.randomUUID().toString();//2.设置文件存储地址,若不存在,则生成File dir = new File(basePath + fileName);if (!dir.exists()){dir.mkdirs();}//3.将前端传过来的文件存到本地try {file.transferTo(dir);} catch (IOException e) {throw new RuntimeException(e);}return R.success(fileName);
}
2.保存
分析:dish地址,POST方式
第一次直接进行保存,发现出现一些问题。
@PostMapping
public R<String> dish(@RequestBody DishDto dishDto){log.info("dishDto:{}",dishDto);//dishDto:DishDto(flavors=[DishFlavor(id=null, dishId=null, name=甜味, value=["无糖","少糖","半糖","多糖","全糖"], createTime=null, updateTime=null, createUser=null, updateUser=null, isDeleted=null)], categoryName=null, copies=null)dishService.save(dishDto);return R.success("新增菜品成功");
}
没有保存DishFlavor,也就是各种菜品口味信息。
这些保存方法属于业务操作,最好写在service实现类中,增加代码可读性。
这里和视频中的出入比较大(本人写的较为繁琐),建议参考视频学习。
/*** 添加菜品* @param request* @param dishDto* @return*/
@PostMapping
public R<String> dish(HttpServletRequest request, @RequestBody DishDto dishDto){log.info("dishDto:{}",dishDto);//dishDto:DishDto(flavors=[DishFlavor(id=null, dishId=null, name=甜味, value=["无糖","少糖","半糖","多糖","全糖"], createTime=null, updateTime=null, createUser=null, updateUser=null, isDeleted=null)], categoryName=null, copies=null)dishService.saveDishFlavor(request, dishDto);return R.success("新增菜品成功");
}
在IDishService中创建saveDishFlavor方法
package com.itheima.reggie.service;import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Dish;
import com.baomidou.mybatisplus.extension.service.IService;import javax.servlet.http.HttpServletRequest;/*** <p>* 菜品管理 服务类* </p>** @author 酒徒* @since 2022-09-04*/
public interface IDishService extends IService<Dish> {void saveDishFlavor(HttpServletRequest request, DishDto dishDto);
}
在IDishServiceImpl中实现方法
package com.itheima.reggie.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.mapper.DishMapper;
import com.itheima.reggie.service.IDishFlavorService;
import com.itheima.reggie.service.IDishService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;/*** <p>* 菜品管理 服务实现类* </p>** @author 酒徒* @since 2022-09-04*/
@Slf4j
@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements IDishService {@Autowiredprivate IDishFlavorService dishFlavorService;@Override@Transactionalpublic void saveDishFlavor(HttpServletRequest request, DishDto dishDto) {//保存dish的基本信息到dish表this.save(dishDto);//存储dishIdList<DishFlavor> flavors = dishDto.getFlavors();flavors = flavors.stream().map((item) -> {item.setDishId(dishDto.getId());return item;}).collect(Collectors.toList());dishFlavorService.saveBatch(flavors);}
}