ToB企服应用市场:ToB评测及商务社交产业平台
标题:
瑞吉外卖day4
[打印本页]
作者:
王國慶
时间:
2023-5-13 15:56
标题:
瑞吉外卖day4
菜品管理业务开发
文件上传与下载
文件上传
介绍
服务端要接收客户端页面上传的文件,通常都会使用Apache的两个组件
1.commons-file upload
2.commons-io
Spring框架在spring-web包中对文件上传进行了封装。只需要在Controller的方法中声明一个MultipartFile类型的参数即可接受上传的文件
代码实现
@Value("${reggie.path}")
private String basePath;
@PostMapping("/upload")
public R<String> upload(MultipartFile file){
//file是一个临时文件,需要把他转存到指定文件,否则本次请求完成后会被删除
log.info("上传的文件{}",file.toString());
//原始文件名
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();
}
try {
file.transferTo(new File(basePath+fileName));
} catch (IOException e) {
throw new RuntimeException(e);
}
return R.success(fileName);
}
复制代码
upload方法里的形参名要保证与前端提交的表单名一致
在yml配置文件中定义路径变量path
文件下载
代码实现
@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){//len:m每次读取的有效字节数当len=-1表示读取到文件末尾
outputStream.write(bytes,0,len);//**写出指定长度字节数组**:`write(byte[] b, int off, int len)` ,每次写出从off索引开始,len个字节,
outputStream.flush();
}
outputStream.close();
fileInputStream.close();
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
复制代码
新增菜品功能
需求分析
后台系统中可以管理菜品信息,通过新增功能来添加一个新的菜品,在添加菜品时需要选择当前菜品所属菜品分类,并且需要上传菜品图片,在移动端会按照菜品分类来展示对应的菜品信息
数据模型
代码开发
准备工作:
实体类DishFlavor
Mapper接口DishFlavorMapper
业务层接口DishFlavorService
业务层实现类 DishFlavorServicelmpl控制层 DishController
交互过程:
1、页面(backend/page/food/ add.html)发送ajax请求,请求服务端获取菜品分类数据并展示到下拉框中
/**
*
* @param category
* @return
*/
@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);
}
复制代码
2、页面发送请求进行图片上传,请求服务端将图片保存到服务器
3、页面发送请求进行图片下载,将上传的图片进行回显
4、点击保存按钮,发送ajax请求,将菜品相关数据以json形式提交到服务端
前端提交的json数据与dish实体类不是一一对应,需要定义dishDao类来接受数据
DTO:全称为Data Transfer Object,即数据传输对象,一般用于展示层和服务层之间的数据传输
@Data
public class DishDto extends Dish {
private List<DishFlavor> flavors = new ArrayList<>();
private String categoryName;
private Integer copies;
}
复制代码
菜品信息分页查询
代码开发-梳理交互
1、页面(backend/page/food/list.html)发送ajax请求,将分页查询参数(page、pageSize,name)
提交到服务端,获取分页数据
2、页面发送请求,请求服务端进行图片下载,用于页面图片展示
代码实现
/**
* 菜品分页查询
* @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);
Page<DishDto> dishDtoPage = new Page<>();
//构造查询构造器对象
LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
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();
//根据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);
}
复制代码
前端渲染页面需要categoryName参数。实体类dish中无对应属性,所以不能直接将获取到的pageInfo响应给客户端。再声明泛型为DishDao的Page对象。将pageInfo中的属性拷贝到dishDaoPage中返回给客户端,但由于pageInfo中的records属性中寸的是dish对象,需要单独处理,将records中的dish对象转换为dishDao对象存到新集合中。最后将dishDaoPage返回给前端。
修改菜品
需求分析
在菜品管理列表页面点击修改按钮,跳转到修改菜品页面,在修改页面回显菜品相关信息并进行修改,点击确定按钮完成相关操作
代码实现
页面的回显信息中包含菜品口味,因此服务端应向客户端返回dishDto类型的数据,在dishService中声明getByIdWithFlavor方法,根据id查询菜品信息以及菜品口味信息封装成dishDto对象,返回
@Override
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;
}
复制代码
调用dishSer中的getByIdWithFlavor方法,将返回值响应给客户端,实现数据回显
@GetMapping("/{id}")
public R<DishDto> get(@PathVariable Long id){
DishDto byIdWithFlavor = dishService.getByIdWithFlavor(id);
return R.success(byIdWithFlavor);
}
复制代码
将修改后的数据保存到数据库中,需要分别更新菜品表和菜品口味表。
菜品口味表的更新分两步,第一步先将当前口味表中对应的数据删除,再添加客户端提交过来的数据实现数据更新
@Override
public void updateWithFlavor(DishDto dishDto) {
//更新dish表基本信息
this.updateById(dishDto);
//清理当前菜品口味对应数据-----dishFlavor表对应的删除操作
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);
}
复制代码
/**
* 修改菜品
* @param dishDto
* @return
*/
@PutMapping
public R<String> update(@RequestBody DishDto dishDto){
log.info(dishDto.toString());
dishService.updateWithFlavor(dishDto);
return R.success("修改菜品成功");
}
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4