day 06 商品图片上传

此文档是依据上课流程编写,更多细节及图片请参见刘老师的专栏

江哥的专栏

《cgb2008-京淘day06》

一. 实现商品CRUD操作
  1. 商品高低架操作

    i. 编辑ItemController

    /* 业务:商品的高低架   url: http://localhost:8091/item/[instock|reself]   参数: 1/2   返回值: SysResult   SpringMVC参数接管阐明:以,宰割则主动转化为数组类型   */@RequestMapping("/{op}")@ResponseBodypublic SysResult opStock(@PathVariable String op,Long[] ids){   if(op.equals("instock")){      System.out.println("=== Instock ===");      itemService.opStock(ids,2);   }else if(op.equals("reshelf")){      System.out.println("=== Reshelf ===");      itemService.opStock(ids,1);   }   return SysResult.success();}

    ii. 编辑ItemServiceImpl

    @Overridepublic void opStock(Long[] ids,int status) {   //1.以MP的办法操作数据库 只批改状态码/updated工夫   Item item = new Item();   QueryWrapper queryWrapper = new QueryWrapper();   queryWrapper.in("id",ids);   item.setStatus(status);   itemMapper.update(item,queryWrapper);   //2.手写SQL   itemMapper.updateStatus(ids,status);}

    iii. 编辑ItemMapper.xml

    void updateStatus(@Param("ids") Long[] ids, @Param("status") int status);
    <update id="updateStatus">   UPDATE tb_item SET status=#{status},updated=now()   WHERE id IN(   <foreach collection="ids" item="id" separator=",">      #{id}   </foreach>   )</update>
二. 实现商品详情信息的展示
  1. 业务阐明

    个别用户查问商品时,只须要展示展现商品相干信息即可,如果用户点击某个商品时才会展示商品详情,因为商品详情信息是大字段,检索绝对较慢节约性能。

    1) tb_item;2) tb_item_desc 一对一

    i. 编辑ItemDesc pojo对象

    @Data@AllArgsConstructor@NoArgsConstructor@Accessors(chain = true)@TableName("tb_item_desc")public class ItemDesc extends BasePojo{    @TableId    private Long itemId; //与item表中的数据统一    private String itemDesc;}

    ii. 编辑ItemDescMapper

    @Mapperpublic interface ItemDescMapper extends BaseMapper<ItemDesc> {}
  2. 富文本编辑器介绍

    <script type="text/javascript">   $(function(){      KindEditor.ready(function(){         KindEditor.create("#editor")      })   })</script><textarea style="width:700px;height:350px" id="editor"></textarea>
  3. 重构商品新增

    因为商品的新增是将Item/ItemDesc对象一起新增,所以要实现两张表的入库。

    i. 编辑ItemController

    @RequestMapping("/save")@ResponseBodypublic SysResult saveItem(Item item, ItemDesc itemDesc){   itemService.saveItem(item,itemDesc);   return SysResult.success();}

    ii. 编辑ItemServiceImpl

    // Item表主键自增@Override@Transactionalpublic void saveItem(Item item, ItemDesc itemDesc) {   item.setStatus(1);   itemMapper.insert(item);   //MP用法:如果实现了主键自增,主动实现了主键回显   //获取主键信息   itemDesc.setItemId(item.getId());   itemDescMapper.insert(itemDesc);}
  4. 重构商品编辑

    查问到商品的详情信息,返回给用户,而后将批改后的内容执行两次入库操作。

    i. 编辑ItemController

    /* 业务:依据商品id号,检索商品详情   url: http://localhost:8091/item/desc/1233   参数: rest格调   返回值: SysResult   SpringMVC参数接管阐明:以,宰割则主动转化为数组类型   */@RequestMapping("/query/item/desc/{itemId}")@ResponseBodypublic SysResult findItemDescById(@PathVariable Long itemId){   ItemDesc itemDesc = itemService.findItemDescById(itemId);   return SysResult.success(itemDesc);}

    ii. 编辑ItemServiceImpl

    @Overridepublic ItemDesc findItemDescById(Long itemId) {   return itemDescMapper.selectById(itemId);}
  5. 重构商品更新

    用户在更新商品时,要更新两张表的数据Item/ItemDesc

    i. 编辑ItemController

    @RequestMapping("/update")@ResponseBodypublic SysResult updateItem(Item item,ItemDesc itemDesc){   itemService.updateItem(item,itemDesc);   return SysResult.success();}

    ii. 编辑ItemServiceImpl

    public void updateItem(Item item, ItemDesc itemDesc) {   itemMapper.updateById(item);   //补全数据   itemDesc.setItemId(item.getId());   itemDescMapper.updateById(itemDesc);}
  6. 重构商品删除

    i. 编写ItemServiceImpl

    public void deleteItems(Integer[] ids) {   //itemMapper.deleteBatchIds(Arrays.asList(ids));  //MP   itemMapper.deleteItems(Arrays.asList(ids));  //手写SQL   itemDescMapper.deleteBatchIds(Arrays.asList(ids)));}
三. 实现商品图片上传
  1. 文件上传入门案例

    i. 页面标识

    <h1>实现文件长传</h1><!--enctype="开启多媒体标签"  --><form action="http://localhost:8091/file" method="post" enctype="multipart/form-data">   <input name="fileImage" type="file" />   <input type="submit" value="提交"/></form>

    ii. 编辑FileController

    @RestControllerpublic class FileController {    @RequestMapping("/file")    public String file(MultipartFile fileImage) throws IOException {        //1.获取图片的名称        String name = fileImage.getOriginalFilename();        //2.定义文件目录        String fileDirPath = "E:/jt_img";        //3.创立目录        File fileDir = new File(fileDirPath);        if(!fileDir.exists()){            fileDir.mkdirs();        }        //4.生成文件全门路        String filePath = fileDirPath+"/"+name;        File imageFile = new File(filePath);        //5.实现文件上传        fileImage.transferTo(imageFile);        return "FILE UPLOAD OK";    }}
  2. 业务实现

    i. 形容

    url:localhost:8091/pic/upload?dir=image

    参数类型:uploadFile

    返回值JSON构造:{"error":0,"url":"图片保留门路","width":宽度,"height":高度}

    ii. 编辑ImageVO

    @Data@NoArgsConstructor@AllArgsConstructor@Accessors(chain = true)public class ImageVO {    //{"error":0,"url":"图片保留门路","width":宽度,"height":高度}    private Integer error;    private String url;    private Integer width;    private Integer height;    public static ImageVO fail(){       return new ImageVO(1,null,null,null);    }    public static ImageVO success(String url,Integer width,Integer height){       return new ImageVO(0, url, width, height);    }}

    iii. 编辑FileController

    @Autowiredprivate FileService fileService;/* 业务需要:实现文件上传操作    url: localhost:8091/pic/upload?dir=image    参数: uploadFile    返回值: ImageVO*/@RequestMapping("/pic/upload")public ImageVO upload(MultipartFile uploadFile){    return fileService.upload(uploadFile);}

    iv. 编辑FileServiceImpl

    @Servicepublic class FileServiceImpl implements FileService{    private static Set<String> typeSet = new HashSet<>();    //动态代码块为动态成员赋值    static {        typeSet.add(".jpg");        typeSet.add(".png");        typeSet.add(".gif");    }    /* 业务逻辑:实现文件上传        1.校验图片的类型 jpg png gif        2.校验文件是否为恶意程序        3.采纳分目录的构造进行存储        4.防止文件重名 UUID     */    @Override    public ImageVO upload(MultipartFile uploadFile) {        //1.利用汇合校验/利用正则表达式        String fileName = uploadFile.getOriginalFilename().toLowerCase();        int index = fileName.lastIndexOf(".");        String fileType = fileName.substring(index);  //.jpg        //List Map Set []        if(!typeSet.contains(fileType))            return ImageVO.fail();        //2.如果是图片 高度 宽度        try {            BufferedImage bufferedImage = ImageIO.read(uploadFile.getInputStream());            int width = bufferedImage.getWidth();            int height = bufferedImage.getHeight();            if(width==0||height==0)                return ImageVO.fail();            //3.依照 年-月-日 的形式进行目录的划分            String fileDir = "E:/jt_img";            String dateDir = new SimpleDateFormat("/yyyy/MM/dd/")                    .format(new Date());            //E:/jt_img/2020/12/1/            String fileDirPath = fileDir+dateDir;            File dirFile = new File(fileDirPath);            if(!dirFile.exists())                dirFile.mkdirs();            //4.UUID 32位16进制数 --> 2^128            //  hashCode 8为16进制数 --> 2^32            String uuid = java.util.UUID.randomUUID().toString()                    .replace("-", "");            String uuidName = uuid+fileType;            File realFile = new File(fileDirPath+uuidName);            uploadFile.transferTo(realFile);            String url = "";            return ImageVO.success(url, width, height);        } catch (IOException e) {            e.printStackTrace();            return ImageVO.fail();  //报错返回        }    }}
作业: 理解反向代理/正向代理;磁盘地址优化