1. 程式人生 > >JavaWeb從新手到入門(五)Spring Mybatis EasyUI實現商品列表

JavaWeb從新手到入門(五)Spring Mybatis EasyUI實現商品列表

參考:《傳智播客-淘淘商城》

一、商品列表功能

商品列表功能是後端維護購物網站的商品的功能,提供了顯示、新增、編輯、刪除、下架和上架功能,顯示如下:


二、顯示功能的實現

開啟查詢商品後,後端首先按照分頁刷新出商品的資訊,因此顯示功能是第一步。

2.1 前端程式碼實現

前端程式碼的實現上主要包括介面顯示和訪問動作兩項。介面顯示採用easyui-datagrid控制元件實現,控制元件的程式碼如下:

<table class="easyui-datagrid" id="itemList" title="商品列表" 
       data-options="singleSelect:false,collapsible:true,pagination:true,url:'/item/list',method:'get',pageSize:30,toolbar:toolbar">
    <thead>
        <tr>
        	<th data-options="field:'ck',checkbox:true"></th>
        	<th data-options="field:'id',width:60">商品ID</th>
            <th data-options="field:'title',width:200">商品標題</th>
            <th data-options="field:'cid',width:100">葉子類目</th>
            <th data-options="field:'sellPoint',width:100">賣點</th>
            <th data-options="field:'price',width:70,align:'right',formatter:TAOTAO.formatPrice">價格</th>
            <th data-options="field:'num',width:70,align:'right'">庫存數量</th>
            <th data-options="field:'barcode',width:100">條形碼</th>
            <th data-options="field:'status',width:60,align:'center',formatter:TAOTAO.formatItemStatus">狀態</th>
            <th data-options="field:'created',width:130,align:'center',formatter:TAOTAO.formatDateTime">建立日期</th>
            <th data-options="field:'updated',width:130,align:'center',formatter:TAOTAO.formatDateTime">更新日期</th>
        </tr>
    </thead>
</table>
控制元件附帶的動作為“GET”,url為“/item/list”,且附帶引數為“page=1&rows=30

頁數隨著資料網格下方的頁碼變化,前端發生翻頁動作時,向後端重新發送請求,這需要後端進行處理。

2.2 後端程式碼實現

與前端程式碼對應,後端需要對“/item/list?page=1&rows=30”的url做出相應,分為如下步驟:

1. 在priv.ality.common中建立pojo物件,用於定義EasyUIDataGrid的資料物件,資料獲取和更新時都會用到。

package priv.ality.utils;

import java.util.List;

public class EasyUIDataGridResult {
    private long total;
    private List<?> rows;
    public long getTotal() {
        return total;
    }
    public void setTotal(long total) {
        this.total = total;
    }
    public List<?> getRows() {
        return rows;
    }
    public void setRows(List<?> rows) {
        this.rows = rows;
    }
}
該類中包含了EasyUIDataGrid中需要用到的資料和資料長度。

2. 在priv.ality.service.ItemService中宣告資料更新方法getItemList

package priv.ality.service;

import priv.ality.pojo.TbItem;
import priv.ality.utils.EasyUIDataGridResult;

import java.util.List;

public interface ItemService {
    TbItem getItemById(Long itemId);
    EasyUIDataGridResult getItemList(int page, int rows);
}
3. 在priv.ality.service.impl.ItemServiceImpl類中新增方法的實現:
@Override
    public EasyUIDataGridResult getItemList(int page, int rows) {
        //分頁處理
        PageHelper.startPage(page, rows);
        //執行查詢
        TbItemExample example = new TbItemExample();
        List<TbItem> list = itemMapper.selectByExample(example);
        //取分頁資訊
        PageInfo<TbItem> pageInfo = new PageInfo<>(list);
        //返回處理結果
        EasyUIDataGridResult result = new EasyUIDataGridResult();
        result.setTotal(pageInfo.getTotal());
        result.setRows(list);

        return result;
    }

該方法使用了PageHelper庫提供Mybatis的分頁功能,並使用EasyUIDataGrid物件作為返回值返回給DataGrid控制元件,由控制元件進行抽取和

4.  在priv.ality.controller中新增對URL“/item/list”的處理
    @RequestMapping("/item/list")
    @ResponseBody
    private EasyUIDataGridResult getItemList(Integer page, Integer rows) {
        return itemService.getItemList(page, rows);
    }
controller中通過呼叫itemService中的getItemList方法提供資料完成功能。

三、新增功能

商品列表除了基本的顯示功能之外,還提供資料的增刪查改,有一個工具欄“商品列表”用以提供快捷操作:


商品列表的原始碼如下:

var toolbar = [{
        text:'新增',
        iconCls:'icon-add',
        handler:function(){ ; }
    },{
        text:'編輯',
        iconCls:'icon-edit',
        handler:function(){ ; }
    },{
        text:'刪除',
        iconCls:'icon-cancel',
        handler:function(){ ; }
    },'-',{
        text:'下架',
        iconCls:'icon-remove',
        handler:function(){ ; }
    },{
        text:'上架',
        iconCls:'icon-remove',
        handler:function(){ ; }
    }];
當前程式碼只包含了顯示樣式,本篇文章只涉及“新增功能"

新增功能與Menu-Tree中的功能保持一致,當點選“新增”按鈕時,頁面跳轉到“新增商品”頁面:


跳轉過程的程式碼(即“商品列表”中“新增”工具的程式碼)如下:

    {
        text:'新增',
        iconCls:'icon-add',
        handler:function(){
        	$(".tree-title:contains('新增商品')").parent().click();
        }
    }
$(".tree-title:contains('新增商品')").parent().click();

如上提供了跳轉到“新增商品”的操作,下面分析該操作。

“新增商品”頁見上,頁面主要實現的內容有:

  • 1. 商品類目的選擇
  • 2. 商品標題、價格和數量的必選項設定
  • 3. 商品圖片的上傳
  • 4. 富文字商品描述

首先給出新增商品頁的佈局程式碼:

<div style="padding:10px 10px 10px 10px">
	<form id="itemAddForm" class="itemForm" method="post">
	    <table cellpadding="5">
	        <tr>
	            <td>商品類目:</td>
	            <td>
	            	<a href="javascript:void(0)" class="easyui-linkbutton selectItemCat">選擇類目</a>
	            	<input type="hidden" name="cid" style="width: 280px;"></input>
	            </td>
	        </tr>
	        <tr>
	            <td>商品標題:</td>
	            <td><input class="easyui-textbox" type="text" name="title" data-options="required:true" style="width: 280px;"></input></td>
	        </tr>
	        <tr>
	            <td>商品賣點:</td>
	            <td><input class="easyui-textbox" name="sellPoint" data-options="multiline:true,validType:'length[0,150]'" style="height:60px;width: 280px;"></input></td>
	        </tr>
	        <tr>
	            <td>商品價格:</td>
	            <td><input class="easyui-numberbox" type="text" name="priceView" data-options="min:1,max:99999999,precision:2,required:true" />
	            	<input type="hidden" name="price"/>
	            </td>
	        </tr>
	        <tr>
	            <td>庫存數量:</td>
	            <td><input class="easyui-numberbox" type="text" name="num" data-options="min:1,max:99999999,precision:0,required:true" /></td>
	        </tr>
	        <tr>
	            <td>條形碼:</td>
	            <td>
	                <input class="easyui-textbox" type="text" name="barcode" data-options="validType:'length[1,30]'" />
	            </td>
	        </tr>
	        <tr>
	            <td>商品圖片:</td>
	            <td>
	            	 <a href="javascript:void(0)" class="easyui-linkbutton picFileUpload">上傳圖片</a>
	                 <input type="hidden" name="image"/>
	            </td>
	        </tr>
	        <tr>
	            <td>商品描述:</td>
	            <td>
	                <textarea style="width:800px;height:300px;visibility:hidden;" name="desc"></textarea>
	            </td>
	        </tr>
	        <tr class="params hide">
	        	<td>商品規格:</td>
	        	<td>
	        		
	        	</td>
	        </tr>
	    </table>
	    <input type="hidden" name="itemParams"/>
	</form>
	<div style="padding:5px">
	    <a href="javascript:void(0)" class="easyui-linkbutton" onclick="submitForm()">提交</a>
	    <a href="javascript:void(0)" class="easyui-linkbutton" onclick="clearForm()">重置</a>
	</div>
</div>

下面依次對四個方面進行實現。

四、新增功能的實現

4.1 商品類目

前端程式碼

商品類目的前端佈局程式碼如下:

                <tr>
	            <td>商品類目:</td>
	            <td>
	            	<a href="javascript:void(0)" class="easyui-linkbutton selectItemCat">選擇類目</a>
	            	<input type="hidden" name="cid" style="width: 280px;"></input>
	            </td>
	        </tr>

該佈局中“選擇商品”的屬性為“easyui-linkbutton”,該按鈕並沒有註冊OnClick事件,而是註冊一個為“selectItemCat”的樣式,該樣式由/js/common.js中,定義如下:

    // 初始化選擇類目元件
    initItemCat : function(data){
    	$(".selectItemCat").each(function(i,e){
    		var _ele = $(e);
    		if(data && data.cid){
    			_ele.after("<span style='margin-left:10px;'>"+data.cid+"</span>");
    		}else{
    			_ele.after("<span style='margin-left:10px;'></span>");
    		}
    		_ele.unbind('click').click(function(){
    			$("<div>").css({padding:"5px"}).html("<ul>")
    			.window({
    				width:'500',
    			    height:"450",
    			    modal:true,
    			    closed:true,
    			    iconCls:'icon-save',
    			    title:'選擇類目',
    			    onOpen : function(){
    			    	var _win = this;
    			    	$("ul",_win).tree({
    			    		url:'/item/cat/list',
    			    		animate:true,
    			    		onClick : function(node){
    			    			if($(this).tree("isLeaf",node.target)){
    			    				// 填寫到cid中
    			    				_ele.parent().find("[name=cid]").val(node.id);
    			    				_ele.next().text(node.text).attr("cid",node.id);
    			    				$(_win).window('close');
    			    				if(data && data.fun){
    			    					data.fun.call(this,node);
    			    				}
    			    			}
    			    		}
    			    	});
    			    },
    			    onClose : function(){
    			    	$(this).window("destroy");
    			    }
    			}).window('open');
    		});
    	});
    },
該樣式類selectItemCat使用each對所有繫結該事件的樣式迴圈初始化,在該類首先對click事件進行解綁,然後繫結方法function:
                      $("<div>").css({padding:"5px"}).html("<ul>")
    			.window({
    				width:'500',
    			    height:"450",
    			    modal:true,
    			    closed:true,
    			    iconCls:'icon-save',
    			    title:'選擇類目',
    			    onOpen : function(){
    			    	var _win = this;
    			    	$("ul",_win).tree({
    			    		url:'/item/cat/list',
    			    		animate:true,
    			    		onClick : function(node){
    			    			if($(this).tree("isLeaf",node.target)){
    			    				// 填寫到cid中
    			    				_ele.parent().find("[name=cid]").val(node.id);
    			    				_ele.next().text(node.text).attr("cid",node.id);
    			    				$(_win).window('close');
    			    				if(data && data.fun){
    			    					data.fun.call(this,node);
    			    				}
    			    			}
    			    		}
    			    	});
    			    },
    			    onClose : function(){
    			    	$(this).window("destroy");
    			    }
    			}).window('open');
該動作建立並開啟一個模態視窗,該視窗的開啟動作中進行AJAX請求向伺服器請求資料,並將資料填充到easy-ui的非同步樹形控制元件中,設定url為'/item/cat/list',這也需要伺服器端對該URL進行相應。

easy-ui中的非同步tree控制元件初始化時首先讀取當前樹的節點,當展開一個封閉的節點時如果節點未曾載入,則在url中新增請求引數:節點ID,然後向伺服器發起請求,伺服器端進行相應時為JSON資料,且具備結構要求:

[{    
    "id": 1,    
    "text": "Node 1",    
    "state": "closed"
 }
{    
    "id": 2,    
    "text": "Node 2",    
    "state": "closed"
 }
]

state的值要求如下:如果當前節點為父節點,state應為“closed”、如果是葉子節點則應該為“open”。

前端程式碼分析完畢,對於JQuery的API熟練度不夠,還沒發自己寫出來一個=_=!

後端程式碼

1. 建立EasyUITreeNode這個pojo物件

EasyUITreeNode用於定義樹形節點的各個節點資料,由於類比較基礎,放置在ality-common工程中:

public class EasyUITreeNode {

	private long id;
	private String text;
	private String state;
	public long getId() {
		return id;
	}
	public void setId(long id) {
		this.id = id;
	}
	public String getText() {
		return text;
	}
	public void setText(String text) {
		this.text = text;
	}
	public String getState() {
		return state;
	}
	public void setState(String state) {
		this.state = state;
	}
}
2. 建立ItemCatService介面,代表商品新增相關的服務
package priv.ality.service;

import priv.ality.utils.EasyUITreeNode;

import java.util.List;

public interface ItemCatService {
    public List<EasyUITreeNode> getItemCatList(long parentId);
}

該服務的方法getItemCatList使用引數parentId對應前端分析的url中帶來的引數,返回值為EasyUITreeNode的List物件。

3. 建立該介面的實現ItemCatServiceImpl:
package priv.ality.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import priv.ality.mapper.TbItemCatMapper;
import priv.ality.pojo.TbItemCat;
import priv.ality.pojo.TbItemCatExample;
import priv.ality.service.ItemCatService;
import priv.ality.utils.EasyUITreeNode;

import java.util.ArrayList;
import java.util.List;

public class ItemCatServiceImpl implements ItemCatService {
    @Autowired
    private TbItemCatMapper itemCatMapper;

    @Override
    public List<EasyUITreeNode> getItemCatList(long parentId) {
        // 根據parentId查詢分類列表
        TbItemCatExample example = new TbItemCatExample();
        //設定查詢條件
        TbItemCatExample.Criteria criteria = example.createCriteria();
        criteria.andParentIdEqualTo(parentId);
        //執行查詢
        List<TbItemCat> list = itemCatMapper.selectByExample(example);
        //轉換成EasyUITreeNode列表
        List<EasyUITreeNode> resultList = new ArrayList<>();
        for (TbItemCat tbItemCat : list) {
            //建立一個節點物件
            EasyUITreeNode node = new EasyUITreeNode();
            node.setId(tbItemCat.getId());
            node.setText(tbItemCat.getName());
            node.setState(tbItemCat.getIsParent()?"closed":"open");
            //新增到列表中
            resultList.add(node);
        }
        return resultList;
    }
}
該實現中使用Example物件和Criteria物件設定查詢條件,獲取了ParentId等於入參的所有結果,並按照非同步Tree要求的格式進行封裝後返回結果。

4. 在Controller中新增方法接受引數並返回結果(JSON資料)。

package priv.ality.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import priv.ality.service.ItemCatService;
import priv.ality.utils.EasyUITreeNode;

import java.util.List;

@Controller
@RequestMapping("/item/cat")
public class ItemCatController {
    @Autowired
    private ItemCatService itemCatService;

    @RequestMapping("/list")
    @ResponseBody
    public List<EasyUITreeNode> getItemCatList(@RequestParam(value="id",defaultValue = "0")Long parentId){
        return itemCatService.getItemCatList(parentId);
    }
}
功能完成結果如下:


如上可見,商品類目選擇功能已經得到實現。

ps:入職新公司,技術棧發生變更,由JavaWeb轉大資料方向,語言轉向Ruby和Node.js,所以下面就暫時暫停更新這個系列的文章啦,有的閒工夫再來~