第四阶段笔记 Jingtao_day05

元胞沙漏
• 阅读 833

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

作业:实现商品上架/下架操作
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Easter79 Easter79
3年前
sql注入
反引号是个比较特别的字符,下面记录下怎么利用0x00SQL注入反引号可利用在分隔符及注释作用,不过使用范围只于表名、数据库名、字段名、起别名这些场景,下面具体说下1)表名payload:select\from\users\whereuser\_id1limit0,1;!(https://o
Wesley13 Wesley13
3年前
VBox 启动虚拟机失败
在Vbox(5.0.8版本)启动Ubuntu的虚拟机时,遇到错误信息:NtCreateFile(\\Device\\VBoxDrvStub)failed:0xc000000034STATUS\_OBJECT\_NAME\_NOT\_FOUND(0retries) (rc101)Makesurethekern
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Easter79 Easter79
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Stella981 Stella981
3年前
Linux日志安全分析技巧
0x00前言我正在整理一个项目,收集和汇总了一些应急响应案例(不断更新中)。GitHub地址:https://github.com/Bypass007/EmergencyResponseNotes本文主要介绍Linux日志分析的技巧,更多详细信息请访问Github地址,欢迎Star。0x01日志简介Lin