1. 程式人生 > >第1章-系統設計與工程搭建

第1章-系統設計與工程搭建

第一章節-系統設計與工程搭建


學習目標

  • 瞭解需求分析
  • 理解系統設計以及restful
  • 完成專案前期準備工作 (JDK 與 本地倉庫)
  • 完成專案父模組的搭建
  • 完成基礎微服務-標籤crud的功能,掌握公共異常類處理

1. 需求分析

1.1 本專案簡介

  • 這是一個專屬社交平臺,包括頭條,問答,活動,社交,吐槽,招聘 等六大板塊

1.2 需求規格說明書

在需求規格說明書.doxc

2.系統設計

2.1 系統架構

  • 採用前後端分離設計
  • 後端使用spring的全家桶實現
    • SpringBoot
    • SpringCloud
    • SpringMVC
    • SpringData

2.2 模組劃分

  • 本專案共分為18個模組(其中17個是微服務)
  • 結構資訊如下
模組名稱 模組中文名
tensquare_common 公共模組
tensquare_article 文章微服務
tensquare_base 基礎微服務
tensquare_friend 交友微服務
tensquare_gathering 活動微服務
tensquare_qa 問答微服務
tensquare_recruit 招聘微服務
tensquare_user 使用者微服務
tensquare_spit 吐槽微服務
tensquare_search 搜尋微服務
tensquare_web 前臺微服務閘道器
tensquare_manager 後臺為服務閘道器
tensquare_eureka 註冊中心
tensquare_config 配置中心
tensquare_sms 簡訊微服務
tensquare_article_crawler 文章爬蟲微服務
tensquare_user_crawler 使用者爬蟲微服務
tensquare_ai 人工智慧微服務

本章我們需要搭建的是

搭建父工程 tensquare-parent、
公共子模組tensquare-common、
基礎微服務 tensquare-base。

2.3 表結構分析

這裡我們採用分庫分表的設計,每個業務模組為一個獨立的資料庫

詳細請看資料庫文件.xlsx

  • tensquare_article 文章
  • tensquare_base 基礎
  • tensquare_friend 交友
  • tensquare_gathering 活動
  • tensquare_qa 問答
  • tensquare_recruit 招聘
  • tensquare_user 使用者
  • tensquare_spit 吐槽

2.4 API文件

課程提供了前後端開發介面文件(採用Swagger語言進行編寫),並與Ngin進行了整
合。雙擊Nginx執行檔案啟動後,在位址列輸入 http://localhost:801 即可訪問API文件

  • 前後端約定的返回碼列表:
狀態描述 返回碼
成功 20000
失敗 20001
使用者名稱密碼錯誤 20002
許可權不足 20003
遠端呼叫失敗 20004
重複操作 20005

2.5 理解RESTFUL

2.5.1 什麼是RestFul

RESTful架構,就是目前最流行的一種網際網路軟體架構。它結構清晰、符合標準、易
於理解、擴充套件方便,所以正得到越來越多網站的採用。REST這個詞,是Roy Thomas
Fielding在他2000年的博士論文中提出的 .

REST 是Representational State Transfer的縮寫,翻譯是”表現層狀態轉化”。 可以
總結為一句話:REST是所有Web應用都應該遵守的架構設計指導原則。

面向資源是REST最明顯的特徵,對於同一個資源的一組不同的操作。資源是伺服器
上一個可命名的抽象概念,資源是以名詞為核心來組織的,首先關注的是名詞。REST要
求,必須通過統一的介面來對資源執行各種操作。對於每個資源只能執行一組有限的操
作。

7個HTTP方法:GETPOSTPUTDELETEPATCHHEADOPTIONS

  • GET

安全且冪等
獲取表示
變更時獲取表示(快取)

響應狀態碼 含義
200(OK) 表示已在響應中發出
204(無內容) 資源有空表示
301(Moved Permanently) 資源的URI已被更新
303(See Other) 其他(如,負載均衡)
304(not modified) 資源未更改(快取)
400 (bad request) 指代壞請求(如,引數錯誤)
404 (not found) 資源不存在
406 (not acceptable) 服務端不支援所需表示
500 (internal server error) 通用錯誤響應
503 (Service Unavailable) 服務端當前無法處理請求
  • POST

不安全且不冪等
使用服務端管理的(自動產生)的例項號建立資源
建立子資源
北京市昌平區建材城西路金燕龍辦公樓一層 電話:400-618-9090部分更新資源
如果沒有被修改,則不過更新資源(樂觀鎖)

響應狀態碼 含義
200(OK) -如果現有資源已被更改
201(created) - 如果新資源被建立
202(accepted) - 已接受處理請求但尚未完成(非同步處理)
301(Moved Permanently) - 資源的URI被更新
303(See Other) - 其他(如,負載均衡)
400(bad request) - 指代壞請求
404 (not found) - 資源不存在
406 (not acceptable) - 服務端不支援所需表示
409 (conflict) - 通用衝突
412 (Precondition Failed) - 前置條件失敗(如執行條件更新時的衝突)
415 (unsupported media type) - 接受到的表示不受支援
500 (internal server error) - 通用錯誤響應
503 (Service Unavailable) - 服務當前無法處理請求
  • PUT

不安全但冪等
用客戶端管理的例項號建立一個資源
通過替換的方式更新資源
如果未被修改,則更新資源(樂觀鎖)

響應狀態碼 含義
200 (OK) – 如果已存在資源被更改
201 (created) – 如果新資源被建立
301(Moved Permanently) – 資源的URI已更改
303 (See Other) – 其他(如,負載均衡)
400 (bad request) – 指代壞請求
404 (not found) – 資源不存在

406 (not acceptable)- 服務端不支援所需表示
409 (conflict)|-- 通用衝突
412 (Precondition Failed)|-- 前置條件失敗(如執行條件更新時的衝突)
415 (unsupported media type)|-- 接受到的表示不受支援
500 (internal server error)|-- 通用錯誤響應
503 (Service Unavailable)|-- 服務當前無法處理請求

  • DELETE

不安全但冪等
刪除資源

響應狀態碼 含義
200 (OK) - 資源已被刪除
301 (Moved Permanently) - 資源的URI已更改
303 (See Other) - 其他,如負載均衡
400 (bad request) - 指代壞請求
404 (not found) - 資源不存在
409 (conflict) - 通用衝突
500 (internal server error) - 通用錯誤響應
503 (Service Unavailable) - 服務端當前無法處理請求

3.專案前期準備

3.1 開發環境

本課程所環境都是基於Docker的,所以需要一個centos7的linux並且安裝docker,記憶體建議最小4G以上

  • JDK1.8
  • 資料庫mysql 5.7
  • 開發工具 idea 2017.1.2
  • maven版本3.3.9
  • docker 最新版本
  • centos7
  • VMware Workstation Pro 12

3.2 MySql 建庫建表

使用docker環境建立

  • (1) 下載映象
docker pull centos/mysql-57-centos7
  • (2) 建立容器
docker run -di --name=tensquare_mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=1230 centos/mysql-57-centos7
  • (3) SQLyog 連線,並執行建立表語句

3.3 測試工具Postman

Postman中文版是postman這款強大網頁除錯工具的windows客戶端,提供功能強大的
Web API & HTTP 請求除錯。軟體功能非常強大,介面簡潔明晰、操作方便快捷,設計得
很人性化。Postman中文版能夠傳送任何型別的HTTP 請求 (GET, HEAD, POST, PUT…),
附帶任何數量的引數

  • (1) 預設安裝
  • (2) 註冊賬號
  • (3) 使用註冊賬號登入

4. 工程搭建

4.1 父工程搭建

  • (1) 新建Maven工程
  • (2) 填寫GroupId 和 Artifacetld
  • (3) 選擇儲存位置,完成建立
  • (4) 刪除src目錄
  • (5) 修改基礎pom.xml檔案 增加如下配置
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.12</version>
        </dependency>
    </dependencies>


    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>

        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
        <pluginRepository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
  • (6) 你可以啟用Enable Auto-Import 自動匯入依賴(修改了pom檔案idea右下角會提示)

4.2 搭建公共子模組

4.2.1 建立 搭建公共子模組 tensquare-common

4.2.2 建立返回結果實體類

  • (1) 新建entity包,包下建立類Result,用於控制器類返回結果

如果需要用idea生成getset alt + insert

package entity;

import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

@Data
@NoArgsConstructor
@Accessors(chain = true)
@Builder
public class Result {

    private boolean flag;//是否成功
    private Integer code;// 返回碼
    private String message;//返回資訊
    private Object data;// 返回資料

    public Result(boolean flag, Integer code, String message) {
        this.flag = flag;
        this.code = code;
        this.message = message;
    }

    public Result(boolean flag, Integer code, String message, Object data) {
        this.flag = flag;
        this.code = code;
        this.message = message;
        this.data = data;
    }

    /**
     * 成功返回實體
     * @param message
     * @return
     */
    public static Result success(String message) {
        return new Result(true,StatusCode.OK,message);
    }

    /**
     * 成功返回實體
     * @param message
     * @param data
     * @return
     */
    public static Result success(String message,Object data) {
        return new Result(true,StatusCode.OK,message,data);
    }


    /**
     * 失敗返回實體
     * @param code
     * @param message
     * @return
     */
    public static Result fail(Integer code,String message) {
        return new Result(false,code,message);
    }

    /**
     * 失敗返回實體
     * @param code
     * @param message
     * @param object
     * @return
     */
    public static Result fail(Integer code,String message,Object object) {
        return new Result(true,code,message,object);
    }
}
  • (2) 建立類PageResult ,用於返回分頁結果
package entity;

import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.util.List;

/**
 * 分頁的結果類
 *
 * @param <T>
 */
@Data
@NoArgsConstructor
@Accessors(chain = true)
@Builder
public class PageResult<T> {
    private Long total;
    private List<T> rows;

    public PageResult(Long total, List<T> rows) {
        super();
        this.total = total;
        this.rows = rows;
    }
}

4.2.3 返回碼定義類

package entity;

/**
 * 狀態碼實體類
 */
public class StatusCode {
    public static final int OK = 20000;//成功
    public static final int ERROR = 20001;//失敗
    public static final int LOGIN_ERROR = 20002;//使用者名稱或密碼錯誤
    public static final int ACCESS_ERROR = 20003;//許可權不足
    public static final int REMOTE_ERROR = 20004;//遠端呼叫失敗
    public static final int REP_ERROR = 20005;//重複操作
}

4.2.4 分散式ID生成器

由於我們的資料庫在生產環境中要分片部署(MyCat),所以我們不能使用資料庫本
身的自增功能來產生主鍵值,只能由程式來生成唯一的主鍵值。我們採用的是開源的
twitter( 非官方中文慣稱:推特.是國外的一個網站,是一個社交網路及微部落格服務) 的
snowflake (雪花)演算法。

snowflake 共有64bit組成

  • 1 bit: 不用 (1)
  • 41 bit : 時間戳 (2-42)
  • 10 bit : 工作機器ID (41-52)
  • 12 bit : 序列號 (52-64)

預設情況下41bit的時間戳可以支援該演算法使用到2082年,10bit的工作機器id可以
支援1024臺機器,序列號支援1毫秒產生4096個自增序列id . SnowFlake的優點是,整
體上按照時間自增排序,並且整個分散式系統內不會產生ID碰撞(由資料中心ID和機器ID
作區分),並且效率較高,經測試,SnowFlake每秒能夠產生26萬ID左右
我們課程中已經提供了分散式ID生成器.

tensquare-common 工程建立util包,將IdWorker.java 直接拷貝到 tensquare-common
工程的util包中。

5.基礎微服務-標籤CRUD

5.1 模組搭建

(1) 搭建基礎微服務模組 tensquare-base , pom.xml引入依賴

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.5</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.tensquare</groupId>
            <artifactId>tensquare-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

(2) 建立啟動類

tips : IDEA建立main方法的快捷鍵是 psvm

package com.tensquare.base;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import util.IdWorker;

/**
 * 啟動類
 */
@EnableAspectJAutoProxy
@EnableAutoConfiguration
@SpringBootApplication
public class BaseApplication {

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

    @Bean
    public IdWorker idWorker() {
        return new IdWorker(1, 1);
    }
}

(3) 在resources 下建立application.yml

server:
  port: 9001
spring:
  application:
    name: tensquare-base
  datasource:
    driverClassName: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/tensquare_base?characterEncoding=utf-8
    username: root
    password: 1230
  # jpa 相關配置
  jpa:
    database: mysql
    show-sql: true
    generate-ddl: true

5.2 標籤管理-CRUD

5.2.1 表結構分析

表名稱:tb_label

欄位名 欄位含義 欄位型別 備註
id ID 文字
labelname 標籤名稱 文字
state 狀態 文字 0:無效 1:有效
count 使用數量 整型
fans 關注數 整型
recommend 是否推薦 文字 0:不推薦 1:推薦

5.2.2 CRUD實現

  • (1) 實體類(entity)

com.tensquare.base.pojo 包下建立 Label

package com.tensquare.base.pojo;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Data
@Entity
@Table(name="tb_label")
public class Label {
    @Id
    private String id;//
    private String labelname;//標籤名稱
    private String state;//狀態
    private Long count;//使用數量
    private Long fans;//關注數
    private String recommend;//是否推薦
}
  • (2) 建立資料訪問介面(dao)
package com.tensquare.base.dao;

import com.tensquare.base.pojo.Label;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

/**
* 標籤資料訪問介面
* JpaRepository提供了基本的增刪改查
* JpaSpecificationExecutor用於做複雜的條件查詢
*/
public interface LabelDao
       extends JpaRepository<Label,String>,
               JpaSpecificationExecutor<Label> {

}
  • (3) 業務邏輯類(service)

com.tensquare.base.service 包下建立 LabelService

package com.tensquare.base.service;

import com.tensquare.base.dao.LabelDao;
import com.tensquare.base.pojo.Label;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype