电商项目day03(前端分层开发&规格实现)

今日目标:

    理解前端分层开发
    实现控制器继承
    能够使用mybatis逆向工程生成dao层代码
    完成规格管理功能

一、js代码重构

首先介绍javaee的三层架构:   最重要的目的就是解耦

         web  接收请求,处理响应
        service  处理业务逻辑
        dao  数据处理

前端开发我们也可以进行分层开发,分为controller层,service层

        controller:控制器,封装和处理数据
        service:服务层,与后端进行请求交互。
        好处:代码逻辑职责更明确,代码复用性更强

这样做的好处是代码分离了,代码的复用性也提高了。

java种代码抽取的方案如下:

1、工具类              2、继承                   3、AOP面向切面编程

在前端开发有控制器继承

    伪继承:实现思路是,共享$scope变量

前端代码的抽取过程如下:

1、自定义服务,将之前所有请求后台的代码抽取出来

自定义一个brandService模块抽取方法如下:

//自定义服务
        app.service('brandService',function ($http) {
            定义查询所有品牌列表的方法
            this.findAll=function () {
                return $http.get("../brand/findAll.do");
            }
            //条件查询和分页展示
            this.reloadList=function (pageNum,pageSize,searchEntity) {
                return $http.post("../brand/search.do?pageNum="+pageNum+"&pageSize="+pageSize,
                    searchEntity);
            }
            //添加和修改
            this.add=function (entity) {
                return $http.post("../brand/add.do",entity);
            }
            //修改
            this.update=function (entity) {
                return $http.post("../brand/update.do",entity);
            }
            //通过id查找
            this.findOne=function (id) {
                return $http.get("../brand/findOne.do?id="+id);
            }
            //删除
            this.delete=function (selectIds) {
                return $http.get("../brand/delete.do?ids="+selectIds);
            }


        })

2、创建controller层和service层,baseController.js   对js代码进行抽取,这样做的好处是,后期维护方便,便于维护

代码抽取完成如图所示;

二、mybatis逆向工程

逆向工程生成代码分析
    生成的DAO层接口中有:根据主键查询、修改、删除等,根据条件进行增删改查操作
    XXXExample 封装条件的对象  查询、删除、更新

三、规格管理

1.分页显示+条件查询(通过规格的specName)通过

       分析:这个功能和上次的品牌表的设计是一样的

 后台实现:

通过search方法传递三个参数(TbSpecification  pageNum  pageSize),通过mybatis生成自动生成的方法,进行封装,通过查询的结果分装给pageResult()

前台实现:定义search方法,通过angularjs的内置服务,实现发送请求

后台核心代码:

 public PageResult findPage(TbSpecification specification, Integer pageNum, Integer pageSize) {
        //分页的实现
        PageHelper.startPage(pageNum,pageSize);

        TbSpecificationExample example = new TbSpecificationExample();
        TbSpecificationExample.Criteria criteria = example.createCriteria();

        //判断
        if(specification!=null){
            String specName = specification.getSpecName();
            if(specName!=null&&!"".equals(specName)){
                //模糊查询
                criteria.andSpecNameLike("%"+specName+"%");
            }
        }
        Page<TbSpecification> pageResult = (Page) specificationMapper.selectByExample(example);
        return new PageResult(pageResult.getTotal(),pageResult.getResult());
    }

前台核心代码:

controller层 
//条件查询和分页展示
    $scope.searchEntity={};//解决初始化参数为空的情况
    $scope.search=function (pageNum,pageSize) {
        specificationService.search($scope.searchEntity,pageNum,pageSize).success(function (response) {
            $scope.paginationConf.totalItems=response.total;
            $scope.list=response.rows;
        })
    }
service层
     //条件查询和分页展示
    this.search=function (searchEntity,pageNum,pageSize) {
        return $http.post("../specification/search.do?pageNum="+pageNum+"&pageSize="+pageSize,searchEntity);
    }
//specification.html
<tbody>
			                          <tr ng-repeat="pojo in list">
			                              <td><input  type="checkbox" ></td>			                              
				                          <td>{{pojo.id}}</td>
									      <td>{{pojo.specName}}</td>
		                                  <td class="text-center">                                           
		                                 	  <button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal">修改</button>                                           
		                                  </td>
			                          </tr>
			                      </tbody>

2.添加功能的实现(注意关联规格选项表)

分析:我们要把两个表的数据一起提交到数据库,那么有两种方法,第一种就是在specification表中添加一个规格选项表的list集合,第二种是,自定义一个组合实体类,用于封装两个表的数据,用户保存我们传过来的两个对象.

我们采用第二种方法进行封装数据.

后台:组装数据,并保存,注意,我们通过规格插入数据,必须返回插入的id值,此时我们通过获取的id值,去关联插入规格选项表中.

前台:在保存上添加点击事件,获得保存,注意新增选项格和删除选项格的实现?

后台代码实现:

//controlelr层
//添加
    @RequestMapping("/add")
    public Result add(@RequestBody Specification specification){
        try {
            specificationService.add(specification);
            return new Result(true,"添加成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false,"添加失败");
        }
    }
service层
//添加的实现
    @Override
    public void add(Specification specification) {
        //获取specification对象
        TbSpecification specification1 = specification.getSpecification();
        specificationMapper.insert(specification1);
        //获取specification的id 值
        Long id = specification1.getId();
        //循环添加
        List<TbSpecificationOption> specificationOptions = specification.getSpecificationOptions();
        for (TbSpecificationOption specificationOption : specificationOptions) {
            //关联id
            specificationOption.setSpecId(specification1.getId());
            specificationOptionMapper.insert(specificationOption);
        }
    }
//注意我们要在插入specification表的时候,返回插入的id值,这样我们就可通过id值,关联插入规格选项表
<insert id="insert" parameterType="com.pinyougou.pojo.TbSpecification" >

    /*添加插入返回的id值*/
    <selectKey resultType="java.lang.Long" order="AFTER" keyProperty="id">
        select last_insert_id() as id
    </selectKey>
    insert into tb_specification (id, spec_name)
    values (#{id,jdbcType=BIGINT}, #{specName,jdbcType=VARCHAR})
  </insert>

前台代码实现:

//controller层
 //初始化对象
    $scope.entity={specificationOptions:[]};
    //添加行
    $scope.addRow=function () {
        $scope.entity.specificationOptions.push({});
    }
    //删除规格选项
    $scope.deleRow=function (index) {
        $scope.entity.specificationOptions.splice(index,1);
    }
//注意在这有个非常重要操作,就是初始化对象,如果不出初始化对象
//添加是我们实体类是一个组装的
//添加
    $scope.save=function () {
        //定义一个变量
        var method=null;
        if($scope.entity.specification.id!=null){
            //修改
            method=specificationService.update($scope.entity);
        }else{
            //新增
            method=specificationService.add($scope.entity);
        }
        method.success(function (response) {
            if (response.success){
                //添加成功
                $scope.reloadList();
            }else{
                //不成功
                alert(response.message);
            }
        })
    }
//页面

<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="specificationController">
  <!-- .box-body -->                
                    <div class="box-header with-border">
                        <h3 class="box-title">规格管理</h3>
                    </div>
                    <div class="box-body">
                        <!-- 数据表格 -->
                        <div class="table-box">

                            <!--工具栏-->
                            <div class="pull-left">
                                <div class="form-group form-inline">
                                    <div class="btn-group">
                                        <button type="button" ng-click="entity={specificationOptions:[]}" class="btn btn-default" title="新建" data-toggle="modal" data-target="#editModal" ><i class="fa fa-file-o"></i> 新建</button>
                                        <button type="button" class="btn btn-default" title="删除" ><i class="fa fa-trash-o"></i> 删除</button>
                                        
                                        <button type="button" class="btn btn-default" title="刷新" onclick="window.location.reload();"><i class="fa fa-refresh"></i> 刷新</button>
                                    </div>
                                </div>
                            </div>
                            <div class="box-tools pull-right">
                                <div class="has-feedback">
							                    规格名称:<input  ng-model="searchEntity.specName">
									<button class="btn btn-default" ng-click="reloadList()" >查询</button>
                                </div>
                            </div>
                            <!--工具栏/-->
			                  <!--数据列表-->
			                  <table id="dataList" class="table table-bordered table-striped table-hover dataTable">
			                      <thead>
			                          <tr>
			                              <th class="" style="padding-right:0px">
			                                  <input id="selall" type="checkbox" class="icheckbox_square-blue">
			                              </th> 
										  <th class="sorting_asc">规格ID</th>
									      <th class="sorting">规格名称</th>									     												
					                      <th class="text-center">操作</th>
			                          </tr>
			                      </thead>
			                      <tbody>
			                          <tr ng-repeat="pojo in list">
			                              <td><input  type="checkbox" ></td>			                              
				                          <td>{{pojo.id}}</td>
									      <td>{{pojo.specName}}</td>
		                                  <td class="text-center">                                           
		                                 	  <button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal">修改</button>                                           
		                                  </td>
			                          </tr>
			                      </tbody>
			                  </table>
			                  <!--数据列表/-->
							<!--分页工具条展示-->
							<tm-pagination conf="paginationConf"></tm-pagination>
                        </div>
                        <!-- 数据表格 /--> 
                     </div>
                    <!-- /.box-body -->                    
	          		    
                                
<!-- 编辑窗口 -->
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog" >
	<div class="modal-content">
		<div class="modal-header">
			<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
			<h3 id="myModalLabel">规格编辑</h3>
		</div>
		<div class="modal-body">							
			
			<table class="table table-bordered table-striped"  width="800px">
		      	<tr>
		      		<td>规格名称</td>
		      		<td><input  class="form-control" ng-model="entity.specification.specName" placeholder="规格名称" >  </td>
		      	</tr>
			 </table>				
			 
			 <!-- 规格选项 -->
			 <div class="btn-group">
                  <button type="button" ng-click="addRow()" class="btn btn-default" title="新建" ><i class="fa fa-file-o"></i> 新增规格选项</button>
                  
             </div>
			 
			 <table class="table table-bordered table-striped table-hover dataTable">
                    <thead>
                        <tr>
                          
					 
				      <th class="sorting">规格选项</th>
				      <th class="sorting">排序</th>																
                      <th class="sorting">操作</th>	
                    </thead>
                    <tbody>
                      <tr ng-repeat="option in entity.specificationOptions">
                           
				            <td>
				            	<input ng-model="option.optionName" class="form-control" placeholder="规格选项">
				            </td>
				            <td>
				            	<input ng-model="option.orders" class="form-control" placeholder="排序">
				            </td>
							<td>
								<button type="button" ng-click="deleRow($index)" class="btn btn-default" title="删除" ><i class="fa fa-trash-o"></i> 删除</button>
							</td>
                      </tr>

                    </tbody>
			  </table> 
			
			
		</div>
		<div class="modal-footer">						
			<button class="btn btn-success" ng-click="save()" data-dismiss="modal" aria-hidden="true">保存</button>
			<button class="btn btn-default" data-dismiss="modal" aria-hidden="true">关闭</button>
		</div>
	  </div>
	</div>
</div>    

</body>

</html>

删除选项格子时,我们通过一个内置对象获取当前index
        ng-click="deleRow($index)"
        注意:在添加时,我们先要获取tb_specification表的添加的id,然后返回id,我们通过设置tb_specificationOptions
        的specificationOption.setSpecId(spe.getId());*******特别注意

注意的问题:后端实现的时候,记得返回插入的id值,要在mapper文件中添加<selectkey>标签返回id值

前台:我们组装信息的时候,注意实体类的初始化

2.修改功能的实现

分析:修改我们实现两个功能,第一个功能:页面回显的问题,第二个问题:修改的时候,我们如何把修改的规格选项保存,原因是这样的,因为可能有添加了行,或者删除了行,所以解决的方法就是删除以前所有的,然后从新添加

后台:通过findOne(id) 返回前天需要显示的信息     修改的时候,我们在service层,删除以前该id的规格选项,然后在添加

前台:页面的回显,绑定数据,

后台核心代码:

 @Override
    public Specification findOne(Long id) {
        //首先获取组合实体类
        Specification specification = new Specification();
        //获取规格数据
        TbSpecification tbSpecification = specificationMapper.selectByPrimaryKey(id);
        specification.setSpecification(tbSpecification);
        //获取规格id
        Long id1 = tbSpecification.getId();

        TbSpecificationOptionExample example = new TbSpecificationOptionExample();
        TbSpecificationOptionExample.Criteria criteria = example.createCriteria();
        criteria.andSpecIdEqualTo(id1);
        List<TbSpecificationOption> specificationOptions =  specificationOptionMapper.selectByExample(example);
        specification.setSpecificationOptions(specificationOptions);
        return specification;
    }

    @Override
    public void update(Specification specification) {
        //修改规格名称
        TbSpecification spec = specification.getSpecification();
        specificationMapper.updateByPrimaryKey(spec);
        Long id = spec.getId();
        //获取规格选项
        List<TbSpecificationOption> specificationOptions = specification.getSpecificationOptions();
        //先删除出,后提交数据
        TbSpecificationOptionExample example = new TbSpecificationOptionExample();
        TbSpecificationOptionExample.Criteria criteria = example.createCriteria();
        criteria.andIdEqualTo(id);
        specificationOptionMapper.deleteByExample(example);
        for (TbSpecificationOption specificationOption : specificationOptions) {
            //设置id
            specificationOption.setSpecId(id);
            //添加
            specificationOptionMapper.insert(specificationOption);
        }
    }

前台代码:

//通过id查找
    @RequestMapping("/findOne")
    public Specification findOne(Long id){
        return specificationService.findOne(id);
    }
    //修改
    @RequestMapping("/update")
    public Result update(@RequestBody Specification specification){
        try {
            specificationService.update(specification);
            return new Result(true,"修改成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false,"修改失败");
        }
    }
//传入id值,返回specification组合实体类
 <button type="button" ng-click="findOne(pojo.id)" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal">修改</button>

3.批量删除的实现

分析:技术难点,如何通过点击复选框,改变复选框的状态  ,我们通过前台封装ids数组,送到后台,然后通过循环删除规格选项表

后台:通过ids循环删除

前台:数组的组装,还有复选框的添加和删除,要通过angularjs的内置对象传递参数

后台代码:

 @Override
    public void delete(Long[] ids) {
        for (Long id : ids) {
            specificationOptionMapper.deleteByPrimaryKey(id);
            TbSpecificationOptionExample example = new TbSpecificationOptionExample();
            TbSpecificationOptionExample.Criteria criteria = example.createCriteria();
            criteria.andSpecIdEqualTo(id);
            specificationOptionMapper.deleteByExample(example);
        }
    }

前台代码:

//注意当我们点击复选框时,我们需要跟新复选框的状态
//定义复选框ids数组值
    $scope.selectIds=[];
//跟新复选框状态
    $scope.updateSelection=function ($event,id) {
        //判断  选中的状态
        if($event.target.checked){
            //选中状态
            $scope.selectIds.push(id);
        }else{
            //取消勾选,移除当前的id值,//参数一:移除当前位置的索引值,参数二:从该处移除几个值
            var index = $scope.selectIds.indexOf(id);
            $scope.selectIds.splice(index,1);
        }
    }

//controller层
 //删除
    $scope.delete=function () {
        if (confirm("您确定要删除吗")){
            specificationService.delete($scope.selectIds).success(function (response) {
                if (response.success){
                    //删除成功
                    $scope.reloadList();
                }else{
                    //删除失败
                    //给提示消息
                    alert(response.message);
                }

            })
        }
    }
//service层
//删除
    this.delete=function (selectIds) {
        return $http.get("../specification/delete.do?ids="+selectIds);
    }
//页面
<tr ng-repeat="pojo in list">
			                              <td><input  type="checkbox"  ng-click="updateSelection($event,pojo.id)"></td>
				                          <td>{{pojo.id}}</td>
									      <td>{{pojo.specName}}</td>
		                                  <td class="text-center">                                           
		                                 	  <button type="button" ng-click="findOne(pojo.id)" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal">修改</button>
		                                  </td>
			                          </tr>

注意:一定细心,思路清晰

四、常见错误

1.添加出现的问题

这个问题是我们未初始化实体变量    解决方法;

//初始化对象
$scope.entity={specificationOptions:[]};

原因是这个:

解决方法:进行初始化      

ng-click="entity={specificationOptions:[]}"

一定要注意变量的初始化

五、总结

添加过程中,出现两张表的添加,我们要封装一个实体类,进行存,注意存的时候返回插入的规格的id,以便于我们根据id插入规格选项表

前端主要是$(index) 这个是angularjs的内置服务   传入当前index值

($(event),pojo)传入的事件,通过这个实现复选框的添加和删除

非常重要:

//初始化对象
$scope.entity={specificationOptions:[]};
//添加行
$scope.addRow=function () {
    $scope.entity.specificationOptions.push({});
}
//删除规格选项
$scope.deleRow=function (index) {
    $scope.entity.specificationOptions.splice(index,1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗的小巍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值