JAVA项目实战瑞吉外卖—day4
文件上传下载
文件上传介绍
文件上传,也称为upload,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程 文件上传在项目中应用非常广泛,我们经常发微博、发微信朋友國都用到了文件上传功能
文件上传时,对页面的form表单有如下要求:
- method=”post” 采用post方式提交数据 使用页面进行文件上传必须是Post请求
- enctype=”multipart/form-data” 采用multipart格式上传文件
- type=”file” 使用input的file控件上传
举例:
1 2 3 4
| <form method= "post" action="/common/upload" enctype="multipart/form-data"> <input name="myFile" type "file" /> <input type="submit" value="提交"/> </form>
|
服务端要接收客户端页面上传的文件,通常都会使用Apache的两个组件:
- commons-fileupload
- commons-io
Spring框架在spring-web包中对文件上传进行了封装,大大简化了服务端代码,我们只需要在Controller的方法中声 一个MultipartFile类型的参数即可接收上传的文件,file就是我们上传的文件
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
@PostMapping("/upload") public R<String> upload(MultipartFile file){
log.info(file.toString()); return null; } }
|
文件下载介绍
文件下载,也称为download,是指将文件从服务器传输到本地计算机的过程。
通过浏览器进行文件下载,通常有两种表现形式:
- 以附件形式下载,弹出保存对话框,将文件保存到指定磁盘目录
- 直接在浏览器中打开
通过浏览器进行文件下载,本质上就是服务端将文件以流的形式写回浏览器的过程。
@Value(“${reggie.path}”)是yml配置的资源路径
1 2 3
| reggie: path: D:\project\ruijiwaimai\imgs\
|
控制层代码编写
前端读取数据接口路径
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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
|
@RestController @RequestMapping("/common") @Slf4j public class CommonController {
@Value("${reggie.path}") private String basePath;
@PostMapping("/upload") public R<String> upload(MultipartFile 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 (IOException e) { e.printStackTrace(); } return R.success(fileName); }
@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(); }
outputStream.close(); fileInputStream.close(); } catch (Exception e) { e.printStackTrace(); }
} }
|
因为是根据前端页面的请求路径写的接口,必须要前端约定的配置一样才能完成io流的读取和写入
新增菜品
这里进行菜品信息的操作是需要进行两张表的操作
- 菜品信息表Dish
- 菜品口味表DishFlavor
因为是操作两张表,未防止数据库出错,所以需要开启事务控制
@Transactional:在需要事务控制的方法上添加注解
注意在springboot启动类添加开启事务的功能:@EnableTransactionManagement
在开发代码之前,需要梳理一下新增菜品时前端页面和服务端的交互过程:
- 1、页面(backend/page/food/add.html)发送ajax请求,请求服务端获取菜品分类数据井展示到下拉框中
- 2、页面发送请求进行国片上传,请求服务端将图片保存到服务器
- 3、页面发送请求进行图片下载,将上传的国片进行回显
- 4、点击保存按钮,发送ajax请求,将菜品相关数据以json形式提交到服务端
开发新增菜品功能,其实就是服务端编写代码去处理前端发送的四次请求即可
第一步
请求服务端获取菜品分类数据井展示到下拉框中 ,根据前端页面返回的Type属性将菜品分类在展示出来
1 2 3 4 5 6 7 8 9 10
| getDishList () { getCategoryList({ 'type': 1 }).then(res => { if (res.code === 1) { this.dishList = res.data } else { this.$message.error(res.msg || '操作失败') } }) },
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
@GetMapping("/list") public R<List<Category>> list(Category category){
LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(category.getType()!=null,Category::getType,category.getType()); queryWrapper.orderByAsc(Category::getSort).orderByDesc(Category::getUpdateTime);
List<Category> list = categoryService.list(queryWrapper);
return R.success(list); }
|
第二步,第三步同上文件上传与下载 因为写的接口一样可以直接调用
第四步
将菜品相关数据以json形式提交到服务端
因为前端返回的数据中含有flavors的数据且是数组类型,原本封装的Dish实体不能将其一起封装成对象,但是其他属性可以封装为Dish对象属性,所以这里需要新一个DTO实体一起接收flavors和Dish属性
DTO:全称为Data Transfer Object,即数据传输对象,一般用于展示层和服务层之间的数据传输
封装dto
1 2 3 4 5 6 7 8 9
| @Data public class DishDto extends Dish { private List<DishFlavor> flavors = new ArrayList<>();
private String categoryName;
private Integer copies; }
|
编写接口
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
| @Service public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {
@Resource private DishFlavorService dishFlavorService;
@Transactional public void saveWithFlavor(DishDto dishDto) {
this.save(dishDto);
Long disId = dishDto.getId();
List<DishFlavor> flavors = dishDto.getFlavors(); flavors = flavors.stream().map((item)->{ item.setDishId(disId); return item; }).collect(Collectors.toList());
dishFlavorService.saveBatch(flavors);
} }
|
分页查询
这部分的分页查询较为麻烦
我整理一下自己的思路在注解上
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 53 54 55
|
@GetMapping("/page") public R<Page> page(int page,int pageSize,String name){
Page<Dish> pageInfo = new Page<>(page,pageSize); Page<DishDto> dishDtoPage = new Page<>(page,pageSize);
LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<Dish>();
queryWrapper.like(name!=null,Dish::getName,name);
queryWrapper.orderByDesc(Dish::getUpdateTime);
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(); BeanUtils.copyProperties(item,dishDto);
Long categoryId = item.getCategoryId(); 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); }
|
修改菜品
操作两张表需要进行事务处理
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
|
@Transactional public void updateWithFlavor(DishDto dishDto) {
this.updateById(dishDto);
LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(DishFlavor::getDishId,dishDto.getId()); dishFlavorService.remove(queryWrapper);
List<DishFlavor> flavors = dishDto.getFlavors();
flavors = flavors.stream().map((item)->{ item.setDishId(dishDto.getId()); return item; }).collect(Collectors.toList());
dishFlavorService.saveBatch(flavors); }
|
删除菜品
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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
public R<String> deleteByIdWithFlavor(List<Long> ids) {
LambdaQueryWrapper<SetmealDish> setmealDishLambdaQueryWrapper = new LambdaQueryWrapper<>(); setmealDishLambdaQueryWrapper.in(SetmealDish::getDishId,ids); List<SetmealDish> SetmealDishList = setmealDishService.list(setmealDishLambdaQueryWrapper); if (SetmealDishList.size() == 0){ dishService.deleteByIds(ids); LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.in(DishFlavor::getDishId,ids); dishFlavorService.remove(queryWrapper); return R.success("菜品删除成功"); }
ArrayList<Long> Setmeal_idList = new ArrayList<>(); for (SetmealDish setmealDish : SetmealDishList) { Long setmealId = setmealDish.getSetmealId(); Setmeal_idList.add(setmealId); }
LambdaQueryWrapper<Setmeal> setmealLambdaQueryWrapper = new LambdaQueryWrapper<>(); setmealLambdaQueryWrapper.in(Setmeal::getId,Setmeal_idList); List<Setmeal> setmealList = setmealService.list(setmealLambdaQueryWrapper); for (Setmeal setmeal : setmealList) { Integer status = setmeal.getStatus(); if (status == 1){ return R.error("删除的菜品中有关联在售套餐,删除失败!"); } }
dishService.deleteByIds(ids); LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.in(DishFlavor::getDishId,ids); dishFlavorService.remove(queryWrapper);
LambdaQueryWrapper<DishFlavor> queryWrapper1 = new LambdaQueryWrapper<>(); queryWrapper1.in(DishFlavor::getDishId,ids); dishFlavorService.remove(queryWrapper1);
return R.success("菜品删除成功"); }
public void deleteByIds(List<Long> ids) { LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.in(ids != null, Dish::getId, ids); List<Dish> list = this.list(queryWrapper); for (Dish dish : list) { Integer status = dish.getStatus(); if (status == 0) { this.removeById(dish.getId()); } else { throw new CustomException("删除菜品中有正在售卖菜品,无法全部删除"); } }
}
|
启售停售
启售停售功能是一个更新操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
@PostMapping("/status/{status}")
public R<String> status(@PathVariable("status") Integer status,@RequestParam List<Long> ids){ LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.in(ids !=null,Dish::getId,ids); List<Dish> list = dishService.list(queryWrapper);
for (Dish dish : list) { if (dish != null){ dish.setStatus(status); dishService.updateById(dish); } } return R.success("售卖状态修改成功"); }
|