黑馬暢購商城---2.分佈式文件存儲FastDFS

學習目標

  • ==理解FastDFS工作流程==
  • ==搭建文件上傳微服務==

  • 相冊管理(實戰)

  • 規格參數管理(實戰)

  • 商品分類管理(實戰)

1 FastDFS

1.1 FastDFS簡介

1.1.1 FastDFS體系結構

FastDFS是一個開源的輕量級分佈式文件系統,它對文件進行管理,功能包括:文件存儲、文件同步、文件訪問(文件上傳、文件下載)等,解決了大容量存儲和負載均衡的問題。特別適合以文件爲載體的在線服務,如相冊網站、視頻網站等等。

FastDFS爲互聯網量身定製,充分考慮了冗餘備份、負載均衡、線性擴容等機制,並注重高可用、高性能等指標,使用FastDFS很容易搭建一套高性能的文件服務器集羣提供文件上傳、下載等服務。

FastDFS 架構包括 Tracker server 和 Storage server。客戶端請求 Tracker server 進行文件上傳、下載,通過Tracker server 調度最終由 Storage server 完成文件上傳和下載。

Tracker server 作用是負載均衡和調度,通過 Tracker server 在文件上傳時可以根據一些策略找到Storage server 提供文件上傳服務。可以將 tracker 稱爲追蹤服務器或調度服務器。Storage server 作用是文件存儲,客戶端上傳的文件最終存儲在 Storage 服務器上,Storageserver 沒有實現自己的文件系統而是利用操作系統的文件系統來管理文件。可以將storage稱爲存儲服務器。

1.1.2 上傳流程

客戶端上傳文件後存儲服務器將文件 ID 返回給客戶端,此文件 ID 用於以後訪問該文件的索引信息。文件索引信息包括:組名,虛擬磁盤路徑,數據兩級目錄,文件名。

組名:文件上傳後所在的 storage 組名稱,在文件上傳成功後有storage 服務器返回,需要客戶端自行保存。

虛擬磁盤路徑:storage 配置的虛擬路徑,與磁盤選項store_path*對應。如果配置了

store_path0 則是 M00,如果配置了 store_path1 則是 M01,以此類推。

數據兩級目錄:storage 服務器在每個虛擬磁盤路徑下創建的兩級目錄,用於存儲數據

文件。

文件名:與文件上傳時不同。是由存儲服務器根據特定信息生成,文件名包含:源存儲

服務器 IP 地址、文件創建時間戳、文件大小、隨機數和文件拓展名等信息。

1.2 FastDFS搭建

 

 

1.2.1 安裝FastDFS鏡像

我們使用Docker搭建FastDFS的開發環境,虛擬機中已經下載了fastdfs的鏡像,可以通過docker images查看,如下圖:

拉取鏡像(已經下載了該鏡像,大家無需下載了)

docker pull morunchang/fastdfs

運行tracker

docker run -d --name tracker --net=host morunchang/fastdfs sh tracker.sh

運行storage

docker run -d --name storage --net=host -e TRACKER_IP=192.168.211.132:22122 -e GROUP_NAME=group1 morunchang/fastdfs sh storage.sh
  • 使用的網絡模式是–net=host, 192.168.211.132是宿主機的IP
  • group1是組名,即storage的組
  • 如果想要增加新的storage服務器,再次運行該命令,注意更換 新組名

1.2.2 配置Nginx

Nginx在這裏主要提供對FastDFS圖片訪問的支持,Docker容器中已經集成了Nginx,我們需要修改nginx的配置,進入storage的容器內部,修改nginx.conf

docker exec -it storage  /bin/bash

進入後

vi /etc/nginx/conf/nginx.conf

添加以下內容

上圖配置如下:

1
2
3
4
location ~ /M00 {
     root /data/fast_data/data;
     ngx_fastdfs_module;
}

禁止緩存:

add_header Cache-Control no-store;

退出容器

exit

重啓storage容器

docker restart storage

查看啓動容器docker ps

1
2
9f2391f73d97 morunchang/fastdfs "sh storage.sh" 12 minutes ago Up 12 seconds storage
e22a3c7f95ea morunchang/fastdfs "sh tracker.sh" 13 minutes ago Up 13 minutes tracker

開啓啓動設置

1
2
docker update --restart=always tracker
docker update --restart=always storage

1.3 文件存儲微服務

創建文件管理微服務changgou-service-file,該工程主要用於實現文件上傳以及文件刪除等功能。

1.3.1 pom.xml依賴

修改pom.xml,引入依賴

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>changgou-service</artifactId>
        <groupId>com.changgou</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>changgou-service-file</artifactId>
    <description>文件上傳工程</description>

    <!--依賴包-->
    <dependencies>
        <dependency>
            <groupId>net.oschina.zcx7878</groupId>
            <artifactId>fastdfs-client-java</artifactId>
            <version>1.27.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.changgou</groupId>
            <artifactId>changgou-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

1.3.2 FastDFS配置

在resources文件夾下創建fasfDFS的配置文件fdfs_client.conf

1
2
3
4
5
connect_timeout=60
network_timeout=60
charset=UTF-8
http.tracker_http_port=8080
tracker_server=192.168.211.132:22122

connect_timeout:連接超時時間,單位爲秒。

network_timeout:通信超時時間,單位爲秒。發送或接收數據時。假設在超時時間後還不能發送或接收數據,則本次網絡通信失敗

charset: 字符集

http.tracker_http_port :.tracker的http端口

tracker_server: tracker服務器IP和端口設置

1.3.3 application.yml配置

在resources文件夾下創建application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB
  application:
    name: file
server:
  port: 18082
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:7001/eureka
  instance:
    prefer-ip-address: true
feign:
  hystrix:
    enabled: true

max-file-size是單個文件大小,max-request-size是設置總上傳的數據大小

1.3.4 啓動類

創建com.changgou包,創建啓動類FileApplication

1
2
3
4
5
6
7
8
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
@EnableEurekaClient
public class FileApplication {

    public static void main(String[] args) {
        SpringApplication.run(FileApplication.class);
    }
}

這裏禁止了DataSource的加載創建。

1.4 文件上傳

1.4.1 文件信息封裝

文件上傳一般都有文件的名字、文件的內容、文件的擴展名、文件的md5值、文件的作者等相關屬性,我們可以創建一個對象封裝這些屬性,代碼如下:

創建com.changgou.file.FastDFSFile代碼如下:


public class FastDFSFile implements Serializable {

    //文件名字
    private String name;
    //文件內容
    private byte[] content;
    //文件擴展名
    private String ext;
    //文件MD5摘要值
    private String md5;
    //文件創建作者
    private String author;

    public FastDFSFile(String name, byte[] content, String ext, String md5, String author) {
        this.name = name;
        this.content = content;
        this.ext = ext;
        this.md5 = md5;
        this.author = author;
    }

    public FastDFSFile(String name, byte[] content, String ext) {
        this.name = name;
        this.content = content;
        this.ext = ext;
    }

    public FastDFSFile() {
    }

    //..get..set..toString
}

(可選)測試文件相關操作:


package com.changgou.file.test;

import org.csource.fastdfs.*;
import org.junit.Test;

import java.io.*;
import java.net.InetSocketAddress;

/**
 * 描述
 *
 * @author 三國的包子
 * @version 1.0
 * @package PACKAGE_NAME *
 * @since 1.0
 */

public class FastdfsClientTest {

    /**
     * 文件上傳
     *
     * @throws Exception
     */
    @Test
    public void upload() throws Exception {

        //加載全局的配置文件
        ClientGlobal.init("C:\\Users\\Administrator\\IdeaProjects\\beike\\changgou\\changgou-service\\changgou-service-file\\src\\main\\resources\\fdfs_client.conf");

        //創建TrackerClient客戶端對象
        TrackerClient trackerClient = new TrackerClient();
        //通過TrackerClient對象獲取TrackerServer信息
        TrackerServer trackerServer = trackerClient.getConnection();
        //獲取StorageClient對象
        StorageClient storageClient = new StorageClient(trackerServer, null);

        //執行文件上傳
        String[] jpgs = storageClient.upload_file("C:\\Users\\Administrator\\Pictures\\5b13cd6cN8e12d4aa.jpg", "jpg", null);

        for (String jpg : jpgs) {

            System.out.println(jpg);
        }

    }

    @Test
    public void delete() throws Exception {

        //加載全局的配置文件
        ClientGlobal.init("C:\\Users\\Administrator\\IdeaProjects\\beike\\changgou\\changgou-service\\changgou-service-file\\src\\main\\resources\\fdfs_client.conf");

        //創建TrackerClient客戶端對象
        TrackerClient trackerClient = new TrackerClient();
        //通過TrackerClient對象獲取TrackerServer信息
        TrackerServer trackerServer = trackerClient.getConnection();
        //獲取StorageClient對象
        StorageClient storageClient = new StorageClient(trackerServer, null);
        //執行文件上傳

        int group1 = storageClient.delete_file("group1", "M00/00/00/wKjThF1VEiyAJ0xzAANdC6JX9KA522.jpg");
        System.out.println(group1);
    }

    @Test
    public void download() throws Exception {

        //加載全局的配置文件
        ClientGlobal.init("C:\\Users\\Administrator\\IdeaProjects\\beike\\changgou\\changgou-service\\changgou-service-file\\src\\main\\resources\\fdfs_client.conf");

        //創建TrackerClient客戶端對象
        TrackerClient trackerClient = new TrackerClient();
        //通過TrackerClient對象獲取TrackerServer信息
        TrackerServer trackerServer = trackerClient.getConnection();
        //獲取StorageClient對象
        StorageClient storageClient = new StorageClient(trackerServer, null);
        //執行文件上傳
        byte[] bytes = storageClient.download_file("group1", "M00/00/00/wKjThF1VFfKAJRJDAANdC6JX9KA980.jpg");

        File file = new File("D:\\ceshi\\1234.jpg");

        FileOutputStream fileOutputStream = new FileOutputStream(file);

        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);

        bufferedOutputStream.write(bytes);

        bufferedOutputStream.close();

        fileOutputStream.close();
    }

    //獲取文件的信息數據
    @Test
    public void getFileInfo() throws Exception {
        //加載全局的配置文件
        ClientGlobal.init("C:\\Users\\Administrator\\IdeaProjects\\beike\\changgou\\changgou-service\\changgou-service-file\\src\\main\\resources\\fdfs_client.conf");

        //創建TrackerClient客戶端對象
        TrackerClient trackerClient = new TrackerClient();
        //通過TrackerClient對象獲取TrackerServer信息
        TrackerServer trackerServer = trackerClient.getConnection();
        //獲取StorageClient對象
        StorageClient storageClient = new StorageClient(trackerServer, null);
        //執行文件上傳

        FileInfo group1 = storageClient.get_file_info("group1", "M00/00/00/wKjThF1VFfKAJRJDAANdC6JX9KA980.jpg");

        System.out.println(group1);

    }

    //獲取組相關的信息
    @Test
    public void getGroupInfo() throws Exception {
        //加載全局的配置文件
        ClientGlobal.init("C:\\Users\\Administrator\\IdeaProjects\\beike\\changgou\\changgou-service\\changgou-service-file\\src\\main\\resources\\fdfs_client.conf");

        //創建TrackerClient客戶端對象
        TrackerClient trackerClient = new TrackerClient();
        //通過TrackerClient對象獲取TrackerServer信息
        TrackerServer trackerServer = trackerClient.getConnection();

        StorageServer group1 = trackerClient.getStoreStorage(trackerServer, "group1");
        System.out.println(group1.getStorePathIndex());

        //組對應的服務器的地址  因爲有可能有多個服務器.
        ServerInfo[] group1s = trackerClient.getFetchStorages(trackerServer, "group1", "M00/00/00/wKjThF1VFfKAJRJDAANdC6JX9KA980.jpg");
        for (ServerInfo serverInfo : group1s) {
            System.out.println(serverInfo.getIpAddr());
            System.out.println(serverInfo.getPort());
        }
    }

    @Test
    public void getTrackerInfo() throws Exception {
        //加載全局的配置文件
        ClientGlobal.init("C:\\Users\\Administrator\\IdeaProjects\\beike\\changgou\\changgou-service\\changgou-service-file\\src\\main\\resources\\fdfs_client.conf");

        //創建TrackerClient客戶端對象
        TrackerClient trackerClient = new TrackerClient();
        //通過TrackerClient對象獲取TrackerServer信息
        TrackerServer trackerServer = trackerClient.getConnection();

        InetSocketAddress inetSocketAddress = trackerServer.getInetSocketAddress();
        System.out.println(inetSocketAddress);

    }


}

1.4.2 文件操作

創建com.changgou.util.FastDFSClient類,在該類中實現FastDFS信息獲取以及文件的相關操作,代碼如下:

(1)初始化Tracker信息

com.changgou.util.FastDFSClient類中初始化Tracker信息,在類中添加如下靜態塊:


/***
 * 初始化tracker信息
 */
static {
    try {
        //獲取tracker的配置文件fdfs_client.conf的位置
        String filePath = new ClassPathResource("fdfs_client.conf").getPath();
        //加載tracker配置信息
        ClientGlobal.init(filePath);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

(2)文件上傳

在類中添加如下方法實現文件上傳:

 

 



32
/****
 * 文件上傳
 * @param file : 要上傳的文件信息封裝->FastDFSFile
 * @return String[]
 *          1:文件上傳所存儲的組名
 *          2:文件存儲路徑
 */
public static String[] upload(FastDFSFile file){
    //獲取文件作者
    NameValuePair[] meta_list = new NameValuePair[1];
    meta_list[0] =new NameValuePair(file.getAuthor());

    /***
     * 文件上傳後的返回值
     * uploadResults[0]:文件上傳所存儲的組名,例如:group1
     * uploadResults[1]:文件存儲路徑,例如:M00/00/00/wKjThF0DBzaAP23MAAXz2mMp9oM26.jpeg
     */
    String[] uploadResults = null;
    try {
        //創建TrackerClient客戶端對象
        TrackerClient trackerClient = new TrackerClient();
        //通過TrackerClient對象獲取TrackerServer信息
        TrackerServer trackerServer = trackerClient.getConnection();
        //獲取StorageClient對象
        StorageClient storageClient = new StorageClient(trackerServer, null);
        //執行文件上傳
        uploadResults = storageClient.upload_file(file.getContent(), file.getExt(), meta_list);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return uploadResults;
}

(3)獲取文件信息

在類中添加如下方法實現獲取文件信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/***
 * 獲取文件信息
 * @param groupName:組名
 * @param remoteFileName:文件存儲完整名
 */
public static FileInfo getFile(String groupName,String remoteFileName){
    try {
        //創建TrackerClient對象
        TrackerClient trackerClient = new TrackerClient();
        //通過TrackerClient獲得TrackerServer信息
        TrackerServer trackerServer =trackerClient.getConnection();
        //通過TrackerServer獲取StorageClient對象
        StorageClient storageClient = new StorageClient(trackerServer,null);
        //獲取文件信息
        return storageClient.get_file_info(groupName,remoteFileName);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

(4)文件下載

在類中添加如下方法實現文件下載:


/***
 * 文件下載
 * @param groupName:組名
 * @param remoteFileName:文件存儲完整名
 * @return
 */
public static InputStream downFile(String groupName,String remoteFileName){
    try {
        //創建TrackerClient對象
        TrackerClient trackerClient = new TrackerClient();
        //通過TrackerClient對象創建TrackerServer
        TrackerServer trackerServer = trackerClient.getConnection();
        //通過TrackerServer創建StorageClient
        StorageClient storageClient = new StorageClient(trackerServer,null);
        //通過StorageClient下載文件
        byte[] fileByte = storageClient.download_file(groupName, remoteFileName);
        //將字節數組轉換成字節輸入流
        return new ByteArrayInputStream(fileByte);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

(5)文件刪除實現

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/***
 * 文件刪除實現
 * @param groupName:組名
 * @param remoteFileName:文件存儲完整名
 */
public static void deleteFile(String groupName,String remoteFileName){
    try {
        //創建TrackerClient對象
        TrackerClient trackerClient = new TrackerClient();
        //通過TrackerClient獲取TrackerServer對象
        TrackerServer trackerServer = trackerClient.getConnection();
        //通過TrackerServer創建StorageClient
        StorageClient storageClient = new StorageClient(trackerServer,null);
        //通過StorageClient刪除文件
        storageClient.delete_file(groupName,remoteFileName);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

(6)獲取組信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/***
 * 獲取組信息
 * @param groupName :組名
 */
public static StorageServer getStorages(String groupName){
    try {
        //創建TrackerClient對象
        TrackerClient trackerClient = new TrackerClient();
        //通過TrackerClient獲取TrackerServer對象
        TrackerServer trackerServer = trackerClient.getConnection();
        //通過trackerClient獲取Storage組信息
        return trackerClient.getStoreStorage(trackerServer,groupName);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

(7)根據文件組名和文件存儲路徑獲取Storage服務的IP、端口信息


16
17
18
/***
 * 根據文件組名和文件存儲路徑獲取Storage服務的IP、端口信息
 * @param groupName :組名
 * @param remoteFileName :文件存儲完整名
 */
public static ServerInfo[] getServerInfo(String groupName, String remoteFileName){
    try {
        //創建TrackerClient對象
        TrackerClient trackerClient = new TrackerClient();
        //通過TrackerClient獲取TrackerServer對象
        TrackerServer trackerServer = trackerClient.getConnection();
        //獲取服務信息
        return trackerClient.getFetchStorages(trackerServer,groupName,remoteFileName);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

(8)獲取Tracker服務地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/***
 * 獲取Tracker服務地址
 */
public static String getTrackerUrl(){
    try {
        //創建TrackerClient對象
        TrackerClient trackerClient = new TrackerClient();
        //通過TrackerClient獲取TrackerServer對象
        TrackerServer trackerServer = trackerClient.getConnection();
        //獲取Tracker地址
        return "http://"+trackerServer.getInetSocketAddress().getHostString()+":"+ClientGlobal.getG_tracker_http_port();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

(9)優化

我們可以發現,上面所有方法中都會涉及到獲取TrackerServer或者StorageClient,我們可以把它們單獨抽取出去,分別在類中添加如下2個方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/***
 * 獲取TrackerServer
 */
public static TrackerServer getTrackerServer() throws Exception{
    //創建TrackerClient對象
    TrackerClient trackerClient = new TrackerClient();
    //通過TrackerClient獲取TrackerServer對象
    TrackerServer trackerServer = trackerClient.getConnection();
    return trackerServer;
}

/***
 * 獲取StorageClient
 * @return
 * @throws Exception
 */
public static StorageClient getStorageClient() throws Exception{
    //獲取TrackerServer
    TrackerServer trackerServer = getTrackerServer();
    //通過TrackerServer創建StorageClient
    StorageClient storageClient = new StorageClient(trackerServer,null);
    return storageClient;
}

修改其他方法,在需要使用TrackerServer和StorageClient的時候,直接調用上面的方法,完整代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
public class FastDFSClient {

    /***
     * 初始化tracker信息
     */
    static {
        try {
            //獲取tracker的配置文件fdfs_client.conf的位置
            String filePath = new ClassPathResource("fdfs_client.conf").getPath();
            //加載tracker配置信息
            ClientGlobal.init(filePath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /****
     * 文件上傳
     * @param file : 要上傳的文件信息封裝->FastDFSFile
     * @return String[]
     *          1:文件上傳所存儲的組名
     *          2:文件存儲路徑
     */
    public static String[] upload(FastDFSFile file){
        //獲取文件作者
        NameValuePair[] meta_list = new NameValuePair[1];
        meta_list[0] =new NameValuePair(file.getAuthor());

        /***
         * 文件上傳後的返回值
         * uploadResults[0]:文件上傳所存儲的組名,例如:group1
         * uploadResults[1]:文件存儲路徑,例如:M00/00/00/wKjThF0DBzaAP23MAAXz2mMp9oM26.jpeg
         */
        String[] uploadResults = null;
        try {
            //獲取StorageClient對象
            StorageClient storageClient = getStorageClient();
            //執行文件上傳
            uploadResults = storageClient.upload_file(file.getContent(), file.getExt(), meta_list);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return uploadResults;
    }


    /***
     * 獲取文件信息
     * @param groupName:組名
     * @param remoteFileName:文件存儲完整名
     */
    public static FileInfo getFile(String groupName,String remoteFileName){
        try {
            //獲取StorageClient對象
            StorageClient storageClient = getStorageClient();
            //獲取文件信息
            return storageClient.get_file_info(groupName,remoteFileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /***
     * 文件下載
     * @param groupName:組名
     * @param remoteFileName:文件存儲完整名
     * @return
     */
    public static InputStream downFile(String groupName,String remoteFileName){
        try {
            //獲取StorageClient
            StorageClient storageClient = getStorageClient();
            //通過StorageClient下載文件
            byte[] fileByte = storageClient.download_file(groupName, remoteFileName);
            //將字節數組轉換成字節輸入流
            return new ByteArrayInputStream(fileByte);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /***
     * 文件刪除實現
     * @param groupName:組名
     * @param remoteFileName:文件存儲完整名
     */
    public static void deleteFile(String groupName,String remoteFileName){
        try {
            //獲取StorageClient
            StorageClient storageClient = getStorageClient();
            //通過StorageClient刪除文件
            storageClient.delete_file(groupName,remoteFileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /***
     * 獲取組信息
     * @param groupName :組名
     */
    public static StorageServer getStorages(String groupName){
        try {
            //創建TrackerClient對象
            TrackerClient trackerClient = new TrackerClient();
            //通過TrackerClient獲取TrackerServer對象
            TrackerServer trackerServer = trackerClient.getConnection();
            //通過trackerClient獲取Storage組信息
            return trackerClient.getStoreStorage(trackerServer,groupName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /***
     * 根據文件組名和文件存儲路徑獲取Storage服務的IP、端口信息
     * @param groupName :組名
     * @param remoteFileName :文件存儲完整名
     */
    public static ServerInfo[] getServerInfo(String groupName, String remoteFileName){
        try {
            //創建TrackerClient對象
            TrackerClient trackerClient = new TrackerClient();
            //通過TrackerClient獲取TrackerServer對象
            TrackerServer trackerServer = trackerClient.getConnection();
            //獲取服務信息
            return trackerClient.getFetchStorages(trackerServer,groupName,remoteFileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /***
     * 獲取Tracker服務地址
     */
    public static String getTrackerUrl(){
        try {
            //創建TrackerClient對象
            TrackerClient trackerClient = new TrackerClient();
            //通過TrackerClient獲取TrackerServer對象
            TrackerServer trackerServer = trackerClient.getConnection();
            //獲取Tracker地址
            return "http://"+trackerServer.getInetSocketAddress().getHostString()+":"+ClientGlobal.getG_tracker_http_port();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /***
     * 獲取TrackerServer
     */
    public static TrackerServer getTrackerServer() throws Exception{
        //創建TrackerClient對象
        TrackerClient trackerClient = new TrackerClient();
        //通過TrackerClient獲取TrackerServer對象
        TrackerServer trackerServer = trackerClient.getConnection();
        return trackerServer;
    }

    /***
     * 獲取StorageClient
     * @return
     * @throws Exception
     */
    public static StorageClient getStorageClient() throws Exception{
        //獲取TrackerServer
        TrackerServer trackerServer = getTrackerServer();
        //通過TrackerServer創建StorageClient
        StorageClient storageClient = new StorageClient(trackerServer,null);
        return storageClient;
    }
}

1.4.3 文件上傳

創建一個FileController,在該控制器中實現文件上傳操作,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@RestController
@CrossOrigin
public class FileController {

    /***
     * 文件上傳
     * @return
     */
    @PostMapping(value = "/upload")
    public String upload(@RequestParam("file")MultipartFile file) throws Exception {
        //封裝一個FastDFSFile
        FastDFSFile fastDFSFile = new FastDFSFile(
                file.getOriginalFilename(), //文件名字
                file.getBytes(),            //文件字節數組
                StringUtils.getFilenameExtension(file.getOriginalFilename()));//文件擴展名

        //文件上傳
        String[] uploads = FastDFSClient.upload(fastDFSFile);
        //組裝文件上傳地址
        return FastDFSClient.getTrackerUrl()+"/"+uploads[0]+"/"+uploads[1];
    }
}

1.5 Postman測試文件上傳

步驟:

1、選擇post請求方式,輸入請求地址 http://localhost:18082/upload

2、填寫Headers

1
2
Key:Content-Type
Value:multipart/form-data

3、填寫body

選擇form-data 然後選擇文件file 點擊添加文件,最後發送即可。

訪問http://192.168.211.132:8080/group1/M00/00/00/wKjThF0DBzaAP23MAAXz2mMp9oM26.jpeg如下圖

注意,這裏每次訪問的端口是8080端口,訪問的端口其實是storage容器的nginx端口,如果想修改該端口可以直接進入到storage容器,然後修改即可。

1
2
docker exec -it storage  /bin/bash
vi /etc/nginx/conf/nginx.conf

修改後重啓storage即可根據自己修改的端口訪問圖片了。

2 相冊管理(實戰)

2.1 需求分析

相冊是用於存儲圖片的管理單元,我們通常會將商品的圖片先上傳到相冊中,在添加商品時可以直接在相冊中選擇,獲取相冊中的圖片地址,保存到商品表中。

前端交互方式見管理後臺的靜態原型

2.2 表結構分析

tb_album 表(**相冊表**)

字段名稱 字段含義 字段類型 備註
id 編號 BIGINT(20) 主鍵
title 相冊名稱 VARCHAR(100)  
image 相冊封面 VARCHAR(100)  
image_items 圖片列表 TEXT  

表中image_items數據如下示例:

1
2
3
4
5
6
7
8
9
10
11
12
[
  {
    "url": "http://localhost:9101/img/1.jpg",
    "uid": 1548143143154,
    "status": "success"
  },
  {
    "url": "http://localhost:9101/img/7.jpg",
    "uid": 1548143143155,
    "status": "success"
  }
]

2.3 代碼實現

2.3.1 Pojo

在changgou-service-goods-api工程中創建com.changgou.goods.pojo.Album,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Table(name="tb_album")
public class Album implements Serializable{

	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
	private Long id;//編號

    @Column(name = "title")
	private String title;//相冊名稱

    @Column(name = "image")
	private String image;//相冊封面

    @Column(name = "image_items")
	private String imageItems;//圖片列表

	//get...set...toString..
}

2.3.2 Dao

在changgou-service-goods中創建com.changgou.goods.dao.AlbumMapper接口,代碼如下:

1
2
public interface AlbumMapper extends Mapper<Album> {
}

2.3.3 業務層

(1)業務層接口

在changgou-service-goods中創建com.changgou.goods.service.AlbumService接口,並添加常用方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public interface AlbumService {

    /***
     * Album多條件分頁查詢
     * @param album
     * @param page
     * @param size
     * @return
     */
    PageInfo<Album> findPage(Album album, int page, int size);

    /***
     * Album分頁查詢
     * @param page
     * @param size
     * @return
     */
    PageInfo<Album> findPage(int page, int size);

    /***
     * Album多條件搜索方法
     * @param album
     * @return
     */
    List<Album> findList(Album album);

    /***
     * 刪除Album
     * @param id
     */
    void delete(Long id);

    /***
     * 修改Album數據
     * @param album
     */
    void update(Album album);

    /***
     * 新增Album
     * @param album
     */
    void add(Album album);

    /**
     * 根據ID查詢Album
     * @param id
     * @return
     */
     Album findById(Long id);

    /***
     * 查詢所有Album
     * @return
     */
    List<Album> findAll();
}

(2)業務層實現類

在changgou-service-goods中創建com.changgou.goods.service.impl.AlbumServiceImpl,並實現接口方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
@Service
public class AlbumServiceImpl implements AlbumService {

    @Autowired
    private AlbumMapper albumMapper;


    /**
     * Album條件+分頁查詢
     * @param album 查詢條件
     * @param page 頁碼
     * @param size 頁大小
     * @return 分頁結果
     */
    @Override
    public PageInfo<Album> findPage(Album album, int page, int size){
        //分頁
        PageHelper.startPage(page,size);
        //搜索條件構建
        Example example = createExample(album);
        //執行搜索
        return new PageInfo<Album>(albumMapper.selectByExample(example));
    }

    /**
     * Album分頁查詢
     * @param page
     * @param size
     * @return
     */
    @Override
    public PageInfo<Album> findPage(int page, int size){
        //靜態分頁
        PageHelper.startPage(page,size);
        //分頁查詢
        return new PageInfo<Album>(albumMapper.selectAll());
    }

    /**
     * Album條件查詢
     * @param album
     * @return
     */
    @Override
    public List<Album> findList(Album album){
        //構建查詢條件
        Example example = createExample(album);
        //根據構建的條件查詢數據
        return albumMapper.selectByExample(example);
    }


    /**
     * Album構建查詢對象
     * @param album
     * @return
     */
    public Example createExample(Album album){
        Example example=new Example(Album.class);
        Example.Criteria criteria = example.createCriteria();
        if(album!=null){
            // 編號
            if(!StringUtils.isEmpty(album.getId())){
                    criteria.andEqualTo("id",album.getId());
            }
            // 相冊名稱
            if(!StringUtils.isEmpty(album.getTitle())){
                    criteria.andLike("title","%"+album.getTitle()+"%");
            }
            // 相冊封面
            if(!StringUtils.isEmpty(album.getImage())){
                    criteria.andEqualTo("image",album.getImage());
            }
            // 圖片列表
            if(!StringUtils.isEmpty(album.getImageItems())){
                    criteria.andEqualTo("imageItems",album.getImageItems());
            }
        }
        return example;
    }

    /**
     * 刪除
     * @param id
     */
    @Override
    public void delete(Long id){
        albumMapper.deleteByPrimaryKey(id);
    }

    /**
     * 修改Album
     * @param album
     */
    @Override
    public void update(Album album){
        albumMapper.updateByPrimaryKey(album);
    }

    /**
     * 增加Album
     * @param album
     */
    @Override
    public void add(Album album){
        albumMapper.insert(album);
    }

    /**
     * 根據ID查詢Album
     * @param id
     * @return
     */
    @Override
    public Album findById(Long id){
        return  albumMapper.selectByPrimaryKey(id);
    }

    /**
     * 查詢Album全部數據
     * @return
     */
    @Override
    public List<Album> findAll() {
        return albumMapper.selectAll();
    }
}

2.3.4 控制層

在changgou-service-service工程中創建com.changgou.goods.controller.AlbumController,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
@RestController
@RequestMapping("/album")
@CrossOrigin
public class AlbumController {

    @Autowired
    private AlbumService albumService;

    /***
     * Album分頁條件搜索實現
     * @param album
     * @param page
     * @param size
     * @return
     */
    @PostMapping(value = "/search/{page}/{size}" )
    public Result<PageInfo> findPage(@RequestBody(required = false)  Album album, @PathVariable  int page, @PathVariable  int size){
        //執行搜索
        PageInfo<Album> pageInfo = albumService.findPage(album, page, size);
        return new Result(true,StatusCode.OK,"查詢成功",pageInfo);
    }

    /***
     * Album分頁搜索實現
     * @param page:當前頁
     * @param size:每頁顯示多少條
     * @return
     */
    @GetMapping(value = "/search/{page}/{size}" )
    public Result<PageInfo> findPage(@PathVariable  int page, @PathVariable  int size){
        //分頁查詢
        PageInfo<Album> pageInfo = albumService.findPage(page, size);
        return new Result<PageInfo>(true,StatusCode.OK,"查詢成功",pageInfo);
    }

    /***
     * 多條件搜索品牌數據
     * @param album
     * @return
     */
    @PostMapping(value = "/search" )
    public Result<List<Album>> findList(@RequestBody(required = false)  Album album){
        List<Album> list = albumService.findList(album);
        return new Result<List<Album>>(true,StatusCode.OK,"查詢成功",list);
    }

    /***
     * 根據ID刪除品牌數據
     * @param id
     * @return
     */
    @DeleteMapping(value = "/{id}" )
    public Result delete(@PathVariable Long id){
        albumService.delete(id);
        return new Result(true,StatusCode.OK,"刪除成功");
    }

    /***
     * 修改Album數據
     * @param album
     * @param id
     * @return
     */
    @PutMapping(value="/{id}")
    public Result update(@RequestBody  Album album,@PathVariable Long id){
        //設置主鍵值
        album.setId(id);
        //修改數據
        albumService.update(album);
        return new Result(true,StatusCode.OK,"修改成功");
    }

    /***
     * 新增Album數據
     * @param album
     * @return
     */
    @PostMapping
    public Result add(@RequestBody   Album album){
        albumService.add(album);
        return new Result(true,StatusCode.OK,"添加成功");
    }

    /***
     * 根據ID查詢Album數據
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Result<Album> findById(@PathVariable Long id){
        //根據ID查詢
        Album album = albumService.findById(id);
        return new Result<Album>(true,StatusCode.OK,"查詢成功",album);
    }

    /***
     * 查詢Album全部數據
     * @return
     */
    @GetMapping
    public Result<Album> findAll(){
        List<Album> list = albumService.findAll();
        return new Result<Album>(true, StatusCode.OK,"查詢成功",list) ;
    }
}

3 規格參數模板(實戰)

3.1 需求分析

規格參數模板是用於管理規格參數的單元。規格是例如顏色、手機運行內存等信息,參數是例如系統:安卓(Android)後置攝像頭像素:2000萬及以上 熱點:快速充電等信息 。

前端交互方式見管理後臺的靜態原型

3.2 表結構分析

規格參數模板相關的表有3個

tb_template 表(模板表)

字段名稱 字段含義 字段類型 字段長度 備註
id ID INT    
name 模板名稱 VARCHAR    
spec_num 規格數量 INT    
para_num 參數數量 INT    

tb_spec 表( 規格表)

字段名稱 字段含義 字段類型 字段長度 備註
id ID INT    
name 名稱 VARCHAR    
options 規格選項 VARCHAR    
seq 排序 INT    
template_id 模板ID INT    

tb_para 表(參數表)

字段名稱 字段含義 字段類型 字段長度 備註
id id INT    
name 名稱 VARCHAR    
options 選項 VARCHAR    
seq 排序 INT    
template_id 模板ID INT    

模板與規格是一對多關係 ,模板與參數是一對多關係

3.3 模板管理

3.3.1 Pojo

在changgou-service-goods-api工程中創建com.changgou.goods.pojo.Template,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Table(name="tb_template")
public class Template implements Serializable{

	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
	private Integer id;//ID

    @Column(name = "name")
	private String name;//模板名稱

    @Column(name = "spec_num")
	private Integer specNum;//規格數量

    @Column(name = "para_num")
	private Integer paraNum;//參數數量
	//..get..set..toString
}

3.3.2 Dao

在changgou-service-goods中創建com.changgou.goods.dao.TemplateMapper,代碼如下:

1
2
public interface TemplateMapper extends Mapper<Template> {
}

3.3.3 業務層

(1)業務層接口

在changgou-service-goods中創建com.changgou.goods.service.TemplateService接口,並添加相關方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public interface TemplateService {

    /***
     * Template多條件分頁查詢
     * @param template
     * @param page
     * @param size
     * @return
     */
    PageInfo<Template> findPage(Template template, int page, int size);

    /***
     * Template分頁查詢
     * @param page
     * @param size
     * @return
     */
    PageInfo<Template> findPage(int page, int size);

    /***
     * Template多條件搜索方法
     * @param template
     * @return
     */
    List<Template> findList(Template template);

    /***
     * 刪除Template
     * @param id
     */
    void delete(Integer id);

    /***
     * 修改Template數據
     * @param template
     */
    void update(Template template);

    /***
     * 新增Template
     * @param template
     */
    void add(Template template);

    /**
     * 根據ID查詢Template
     * @param id
     * @return
     */
     Template findById(Integer id);

    /***
     * 查詢所有Template
     * @return
     */
    List<Template> findAll();
}

(2)業務層接口實現類

在changgou-service-goods中創建com.changgou.goods.service.impl.TemplateServiceImpl實現類,並實現對應的方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
@Service
public class TemplateServiceImpl implements TemplateService {

    @Autowired
    private TemplateMapper templateMapper;


    /**
     * Template條件+分頁查詢
     * @param template 查詢條件
     * @param page 頁碼
     * @param size 頁大小
     * @return 分頁結果
     */
    @Override
    public PageInfo<Template> findPage(Template template, int page, int size){
        //分頁
        PageHelper.startPage(page,size);
        //搜索條件構建
        Example example = createExample(template);
        //執行搜索
        return new PageInfo<Template>(templateMapper.selectByExample(example));
    }

    /**
     * Template分頁查詢
     * @param page
     * @param size
     * @return
     */
    @Override
    public PageInfo<Template> findPage(int page, int size){
        //靜態分頁
        PageHelper.startPage(page,size);
        //分頁查詢
        return new PageInfo<Template>(templateMapper.selectAll());
    }

    /**
     * Template條件查詢
     * @param template
     * @return
     */
    @Override
    public List<Template> findList(Template template){
        //構建查詢條件
        Example example = createExample(template);
        //根據構建的條件查詢數據
        return templateMapper.selectByExample(example);
    }


    /**
     * Template構建查詢對象
     * @param template
     * @return
     */
    public Example createExample(Template template){
        Example example=new Example(Template.class);
        Example.Criteria criteria = example.createCriteria();
        if(template!=null){
            // ID
            if(!StringUtils.isEmpty(template.getId())){
                    criteria.andEqualTo("id",template.getId());
            }
            // 模板名稱
            if(!StringUtils.isEmpty(template.getName())){
                    criteria.andLike("name","%"+template.getName()+"%");
            }
            // 規格數量
            if(!StringUtils.isEmpty(template.getSpecNum())){
                    criteria.andEqualTo("specNum",template.getSpecNum());
            }
            // 參數數量
            if(!StringUtils.isEmpty(template.getParaNum())){
                    criteria.andEqualTo("paraNum",template.getParaNum());
            }
        }
        return example;
    }

    /**
     * 刪除
     * @param id
     */
    @Override
    public void delete(Integer id){
        templateMapper.deleteByPrimaryKey(id);
    }

    /**
     * 修改Template
     * @param template
     */
    @Override
    public void update(Template template){
        templateMapper.updateByPrimaryKey(template);
    }

    /**
     * 增加Template
     * @param template
     */
    @Override
    public void add(Template template){
        templateMapper.insert(template);
    }

    /**
     * 根據ID查詢Template
     * @param id
     * @return
     */
    @Override
    public Template findById(Integer id){
        return  templateMapper.selectByPrimaryKey(id);
    }

    /**
     * 查詢Template全部數據
     * @return
     */
    @Override
    public List<Template> findAll() {
        return templateMapper.selectAll();
    }
}

3.3.4 控制層

在changgou-service-goods中創建com.changgou.goods.controller.TemplateController,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
@RestController
@RequestMapping("/template")
@CrossOrigin
public class TemplateController {

    @Autowired
    private TemplateService templateService;

    /***
     * Template分頁條件搜索實現
     * @param template
     * @param page
     * @param size
     * @return
     */
    @PostMapping(value = "/search/{page}/{size}" )
    public Result<PageInfo> findPage(@RequestBody(required = false)  Template template, @PathVariable  int page, @PathVariable  int size){
        //執行搜索
        PageInfo<Template> pageInfo = templateService.findPage(template, page, size);
        return new Result(true,StatusCode.OK,"查詢成功",pageInfo);
    }

    /***
     * Template分頁搜索實現
     * @param page:當前頁
     * @param size:每頁顯示多少條
     * @return
     */
    @GetMapping(value = "/search/{page}/{size}" )
    public Result<PageInfo> findPage(@PathVariable  int page, @PathVariable  int size){
        //分頁查詢
        PageInfo<Template> pageInfo = templateService.findPage(page, size);
        return new Result<PageInfo>(true,StatusCode.OK,"查詢成功",pageInfo);
    }

    /***
     * 多條件搜索品牌數據
     * @param template
     * @return
     */
    @PostMapping(value = "/search" )
    public Result<List<Template>> findList(@RequestBody(required = false)  Template template){
        List<Template> list = templateService.findList(template);
        return new Result<List<Template>>(true,StatusCode.OK,"查詢成功",list);
    }

    /***
     * 根據ID刪除品牌數據
     * @param id
     * @return
     */
    @DeleteMapping(value = "/{id}" )
    public Result delete(@PathVariable Integer id){
        templateService.delete(id);
        return new Result(true,StatusCode.OK,"刪除成功");
    }

    /***
     * 修改Template數據
     * @param template
     * @param id
     * @return
     */
    @PutMapping(value="/{id}")
    public Result update(@RequestBody  Template template,@PathVariable Integer id){
        //設置主鍵值
        template.setId(id);
        //修改數據
        templateService.update(template);
        return new Result(true,StatusCode.OK,"修改成功");
    }

    /***
     * 新增Template數據
     * @param template
     * @return
     */
    @PostMapping
    public Result add(@RequestBody   Template template){
        templateService.add(template);
        return new Result(true,StatusCode.OK,"添加成功");
    }

    /***
     * 根據ID查詢Template數據
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Result<Template> findById(@PathVariable Integer id){
        //根據ID查詢
        Template template = templateService.findById(id);
        return new Result<Template>(true,StatusCode.OK,"查詢成功",template);
    }

    /***
     * 查詢Template全部數據
     * @return
     */
    @GetMapping
    public Result<Template> findAll(){
        List<Template> list = templateService.findAll();
        return new Result<Template>(true, StatusCode.OK,"查詢成功",list) ;
    }
}

3.4 規格管理

3.4.1 Pojo

在changgou-service-goods-api中創建com.changgou.goods.pojo.Spec,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Table(name="tb_spec")
public class Spec implements Serializable{

	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
	private Integer id;//ID

    @Column(name = "name")
	private String name;//名稱

    @Column(name = "options")
	private String options;//規格選項

    @Column(name = "seq")
	private Integer seq;//排序

    @Column(name = "template_id")
	private Integer templateId;//模板ID
	
	//get..set..toString
}

3.4.2 Dao

在changgou-service-goods中創建com.changgou.goods.dao.SpecMapper,代碼如下:

1
2
public interface SpecMapper extends Mapper<Spec> {
}

3.4.3 業務層

(1)業務層接口

在changgou-service-goods中創建com.changgou.goods.service.SpecService接口,並實現對應的方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public interface SpecService {

    /***
     * Spec多條件分頁查詢
     * @param spec
     * @param page
     * @param size
     * @return
     */
    PageInfo<Spec> findPage(Spec spec, int page, int size);

    /***
     * Spec分頁查詢
     * @param page
     * @param size
     * @return
     */
    PageInfo<Spec> findPage(int page, int size);

    /***
     * Spec多條件搜索方法
     * @param spec
     * @return
     */
    List<Spec> findList(Spec spec);

    /***
     * 刪除Spec
     * @param id
     */
    void delete(Integer id);

    /***
     * 修改Spec數據
     * @param spec
     */
    void update(Spec spec);

    /***
     * 新增Spec
     * @param spec
     */
    void add(Spec spec);

    /**
     * 根據ID查詢Spec
     * @param id
     * @return
     */
     Spec findById(Integer id);

    /***
     * 查詢所有Spec
     * @return
     */
    List<Spec> findAll();
}

(2)業務層實現類

在changgou-service-goods中創建com.changgou.goods.service.impl.SpecServiceImpl,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
@Service
public class SpecServiceImpl implements SpecService {

    @Autowired
    private SpecMapper specMapper;

    @Autowired
    private TemplateMapper templateMapper;

    /**
     * Spec條件+分頁查詢
     * @param spec 查詢條件
     * @param page 頁碼
     * @param size 頁大小
     * @return 分頁結果
     */
    @Override
    public PageInfo<Spec> findPage(Spec spec, int page, int size){
        //分頁
        PageHelper.startPage(page,size);
        //搜索條件構建
        Example example = createExample(spec);
        //執行搜索
        return new PageInfo<Spec>(specMapper.selectByExample(example));
    }

    /**
     * Spec分頁查詢
     * @param page
     * @param size
     * @return
     */
    @Override
    public PageInfo<Spec> findPage(int page, int size){
        //靜態分頁
        PageHelper.startPage(page,size);
        //分頁查詢
        return new PageInfo<Spec>(specMapper.selectAll());
    }

    /**
     * Spec條件查詢
     * @param spec
     * @return
     */
    @Override
    public List<Spec> findList(Spec spec){
        //構建查詢條件
        Example example = createExample(spec);
        //根據構建的條件查詢數據
        return specMapper.selectByExample(example);
    }


    /**
     * Spec構建查詢對象
     * @param spec
     * @return
     */
    public Example createExample(Spec spec){
        Example example=new Example(Spec.class);
        Example.Criteria criteria = example.createCriteria();
        if(spec!=null){
            // ID
            if(!StringUtils.isEmpty(spec.getId())){
                    criteria.andEqualTo("id",spec.getId());
            }
            // 名稱
            if(!StringUtils.isEmpty(spec.getName())){
                    criteria.andLike("name","%"+spec.getName()+"%");
            }
            // 規格選項
            if(!StringUtils.isEmpty(spec.getOptions())){
                    criteria.andEqualTo("options",spec.getOptions());
            }
            // 排序
            if(!StringUtils.isEmpty(spec.getSeq())){
                    criteria.andEqualTo("seq",spec.getSeq());
            }
            // 模板ID
            if(!StringUtils.isEmpty(spec.getTemplateId())){
                    criteria.andEqualTo("templateId",spec.getTemplateId());
            }
        }
        return example;
    }

    /**
     * 刪除
     * @param id
     */
    @Override
    public void delete(Integer id){
        //查詢模板
        Spec spec = specMapper.selectByPrimaryKey(id);
        //變更模板數量
        updateSpecNum(spec,-1);

        //刪除指定規格
        specMapper.deleteByPrimaryKey(id);
    }

    /**
     * 修改Spec
     * @param spec
     */
    @Override
    public void update(Spec spec){
        specMapper.updateByPrimaryKey(spec);
    }

    /**
     * 增加Spec
     * @param spec
     */
    @Override
    public void add(Spec spec){
        specMapper.insert(spec);
        //變更模板數量
        updateSpecNum(spec,1);
    }

    /**
     * 根據ID查詢Spec
     * @param id
     * @return
     */
    @Override
    public Spec findById(Integer id){
        return  specMapper.selectByPrimaryKey(id);
    }

    /**
     * 查詢Spec全部數據
     * @return
     */
    @Override
    public List<Spec> findAll() {
        return specMapper.selectAll();
    }


    /**
     * 修改模板統計數據
     * @param spec:操作的模板
     * @param count:變更的數量
     */
    public void updateSpecNum(Spec spec,int count){
        //修改模板數量統計
        Template template = templateMapper.selectByPrimaryKey(spec.getTemplateId());
        template.setSpecNum(template.getSpecNum()+count);
        templateMapper.updateByPrimaryKeySelective(template);
    }
}

這裏注意,每次執行增加和刪除的時候,需要調用模板,修改統計數據,另外大家思考下,如果是修改呢,是否會對模板統計數據造成變更呢?

3.4.4 控制層

在changgou-service-goods中創建com.changgou.goods.controller.SpecController,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
@RestController
@RequestMapping("/spec")
@CrossOrigin
public class SpecController {

    @Autowired
    private SpecService specService;

    /***
     * Spec分頁條件搜索實現
     * @param spec
     * @param page
     * @param size
     * @return
     */
    @PostMapping(value = "/search/{page}/{size}" )
    public Result<PageInfo> findPage(@RequestBody(required = false)  Spec spec, @PathVariable  int page, @PathVariable  int size){
        //執行搜索
        PageInfo<Spec> pageInfo = specService.findPage(spec, page, size);
        return new Result(true,StatusCode.OK,"查詢成功",pageInfo);
    }

    /***
     * Spec分頁搜索實現
     * @param page:當前頁
     * @param size:每頁顯示多少條
     * @return
     */
    @GetMapping(value = "/search/{page}/{size}" )
    public Result<PageInfo> findPage(@PathVariable  int page, @PathVariable  int size){
        //分頁查詢
        PageInfo<Spec> pageInfo = specService.findPage(page, size);
        return new Result<PageInfo>(true,StatusCode.OK,"查詢成功",pageInfo);
    }

    /***
     * 多條件搜索品牌數據
     * @param spec
     * @return
     */
    @PostMapping(value = "/search" )
    public Result<List<Spec>> findList(@RequestBody(required = false)  Spec spec){
        List<Spec> list = specService.findList(spec);
        return new Result<List<Spec>>(true,StatusCode.OK,"查詢成功",list);
    }

    /***
     * 根據ID刪除品牌數據
     * @param id
     * @return
     */
    @DeleteMapping(value = "/{id}" )
    public Result delete(@PathVariable Integer id){
        specService.delete(id);
        return new Result(true,StatusCode.OK,"刪除成功");
    }

    /***
     * 修改Spec數據
     * @param spec
     * @param id
     * @return
     */
    @PutMapping(value="/{id}")
    public Result update(@RequestBody  Spec spec,@PathVariable Integer id){
        //設置主鍵值
        spec.setId(id);
        //修改數據
        specService.update(spec);
        return new Result(true,StatusCode.OK,"修改成功");
    }

    /***
     * 新增Spec數據
     * @param spec
     * @return
     */
    @PostMapping
    public Result add(@RequestBody   Spec spec){
        specService.add(spec);
        return new Result(true,StatusCode.OK,"添加成功");
    }

    /***
     * 根據ID查詢Spec數據
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Result<Spec> findById(@PathVariable Integer id){
        //根據ID查詢
        Spec spec = specService.findById(id);
        return new Result<Spec>(true,StatusCode.OK,"查詢成功",spec);
    }

    /***
     * 查詢Spec全部數據
     * @return
     */
    @GetMapping
    public Result<Spec> findAll(){
        List<Spec> list = specService.findAll();
        return new Result<Spec>(true, StatusCode.OK,"查詢成功",list) ;
    }
}

3.5 參數管理

3.5.1 Pojo

在changgou-service-goods-api中創建com.changgou.goods.pojo.Para,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Table(name="tb_para")
public class Para implements Serializable{

	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
	private Integer id;//id

    @Column(name = "name")
	private String name;//名稱

    @Column(name = "options")
	private String options;//選項

    @Column(name = "seq")
	private Integer seq;//排序

    @Column(name = "template_id")
	private Integer templateId;//模板ID
	//get..set..toString
}

3.5.2 Dao

在changgou-service-goods中創建com.changgou.goods.dao.ParaMapper,代碼如下:

1
2
public interface ParaMapper extends Mapper<Para> {
}

3.5.3 業務層

(1)業務層接口

在changgou-service-goods中創建com.changgou.goods.service.ParaService接口,並添加常用方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public interface ParaService {

    /***
     * Para多條件分頁查詢
     * @param para
     * @param page
     * @param size
     * @return
     */
    PageInfo<Para> findPage(Para para, int page, int size);

    /***
     * Para分頁查詢
     * @param page
     * @param size
     * @return
     */
    PageInfo<Para> findPage(int page, int size);

    /***
     * Para多條件搜索方法
     * @param para
     * @return
     */
    List<Para> findList(Para para);

    /***
     * 刪除Para
     * @param id
     */
    void delete(Integer id);

    /***
     * 修改Para數據
     * @param para
     */
    void update(Para para);

    /***
     * 新增Para
     * @param para
     */
    void add(Para para);

    /**
     * 根據ID查詢Para
     * @param id
     * @return
     */
    Para findById(Integer id);

    /***
     * 查詢所有Para
     * @return
     */
    List<Para> findAll();
}

(2)業務層接口實現類

在changgou-service-goods中創建com.changgou.goods.service.impl.ParaServiceImpl接口實現類,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
@Service
public class ParaServiceImpl implements ParaService {

    @Autowired
    private ParaMapper paraMapper;

    @Autowired
    private TemplateMapper templateMapper;

    /**
     * Para條件+分頁查詢
     * @param para 查詢條件
     * @param page 頁碼
     * @param size 頁大小
     * @return 分頁結果
     */
    @Override
    public PageInfo<Para> findPage(Para para, int page, int size){
        //分頁
        PageHelper.startPage(page,size);
        //搜索條件構建
        Example example = createExample(para);
        //執行搜索
        return new PageInfo<Para>(paraMapper.selectByExample(example));
    }

    /**
     * Para分頁查詢
     * @param page
     * @param size
     * @return
     */
    @Override
    public PageInfo<Para> findPage(int page, int size){
        //靜態分頁
        PageHelper.startPage(page,size);
        //分頁查詢
        return new PageInfo<Para>(paraMapper.selectAll());
    }

    /**
     * Para條件查詢
     * @param para
     * @return
     */
    @Override
    public List<Para> findList(Para para){
        //構建查詢條件
        Example example = createExample(para);
        //根據構建的條件查詢數據
        return paraMapper.selectByExample(example);
    }


    /**
     * Para構建查詢對象
     * @param para
     * @return
     */
    public Example createExample(Para para){
        Example example=new Example(Para.class);
        Example.Criteria criteria = example.createCriteria();
        if(para!=null){
            // id
            if(!StringUtils.isEmpty(para.getId())){
                    criteria.andEqualTo("id",para.getId());
            }
            // 名稱
            if(!StringUtils.isEmpty(para.getName())){
                    criteria.andLike("name","%"+para.getName()+"%");
            }
            // 選項
            if(!StringUtils.isEmpty(para.getOptions())){
                    criteria.andEqualTo("options",para.getOptions());
            }
            // 排序
            if(!StringUtils.isEmpty(para.getSeq())){
                    criteria.andEqualTo("seq",para.getSeq());
            }
            // 模板ID
            if(!StringUtils.isEmpty(para.getTemplateId())){
                    criteria.andEqualTo("templateId",para.getTemplateId());
            }
        }
        return example;
    }

    /**
     * 刪除
     * @param id
     */
    @Override
    public void delete(Integer id){
        //根據ID查詢
        Para para = paraMapper.selectByPrimaryKey(id);
        //修改模板統計數據
        updateParaNum(para,-1);

        paraMapper.deleteByPrimaryKey(id);
    }

    /**
     * 修改Para
     * @param para
     */
    @Override
    public void update(Para para){
        paraMapper.updateByPrimaryKey(para);
    }

    /**
     * 增加Para
     * @param para
     */
    @Override
    public void add(Para para){
        paraMapper.insert(para);

        //修改模板統計數據
        updateParaNum(para,1);
    }

    /**
     * 根據ID查詢Para
     * @param id
     * @return
     */
    @Override
    public Para findById(Integer id){
        return  paraMapper.selectByPrimaryKey(id);
    }

    /**
     * 查詢Para全部數據
     * @return
     */
    @Override
    public List<Para> findAll() {
        return paraMapper.selectAll();
    }

    /**
     * 修改模板統計數據
     * @param para:操作的參數
     * @param count:變更的數量
     */
    public void updateParaNum(Para para, int count){
        //修改模板數量統計
        Template template = templateMapper.selectByPrimaryKey(para.getTemplateId());
        template.setParaNum(template.getParaNum()+count);
        templateMapper.updateByPrimaryKeySelective(template);
    }
}

3.5.4 控制層

在changgou-service-goods下創建com.changgou.goods.controller.ParaController,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
@RestController
@RequestMapping("/para")
@CrossOrigin
public class ParaController {

    @Autowired
    private ParaService paraService;

    /***
     * Para分頁條件搜索實現
     * @param para
     * @param page
     * @param size
     * @return
     */
    @PostMapping(value = "/search/{page}/{size}" )
    public Result<PageInfo> findPage(@RequestBody(required = false)  Para para, @PathVariable  int page, @PathVariable  int size){
        //執行搜索
        PageInfo<Para> pageInfo = paraService.findPage(para, page, size);
        return new Result(true,StatusCode.OK,"查詢成功",pageInfo);
    }

    /***
     * Para分頁搜索實現
     * @param page:當前頁
     * @param size:每頁顯示多少條
     * @return
     */
    @GetMapping(value = "/search/{page}/{size}" )
    public Result<PageInfo> findPage(@PathVariable  int page, @PathVariable  int size){
        //分頁查詢
        PageInfo<Para> pageInfo = paraService.findPage(page, size);
        return new Result<PageInfo>(true,StatusCode.OK,"查詢成功",pageInfo);
    }

    /***
     * 多條件搜索品牌數據
     * @param para
     * @return
     */
    @PostMapping(value = "/search" )
    public Result<List<Para>> findList(@RequestBody(required = false)  Para para){
        List<Para> list = paraService.findList(para);
        return new Result<List<Para>>(true,StatusCode.OK,"查詢成功",list);
    }

    /***
     * 根據ID刪除品牌數據
     * @param id
     * @return
     */
    @DeleteMapping(value = "/{id}" )
    public Result delete(@PathVariable Integer id){
        paraService.delete(id);
        return new Result(true,StatusCode.OK,"刪除成功");
    }

    /***
     * 修改Para數據
     * @param para
     * @param id
     * @return
     */
    @PutMapping(value="/{id}")
    public Result update(@RequestBody  Para para,@PathVariable Integer id){
        //設置主鍵值
        para.setId(id);
        //修改數據
        paraService.update(para);
        return new Result(true,StatusCode.OK,"修改成功");
    }

    /***
     * 新增Para數據
     * @param para
     * @return
     */
    @PostMapping
    public Result add(@RequestBody   Para para){
        paraService.add(para);
        return new Result(true,StatusCode.OK,"添加成功");
    }

    /***
     * 根據ID查詢Para數據
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Result<Para> findById(@PathVariable Integer id){
        //根據ID查詢
        Para para = paraService.findById(id);
        return new Result<Para>(true,StatusCode.OK,"查詢成功",para);
    }

    /***
     * 查詢Para全部數據
     * @return
     */
    @GetMapping
    public Result<Para> findAll(){
        List<Para> list = paraService.findAll();
        return new Result<Para>(true, StatusCode.OK,"查詢成功",list) ;
    }
}

4 商品分類(實戰)

4.1 需求分析

商品分類一共分三級管理,主要作用是在網站首頁中顯示商品導航,以及在管理後臺管理商品時使用。

前端交互方式見管理後臺的靜態原型

4.2 表結構分析

tb_category 表 (**商品分類**)

字段名稱 字段含義 字段類型 字段長度 備註
id 分類ID INT    
name 分類名稱 VARCHAR    
goods_num 商品數量 INT    
is_show 是否顯示 CHAR   0 不顯示 1顯示
is_menu 是否導航 CHAR   0 不時導航 1 爲導航
seq 排序 INT    
parent_id 上級ID INT    
template_id 模板ID INT    

商品分類與模板是多對一關係

4.3 實現

4.3.1 Pojo

在changgou-service-goods-api中創建com.changgou.goods.pojo.Category,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Table(name="tb_category")
public class Category implements Serializable{

	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
	private Integer id;//分類ID

    @Column(name = "name")
	private String name;//分類名稱

    @Column(name = "goods_num")
	private Integer goodsNum;//商品數量

    @Column(name = "is_show")
	private String isShow;//是否顯示

    @Column(name = "is_menu")
	private String isMenu;//是否導航

    @Column(name = "seq")
	private Integer seq;//排序

    @Column(name = "parent_id")
	private Integer parentId;//上級ID

    @Column(name = "template_id")
	private Integer templateId;//模板ID
	//..set..get..toString
}

4.3.2 Dao

在changgou-servicegoods中創建com.changgou.goods.dao.CategoryMapper接口,代碼如下:

1
2
public interface CategoryMapper extends Mapper<Category> {
}

4.3.3 業務層

(1)業務層接口

修改changgou-service-goods,添加com.changgou.goods.service.CategoryService接口,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public interface CategoryService {

    /***
     * Category多條件分頁查詢
     * @param category
     * @param page
     * @param size
     * @return
     */
    PageInfo<Category> findPage(Category category, int page, int size);

    /***
     * Category分頁查詢
     * @param page
     * @param size
     * @return
     */
    PageInfo<Category> findPage(int page, int size);

    /***
     * Category多條件搜索方法
     * @param category
     * @return
     */
    List<Category> findList(Category category);

    /***
     * 刪除Category
     * @param id
     */
    void delete(Integer id);

    /***
     * 修改Category數據
     * @param category
     */
    void update(Category category);

    /***
     * 新增Category
     * @param category
     */
    void add(Category category);

    /**
     * 根據ID查詢Category
     * @param id
     * @return
     */
     Category findById(Integer id);

    /***
     * 查詢所有Category
     * @return
     */
    List<Category> findAll();

    /***
     * 根據父節點ID查詢
     * @param pid:父節點ID
     */
    List<Category> findByParentId(Integer pid);
}

(2)業務層接口實現類

修改changgou-service-goods,添加com.changgou.goods.service.impl.CategoryServiceImpl接口實現類,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
@Service
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    private CategoryMapper categoryMapper;


    /**
     * Category條件+分頁查詢
     * @param category 查詢條件
     * @param page 頁碼
     * @param size 頁大小
     * @return 分頁結果
     */
    @Override
    public PageInfo<Category> findPage(Category category, int page, int size){
        //分頁
        PageHelper.startPage(page,size);
        //搜索條件構建
        Example example = createExample(category);
        //執行搜索
        return new PageInfo<Category>(categoryMapper.selectByExample(example));
    }

    /**
     * Category分頁查詢
     * @param page
     * @param size
     * @return
     */
    @Override
    public PageInfo<Category> findPage(int page, int size){
        //靜態分頁
        PageHelper.startPage(page,size);
        //分頁查詢
        return new PageInfo<Category>(categoryMapper.selectAll());
    }

    /**
     * Category條件查詢
     * @param category
     * @return
     */
    @Override
    public List<Category> findList(Category category){
        //構建查詢條件
        Example example = createExample(category);
        //根據構建的條件查詢數據
        return categoryMapper.selectByExample(example);
    }


    /**
     * Category構建查詢對象
     * @param category
     * @return
     */
    public Example createExample(Category category){
        Example example=new Example(Category.class);
        Example.Criteria criteria = example.createCriteria();
        if(category!=null){
            // 分類ID
            if(!StringUtils.isEmpty(category.getId())){
                    criteria.andEqualTo("id",category.getId());
            }
            // 分類名稱
            if(!StringUtils.isEmpty(category.getName())){
                    criteria.andLike("name","%"+category.getName()+"%");
            }
            // 商品數量
            if(!StringUtils.isEmpty(category.getGoodsNum())){
                    criteria.andEqualTo("goodsNum",category.getGoodsNum());
            }
            // 是否顯示
            if(!StringUtils.isEmpty(category.getIsShow())){
                    criteria.andEqualTo("isShow",category.getIsShow());
            }
            // 是否導航
            if(!StringUtils.isEmpty(category.getIsMenu())){
                    criteria.andEqualTo("isMenu",category.getIsMenu());
            }
            // 排序
            if(!StringUtils.isEmpty(category.getSeq())){
                    criteria.andEqualTo("seq",category.getSeq());
            }
            // 上級ID
            if(!StringUtils.isEmpty(category.getParentId())){
                    criteria.andEqualTo("parentId",category.getParentId());
            }
            // 模板ID
            if(!StringUtils.isEmpty(category.getTemplateId())){
                    criteria.andEqualTo("templateId",category.getTemplateId());
            }
        }
        return example;
    }

    /**
     * 刪除
     * @param id
     */
    @Override
    public void delete(Integer id){
        categoryMapper.deleteByPrimaryKey(id);
    }

    /**
     * 修改Category
     * @param category
     */
    @Override
    public void update(Category category){
        categoryMapper.updateByPrimaryKey(category);
    }

    /**
     * 增加Category
     * @param category
     */
    @Override
    public void add(Category category){
        categoryMapper.insert(category);
    }

    /**
     * 根據ID查詢Category
     * @param id
     * @return
     */
    @Override
    public Category findById(Integer id){
        return  categoryMapper.selectByPrimaryKey(id);
    }

    /**
     * 查詢Category全部數據
     * @return
     */
    @Override
    public List<Category> findAll() {
        return categoryMapper.selectAll();
    }

    /***
     * 根據父節點ID查詢
     * @param pid:父節點ID
     */
    @Override
    public List<Category> findByParentId(Integer pid) {
        Category category = new Category();
        category.setParentId(pid);
        return categoryMapper.select(category);
    }
}

4.3.4 控制層

修改changgou-service-goods,添加com.changgou.goods.controller.CategoryController,代碼如下:


@RestController
@RequestMapping("/category")
@CrossOrigin
public class CategoryController {

    @Autowired
    private CategoryService categoryService;

    /***
     * Category分頁條件搜索實現
     * @param category
     * @param page
     * @param size
     * @return
     */
    @PostMapping(value = "/search/{page}/{size}" )
    public Result<PageInfo> findPage(@RequestBody(required = false)  Category category, @PathVariable  int page, @PathVariable  int size){
        //執行搜索
        PageInfo<Category> pageInfo = categoryService.findPage(category, page, size);
        return new Result(true,StatusCode.OK,"查詢成功",pageInfo);
    }

    /***
     * Category分頁搜索實現
     * @param page:當前頁
     * @param size:每頁顯示多少條
     * @return
     */
    @GetMapping(value = "/search/{page}/{size}" )
    public Result<PageInfo> findPage(@PathVariable  int page, @PathVariable  int size){
        //分頁查詢
        PageInfo<Category> pageInfo = categoryService.findPage(page, size);
        return new Result<PageInfo>(true,StatusCode.OK,"查詢成功",pageInfo);
    }

    /***
     * 多條件搜索品牌數據
     * @param category
     * @return
     */
    @PostMapping(value = "/search" )
    public Result<List<Category>> findList(@RequestBody(required = false)  Category category){
        List<Category> list = categoryService.findList(category);
        return new Result<List<Category>>(true,StatusCode.OK,"查詢成功",list);
    }

    /***
     * 根據ID刪除品牌數據
     * @param id
     * @return
     */
    @DeleteMapping(value = "/{id}" )
    public Result delete(@PathVariable Integer id){
        categoryService.delete(id);
        return new Result(true,StatusCode.OK,"刪除成功");
    }

    /***
     * 修改Category數據
     * @param category
     * @param id
     * @return
     */
    @PutMapping(value="/{id}")
    public Result update(@RequestBody  Category category,@PathVariable Integer id){
        //設置主鍵值
        category.setId(id);
        //修改數據
        categoryService.update(category);
        return new Result(true,StatusCode.OK,"修改成功");
    }

    /***
     * 新增Category數據
     * @param category
     * @return
     */
    @PostMapping
    public Result add(@RequestBody   Category category){
        categoryService.add(category);
        return new Result(true,StatusCode.OK,"添加成功");
    }

    /***
     * 根據ID查詢Category數據
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Result<Category> findById(@PathVariable Integer id){
        //根據ID查詢
        Category category = categoryService.findById(id);
        return new Result<Category>(true,StatusCode.OK,"查詢成功",category);
    }

    /***
     * 查詢Category全部數據
     * @return
     */
    @GetMapping
    public Result<Category> findAll(){
        List<Category> list = categoryService.findAll();
        return new Result<Category>(true, StatusCode.OK,"查詢成功",list) ;
    }

    /**
     * 根據父ID查詢
     */
    @RequestMapping(value ="/list/{pid}")
    public Result<Category> findByPrantId(@PathVariable(value = "pid")Integer pid){
        //根據父節點ID查詢
        List<Category> list = categoryService.findByParentId(pid);
        return new Result<Category>(true,StatusCode.OK,"查詢成功",list);
    }
}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章