1. 程式人生 > >電商專案day03(前端分層開發&規格實現)

電商專案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);
}