猿创征文|瑞吉外卖——管理端_菜品管理_1

个人名片:

博主酒徒ᝰ.
专栏瑞吉外卖
个人简介沉醉在酒中,借着一股酒劲,去拼搏一个未来。
本篇励志真正的程序员不看参考手册,新手和胆小鬼才会看。

本项目基于B站黑马程序员Java项目实战《瑞吉外卖》,轻松掌握springboot + mybatis plus开发核心技术的真java实战项目。

视频链接【黑马程序员Java项目实战《瑞吉外卖》,轻松掌握springboot + mybatis
plus开发核心技术的真java实战项目】 https://www.bilibili.com/video/BV13a411q753?
点击观看

在页面显示中的输入框查询,删除与停售和起售中的批量与单个。都是在原代码基础上进行修改。不能另写代码,会报错。

因为菜品管理太多了,所有分成三部分来写了。这是第一部分。

一、页面显示

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 {
    
    
    @Autowired
    private IDishService dishService;

    @Autowired
    private 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中的categoryName
        LambdaQueryWrapper<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 {
    
    
    @Autowired
    private IDishService dishService;

    @Autowired
    private 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中的categoryName
            LambdaQueryWrapper<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表中的所有name
    LambdaQueryWrapper<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)
    //添加创建时间和修改时间
    dishDto.setCreateTime(LocalDateTime.now());
    dishDto.setUpdateTime(LocalDateTime.now());
    //添加创建人和修改人
    Long empId = (Long) request.getSession().getAttribute("employee");
    dishDto.setCreateUser(empId);
    dishDto.setUpdateUser(empId);
    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 {
    
    
    @Autowired
    private IDishFlavorService dishFlavorService;

    @Override
    @Transactional
    public void saveDishFlavor(HttpServletRequest request, DishDto dishDto) {
    
    
        //保存dish的基本信息到dish表
        this.save(dishDto);

        //存储dishId
        List<DishFlavor> flavors = dishDto.getFlavors();
        flavors = flavors.stream().map((item) -> {
    
    
            //添加创建时间和修改时间
            item.setCreateTime(LocalDateTime.now());
            item.setUpdateTime(LocalDateTime.now());
            //添加创建人和修改人
            Long empId = (Long) request.getSession().getAttribute("employee");
            item.setCreateUser(empId);
            item.setUpdateUser(empId);
            item.setDishId(dishDto.getId());
            return item;
        }).collect(Collectors.toList());

        dishFlavorService.saveBatch(flavors);
    }
}

猜你喜欢

转载自blog.csdn.net/m0_65144570/article/details/126808278