文件上传下载
import com.cc.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.UUID;
@RestController
@RequestMapping("/common")
@Slf4j
public class CommonController {
//拿到yml里保存的文件路径
@Value("${takeOutFile.fileLocaltion}")
private String fileLoaction;
/**
* 上传图片
* @param file 文件名称,和前台传来的文件名称是一致的
* @return
*/
@PostMapping("/upload")
public Result<String> upLoadFile(MultipartFile file){
//这里的file只是一个临时的文件存储,临时存储到某一个位置,然后待接收完毕后再转存到目标位置上,然后再把这个临时文件删除
//截取文件后缀
String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.'));
//生成UUID
String randomUUID = UUID.randomUUID().toString();
//拼接文件最后名称,结果为文件本体名字+UUID+后缀
String fileName = file.getOriginalFilename() + randomUUID + suffix;
//保证存储的位置有这个文件夹
File dir = new File(fileLoaction);
if (!dir.exists()) {
//目标存储位置不存在,就创建一个文件夹
dir.mkdirs();
}
try {
//转存文件到指定位置+文件的名称全拼
file.transferTo(new File(fileLoaction+fileName));
} catch (IOException e) {
e.printStackTrace();
}
//把文件的名字上传回去,方便后续回显读取路径
return Result.success(fileName);
}
/**
* 文件回显接口
* @param httpServletResponse 响应对象
* @param name 上传的文件名称
* @throws IOException IO异常
*/
@GetMapping("/download")
public void fileDownload(HttpServletResponse httpServletResponse,String name) throws IOException {
//把刚刚存的文件读取到内存中,准备回显
FileInputStream fileInputStream = new FileInputStream(new File(fileLoaction+name));
//把读取到内存中的图片用输出流写入Servlet响应对象里
ServletOutputStream servletOutputStream = httpServletResponse.getOutputStream();
//可选项,选择响应类型
httpServletResponse.setContentType("image/jpeg");
//用byte数组写入,注意是小写b,不是大写,大写就是包装类了
byte[] fileArray = new byte[1024];
int length=0;
try {
//只要没读到数组的尾部就一直读下去,这部分是IO的内容
while ((length=fileInputStream.read(fileArray))!=-1) {
//写入响应流,从0开始,写入到数组末尾长度
servletOutputStream.write(fileArray, 0, length);
//把流里的东西挤出来
servletOutputStream.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭流
fileInputStream.close();
servletOutputStream.close();
}
return;
}
}
新增菜品
/**
* 新增菜品
* @param dishDto 传输对象
* @return
*/
@PostMapping()
public Result<String> addDish(@RequestBody DishDto dishDto) {
log.info(dishDto.toString());
dishService.addDishWithFlavor(dishDto);
return Result.success("保存成功");
}
菜品信息分页查询
/**
* 菜品信息分页查询
* @param page
* @param pageSize
* @param name
* @return
*/
@GetMapping("/page")
public Result<Page> page(int page,int pageSize,String name){
//构造分页构造器对象
Page<Dish> pageInfo = new Page<>(page,pageSize);
//DishDto是前端要的东西和后端的Dish不一样,要扩展一下
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);
//对象拷贝,忽略record对象,因为record就是查出来的记录数,也就是pageInfo
BeanUtils.copyProperties(pageInfo,dishDtoPage,"records");
List<Dish> records = pageInfo.getRecords();
//将List集合搬入Dto中
//这里是流式编程的内容,或者用foreach来进行搬运也可以解决
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 Result.success(dishDtoPage);
}
修改菜品
/**
* 更新菜品操作
* @param dishDto
* @return
*/
@PutMapping()
public Result<String> updateDish(@RequestBody DishDto dishDto) {
log.info(dishDto.toString());
dishService.updateDishWithFlavor(dishDto);
/*
* 大面积全清理的写法
* */
//Set keys = redisTemplate.keys("dish_*");
//redisTemplate.delete(keys);
//精确删除,在售状态的
String redisKey = "dish_" + dishDto.getCategoryId() + "_" + dishDto.getStatus()+"_1";
log.info("准备清理key为:{} 的缓存数据",redisKey);
redisTemplate.delete(redisKey);
return Result.success("更新成功");
}
重写服务
/**
* 更新口味操作,和上面的添加操作异曲同工
* @param dishDto
*/
@Override
@Transactional
public void updateDishWithFlavor(DishDto dishDto) {
//Dish表是可以直接更新操作的,这里也是一样的,传入的是Dish的子类,可以直接操作,默认也就是按Dish类更新了
dishService.updateById(dishDto);
//Dish_Flavor表比较特殊,所以需要先删除再插入
//Dish_Flavor表字段删除,所有当前dish id的口味
LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper();
//子类可以直接获取父类的内容了
lambdaQueryWrapper.eq(DishFlavor::getDishId, dishDto.getId());
dishFlavorService.remove(lambdaQueryWrapper);
//再插入
List<DishFlavor> flavorList=dishDto.getFlavors();
//遍历
for (DishFlavor dishFlavors:flavorList) {
dishFlavors.setDishId(dishDto.getId());
}
//saveBatch是批量集合的存储
dishFlavorService.saveBatch(flavorList);
}