瑞吉外卖业务开发(3)

简介: 瑞吉外卖业务开发

瑞吉外卖业务开发(2)https://developer.aliyun.com/article/1530403

需求分析

  • 员工列表页面可以对员工账号进行启用和禁用处理,账号禁用的员工不能登录系统,启用后方可登录系统
  • 需要注意的是,只有管理员(admin用户)可以对其他用户进行启用,禁用操作,所以普通用户登录系统后启用,禁用按钮不显示.


    前端有一个名字为user的模型数据来之前存储的用户信息,如果user是admin也就是登录的用户是管理与,那么将显示禁用与启用信息.

代码开发

在开发业务之前需要把用到的类和接口基本结构准备好

  • 实体类category
  • Mapper接口CategoryMapper
  • 业务层接口CategoryService
  • 业务层实现类CategoryServiceImpl
  • 控制层CategoryController

操作流程

1、页面(backend/page/category/list.html)发送ajax请求,将新增分类窗口输入的数据以json形式提交到服务端

2、服务端Controller接收页面提交的数据并调用Service将数据进行保存

3、Service调用Mapper操作数据库,保存数据

可以发现新增菜品分类和新增套餐分类的请求服务端地址和JSon格式相同,所以服务端只要提供一个方法处理即可

@RestController  
@RequestMapping("/category")  
public class CategoryController {  
    @Autowired  
    private CategoryService categoryService;  
   @PostMapping  
    public R<String > save(@RequestBody Category category){  
    log.info("category{}",category);  
    categoryService.save(category);  
    return R.success("新增分类成功");  
}  
}

删除分类

需求分析

在分类管理列表页面,可以对某个分类进行删除操作。需要注意的是当分类关联了菜品或者套餐时,此分类不允许删除。

代码开发

在开发代码之前,需要梳理一下整个程序的执行过程:

1、页面发送ajax请求,将参数(id)提交到服务端

2、服务端Controller接收页面提交的数据并调用Service删除数据

3、Service调用Mapper操作数据库

@DeleteMapping  
public R<String> delete(Long id){  
    categoryService.removeById(id);  
    return R.success("删除成功")  
}

完善

和菜品和套餐已经连接的分类不能进行删除,因为我们没有设置外键,所以要用代码实现

@DeleteMapping  
public R<String> delete(Long ids){  
   categoryService.remove(ids);  
   return R.success("删除成功");  
}

[!note]

要在service中自己定义方法,而且可以调用别的service的方法

public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {  
    @Autowired  
    private DishService dishService;  
    @Autowired  
    private SetmealService setmealService;  
    @Override  
    public void remove(Long id) {  
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();  
        queryWrapper.eq(Dish::getCategoryId,id);  
        int count = dishService.count(queryWrapper);  
        if (count>0){  
            throw new CustomException("当期分类下关联了菜品,不能删除");  
        }  
        LambdaQueryWrapper<Setmeal> queryWrapper1 = new LambdaQueryWrapper<>();  
        queryWrapper1.eq(Setmeal::getCategoryId,id);  
        int count1 = setmealService.count(queryWrapper1);  
  
        if (count1>0){  
            throw new CustomException("当期分类下关联了套餐,不能删除");  
  
        }  
        //查询当前分类是否关联了菜品,如果已经关联,抛出一个业务异常  
        //查询当前分类是否关联了套餐,如果已经关联,抛出一个业务异常  
//正常删除分类  
        super.removeById(id);  
  
    }  
}

文件上传与下载

文件上传介绍

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

form表单的要求

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

举例

<form method="post" action="/common/upload" enctype="multipart/form-data"><input name="myFile" type="file" />
<input type="submit" value="提交" /></form>

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

  • commons-fileuplolad
  • commons-io
    Spring框架在spring-web包中对文件上传进行了封装,大大简化了服务端代码,我们只需要在Controller的方法中声明一个MultipartFile类型的参数即可接收上传的文件,例如:
@Slf4j  
@RestController  
@RequestMapping("/common")  
public class CommonController {  
    @Value("/${reggie.path}")  
    private String basePath;  
    @PostMapping("/upload")  
    public R<String> upload(MultipartFile file) throws IOException {  
  
        String originalFilename = file.getOriginalFilename();  
        //获取后缀  
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));  
        //使用UUID重新生成文件名,防止文件名称重复导致覆盖  
        String fileName = UUID.randomUUID().toString()+suffix;  
        //创建一个目录对象  
        File dir = new File(basePath);//判断当前目录是否存在  
        if(!dir.exists()){  
        //目录不存在,需要创建  
            dir.mkdirs();  
        }  
        log.info(basePath+fileName);  
        //file是一个临时文件需要指定保存的位置,否则本次请求完成后文件会被自动删除  
        file.transferTo(new File(basePath+ fileName));  
        return R.success(fileName);  
  
    }  

文件下载

@GetMapping("/download")  
public void download(String  name, HttpServletResponse response){  
  
    try {  
        //输入流,通过输入流读取文件内容  
        FileInputStream fileInputStream = new FileInputStream(basePath+name);  
        //输出流,通过输出流把文件写会浏览器,在浏览器展示图片  
        ServletOutputStream outputStream = response.getOutputStream();  
        int len=0;  
        byte[] bytes = new byte[1024];  
        while ((len=fileInputStream.read(bytes))!=-1){  
            outputStream.write(bytes,0,len);  
            outputStream.flush();  
        }  
        response.setContentType("image/jpeg");  
    } catch (Exception e) {  
        e.printStackTrace();  
    }  
}

新增菜品

需求分析

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

数据模型

新增菜品,其实就是将新增页面录入的菜品信息插入到dish表,如果添加了口味做法,还需要向dish_flavor表插入数据。所以在新增菜品时,涉及到两个表:

  • dish菜品表
  • dish_flavor菜品口味表

代码开发

准备工作

实体类DishFlavor(直接从课程资料中导入即可,Dish实体前面课程中已经导入过了)

Mapper接口DishFlavorMapper

业务层接口DishFlavorService

业务层实现类DishFlavorServicelmpl

控制层DishController

在开发代码之前,需要梳理一下新增菜品时前端页面和服务端的交互过程:

1、页面(badkend/page/food/add.html)发送ajax请求,请求服务端获取菜品分类数据并展示到下拉框中[

2、页面发送请求进行图片上传,请求服务端将图片保存到服务器

3、页面发送请求进行图片下载,将上传的图片进行回显

4、点击保存按钮,发送ajax请求,将菜品相关数据以json形式提交到服务端

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

导入dto

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

[!danger]

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

service

@Autowired  
private DishFlavorService dishFlavorService;  
//添加事务控制  
@Transactional  
@Override  
public void saveWithFlavor(DishDto dishDto) {  
//使用本身的save保存菜品
    this.save(dishDto);  
    Long id = dishDto.getId();  
    List<DishFlavor> flavors = dishDto.getFlavors();  
   flavors=  flavors.stream().map((item)->{  
        item.setDishId(id);  
        return item;  
    }).collect(Collectors.toList());  
  //保存口味信息
    dishFlavorService.saveBatch(flavors);  
}

controller

[[springmvc#9.1、@RequestBody]]

@Autowired  
    private DishService dishService;  
    @Autowired  
    private DishFlavorService dishFlavorService;  
@PostMapping  
    public R<String> save(@RequestBody DishDto dishDto){  
        dishService.saveWithFlavor(dishDto);  
        return R.success("新增菜品成功");  
    }

菜品信息分页查询

系统中的菜品数据很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看,所以一般的系统中都会以分页的方式来展示列表数据。

代码开发

梳理交互流程

在开发代码之前,需要梳理一下菜品分页查询时前端页面和服务端的交互过程:

1、页面(backend/page/food/list.html)发送ajax请求,将分页查询参数(page、pageSize、name)提交到服务端,获取分页数据

2、页面发送请求,请求服务端进行图片下载,用于页面图片展示

开发菜品信息分页查询功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。

controller

@GetMapping("/page")  
public R<Page> page(int page,int pageSize,String name){  
Page<Dish> pageInfo = new Page<>(page,pageSize);  
 LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();  
 queryWrapper.like(name!=null,Dish::getName,name);  
 queryWrapper.orderByDesc(Dish::getCreateTime);  
 dishService.page(pageInfo,queryWrapper);  
 return R.success(pageInfo);  
}

但是有个问题

菜品表中的菜品分类字段是分类的id,前端要求的是菜品分类名称,这样才能展示

所以我们要去处理一下

[!note]

因为原本的Dish里面没有categoryName这个属性,所以要借助DishDto,但是如何根据条件把Dto中的categoryName设置成我们需要的值,并且其余Dish有的我们都要有呢,需要先拷贝pageinfo中除了records的数据,(records)s是查询出来的数据列表,并不是我们需要的,需要把records处理好然后放回去,最后返回的是DishDto类型的Page

#工具类/对象拷贝

BeanUtils.copyProperties

controller

@GetMapping("/page")  
    public R<Page> page(int page,int pageSize,String name){  
    Page<Dish> pageInfo = new Page<>(page,pageSize);  
    Page<DishDto> dishDtoPage= new Page<>();  
     LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();  
     queryWrapper.like(name!=null,Dish::getName,name);  
     queryWrapper.orderByDesc(Dish::getCreateTime);  
     dishService.page(pageInfo,queryWrapper);  
  
        BeanUtils.copyProperties(pageInfo,dishDtoPage,"records");  
        List<Dish> records = pageInfo.getRecords();  
        List<DishDto> list= records.stream().map((item)->{  
            DishDto dishDto = new DishDto();  
            //拷贝Dish里面的属性到DishDto  
            BeanUtils.copyProperties(item,dishDto);  
            //查询到分类id  
            Long categoryId = item.getCategoryId();  
            Category category = categoryService.getById(categoryId);  
            //通过分类id查询到分类名称  
            String categoryName = category.getName();  
            dishDto.setCategoryName(categoryName);  
            return  dishDto;  
//最后通过collect收集成集合  
        }).collect(Collectors.toList());  
  
        dishDtoPage.setRecords(list);  
        //最后传回去的DishDto类型的分页信息  
        return R.success(dishDtoPage);  
  
    }

修改菜品

需求分析

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

代码开发

1、页面发送ajax请求,请求服务端获取分类数据,用于菜品分类下拉框中数据展示

2、页面发送ajax请求,请求服务端,根据id查询当前菜品信息,用于菜品信息回显

3、页面发送请求,请求服务端进行图片下载,用于页图片回显

4、点击保存按钮,页面发送ajax请求,将修改后的菜品相关数据以json形式提交到服务端

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

service中自定义查询来完成查询的功能

public DishDto getByIdWithFlavor(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> list = dishFlavorService.list(queryWrapper);  
    dishDto.setFlavors(list);  
    return dishDto;  
}

controller

因为我们要同时返回菜品信息和口味信息,但是这两个表是单独的,我们的dto中包含了我们需要的属性,完成dto的封装需要查询到dish信息和flavor信息然后封装进去返回

@GetMapping("/{id}")  
public R<DishDto> get(@PathVariable Long id){  
    DishDto byIdWithFlavor = dishService.getByIdWithFlavor(id);  
    return R.success(byIdWithFlavor);  
}


瑞吉外卖业务开发(4)https://developer.aliyun.com/article/1530409

相关文章
|
6月前
|
Java 关系型数据库 MySQL
基于SpringBoot华强北二手手机商城系统
基于SpringBoot华强北二手手机商城系统
|
5月前
|
前端开发 Java API
苍穹外卖开发心得(上)
苍穹外卖开发心得(上)
235 5
|
5月前
|
缓存 JavaScript Java
苍穹外卖开发心得(下)
苍穹外卖开发心得(下)
129 5
|
5月前
|
运维 前端开发 测试技术
瑞吉外卖业务开发(1)
瑞吉外卖业务开发
72 3
|
5月前
|
JSON 前端开发 Java
瑞吉外卖业务开发(2)
瑞吉外卖业务开发
48 3
|
5月前
|
JSON 前端开发 安全
瑞吉外卖业务开发(4)
瑞吉外卖业务开发
37 2
|
6月前
|
搜索推荐 前端开发 Java
酒水商城|基于Springboot实现酒水商城系统
酒水商城|基于Springboot实现酒水商城系统
|
6月前
|
搜索推荐 前端开发 Java
酒水推荐商城|基于Springboot实现酒水商城系统
酒水推荐商城|基于Springboot实现酒水商城系统
|
SQL 缓存 JSON
瑞吉外卖笔记
这是一份写给自己的笔记,主要记录瑞吉外卖项目中自己没有了解过的知识点。我将按照功能来分别解析
725 1
|
负载均衡 Java 数据库连接
瑞吉外卖项目
瑞吉外卖项目
98 0