4

第四阶段笔记 Jingtao_day06

 3 years ago
source link: https://segmentfault.com/a/1190000038389717
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

day 06 商品图片上传

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

江哥的专栏

cgb2008-京淘day06

一. 完成商品CRUD操作

  1. 商品上下架操作

    i. 编辑ItemController

    /* 业务:商品的上下架
       url: http://localhost:8091/item/[instock|reself]
       参数: 1/2
       返回值: SysResult
       SpringMVC参数接收说明:以,分割则自动转化为数组类型
       */
    @RequestMapping("/{op}")
    @ResponseBody
    public 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

    @Override
    public 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

    @Mapper
    public 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")
    @ResponseBody
    public SysResult saveItem(Item item, ItemDesc itemDesc){
       itemService.saveItem(item,itemDesc);
       return SysResult.success();
    }

    ii. 编辑ItemServiceImpl

    // Item表主键自增
    @Override
    @Transactional
    public 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}")
    @ResponseBody
    public SysResult findItemDescById(@PathVariable Long itemId){
       ItemDesc itemDesc = itemService.findItemDescById(itemId);
       return SysResult.success(itemDesc);
    }

    ii. 编辑ItemServiceImpl

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

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

    i. 编辑ItemController

    @RequestMapping("/update")
    @ResponseBody
    public 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

    @RestController
    public 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

    @Autowired
    private 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

    @Service
    public 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();  //报错返回
            }
        }
    }

作业: 了解反向代理/正向代理;磁盘地址优化


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK