如何做一個電商系統(tǒng)(二)

1.如何做一個電商系統(tǒng)

1.1.目標(biāo)

需求:完成商品添加業(yè)務(wù)。

第一步:理解商品模塊的業(yè)務(wù)(通過ER圖理解)

考核的知識點,通過數(shù)據(jù)庫結(jié)構(gòu)快速生成ER圖。同自己的理解畫好關(guān)系。

問題:為什么數(shù)據(jù)庫表不建外鍵約束?

答:外鍵約束確保了數(shù)據(jù)的完整性,但是也約束數(shù)據(jù)的靈活性。如果將外鍵在數(shù)據(jù)里創(chuàng)建,不適合需求多變的項目。

第二步:查詢商品類目(以樹形結(jié)構(gòu)顯示,UI設(shè)計的要求)

考核的知識點,就是如何封裝一個樹狀的數(shù)據(jù)結(jié)構(gòu)。

第三步:實現(xiàn)圖片的上傳(要求:上傳到指定的FTP服務(wù)器)

考核的知識點:

1. Linux系統(tǒng)的使用

2. tengine 純HTTP的web服務(wù)器

3. SpringMVC的上傳功能

4. FTP的數(shù)據(jù)傳到

第四步:設(shè)置類目的參數(shù)規(guī)格模板

考核的知識點:JSON數(shù)據(jù)格式轉(zhuǎn)換。

第五步:商品的保存

考核的知識點:使用MybatisPlus插入數(shù)據(jù)

1.2.功能分析

1.2.1.相關(guān)數(shù)據(jù)表

說明:與商品模塊有關(guān)的表,總共有5張。關(guān)系如下:

image.png

1.2.2.實現(xiàn)的思路

(1)每個商品都有一個分類,所以要實現(xiàn)商品類目選擇功能。

(2)商品有一個圖片屬性,所以要實現(xiàn)圖片上傳的功能。

(3)每個商品都有規(guī)格參數(shù),所以要實現(xiàn)商品規(guī)格參數(shù)編輯功能。

(4)將商品的規(guī)格參數(shù)、商品詳情、商品信息分別保存到三張表中。

2.第一部分:實現(xiàn)商品類目選擇功能

2.1.需求分析

在商品頁面,點擊”選擇類目”按鈕,生成商品類目異步樹。

image.png

對應(yīng)的數(shù)據(jù)庫表為tb_item_cat,表結(jié)構(gòu)為:

image.png

實現(xiàn)的思路:

業(yè)務(wù)理解:在加載樹控件的時候,將所有頂級的類目顯示出來。所以的子節(jié)點在展開的時候傳入節(jié)點對應(yīng)的類目編號(ID),查詢對應(yīng)的類目數(shù)據(jù)。

根據(jù)業(yè)務(wù)理解:

(1)加載樹控件。(本項目使用的是easyui-tree插件,第一次傳遞的cid=0)

(2)確定異步樹請求的參數(shù)及返回的節(jié)點結(jié)構(gòu)。(要構(gòu)建easyui-tree對應(yīng)的業(yè)務(wù)模型VO,id、text、status)

(3)請求數(shù)據(jù)庫,生成樹結(jié)構(gòu)。(根據(jù)parent_id字段查詢子節(jié)點實現(xiàn)。)

2.2.實現(xiàn)步驟

2.2.1.第一步:加載樹控件

(1)定義類目選擇的按鈕。(點擊按鈕,加載異步樹控件)

image.png

(2)加載異步樹控件

image.png

查看EasyUI的API文檔,我們知道:url是請求路徑。

image.png

2.2.2.第二步:確定加載樹請求的參數(shù)

查看API文檔,我們知道請求的參數(shù)名是id,是當(dāng)前節(jié)點的id值。

image.png

2.2.3.第三步:確定樹節(jié)點結(jié)構(gòu)

查看API文檔,節(jié)點包括id、text、state三個基本屬性。

image.png

2.2.4.第四步:java代碼實現(xiàn)異步樹

2.2.4.1.Step1:代碼結(jié)構(gòu)

Controller:負(fù)載從頁面接收節(jié)點的id,返回該節(jié)點的所有子節(jié)點;

Service:實現(xiàn)查詢邏輯,根據(jù)父節(jié)點id,查詢所有的子節(jié)點

Mapper:基于BASEMapper實現(xiàn)

2.2.4.2.Step2:請求響應(yīng)格式

<colgroup><col style="width: 130px;"><col style="width: 358px;"></colgroup>
請求路徑      /item/cat/list
請求參數(shù)      id=nodeId(首次加載生成一級目錄時,默認(rèn)id=0)
響應(yīng)格式      {“id”:”1”  “text”:”node1”  “state”:”open}

2.2.4.3.Step3:創(chuàng)建EUTreeNode類

在ego-base工程中創(chuàng)建。

//自定義異步樹節(jié)點結(jié)構(gòu)

public class EUTreeNode {

    private long id;

    private String text;

    private String state;

     //補全get、set方法

}

2.2.4.4.Step4:創(chuàng)建ItemCat類

--在ego-base中創(chuàng)建

@TableName(value="tb_item_cat")     

public class ItemCat {

    @TableId(value="id",type=IdType.AUTO)

    private Long id;

    @TableField(value="parent_id")

    private Long parentId;

    private String name;

    private int status;

    @TableField(value="sort_order")

    private int sortOrder;

    @TableField(value="is_parent")

    private byte isParent;

    private Date created;

    private Date updated;

    public ItemCat() {

       super();

    }

    public Long getId() {

       return id;

    }

    // 補全get、set方法

}

2.2.4.5.Step5:創(chuàng)建ItemCatMapper接口

--在ego-base中創(chuàng)建

package cn.gzsxt.base.mapper;     

import com.baomidou.mybatisplus.mapper.BaseMapper;

import cn.gzsxt.base.pojo.ItemCat;

public interface ItemCatMapper extends BaseMapper<ItemCat>{

}

2.2.4.6.Step6:創(chuàng)建ItemCatService接口及實現(xiàn)類

在ego-manager項目中創(chuàng)建。

package cn.gzsxt.manager.service.impl;     

import java.util.ArrayList;

import java.util.List;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;

import cn.gzsxt.base.mapper.ItemCatMapper;

import cn.gzsxt.base.pojo.ItemCat;

import cn.gzsxt.base.vo.EUTreeNode;

import cn.gzsxt.manager.service.ItemCatService;

@Service

public class ItemCatServiceImpl extends ServiceImpl<ItemCatMapper,      ItemCat> implements ItemCatService{

    @Override

    public List<EUTreeNode> getByParentId(Long parentId) {

       List<EUTreeNode> nodes = new ArrayList<>();

       EntityWrapper<ItemCat> ew = new EntityWrapper<>();

       ew.eq("parent_id", parentId);

       List<ItemCat> selectList = selectList(ew);

       EUTreeNode node = null;

       for (ItemCat itemCat : selectList) {

           node = new EUTreeNode();

           node.setId(itemCat.getId());

           node.setText(itemCat.getName());

           if(1==itemCat.getIsParent()){

              node.setState("closed");

           }else{

              node.setState("open");

           }

           nodes.add(node);

       }

       return nodes;

    }

}

2.2.4.7.Step7:創(chuàng)建ItemCatController類

package cn.gzsxt.manager.controller;     

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.bind.annotation.ResponseBody;

import cn.gzsxt.common.pojo.EUTreeNode;

import cn.gzsxt.manager.service.ItemCatService;

@Controller

@RequestMapping("/item/cat")

public class ItemCatController {

    @Autowired

    private ItemCatService catService;

    @RequestMapping(value="/list")

    @ResponseBody

    public List<EUTreeNode>      initTreeByParentId(@RequestParam(defaultValue="0")Long id){

       List<EUTreeNode> list = catService.getByParantId(id);

       return list;

    }

}

2.3.保存類目id到頁面表單

說明:當(dāng)點擊葉子節(jié)點時,將該節(jié)點的id值,保存到頁面表單中。

image.png

類目id的值,保存在頁面表單的位置:

image.png

3.第二部分:實現(xiàn)商品圖片上傳功能

3.1.傳統(tǒng)上傳方式的問題

在傳統(tǒng)上傳方式中,在項目的跟目錄下創(chuàng)建upload目錄,將圖片上傳到tomcat服務(wù)器中。

image.png

但是在分布式環(huán)境下,是有多個Tomcat存在的,當(dāng)把圖片直接上傳到Tomcat服務(wù)器時,容易出現(xiàn)圖片丟失的問題。

image.png

3.2.分布式系統(tǒng)圖片上傳方案

3.2.1.思路分析

直接將圖片上傳到一個指定的目錄,訪問、下載圖片都訪問這個目錄。

由于項目最終是要部署到Linux環(huán)境,所以直接將圖片上傳到Linux服務(wù)器。

image.png

問題:那如何將圖片上傳到Linux呢?

答:使用vsftpd組件,實現(xiàn)文件傳輸。

3.2.2.vsftpd簡介

問題1:vsftpd是什么?

答:ftp(File Transfer Protocol)文件傳輸協(xié)議。(實現(xiàn)不同操作系統(tǒng)之間文件的傳輸??

vsftpd是一個基于ftp協(xié)議的文件傳輸服務(wù)器軟件。

問題2:vsftpd作用是什么?

答:傳輸文件的文件服務(wù)器。(跨平臺、跨操作系統(tǒng))

問題3:如何使用?

答:服務(wù)端:在linux安裝vsftpd軟件,開啟服務(wù)。

客戶端:通過FtpClient客戶端建立和服務(wù)器的連接,向服務(wù)器發(fā)送請求。

3.3.實現(xiàn)步驟說明

(1)在Linux上安裝vsftpd服務(wù)。

(2)根據(jù)圖片的地址訪問圖片。(最終保存到數(shù)據(jù)庫的是圖片的路徑)

(3)web工程中實現(xiàn)圖片上傳。

3.4.實現(xiàn)步驟

3.4.1.第一部分:在Linux上部署vsftpd服務(wù)

思路 :(1)安裝軟件

(2)測試服務(wù)是否可用

3.4.1.1.第一步:安裝vsftpd軟件

[root@node0719 ~]# yum -y install vsftpd

3.4.1.2.第二步:關(guān)閉匿名訪問

修改vsftpd配置文件 vim /etc/vsftpd/vsftpd.conf

image.png

3.4.1.3.第三步:添加一個FTP用戶

創(chuàng)建一個用戶,專門用來訪問vsftpd服務(wù)。

[root@node0719 ~]# useradd ftpuser     

[root@node0719 ~]# passwd ftpuser

3.4.1.4.第四步:設(shè)置防火墻

vsftpd服務(wù)默認(rèn)端口號為21,修改防火墻,開放此端口,重啟防火墻。

[root@node0719 ~]# vim /etc/sysconfig/iptables     

[root@node0719 ~]# service iptables restart
        12.第五步:修改selinux(Linux安全內(nèi)核系統(tǒng))

(1)先查看selinux,默認(rèn)是禁用了ftp訪問的。

[root@bogon ~]# getsebool -a | grep ftp       

allow_ftpd_anon_write --> off

allow_ftpd_full_access --> off

allow_ftpd_use_cifs --> off

allow_ftpd_use_nfs --> off

ftp_home_dir --> off

ftpd_connect_db --> off

ftpd_use_passive_mode --> off

httpd_enable_ftp_server --> off

tftp_anon_write --> off

(2)修改selinux,開放ftp訪問權(quán)限

[root@bogon ~]# setsebool -P allow_ftpd_full_access on     

[root@bogon ~]# setsebool -P ftp_home_dir on
        13.第六步:啟動vsftpd服務(wù)
[root@node0719 vsftpd]# service vsftpd start

為 vsftpd 啟動 vsftpd: [確定]

        14.第七步:通過瀏覽器訪問測試

訪問地址:ftp://192.168.23.12:21,發(fā)現(xiàn)無法訪問。

原因:被動模式下,數(shù)據(jù)傳輸服務(wù)被防火墻攔截了。

(1)被動模式

第二次請求過程中,客戶端跟服務(wù)端建立數(shù)據(jù)通道;

服務(wù)端被動將數(shù)據(jù)響應(yīng)給客戶端。

第二次請求數(shù)據(jù)傳輸,會隨機生成一個服務(wù)端口。被防火墻禁用。

image.png

(2)主動模式

服務(wù)端主動向客戶端發(fā)送數(shù)據(jù),會被客戶端的防火墻禁掉。

多數(shù)客戶端不支持主動模式,不安全。

image.png

3.4.1.8.第八步:配置被動模式

(1)編輯/etc/vsftpd/vsftpd.conf文件

[root@bogon ~]# vim /etc/vsftpd/vsftpd.conf

(2)添加防火墻范圍設(shè)置(在文件尾部添加即可):

pasv_min_port=30000

pasv_max_port=30999

(3)修改防火墻,開啟30000:30999之間所有的端口。

(4)重啟防火墻。

(5)重啟vsftpd服務(wù)

image.png

再次訪問瀏覽器,發(fā)現(xiàn)可以正常連接了。

image.png

3.4.1.9.第九步:java代碼測試上傳功能

Java代碼中,是通過FtpClient客戶端建立和服務(wù)端的連接的。在ego-base工程中測試。

(1)在ego-base中添加ftp服務(wù)的依賴。

<dependency>     

       <groupId>commons-net</groupId>

       <artifactId>commons-net</artifactId>

</dependency>

(2)創(chuàng)建測試類

說明:使用ftpuser用戶上傳。指定上從目錄/home/ftpuser/ego/images

注意:為了保證ftpuser有這個目錄下的寫權(quán)限,我們要用ftpuser用戶創(chuàng)建這個目錄。

su命令:切換用戶

[root@node0719 ~]#su ftpuser     

[ftpuser@node0719 ~]#mkdir -p /home/ftpuser/ego/images

測試類TestFtp

package cn.gzsxt.manager.test;     

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.net.SocketException;

import org.apache.commons.net.ftp.FTP;

import org.apache.commons.net.ftp.FTPClient;

public class TestFtp {

    static String baseUrl = "/home/ftpuser/ego/images";

    public static void main(String[] args) {

       //1、建立和服務(wù)端的連接

       FTPClient client = new FTPClient();

       try {

           client.connect("192.168.23.12", 21);

           //2、身份認(rèn)證

           client.login("ftpuser", "ftpuser");

           //3、指定源文件

           File file = new File("F:\\圖片\\5b7a8115N89613314.jpg");

           InputStream local = new FileInputStream(file);

           //4、指定文件上傳的方式   二進(jìn)制字節(jié)碼

           client.setFileType(FTP.BINARY_FILE_TYPE);

           //5、指定上傳目錄  默認(rèn)是/home/ftpuser,即ftpuser用戶的家目錄

           // 切換到ftpuser用戶來創(chuàng)建目錄。          /home/ftpuser/ego/images/

           client.changeWorkingDirectory("/home/ftpuser/ego/images");

           //6、設(shè)置文件上傳的模式,指定為被動模式

           client.enterLocalPassiveMode();

           boolean flag = client.storeFile("test.jpg", local);

           if(flag){

              System.out.println("上傳成功");

           }else{

              System.out.println("上傳失敗");

           }

       } catch (SocketException e) {

           e.printStackTrace();

       } catch (IOException e) {

           e.printStackTrace();

       }

    }

}

3.4.1.10.封裝FTPUtils工具類

package cn.gzsxt.base.utils;     

import java.io.IOException;

import java.io.InputStream;

import org.apache.commons.net.ftp.FTP;

import org.apache.commons.net.ftp.FTPClient;

public class FtpUtils {

    FTPClient client = null;

    /**

     * 文件上傳

     * @param hostName   ftp主機名

     * @param port       ftp主機端口

     * @param username   上傳用戶名

     * @param password   上傳用戶密碼

     * @param basePath   上傳基礎(chǔ)路徑

     * @param filePath   文件存放路徑

     * @param remoteFileName  上傳后文件名稱

     * @param in         文件輸入流

     * @return

     */

    public static boolean upload(String hostName,int port,String      username,String password,String basePath,

           String filePath,String remoteFileName,InputStream in){

       //1、創(chuàng)建客戶端

       FTPClient client = new FTPClient();

       try {

           //2、建立和服務(wù)端的鏈接

           client.connect(hostName, port);

           //3、登陸服務(wù)端

           client.login(username, password);

           //4、指定圖片上傳的方式為二進(jìn)制,即字節(jié)流

           client.setFileType(FTP.BINARY_FILE_TYPE);

           //5、指定上傳的訪問模式為被動模式    說明:大部分的操作系統(tǒng),默認(rèn)的都是被動模式,并且禁用了主動了模式

           client.enterLocalPassiveMode();

           //6、指定上傳的目錄     默認(rèn)目錄 是當(dāng)前ftpuser用戶的家目錄   

           boolean flag =      client.changeWorkingDirectory(basePath+filePath);

           //如果切換目錄失敗,則創(chuàng)建指定的目錄

           if(!flag){

              //創(chuàng)建目錄失敗,則可能是存在沒有創(chuàng)建的父目錄

              if(!client.makeDirectory(basePath+filePath)){

                  String tempPath = basePath;

                  String[] split = filePath.split("/");

                  for (String string : split) {

                     if(null!=string && !"".equals(string)){

                         tempPath = tempPath+"/"+string;

                         //先判斷第一層路徑是否存在,如果不存在,則創(chuàng)建

                         if(!client.changeWorkingDirectory(tempPath)){

                            //如果創(chuàng)建第一層路徑成功,則判斷是否能切換到這一層路徑

                            if(client.makeDirectory(tempPath)){

                                //切換失敗,則返回false

                                if(!client.changeWorkingDirectory(tempPath)){

                                   return false;

                                }

                            //如果創(chuàng)建第一層路徑失敗,則直接返回false

                            }else{

                                return false;

                            }

                         }

                     //如果有空路徑,則直接跳過

                     }else{

                         continue;

                     }

                  }

              }else{

                  //創(chuàng)建成功,則直接切換到指定的目錄

                  if(!client.changeWorkingDirectory(basePath+filePath)){

                     return false;

                  }

              }

           }

           //8、上傳

           boolean result = client.storeFile(remoteFileName, in);

           return result;

       } catch (Exception e) {

           e.printStackTrace();

           return false;

       }finally {

           //9,退出登錄,并關(guān)閉連接

           try {

              if(client.logout()){

                  client.disconnect();

              }

           } catch (IOException e) {

              e.printStackTrace();

           }

       }

    }

}

3.4.2.第二部分:搭建圖片服務(wù)器訪問圖片

我們知道,圖片等靜態(tài)資源需要服務(wù)器加載,才能被訪問到。

這里我們選擇Tengine做服務(wù)器,來加載圖片。

問題1:Tengine是什么?

答:Tengine是web服務(wù)器。

問題2:web服務(wù)器常用種類?

答:apache、IIS、nginx

問題3:web服務(wù)器和web應(yīng)用服務(wù)器的區(qū)別?

答:web應(yīng)用服務(wù)器,是用來處理動態(tài)請求,常見的以tomcat、jetty等servlet容器為代表????????????????????

web服務(wù)器,只能處理靜態(tài)資源請求。

如果要處理動態(tài)請求,需要通過其動態(tài)代理功能實現(xiàn)。

問題3:為什么不用Tomcat呢?

答:(1)Tomcat是servlet容器,處理靜態(tài)資源的速度遠(yuǎn)低于Tengine。

(2)Tomcat的并發(fā)連接數(shù),遠(yuǎn)遠(yuǎn)低于Tengine。

所以,這里我們選擇Tengine做圖片服務(wù)器。

搭建步驟說明:

(1)安裝Tengine。(源碼安裝)

(2)配置圖片服務(wù)。

3.4.2.1.第一步:上傳、解壓

[root@node0719 ~]# tar -zxvf tengine-2.1.0.tar.gz

3.4.2.2.第二步:預(yù)編譯

預(yù)編譯作用:檢查編譯過程中所需要的依賴、環(huán)境。

依次安裝預(yù)編譯過程中,所需要的環(huán)境。(根據(jù)個人虛擬機安裝所缺環(huán)境)

[root@node07192 ~]# cd tengine-2.1.0     

[root@node07192 tengine-2.1.0]# ./configure

(1)缺少c編譯環(huán)境

image.png
[root@node07192 tengine-2.1.0]# yum -y install gcc-c++

(2)缺少pcre環(huán)境

image.png
[root@node07192 tengine-2.1.0]# yum -y install pcre-devel

(3)缺少openssl環(huán)境

image.png
[root@node07192 tengine-2.1.0]# yum install -y openssl openssl-devel

(4)缺少zlib環(huán)境

[root@node07192 tengine-2.1.0]# yum install -y zlib zlib-devel

3.4.2.3.第三步:編譯

[root@node07192 tengine-2.1.0]# make

3.4.2.4.第四步:安裝

默認(rèn)安裝路徑/usr/local/nginx/

[root@node07192 tengine-2.1.0]# make install

3.4.2.5.第五步:啟動Tengine服務(wù)器

[root@node07192 tengine-2.1.0]# cd /usr/local/nginx/sbin/     

[root@node07192 sbin]# ./nginx
        23.第六步:訪問測試

(1)查看配置文件。默認(rèn)服務(wù)端口是80

[root@node07192 sbin]# cd ../conf     

[root@node07192 conf]# vim nginx.conf
image.png

(2)修改防火墻,開發(fā)80端口。重啟防火墻

[root@node07192 conf]# vim /etc/sysconfig/iptables     

[root@node07192 conf]# service iptables restart

(3)瀏覽器訪問地址 http://192.168.23.12:80

image.png

3.4.2.7.第七步:配置圖片服務(wù)

(1)修改/conf/nginx.conf文件。指定圖片根路徑和服務(wù)端口

image.png

(2)重啟tengine服務(wù)器

[root@node07192 sbin]# ./nginx -s reload

(3)瀏覽器訪問圖片

注意:服務(wù)器加載的根路徑是/home/ftpuser/ego

所以瀏覽器中訪問圖片的目錄為/images/+圖片名稱.jpg

image.png

(4)解決訪問圖片的權(quán)限問題

在第六步中,我們訪問的頁面是/html/index.html

所以:我們只需要將圖片的權(quán)限修改為index.html一致即可。

查看/html/index.html的權(quán)限

image.png
image.png

修改ftpuser目錄的權(quán)限為可讀、可執(zhí)行

[root@node07192 nginx]# chmod 705 /home/ftpuser

(5)重新訪問圖片,成功!!!

image.png

圖片訪問路徑說明:
圖片真實目錄時 /home/ftpuser/ego/images
在Tengine中,設(shè)置得圖片資源的根目錄為 /home/ftpuser/ego
意味著,我們每次請求圖片的時候,是直接到/home/ftpuser/ego這個目錄下,找圖片的。因此圖片的訪問路徑中,/home/ftpuser/ego這個路徑是要省掉的。

3.4.3.第三部分:SpringMVC實現(xiàn)上傳

3.4.3.1.思路

(1)使用Springmvc上傳組件,從頁面表單接收圖片

(2)使用vsftpd組件,將圖片上傳到Linux服務(wù)器。

 (a)、服務(wù)端:在Linux上安裝ftp服務(wù)端vsftpd軟件,并開啟服務(wù)。

 (b)、客戶端:在java代碼中使用FtpClient客戶端建立與服務(wù)器的連接

(3)返回值:返回圖片上傳之后的訪問路徑。

為什么?

因為保存圖片到數(shù)據(jù)庫的時候,保存的就是圖片的訪問路徑。

3.4.3.2.前端js實現(xiàn)

前端使用kindeditor,初始化上傳組件

image.png

調(diào)用上傳組件的初始化方法:

image.png

上傳組件在common.js中定義

image.png

上傳組件的初始化方法init

image.png

3.4.3.3.后臺java實現(xiàn)

3.4.3.3.1.代碼結(jié)構(gòu)

Controller:從表單接收圖片,返回圖片的回調(diào)地址

Service:創(chuàng)建FtpClient客戶端,將圖片直接上傳到Linux服務(wù)器

3.4.3.3.2.請求響應(yīng)格式
請求路徑      /pic/upload
請求方式      Post
請求參數(shù)      uploadFile
返回值結(jié)構(gòu)      參考Kindeditor官方文檔(http://kindeditor.net/docs/upload.html)

Kindeditor官方文檔要求的返回格式類型

image.png
3.4.3.3.3.定義返回值類型

在ego-base工程中定義。

package cn.gzsxt.base.pojo;     

/**

* KindEditer文件上傳返回格式

* @author ccnulyq

*

*/

public class UploadResult {

    private int error;   //0 表示成功   1表示失敗

    private String url;   //成功時,圖片的訪問地址

    private String message;  //失敗時,錯誤信息

    public PictureResult() {

       super();

    }

//補充get、set方法

}
3.4.3.3.4.在ego-manager工程中添加Springmvc上傳組件及Pom依賴

(1)、修改spring-mvc.xml,添加上傳組件

<!-- 定義文件上傳解析器 -->     

<bean name="multipartResolver"      class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

       <!-- 設(shè)定默認(rèn)編碼 -->

       <property name="defaultEncoding" value="UTF-8"></property>

       <!-- 設(shè)定文件上傳的最大值5MB,5*1024*1024 -->

       <property name="maxUploadSize" value="5242880"></property>

</bean>

(2)、修改pom.xml,添加上傳依賴common-fileupload.jar

<!-- 文件上傳組件 -->     

<dependency>

       <groupId>commons-fileupload</groupId>

       <artifactId>commons-fileupload</artifactId>

</dependency>

(3)將vsftpd服務(wù)端請求參數(shù)寫到properties配置文件中

#圖片上傳基本配置     

FTP_HOST=192.168.4.253

FTP_PORT=21

FTP_USER=ftpuser

FTP_PASSWD=ftpuser

FTP_BASE_URL=/home/ftpuser/ego/images

PICTURE_BASE_URL=http://192.168.4.253/images
3.4.3.3.5.Service層代碼實現(xiàn)

--創(chuàng)建UploadService接口及其實現(xiàn)類

package cn.gzsxt.manager.service.impl;     

import java.io.IOException;

import java.text.SimpleDateFormat;

import java.util.Date;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Service;

import org.springframework.web.multipart.MultipartFile;

import cn.gzsxt.base.utils.FtpUtils;

import cn.gzsxt.base.utils.IDUtils;

import cn.gzsxt.base.vo.UploadResult;

import cn.gzsxt.manager.service.UploadService;

@Service

public class UploadServiceImpl implements UploadService{

    /*

     * FTP_HOST=192.168.4.253

FTP_PORT=21

FTP_USERNAME=ftpuser

FTP_PASSWORD=ftpuser

FTP_BASE_URL=/home/ftpuser/ego/images

PICTURE_BASE_URL=http://192.168.4.253/images

     */

    @Value("${FTP_HOST}")

    private String FTP_HOST;

    @Value("${FTP_PORT}")

    private Integer FTP_PORT;

    @Value("${FTP_USERNAME}")

    private String FTP_USERNAME;

    @Value("${FTP_PASSWORD}")

    private String FTP_PASSWORD;

    @Value("${FTP_BASE_URL}")

    private String FTP_BASE_URL;

    @Value("${PICTURE_BASE_URL}")

    private String PICTURE_BASE_URL;

    @Override

    public UploadResult upload(MultipartFile file) {

       UploadResult result = new UploadResult();

       //需求:將上傳的圖片按日期來分類    /2019/02/25/1.jpg    

       Date date = new Date();

       //獲取日期的目錄格式

       String filePath = "/"+ new      SimpleDateFormat("yyyy").format(date)+

                    "/"+new SimpleDateFormat("MM").format(date)+

                    "/"+new SimpleDateFormat("dd").format(date);

       //獲取圖片的類型   .jpg   .png

       String originalFilename = file.getOriginalFilename();

       String filtType =      originalFilename.substring(originalFilename.lastIndexOf("."));

       String remoteFileName = IDUtils.getImageName()+filtType;

       try {

           boolean upload = FtpUtils.upload(FTP_HOST, FTP_PORT,      FTP_USERNAME, FTP_PASSWORD, FTP_BASE_URL, filePath, remoteFileName,      file.getInputStream());

           if(upload){

              result.setError(0);

              //   192.168.4.253/images     /2019/02/25    /        111111.jpg

              result.setUrl(PICTURE_BASE_URL+filePath+"/"+remoteFileName);

           }else{

              result.setError(1);

              result.setMessage("上傳失敗,請稍后再試!");

           }

       } catch (IOException e) {

           e.printStackTrace();

           result.setError(1);

           result.setMessage("上傳失敗,請稍后再試!");

       }

       return result;

    }

}
3.4.3.3.6.ID生成工具類
package org.ranger.base.utils;     

import java.util.Random;

/**

* 各種id生成策略

*/

public class IDUtils {

    /**

     * 圖片名生成

     */

    public static String getImageName() {

       //取當(dāng)前時間的長整形值包含毫秒

       long millis = System.currentTimeMillis();

       //long millis = System.nanoTime();

       //加上三位隨機數(shù)

       Random random = new Random();

       int end3 = random.nextInt(999);

       //如果不足三位前面補0

       String str = millis + String.format("%03d", end3);

       return str;

    }

    /**

     * 商品id生成

     */

    public static long getItemId() {

       //取當(dāng)前時間的長整形值包含毫秒

       long millis = System.currentTimeMillis();

       //long millis = System.nanoTime();

       //加上兩位隨機數(shù)

       Random random = new Random();

       int end2 = random.nextInt(99);

       //如果不足兩位前面補0

       String str = millis + String.format("%02d", end2);

       long id = new Long(str);

       return id;

    }

}
3.4.3.3.7.Controller層代碼實現(xiàn)

--創(chuàng)建UploadController類

package cn.gzsxt.manager.controller;     

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.ResponseBody;

import org.springframework.web.multipart.MultipartFile;

import cn.gzsxt.base.vo.UploadResult;

import cn.gzsxt.manager.service.UploadService;

@Controller

public class UploadController {

    @Autowired

    private UploadService uploadService;

    @RequestMapping(value="/pic/upload",method=RequestMethod.POST)

    @ResponseBody

    public UploadResult upload(MultipartFile uploadFile){

       UploadResult result = uploadService.upload(uploadFile);

       return result;

    }

}
3.4.3.3.8.測試結(jié)果,上傳成功!!!
image.png

3.4.3.4.將上傳結(jié)果保存到頁面表單域

image.png
image.png

頁面效果

image.png

4.第三部分:kindEditor編輯商品屬性

純前端js實現(xiàn),不需要java后臺代碼支持。

原理:內(nèi)置了一個HTML編輯器,將HTML頁面轉(zhuǎn)換成文本類型,將值傳給指定的元素。

image.png

5.第四部分:商品規(guī)格參數(shù)

image.png

5.1.格式

規(guī)格分組1

|-規(guī)格項1:規(guī)格值1

|-規(guī)格項2:規(guī)格值2

|-規(guī)格項n:規(guī)格值n

規(guī)格分組2

|-規(guī)格項11:規(guī)格值11

|-規(guī)格項22:規(guī)格值22

|-規(guī)格項nn:規(guī)格值nn

規(guī)格分組3

|-規(guī)格項112:規(guī)格值112

|-規(guī)格項222:規(guī)格值222

|-規(guī)格項nnn:規(guī)格值nnn

5.2.特點

(1)每一類商品的規(guī)格分組是相同的。

(2)每一個規(guī)格分組對應(yīng)多個規(guī)格項。

(3)每一個商品的規(guī)格值不同。

5.3.設(shè)計思路

image.png

(1)給商品的每一個分類創(chuàng)建一個規(guī)格參數(shù)模板。(tb_item_param)

(2)添加商品的時候,根據(jù)該類商品的參數(shù)模板,填寫規(guī)格值。

(3)將頁面填寫的規(guī)格值,保存到數(shù)據(jù)庫。(tb_item_param_item)

5.4.實現(xiàn)流程

(1)添加商品規(guī)格參數(shù)模板

(2)根據(jù)規(guī)格參數(shù)模板生成規(guī)格值

5.4.1.第一部分:創(chuàng)建規(guī)格參數(shù)模板

5.4.1.1.第一步:判斷是否已經(jīng)添加規(guī)格參數(shù)模板

(1)js實現(xiàn)

image.png

(2)請求響應(yīng)格式

請求路徑      /item/param/query/itemcatid/{itemCatId}
請求方式      GET
請求參數(shù)      /{itemCatId} 路徑變量,商品類目id
響應(yīng)結(jié)果      {status:200 data:data}

(3)創(chuàng)建ItemParam類

package cn.gzsxt.base.pojo;     

import java.util.Date;

import com.baomidou.mybatisplus.annotations.TableField;

import com.baomidou.mybatisplus.annotations.TableId;

import com.baomidou.mybatisplus.annotations.TableName;

import com.baomidou.mybatisplus.enums.IdType;

@TableName(value="tb_item_param")

public class ItemParam {

    @TableId(value="id",type=IdType.AUTO)

    private Long id;

    @TableField(value="item_cat_id")

    private long itemCatId;

    @TableField(value="param_data")

    private String paramData;

    private Date created;

    private Date updated;

    public ItemParam() {

       super();

    }

//補全get、set方法

}

(4)創(chuàng)建EgoResult返回值類

--說明:在ego-base中定義,并修改pom文件,添加json依賴

package cn.gzsxt.base.vo;     

import java.util.List;

import com.fasterxml.jackson.databind.JsonNode;

import com.fasterxml.jackson.databind.ObjectMapper;

/**

* 好易購商城自定義響應(yīng)結(jié)構(gòu)

*/

public class EgoResult {

    // 定義jackson對象

    private static final ObjectMapper MAPPER = new ObjectMapper();

    // 響應(yīng)業(yè)務(wù)狀態(tài)

    private Integer status;

    // 響應(yīng)消息

    private String msg;

    // 響應(yīng)中的數(shù)據(jù)

    private Object data;

    public static EgoResult build(Integer status, String msg, Object      data) {

        return new EgoResult(status, msg, data);

    }

    public static EgoResult ok(Object data) {

        return new EgoResult(data);

    }

    public static EgoResult ok() {

        return new EgoResult(null);

    }

    public EgoResult() {

    }

    public static EgoResult build(Integer status, String msg) {

        return new EgoResult(status, msg, null);

    }

    public EgoResult(Integer status, String msg, Object data) {

        this.status = status;

        this.msg = msg;

        this.data = data;

    }

    public EgoResult(Object data) {

        this.status = 200;

        this.msg = "OK";

        this.data = data;

    }

//    public Boolean isOK() {

//        return this.status == 200;

//    }

    public Integer getStatus() {

        return status;

    }

    public void setStatus(Integer status) {

        this.status = status;

    }

    public String getMsg() {

        return msg;

    }

    public void setMsg(String msg) {

        this.msg = msg;

    }

    public Object getData() {

        return data;

    }

    public void setData(Object data) {

        this.data = data;

    }

    /**

     * 將json結(jié)果集轉(zhuǎn)化為EgoResult對象

     *

     * @param jsonData json數(shù)據(jù)

     * @param clazz EgoResult中的object類型

     * @return

     */

    public static EgoResult formatToPojo(String jsonData, Class<?>      clazz) {

        try {

            if (clazz == null) {

                return MAPPER.readValue(jsonData, EgoResult.class);

            }

            JsonNode jsonNode = MAPPER.readTree(jsonData);

            JsonNode data = jsonNode.get("data");

            Object obj = null;

            if (clazz != null) {

                if (data.isObject()) {

                    obj = MAPPER.readValue(data.traverse(), clazz);

                } else if (data.isTextual()) {

                    obj = MAPPER.readValue(data.asText(), clazz);

                }

            }

            return build(jsonNode.get("status").intValue(),      jsonNode.get("msg").asText(), obj);

        } catch (Exception e) {

            return null;

        }

    }

    /**

     * 沒有object對象的轉(zhuǎn)化

     *

     * @param json

     * @return

     */

    public static EgoResult format(String json) {

        try {

            return MAPPER.readValue(json, EgoResult.class);

        } catch (Exception e) {

            e.printStackTrace();

        }

        return null;

    }

    /**

     * Object是集合轉(zhuǎn)化

     *

     * @param jsonData json數(shù)據(jù)

     * @param clazz 集合中的類型

     * @return

     */

    public static EgoResult formatToList(String jsonData, Class<?>      clazz) {

        try {

            JsonNode jsonNode = MAPPER.readTree(jsonData);

            JsonNode data = jsonNode.get("data");

            Object obj = null;

            if (data.isArray() && data.size() > 0) {

                obj = MAPPER.readValue(data.traverse(),

                             MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));

            }

            return build(jsonNode.get("status").intValue(),      jsonNode.get("msg").asText(), obj);

        } catch (Exception e) {

            return null;

        }

    }

}

(5)創(chuàng)建ItemParamMapper接口

--說明:在ego-base中創(chuàng)建

package cn.gzsxt.base.mapper;     

import java.util.List;

import java.util.Map;

import org.apache.ibatis.annotations.Param;

import org.apache.ibatis.annotations.Select;

import com.baomidou.mybatisplus.mapper.BaseMapper;

import cn.gzsxt.base.pojo.ItemParam;

public interface ItemParamMapper extends BaseMapper<ItemParam>{

}

(6)Service層實現(xiàn)

--創(chuàng)建ItemParamService接口及其實現(xiàn)類

package cn.gzsxt.manager.service.impl;     

import java.util.Date;

import java.util.List;

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.mapper.EntityWrapper;

import cn.gzsxt.base.mapper.ItemParamMapper;

import cn.gzsxt.base.pojo.ItemParam;

import cn.gzsxt.base.vo.EUDataGridResult;

import cn.gzsxt.base.vo.EgoResult;

import cn.gzsxt.manager.service.ItemParamService;

@Service

public class ItemParamServiceImpl implements ItemParamService{

    @Autowired

    private ItemParamMapper itemParamMapper;

    @Override

    public EgoResult getByItemCatId(long catId) {

       EntityWrapper<ItemParam> ew = new EntityWrapper<>();

       ew.eq("item_cat_id", catId);

       List<ItemParam> selectList = itemParamMapper.selectList(ew);

       if(null!=selectList && selectList.size()>0){

           return EgoResult.ok(selectList.get(0));

       }

       return EgoResult.build(400, "沒有查到該類商品的模板");

    }

}

(4)Controller層實現(xiàn)

--創(chuàng)建ItemParamController類

package cn.gzsxt.manager.controller;     

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.ResponseBody;

import cn.gzsxt.base.vo.EUDataGridResult;

import cn.gzsxt.base.vo.EgoResult;

import cn.gzsxt.manager.service.ItemParamService;

@Controller

@RequestMapping("/item/param")

public class ItemParamController {

    @Autowired

    private ItemParamService service;

    @RequestMapping("/query/itemcatid/{itemcatid}")

    @ResponseBody

    public EgoResult selectByCatId(@PathVariable("itemcatid")Long      itemCatId){

       EgoResult result = service.getByItemCatId(itemCatId);

       return result;

    }

}

5.4.1.2.第二步:添加規(guī)格參數(shù)模板

(1)前端js實現(xiàn)

image.png
image.png

(2)后臺java代碼實現(xiàn)

請求路徑      /item/param/save/{cid}
請求方式      POST
請求參數(shù)      /{cid}  (類目id)  ;paramData  (json格式)
響應(yīng)結(jié)果      EgoResult

(3)Service層實現(xiàn)

--修改ItemParamService接口及其實現(xiàn)類,添加保存方法

//只有配置了rollbackFor = Exception.class,在service對異常進(jìn)行處理時,才會有回滾     

    @Transactional(rollbackFor = Exception.class)

    @Override

    public EgoResult save(Long itemCatId, String paramData) {

       try {

           ItemParam entity = new ItemParam();

           entity.setItemCatId(itemCatId);

           entity.setParamData(paramData);

           entity.setCreated(new Date());

           entity.setUpdated(entity.getCreated());

           itemParamMapper.insert(entity);

           return EgoResult.ok();

       } catch (Exception e) {

           e.printStackTrace();

           return EgoResult.build(400, "保存失敗");

       }

    }

(4)Controller層實現(xiàn)

--修改ItemParamController,添加保存方法

@RequestMapping("/save/{cid}")

    @ResponseBody

    public EgoResult saveItemParam(@PathVariable Long cid, String      paramData) {

       EgoResult result = itemParamService.saveItemParam(cid,      paramData);

    }

5.4.2.第二部分:根據(jù)參數(shù)模板生成商品規(guī)格參數(shù)值表單

新增商品 --> 選擇類目 --> 查找類目所對應(yīng)的模板 --> 生成表單

(1)前端js實現(xiàn)

image.png
image.png

2. java后臺(已實現(xiàn))

5.4.2.1.第一步:修改Controller代碼

    @RequestMapping("/save/{catId}")     

    @ResponseBody

    public EgoResult save(@PathVariable("catId")Long catId,String      paramData){

       EgoResult result = service.save(catId, paramData);

       return result;

    }

5.4.2.2.第二步:修改Service代碼

    @Override     

    public EgoResult save(Long catId, String paramData) {

       ItemParam param = new ItemParam();

       param.setItemCatId(catId);

       param.setParamData(paramData);

       param.setCreated(new Date());

       param.setUpdated(param.getCreated());

       mapper.insert(param);

       return EgoResult.ok();

    }

6.第五部分:保存商品

保存商品,需要同時保存商品信息、商品的描述信息和商品的規(guī)格參數(shù),分別對應(yīng)表tb_item、tb_item_desc、tb_item_param_item三張表。

6.1.前端js實現(xiàn)

6.1.2.使用KindEditor富文本編輯器,編輯商品描述信息

image.png

6.1.3.將商品規(guī)格參數(shù)表單數(shù)據(jù),轉(zhuǎn)換成json格式

image.png

6.1.4.提交保存商品請求

image.png

6.2.后臺java實現(xiàn)

6.2.1.請求響應(yīng)格式

請求路徑      /item/save
請求方式      POST
請求參數(shù)      TbItem、desc、itemParams
響應(yīng)格式      {“status”:200   data:data}   參考http響應(yīng)格式

6.2.2.代碼結(jié)構(gòu)

Controller:從表單接收數(shù)據(jù),封裝到JavaBean中

Service:實現(xiàn)保存邏輯,防止事務(wù)一致性問題。

Mapper:Mybatis-plus實現(xiàn)

6.2.3.創(chuàng)建pojo

--在ego-base工程中創(chuàng)建

(1)創(chuàng)建ItemDesc類

package cn.gzsxt.base.pojo;     

import java.util.Date;

import com.baomidou.mybatisplus.annotations.TableField;

import com.baomidou.mybatisplus.annotations.TableId;

import com.baomidou.mybatisplus.annotations.TableName;

import com.baomidou.mybatisplus.enums.IdType;

@TableName(value="tb_item_desc")

public class ItemDesc {

    @TableId(value="item_id",type=IdType.INPUT)

    private Long itemId;

    @TableField(value="item_desc")

    private String itemDesc;

    private Date created;

    private Date updated;

    public ItemDesc() {

       super();

    }

    // 補全get、set方法

}

(2)創(chuàng)建ItemParamItem類

package cn.gzsxt.base.pojo;     

import java.util.Date;

import com.baomidou.mybatisplus.annotations.TableField;

import com.baomidou.mybatisplus.annotations.TableId;

import com.baomidou.mybatisplus.annotations.TableName;

import com.baomidou.mybatisplus.enums.IdType;

/**商品規(guī)格參數(shù)值表

*

* 商品的規(guī)格參數(shù)(商品的描述信息)

*    做了水平拆表的處理。

*   

*    好處:減小商品的表的體積,讓商品表查詢效率更高

*    

* 什么情況下需要做水平拆表?

* (1)大文本的字段。

* (2)這個大文本的字段不常用

*

* @author ccnulyq

*

*/

@TableName(value="tb_item_param_item")

public class ItemParamItem {

    @TableId(value="id",type=IdType.AUTO)

    private Long id;

    @TableField(value="item_id")

    private long itemId;

    @TableField(value="param_data")

    private String paramData;

    private Date created;

    private Date updated;

    public ItemParamItem() {

       super();

    }

    // 補全get、set方法

}

6.2.4.創(chuàng)建對應(yīng)的Mapper

--說明:在ego-base工程中創(chuàng)建

(1)創(chuàng)建ItemParamItemMapper接口

package cn.gzsxt.base.mapper;     

import com.baomidou.mybatisplus.mapper.BaseMapper;

import cn.gzsxt.base.pojo.ItemParamItem;

public interface ItemParamItemMapper extends      BaseMapper<ItemParamItem>{

}

(2)創(chuàng)建ItemDescMapper接口

package cn.gzsxt.base.mapper;     

import com.baomidou.mybatisplus.mapper.BaseMapper;

import cn.gzsxt.base.pojo.ItemDesc;

public interface ItemDescMapper extends BaseMapper<ItemDesc>{

}

6.2.5.Service代碼實現(xiàn)

--修改ItemService接口及其實現(xiàn)類,新增save方法

--注意:注入ItemDescMapper、ItemParamItemMapper

@Service

public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item>      implements ItemService{

    @Autowired

    private ItemDescMapper descMapper;

    @Autowired

    private ItemParamItemMapper itemParamMapper;

    @Transactional(rollbackFor=Exception.class)

    @Override

    public EgoResult save(Item item, String desc, String paramData)      {

       try {

           long itemId = IDUtils.getItemId();

           item.setStatus((byte) 1);

           item.setId(itemId);

           item.setCreated(new Date());

           item.setUpdated(item.getCreated());

           this.baseMapper.insert(item);

           //保存商品的描述信息

           ItemDesc itemDesc = new ItemDesc();

           itemDesc.setItemId(itemId);

           itemDesc.setItemDesc(desc);

           itemDesc.setCreated(item.getCreated());

           itemDesc.setUpdated(item.getUpdated());

           descMapper.insert(itemDesc);

           //保存商品的規(guī)格參數(shù)值

           ItemParamItem paramItem = new ItemParamItem();

           paramItem.setItemId(itemId);

           paramItem.setParamData(paramData);

           paramItem.setCreated(item.getCreated());

           paramItem.setUpdated(item.getCreated());

           itemParamMapper.insert(paramItem);

           return EgoResult.ok();

       } catch (Exception e) {

           e.printStackTrace();

       }

       return EgoResult.build(400, "保存失敗,請稍后再試");

    }

}

6.2.6.Controller代碼實現(xiàn)

--修改ItemController類,新增save方法

@RequestMapping(value="/save",method=RequestMethod.POST)

@ResponseBody

public EgoResult save(Item item,String desc,String itemParams){

   EgoResult result = itemService.save(item, desc, itemParams);

   return result;

}

7.商品規(guī)格參數(shù)列表實現(xiàn)

7.1.思路

商品規(guī)格參數(shù)列表的數(shù)據(jù),分別存在了tb_item_param和tb_item_cat兩張表中,因此在mapper層,需要自定義查詢方法,并分頁

image.png

7.2.前端js實現(xiàn)

使用的是easyu-datagrid插件,使用方法參考商品列表實現(xiàn)(第一天內(nèi)容)。

7.3.后臺代碼實現(xiàn)

7.3.1.確定請求響應(yīng)格式

請求路徑      /item/param/list
請求方式      Get
請求參數(shù)      page、rows(分頁)
返回值類型      EUDataGridResult類型

7.3.2.Mapper實現(xiàn)

--說明:連表查詢下,需要自定義查詢方法,基于注解實現(xiàn)

--修改ItemParamMapper接口,新增查詢方法

public interface ItemParamMapper extends BaseMapper<ItemParam>{     

    @Select(value="select p.id,p.item_cat_id as itemCatId,t.name as      itemCatName,p.param_data as paramData,p.created,p.updated "

           + "from tb_item_param p left join tb_item_cat t on      p.item_cat_id = t.id "

           + "limit ${start},${pageSize}")

    List<Map<String, Object>> listAndPage(@Param("start")int      start,@Param("pageSize")int pageSize);

}

7.3.3.Service層實現(xiàn)

--修改ItemParamService接口及其實現(xiàn)類

@Override     

    public EUDataGridResult listAndPage(int curPage, int pageSize) {

       List<Map<String, Object>> list =      itemParamMapper.listAndPage((curPage-1)*pageSize, pageSize);

       Integer count = itemParamMapper.selectCount(null);

       EUDataGridResult result = new EUDataGridResult();

       result.setRows(list);

       result.setTotal(count);

       return result;

    }

7.3.4.Controller層實現(xiàn)

--修改ItemParamController接口

@RequestMapping("/list")     

    @ResponseBody

    public EUDataGridResult listAndPage(Integer page,Integer rows){

       EUDataGridResult result = service.listAndPage(page, rows);

       return result;

    }

7.4.訪問測試

規(guī)格參數(shù)列表實現(xiàn)?。?!

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容