瑞吉外卖-菜品管理

菜品管理

文件的上传和下载

文件上传的介绍:

image-20220722162919393

image-20220722163109156

文件上传的代码实现:

首先将文件上传的upload.html页面复制到page目录下的demo目录中。

访问upload.html,上传文件时请求路径为:

image-20220722164859836

因此新建一个CommonController进行文件上传和下载。

CommonController中文件上传的代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
* 文件上传和下载
*/

@RestController
@RequestMapping("/common")
@Slf4j
public class CommonController {

@Value("${reggie.path}")
private String basePath;

/**
* 文件上传
* @param file
* @return
*/
@PostMapping("/upload")
public R<String> upload(MultipartFile file){
//file是个临时文件,需要转存,否则本次请求完之后的临时文件将删除
log.info(file.toString());

String originalFilename = file.getOriginalFilename();
String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));

String fileName = UUID.randomUUID().toString()+suffix;
//新键目录
File dir = new File(basePath);
if (!dir.exists()){ //如果目录不存在,则创建目录
dir.mkdirs();
}
try {
//将文件转移到指定的目录中
file.transferTo(new File(basePath+fileName));
} catch (Exception e) {
e.printStackTrace();
}
return R.success(fileName);
}

}

其中application.yml文件:

1
2
reggie:
path: D:\img\ #设置图片下载下来后存储的位置

文件下载的介绍:

image-20220722163226124

根据浏览器发出的响应,所以应该为:@GetMapping("/download")

image-20220809091310266

文件下载的代码:(下面这个代码将本机电脑作为服务器进行传输)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* 文件下载
* @param name
* @param response
* @return
*/
@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];
//将读到的内容放入到bytes中去
while ((len = fileInputStream.read(bytes))!=-1){
//通过输出流向浏览器写
outputStream.write(bytes,0,len);
outputStream.flush();
}
fileInputStream.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}

新增菜品

分析

image-20220809215512022

image-20220809220732856

第一步:根据条件动态查询分类数据:

点击菜品分类时,所发出的请求为:

image-20220809220843612

因此CategoryController.java的代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 根据类型查询的食品种类数据
* @return
*/
@RequestMapping("/list")
public R<List<Category>> getCategory(Category category){
//构造条件构造器
LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//查询条件,从数据库中找到相同类型的菜品
lambdaQueryWrapper.eq(category.getType()!=null,Category::getType,category.getType());
//排序顺序
lambdaQueryWrapper.orderByAsc(Category::getSort).orderByDesc(Category::getUpdateTime);
List<Category> list = categoryService.list(lambdaQueryWrapper);
return R.success(list);
}

补充知识:

DTO:(Data Transfer Object 数据传输对象)当实体中的属性不能够进行作为参数传输时,也就是浏览器发送过来的数据中的参数,实体类中不包含时进行使用。

新增菜品的代码为:

因为新增菜品时,操作的是两个表,一个是菜品表,一个是口味表,所以不能用普通的save方法,因此自己写一个保存口味和菜品的方法:

因为操作的是两个表,因此也要开启事务,保证两个表一起成功,一起失败

DishServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 新增菜品,同时保存对应的口味
* @param dishDto
*/
@Override
@Transactional
public void saveWithFlavor(DishDto dishDto) {

//保存到菜单中
this.save(dishDto);
//获取菜品的id,因为保存到口味表中时会用到
Long id = dishDto.getId();

//获取所有的口味列表
List<DishFlavor> flavors = dishDto.getFlavors();

//将所有的口味添加菜品id,并转化为list
flavors = flavors.stream().map((item)->{
item.setDishId(id);
return item;
}).collect(Collectors.toList());
//保存到口味中
dishFlavorService.saveBatch(flavors);

}

DishController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
*菜品管理
*/
@RequestMapping("/dish")
@RestController
@Slf4j
public class DishController {
@Autowired
private DishService dishService;

@PostMapping
public R<String> save(@RequestBody DishDto dishDto){
log.info(dishDto.toString());
dishService.saveWithFlavor(dishDto);
return R.success("添加菜品成功");
}

}

菜品信息分页查询

菜品的分页展示,比之前的两个分页要难一些,因为要展示图片,和菜品分类的名称(因为菜品里面没有菜品名称的属性,有的是菜品的id,因此要对照菜品的分类来进行显示)

image-20220810163605767

分析:

image-20220810163900469

前端发送的请求:

image-20220810170247219

代码为:(相对复杂,因为页面要展示菜品的名称而不是id,所以不能使用Dish,要使用DishDto)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* 分页
* @param page
* @param pageSize
* @param name
* @return
*/
@GetMapping("/page")
public R<Page> page(int page,int pageSize,String name){
//构造分页构造器
Page<Dish> pageInfo = new Page<>(page,pageSize);
//因为Dish中没有菜品分类名称,只有菜品分类id,而DishDTO中又分类名称,所以,要将查询的结果拷贝到DishDTO中
Page<DishDto> dishDtoPage = new Page<>();

//构造条件构造器
LambdaQueryWrapper<Dish> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.like(name!=null,Dish::getName,name);
lambdaQueryWrapper.orderByDesc(Dish::getUpdateTime);
//执行分页查询
dishService.page(pageInfo,lambdaQueryWrapper);
//对象拷贝,忽略records属性(records就是所有菜品的列表项),因为我们要自己定义records,将id变为name
BeanUtils.copyProperties(pageInfo,dishDtoPage,"records");

//获取dish中菜单的每一项
List<Dish> records = pageInfo.getRecords();

//将菜单的每一项拷贝到dishDto中,并重新设置菜品分类的名称,自己设置忽略的records
List<DishDto> dishDtoList = records.stream().map((item)->{
DishDto dishDto = new DishDto();

//对象拷贝,因为dishDto,是新建的,要将dish中的record拷贝到dishDto中
BeanUtils.copyProperties(item,dishDto);

//获取分类id
Long categoryId = item.getCategoryId();
//根据分类id获取分类
Category category = categoryService.getById(categoryId);
if (category!=null){
//通过分类获取分类名称
String categoryName = category.getName();
//设置dishDto的分类名称
dishDto.setCategoryName(categoryName);
}
return dishDto;

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

//将修改完的records设置给dishDtoPage
dishDtoPage.setRecords(dishDtoList);

return R.success(dishDtoPage);
}

修改菜品

image-20220811213647314

第一步:首先,要将菜品信息进行回显

image-20220811214704864

代码为:

首先要根据页面发送请求中的id查询,以上这些菜品的基本的信息以及口味。

编写DishService代码,写根据id获取信息的代码,因为不仅要获取基本的Dish信息还要获取口味信息。

DishServiceImpl.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 根据id获取菜品基本信息和口味
* 回显
* @param id
* @return
*/
public DishDto getByIdWithFlavor(Long id) {

Dish dish = dishService.getById(id);

DishDto dishDto = new DishDto();

//将基本的信息copy过去
BeanUtils.copyProperties(dish,dishDto);

LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//根据id查询口味
lambdaQueryWrapper.eq(DishFlavor::getDishId,dish.getId());
//以列表的形式展示
List<DishFlavor> list = dishFlavorService.list(lambdaQueryWrapper);
//设置口味
dishDto.setFlavors(list);
return dishDto;
}

DishController.java:

1
2
3
4
5
6
7
8
9
10
/**
* 修改菜品时,将菜品信息进行回显
* @param id
* @return
*/
@GetMapping("/{id}")
public R<DishDto> get(@PathVariable Long id){
DishDto dishDto = dishService.getByIdWithFlavor(id);
return R.success(dishDto);
}

回显成功:

image-20220811220005154

第二步:点击保存,修改成功:

修改也不能用系统给的普通修改,因为要修改两个表,菜品表和口味表。因此要重写更新方法

DishServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 更新菜品信息和口味
*/
public void updateWithFlavor(DishDto dishDto) {
//更新菜单信息
this.updateById(dishDto);

//清理当前菜品的口味数据
LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(DishFlavor::getDishId,dishDto.getId());
dishFlavorService.remove(lambdaQueryWrapper);

//添加更新后的口味数据
Long id = dishDto.getId();
//获取新更新的口味
List<DishFlavor> flavors = dishDto.getFlavors();
//设置口味的id
flavors = flavors.stream().map((item)->{
item.setDishId(id);
return item;
}).collect(Collectors.toList());
dishFlavorService.saveBatch(flavors);
}

DishController.java

1
2
3
4
5
6
7
8
9
/**
* 修改菜品,点击保存
* @return
*/
@PutMapping
public R<String> update(@RequestBody DishDto dishDto){
dishService.updateWithFlavor(dishDto);
return R.success("修改菜品成功");
}

成功~~


瑞吉外卖-菜品管理
http://example.com/2022/08/11/瑞吉外卖-day03/
作者
zlw
发布于
2022年8月11日
许可协议