乐趣区

关于java:第四阶段笔记-Jingtaoday05

day 05 商品模块 CRUD

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

江哥的专栏

《cgb2008- 京淘 day05》

一. 实现商品分类的展示
  1. 树形构造展示

    子节点的加载依赖于父节点的状态

    i. 用户在默认的条件下如果没有开展子节点则不会发出请求

    ii. 当用户关上关闭的节点时,会将以后节点的 id 作为参数,向服务器发送申请

  2. 编辑 ItemCatController

    /* 业务需要: 实现商品分类树形构造的展现
        url: http://localhost:8091/item/cat/list
        参数: id = 父级节点的 id
        返回值: List<EasyUITree>
    */
    @RequestMapping("/list")
    public List<EasyUITree> showTree(Long id){
        // 临时只查问一级菜单信息
        Long parentId = (id==null)?0L:id;
        // 数据库记录 ItemCat 对象, 页面中要的数据 EasyUITree
        // 须要将 pojo 对象转换为 vo 对象 get/set...
        List<EasyUITree> list = itemCatService.findAllCat();
        return list;
    }
  3. 编辑 ItemCatService

    /* 依据 parentId 获取 List 汇合
       将这个汇合转换为 vo 的汇合
     */
    @Override
    public List<EasyUITree> findAllCat(long parentId) {List<EasyUITree> easyUITrees = new ArrayList<>();
        QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", parentId);
        List<ItemCat> itemCats  = itemCatMapper.selectList(queryWrapper);
        itemCats.forEach(item->{EasyUITree easyUITree = new EasyUITree();
            easyUITree.setId(item.getId()).setText(item.getName());
            if (item.getIsParent())
                easyUITree.setState("closed");
            else
                easyUITree.setState("open");
            easyUITrees.add(easyUITree);
        });
        return easyUITrees;
    }
二. 实现商品 CRUD 操作
  1. 商品的新增

    i. 业务逻辑

    ​ 1) 申请的 url:http://localhost:8091/item/save

    ​ 2) 用户的参数:cid=76&title=1&sellPoint=2&priceView=3.00&price=300&num=4&barcode=5&image&itemDesc=6&itemParams=[]

    ​ 3) JS 代码

    function submitForm(){
       // 表单校验
       if(!$('#itemAddForm').form('validate')){$.messager.alert('提醒','表单还未填写实现!');
          return ;
       }
       // 转化价格单位,将元转化为分
       //$("XX").val() 取值, $("XX").val(100) 赋值
       $("#itemAddForm [name=price]").val(eval($("#itemAddForm [name=priceView]").val()) * 100);
       itemAddEditor.sync();// 将输出的内容同步到多行文本中
       
       var paramJson = [];
       $("#itemAddForm .params li").each(function(i,e){var trs = $(e).find("tr");
          var group = trs.eq(0).text();
          var ps = [];
          for(var i = 1;i<trs.length;i++){var tr = trs.eq(i);
             ps.push({"k" : $.trim(tr.find("td").eq(0).find("span").text()),
                "v" : $.trim(tr.find("input").val())
             });
          }
          paramJson.push({
             "group" : group,
             "params": ps
          });
       });
       paramJson = JSON.stringify(paramJson);// 将对象转化为 json 字符串
       
       $("#itemAddForm [name=itemParams]").val(paramJson);
       
       /*$.post/get(url,JSON,function(data){....})  
          ?id=1&title="天龙八部 &key=value...."
       */
       //alert($("#itemAddForm").serialize());
       // 参数的写法:
       //{key1:value1,key2:value2}
       //?key1=value1&key2=value2
       //.serialize() - API
       $.post("/item/save",$("#itemAddForm").serialize(), function(data){if(data.status == 200){$.messager.alert('提醒','新增商品胜利!');
          }else{$.messager.alert("提醒","新增商品失败!");
          }
       });
    }

    ii. 编辑 SysResult VO 对象

    @Data
    @Accessors(chain = true)
    @NoArgsConstructor
    @AllArgsConstructor
    public class SysResult {
        private Integer status; //200 示意胜利 201 示意失败
        private String msg; // 服务器给用户的提示信息
        private Object data; // 服务器返回给用户的数据
    
        // 封装工具 API
        public static SysResult fail(){return new SysResult(201,"服务器调用异样",null);
        }
    
        public static SysResult success(){return new SysResult(200,"业务执行胜利",null);
        }
    
        public static SysResult success(Object data){return new SysResult(200,"业务执行胜利",data);
        }
    
        public static SysResult success(String msg,Object data){return new SysResult(200,msg,data);
        }
    
    }

    iii. 编辑 ItemController

    /* 业务: 商品的新增操作
       url: http://localhost:8091/item/save
       参数: 整个表单进行提交 应用对象接管
       返回值: SysResult*/
    @RequestMapping("/save")
    @ResponseBody
    public SysResult saveItem(Item item){
       try {itemService.saveItem(item);
          return SysResult.success();}catch (Exception e){e.printStackTrace();
          return SysResult.fail();}
    }

    iv. 编辑 ItemServiceImpl

    @Override
    @Transactional
    public void saveItem(Item item) {Date date = new Date();
       item.setStatus(1).setCreated(date).setUpdated(date);
       itemMapper.insert(item);
    }
  2. 参数主动填充性能

    i. 业务需要:在用户入库 / 更新操作时,是否实现工夫的主动填充,简化用户的操作步骤。

    ii. 编辑 BasePojo,增加注解

    //pojo 基类, 实现 2 个工作:2 个日期, 实现序列化
    @Data
    @Accessors(chain=true)
    public class BasePojo implements Serializable{@TableField(fill = FieldFill.INSERT)  // 新增操作时, 增加数据
       private Date created;
       @TableField(fill = FieldFill.INSERT_UPDATE)  // 新增更新操作时, 增加数据
       private Date updated;
    
    }

    iii. 编辑 MyMetaObjectHandler 配置类

    @Slf4j
    @Component  // 将对象交给容器治理
    public class MyMetaObjectHandler implements MetaObjectHandler {   
        // 实现入库和更新操作的主动赋值
        @Override
        public void insertFill(MetaObject metaObject) {Date date = new Date();
            this.setInsertFieldValByName("created", date, metaObject);
            this.setInsertFieldValByName("updated",date,metaObject);
        }
        @Override
        public void updateFill(MetaObject metaObject) {Date date = new Date();
            this.setInsertFieldValByName("updated", date, metaObject);
        }
    }
  3. 全局异样解决机制

    i. 阐明

    ​ 1) 如果将大量的异样解决写到代码中,尽管能够保障程序稳固的运行,然而代码的构造十分的凌乱;

    ​ 2) 异样时程序运行状态的一种体现,如果没有一种对立的规定来解决异样,则程序一旦出错问题无奈定位;

    ​ 3) 问:异样从哪里接管?异样应该在 Controll 层进行拦挡

    ​ Mapper –> Service –> Controller –> 用户

    ii. 引入 jar 包

    <!-- 增加 httpClient jar 包 -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
    </dependency>
    <!-- 引入 dubbo 配置 -->
    <dependency>
        <groupId>com.alibaba.boot</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
        <version>0.2.0</version>
    </dependency>-->
    <!-- 增加 Quartz 的反对 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-quartz</artifactId>
    </dependency>-->
    <!-- 引入 aop 反对 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <!--spring 整合 redis -->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
    </dependency>

    iii. 编辑 SystemException 切面

    //@Aspect
    //@Component
    @RestControllerAdvice //AOP+ 异样告诉
    public class SystemException {
        // 当遇到某种类型的异样时才会执行
        @ExceptionHandler({RuntimeException.class, SQLException.class})
        public Object exception(){return SysResult.fail();
        }
    }
  4. 商品分类名称的回显

    i. 须要将 cid 展示为具体的名称

    ii. 编辑 item_list 页面的 js

    /* 实现商品分类名称的回显
        1. 获取商品分类的 id
        2. 发送 ajax 申请
        3. 将后果在指定地位展示
    */
    let cid = data.cid;
    $.get("/item/cat/queryItemName",{"itemCatId":cid},function(data){
        //data 代表返回值后果 -- 商品分类名称
        $("#itemeEditForm input[name='cid']").prev("span").text(data);
    })
  5. 商品批改

    i. 查看页面的 JS

    $.post("/item/update",$("#itemeEditForm").serialize(), function(data){if(data.status == 200){$.messager.alert('提醒','批改商品胜利!','info',function(){$("#itemEditWindow").window('close');
             $("#itemList").datagrid("reload");
          });
       }else{$.message.alert("提醒",data.msg);
       }
    });

    ii. 编辑 ItemController

    /* 业务: 商品的批改操作
       url: http://localhost:8091/item/update
       参数: 整个表单进行提交 应用对象接管
       返回值: SysResult*/
    @RequestMapping("/update")
    @ResponseBody
    public SysResult updateItem(Item item){itemService.updateItem(item);
       return SysResult.success();}

    iii. 编辑 ItemServiceImpl

    @Override
    @Transactional
    public void updateItem(Item item) {itemMapper.updateById(item);
    }
  6. 商品删除

    i. 业务剖析

    ​ 当用户选中数据之后,点击删除按钮时应该执行删除的操作,利用 MP 的形式实现数据删除,利用手写 SQL 的模式,手动删除数据。

    ​ 1) url: /item/delete;2) 参数:Integer[] ids;3) 页面 JS 的剖析

    ii. 编辑 ItemController

    /* 业务: 商品的删除操作
        url: http://localhost:8091/item/delete
        参数: Integer[] ids
        返回值: SysResult
    
        常识扩大:
         问题: 页面中 <input name="id" value="100"/> 参数是如何承受的, 底层实现是什么?
     客户端 --> Servlet[http 协定]Request 对象 <-- 后端服务器 (取值)req.getParameter("id")
     */
    @RequestMapping("/delete")
    @ResponseBody
    public SysResult deleteItems(Integer[] ids/*,HttpServletRequest req, HttpResponse resp*/){itemService.deleteItems(ids);
        return SysResult.success();}

    iii. 编辑 ItemServiceImpl

    @Override
    @Transactional
    public void deleteItems(Integer[] ids) {//itemMapper.deleteBatchIds(Arrays.asList(ids)); //MP
       itemMapper.deleteItems(Arrays.asList(ids)); // 手写 SQL
    }

    iv. 编辑 ItemMapper(.xml)

    void deleteItems(@Param("ids") List<Integer> ids);
    <!-- 1. 实现商品删除    
         知识点:MyBatis 参数传递问题
         起因: MyBatis 底层实现时通过下标取值
    
         核心思想: 将多值转换为单值
         罕用办法:1. 应用对象封装,2. 能够封装为数组,3.Map 汇合
         1.#{对象的属性},2.array/list,3.#{key}-->
    <delete id="deleteItems" parameterType="list">
       DELETE FROM tb_item
       WHERE id IN
       <foreach collection="ids" separator="," open="(" close=")" item="id">
          #{id}
       </foreach>
    </delete>
  7. 商品上架 / 下架操作

    i. 业务需要

    ​ 当用户点击上架或者下架按钮时,须要动静批改状态信息。要求用一个办法实现。

    ​ 1) url:/item/{instock},/item/{reself};2) 参数:id

    ii. 下架 status=2,上架 status=1

作业:实现商品上架 / 下架操作
退出移动版