瑞吉外卖功能开发----菜品管理

一、文件的上传下载

1.1 文件上传基础

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

method=“post”采用post方式提交数据
enctype=“multipart/form-data”采用multipart格式上传文件
type=“file”使用input的file控件上传

在这里插入图片描述

服务端要接收客户端页面上传的文件,通常都会使用Apache的两个组件:

commons-fileupload
commons-io

Spring框架在spring-web包中对文件上传进行了封装,大大简化了服务端代码,我们只需要
一个MultipartFile类型的参数即可接收上传的文件,例如:
在这里插入图片描述

2.2 文件下载基础

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

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

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

二、文件上传—upload

2.1 代码实现
 /**
     * 文件上传
     * @param file
     * @return
     */
    @PostMapping("/upload")
    public R<String> upload(MultipartFile file){
        log.info(file.toString());
        //原始文件名
        String originFilename = file.getOriginalFilename();
        String suffix = originFilename.substring(originFilename.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);
    }
2.2 函数学习

String suffix =
originFilename.substring(originFilename.lastIndexOf(“.”));

substring函数
函数源码解释

Returns a string that is a substring of this string. The substring begins with the character at the specified index and extends to the end of this string.

substring() 方法返回字符串的子字符串。
语法

public String substring(int beginIndex)

public String substring(int beginIndex, int endIndex)

参数

beginIndex – 起始索引(包括), 索引从 0 开始。

endIndex – 结束索引(不包括)。

实例

public class RunoobTest {
    public static void main(String args[]) {
        String Str = new String("This is text");
 
        System.out.print("返回值 :" );
        System.out.println(Str.substring(4) );
 
        System.out.print("返回值 :" );
        System.out.println(Str.substring(4, 10) );
    }
}

以上程序执行结果为:

返回值 : is text
返回值 : is te

lastIndexOf函数
直接上代码

String s = "01234560123456";

int a = s.lastIndexOf('1'); // 返回最后一个字符1的下标
int b = s.lastIndexOf("23"); // 返回最后一个字符串“23”的下标
int c = s.lastIndexOf('1',5); // 以下标5为终点,返回最后一个字符1的下标
int d = s.lastIndexOf("23",5); // 以下标5为终点,返回最后一个字符串“23”的下标

System.out.println(a + " " + b + " " + c + " "+ d);

在这里插入图片描述
注意 lastIndexOf(“str”, index)方法,这里返回的是 从下标0开始,以index结尾(包含index下标)之间搜索最后一个字符或字符串下标。

indexOf()方法:

String s = "01234560123456";

int a = s.indexOf('1'); // 返回第一个字符1的下标
int b = s.indexOf("23"); // 返回第一个字符串“23”的下标
int c = s.indexOf('1',5); // 以下标5开始,返回第一个字符1的下标
int d = s.indexOf("23",5); // 以下标5开始,返回第一个字符串“23”的下标

System.out.println(a + " " + b + " " + c + " "+ d);

在这里插入图片描述

三、 文件下载—download

3.1 代码实现
 /**
     * 文件下载
     * @param name
     * @param response
     */
    @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();
        }

    }

四、 新增菜品

4.1 代码开发-梳理交互过程

1、页面(backend/page/food/add.html)发送ajax请求,请求服务端获取菜品分类数据并展示到下拉框中
2、页面发送请求进行图片上传,请求服务端将图片保存到服务器
3、页面发送请求进行图片下载,将上传的图片进行回显
4、点击保存按钮,发送ajax请求,将菜品相关数据以json形式提交到服务端

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

4.2 获取分类数据
/**
     * 菜品管理中获取分类数据
     * @param type
     * @return
     */
    @GetMapping("/list")
    public R<List<Category>> getCategoryList(@RequestParam Integer type){
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Category::getType,type);
        queryWrapper.orderByDesc(Category::getSort).orderByDesc(Category::getUpdateTime);
        List<Category> list= categoryService.list(queryWrapper);
        return R.success(list);
    }
4.3 代码实现

代码开发-导入DT0
导入DishDto,用于封装页面提交的数据

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

注意事项

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

DishDto

package com.itheima.reggie.dto;

import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;

@Data
public class DishDto extends Dish {

    private List<DishFlavor> flavors = new ArrayList<>();

    private String categoryName;

    private Integer copies;
}

DishServiceImpl实现类中

package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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.DishFlavorService;
import com.itheima.reggie.service.DishService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {
    @Autowired
    private DishFlavorService dishFlavorService;

    /**
     * 新增菜品,同时保存对应的口味数据
     * @param dishDto
     */
    @Transactional
    public void saveWithDishFlavor(DishDto dishDto) {
    //保存菜品的基本信息到菜品表dish
        this.save(dishDto);
        Long dishId = dishDto.getId();
    //保存菜品的口味到dishFlavor
        //将dishId保存在dishFlavor表中
        List<DishFlavor> flavorList = dishDto.getFlavors();
        flavorList = flavorList.stream().map((item) ->{
            item.setDishId(dishId);
            return item;
        }).collect(Collectors.toList());
        dishFlavorService.saveBatch(flavorList);
    }
}

DishController

 /**
     * 新增菜品
     * @param dishDto
     * @return
     */
    @PostMapping
    public R<String> addDish(@RequestBody DishDto dishDto){
        log.info(dishDto.toString());
        dishService.saveWithDishFlavor(dishDto);
        return R.success("保存成功");
    }

五、 菜品信息分页查询

5.1 代码开发

这里需要注意的是DishDto继承了Dish,所有这样才能进行全部显示

DishController

/**
     * 菜品的分页查询
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    public R<Page> findPage(@RequestParam Integer page,
                            @RequestParam Integer pageSize,
                            @RequestParam(defaultValue = "") String name){
        Page<Dish> ipage = new Page<>(page,pageSize);
        Page<DishDto> dishDtoPage = new Page<>();
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        if(!"".equals(name)){
            queryWrapper.like(Dish::getName,name);
        }
        queryWrapper.orderByDesc(Dish::getUpdateTime);
        dishService.page(ipage,queryWrapper);

        // 对象拷贝
        BeanUtils.copyProperties(ipage,dishDtoPage,"records");
        List<Dish> records = ipage.getRecords();
        List<DishDto> list = records.stream().map((item) ->{
            DishDto dishDto = new DishDto();

            BeanUtils.copyProperties(item,dishDto);

            Long categoryId = item.getCategoryId();//分类id
            //根据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);
    }

下面这一步是最重要的,将category_id查询变成分类名称

 // 对象拷贝
        BeanUtils.copyProperties(ipage,dishDtoPage,"records");
        List<Dish> records = ipage.getRecords();
        List<DishDto> list = records.stream().map((item) ->{
            DishDto dishDto = new DishDto();

            BeanUtils.copyProperties(item,dishDto);

            Long categoryId = item.getCategoryId();//分类id
            //根据id查询分类对象
            Category category = categoryService.getById(categoryId);
            if(category != null){
                String categoryName = category.getName();
                dishDto.setCategoryName(categoryName);
            }

            return dishDto;
        }).collect(Collectors.toList());

        dishDtoPage.setRecords(list);

六、菜品回显加保存

6.1 交互过程

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

1、页面发送jax请求,请求服务端获取分类数据,用于菜品分类下拉框中数据展示
2、页面发送ajax请求,请求服务端,根据id查询当前菜品信息,用于菜品信息回显
3、页面发送请求,请求服务端进行图片下载,用于页图片回显
4、点击保存按钮,页面发送ajx请求,将修改后的菜品相关数据以)son形式提交到服务端

6.2 代码实现

页面回显
DishServiceImpl实现类中写好方法

/**
     * 根据菜品id进行查询信息,进行回显
     * @param id
     * @return
     */
    @Override
    public DishDto getWithDish(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> dishFlavors = dishFlavorService.list(queryWrapper);
        dishDto.setFlavors(dishFlavors);
        return dishDto;
    }

更新菜品信息

/**
     * 更新菜品信息
     * @param dishDto
     */
    @Override
    @Transactional
    public void updateWithDishFlavor(DishDto dishDto) {
        this.updateById(dishDto);


        // 删除口味,在dishflavor表中
        LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DishFlavor::getDishId,dishDto.getId());
        dishFlavorService.remove(queryWrapper);

        //添加当前提交过来的口味数据,重新保存在dish_flavor表中
        List<DishFlavor> flavorList = dishDto.getFlavors();

        flavorList = flavorList.stream().map((item) ->{
            item.setDishId(dishDto.getId());
            return item;
        }).collect(Collectors.toList());

        dishFlavorService.saveBatch(flavorList);
    }

七、 菜品删除和批量删除

由于此部分内容为自己自由编写,代码实现不一定同意,仅供参考

7.1 代码实现

1.删除需要操作两个表,一个是dish表,一个是dish_flavor
2.主要做两件事删除菜品和删除菜品口味

 /**
     * 删除于批量删除
     * @param id
     * @return
     */
    @DeleteMapping
    public R<String> deleteDish(@RequestParam("ids") Long[] id){
        log.info(id.toString());
        //删除口味
        for (int i = 0; i < id.length; i++) {
            LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(DishFlavor::getDishId,id[i]);
            dishFlavorService.remove(queryWrapper);
        }
        List<Long> idList = Arrays.asList(id);
        dishService.removeByIds(idList);
        return R.success("删除成功");
    }

八、停售与批量停售

8.1 代码实习
/**
     * 停售起售和批量停售起售
     * @param status
     * @param ids
     * @return
     */
    @PostMapping("/status/{status}")
    public R<String> updateStatus(@PathVariable Integer status,Long[] ids){
        for (int i = 0; i < ids.length; i++) {
            Long id = ids[i];
            Dish dish = dishService.getById(id);
            dish.setStatus(status);
            dishService.updateById(dish);
        }
        return R.success("菜品状态更新成功");
    }

九、 套餐管理说明

由于菜品管理和套餐管理逻辑上基本相同,所以就不更新套餐管理,其实只需要去复制代码更改就行,就写一个菜品回显的代码,其他照抄

/**
     * 套餐管理中查找菜品回显
     * @param dish
     * @return
     */
        @GetMapping("/list")
        public R<List<Dish>> queryDishById(Dish dish){
            LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());
            queryWrapper.orderByDesc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
            queryWrapper.eq(Dish::getStatus,1);
            List<Dish> list= dishService.list(queryWrapper);
            return R.success(list);
        }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iii我的天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值