第1章 SAAS-HRM系統概述與搭建環境
- 2019 年 11 月 15 日
- 筆記
版權聲明:本文為部落客原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/pyycsd/article/details/103041048
學習目標:
- 理解SaaS的基本概念
- 了解SAAS-HRM的基本需求和開發方式掌握Power Designer的用例圖
- 完成SAAS-HRM父模組及公共模組的環境搭建完成企業微服務中企業CRUD功能
1. 初識SaaS
1.1 雲服務的三種模式
1.1.1 IaaS(基礎設備即服務)
IaaS(Infrastructure as a Service),即基礎設施即服務。提供給消費者的服務是對所有電腦基礎設施的利用,包括處理CPU、記憶體、存儲、網路和其他基本的計算資源,用戶能夠部署和運行任意軟體,包括作業系統和應用程式。消費者不管理或控制任何雲計算基礎設施,但能控制作業系統的選擇、存儲空間、部署的應用,也有可能獲得有限制的網路組建(例如路由器、防火牆、負載均衡器等)的控制。
1.1.2 PaaS(平台即服務)
Paas(Platform as a Service),即平台及服務。提供給消費者的服務是把客戶端採用的開發語言和工具(例如java、python、.net等)開發的或收購的應用程式部署到供應商的雲計算基礎設施上去。客戶不需要管理或控制底層的雲基礎設施,包括網路、伺服器、作業系統、存儲等,但客戶端能控制部署的應用程式,也可能控制運行程式的託管環境配置。
1.1.3 SaaS(軟體即服務)
SaaS(Software as a Service),即軟體即服務。提供給消費者完整的軟體解決方案,你可以從軟體服務商處以租用或購買等方式獲取軟體應用,組織用戶即可通過Internet連接到該應用(通常使用Web瀏覽器)。所有基礎結構、中間件、應用軟體和應用數據都位於伺服器提供商的數據中心內。服務商負責管理硬體和軟體,並根據適當的服務協議確保應用和數據的可用性和安全性。SaaS讓組織能夠通過最低前期成本的應用快速建成投產。
1.1.4區別和聯繫

1.2 SaaS的概述
1.2.1 Saas詳解
SaaS(Software-as-a-service)的意思是軟體即服務。簡單說就是在線系統模式,即軟體服務商提供的軟體在線服務。
1.2.2 應用領域與行業前景
SaaS軟體就適用對象而言,可以劃分為針對個人的與針對企業的 面向個人的SaaS產品:在線文檔,賬務管理,文件管理,日程計劃、照片管理、聯繫人管理,等等雲類型的服務 而面向企業的SaaS產品主要包括:CRM(客戶關係管理)、ERP(企業資源計劃管理)、線上影片或者與群組通話會議、HRM(人力資源管理)、OA(辦公系統)、外勤管理、財務管理、審批管理等。

1.2.3 Saas與傳統軟體對比
- 降低企業成本:按需購買,即租即用,無需關注軟體的開發維護。
- 軟體更新迭代快速:和傳統軟體相比,由於saas部署在雲端,使得軟體的更新迭代速度加快
- 支援遠程辦公:將數據存儲到雲後,用戶即可通過任何連接到 Internet 的電腦或移動設備訪問其資訊

2. SaaS-HRM 需求分析
2.1 什麼是SaaS-HRM
SaaS-HRM是基於saas模式的人力資源管理系統。他不同於傳統的人力資源軟體應用,使用者只需打開瀏覽器即可管理上百人的薪酬、績效、社保、入職離職。
2.2 原型分析法
原型分析的理念是指在獲取一組基本需求之後,快速地構造出一個能夠反映用戶需求的初始系統原型。讓用戶看到 未來系統的概貌,以 便判斷哪些功能是符合要求的,哪些方面還需要改進,然後不斷地對這些需求進一步補充、細化和修改。依次類推,反覆進行,直到用戶滿意為止並由此開發出完整 的系統。 簡單的說,原型分析法就是在最短的時間內,以最直觀的方式獲取用戶最真實的需求
2.3 UML的用例圖
2.3.1 UML統一建模語言
Unified Modeling Language (UML)又稱統一建模語言或標準建模語言,是始於1997年一個OMG標準,它是一個支援模型化和軟體系統開發的圖形化語言,為軟體開發的所有階段提供模型化和可視化支援,包括由需求分析到 規格,到構造和配置。 面向對象的分析與設計(OOA&D,OOAD)方法的發展在80年代末至90年代中出現了一個高潮,UML是這個高潮的產物。它不僅統一了Booch、Rumbaugh和Jacobson的表示方法,而且對其作了進一步的 發展,並最終統一為大眾所接受的標準建模語言。UML中包含很多圖形(用例圖,類圖,狀態圖等等),其中用例 圖是最能體現系統結構的圖形
2.3.2用例圖
用例圖(use case)主要用來描述用戶與用例之間的關聯關係。說明的是誰要使用系統,以及他們使用該系統可以做些什麼。一個用例圖包含了多個模型元素,如系統、參與者和用例,並且顯示這些元素之間的各種關係,如泛 化、關聯和依賴。它展示了一個外部用戶能夠觀察到的系統功能模型圖。

3系統設計
3.1開發方式
SaaS-IHRM系統採用前後端分離的開發方式。

後端給前端提供數據,前端負責HTML渲染(可以在伺服器渲染,也可以在瀏覽器渲染)和用戶交互。雙方通過文檔的形式規範介面內容
3.2技術架構
(1)前端技術棧 以Node.js為核心的Vue.js前端技術生態架構 (2)後端技術棧 SpringBoot+SpringCloudAlibaba+SpringMVC+MyBatis
3.3系統結構圖

執行文件啟動 後,在地址欄輸入http://localhost:801 即可訪問API文檔
4 工程搭建
4.1 前置知識點的說明
Saas-HRM系統後端採用SpringBoot+SpringCloudAlibaba+SpringMVC+MyBatis Saas-HRM系統前端採用基於nodejs的vue框架完成編寫使用element-ui組件庫快速開發前端介面
4.2 開發環境要求
- JDK1.8
- 資料庫mysql 5.7
- 開發工具 idea
- maven版本3.3.9
4.3 構建公共子模組
4.3.1 構建公共子模組ihrm-common
(1)導入pom.xml依賴
<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.pyy.ihrm</groupId> <artifactId>ihrm-common</artifactId> <version>1.0-SNAPSHOT</version> <description>IHRM-公用模組</description> <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> <java.version>1.8</java.version> <swagger.version>2.9.2</swagger.version> <swagger.model.version>1.5.21</swagger.model.version> <swagger.annotations.version>1.5.21</swagger.annotations.version> <fastjson.version>1.2.58</fastjson.version> <lombok.version>1.16.16</lombok.version> <common.lang3.version>3.8.1</common.lang3.version> </properties> <dependencies> <!-- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> <!-- swagger2 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${swagger.version}</version> <exclusions> <exclusion> <groupId>io.swagger</groupId> <artifactId>swagger-models</artifactId> </exclusion> </exclusions> </dependency> <!-- swagger-models --> <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-models</artifactId> <version>${swagger.model.version}</version> </dependency> <!-- swagger-ui --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${swagger.version}</version> </dependency> <!-- fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <!-- commons lang3 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${common.lang3.version}</version> </dependency> </dependencies> <build> <plugins> <!-- maven 編譯插件 --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
(2)新建com.pyy.ihrm.common.response包,通用類
ResultCode.java 通用狀態碼
package cn.com.thtf.common.response; /** * ======================== * 通用響應狀態 * Created with IntelliJ IDEA. * User:pyy * Date:2019/6/6 * Time:10:10 * Version: v1.0 * ======================== */ public enum ResultCode { /* 成功狀態碼 */ SUCCESS(200,"SUCCESS"), /* 錯誤狀態碼 */ FAIL(500,"ERROR"), /* 參數錯誤:10001-19999 */ PARAM_IS_INVALID(10001, "參數無效"), PARAM_IS_BLANK(10002, "參數為空"), PARAM_TYPE_BIND_ERROR(10003, "參數格式錯誤"), ILLEGAL_PARAM(10004, "查詢標識參數非法!(00=全部 01=結構化 02=非結構化)"), FILE_MAX_SIZE_OVERFLOW(10005, "上傳尺寸過大"), FILE_ACCEPT_NOT_SUPPORT(10006, "上傳文件格式不支援"), SET_UP_AT_LEAST_ONE_ADMIN(10007, "至少指定一個管理員"), URL_INVALID(10008, "地址不合法"), LINK_AND_LOGOUT_NO_MATCH(10009, "主頁地址和註銷地址IP不一致"), IP_AND_PORT_EXISTED(10010, "當前IP和埠已經被佔中"), LINK_IS_REQUIRED(10011, "生成第三方token認證資訊: 主頁地址不能為空,請完善資訊"), DICT_LENGTH_NOT_BLANK(10012, "字典值長度不能為空"), PWD_NO_VALID(100013, "密碼必須是6-20 位,字母、數字、字元(`~!@#$%^&*)"), /* 用戶錯誤:20001-29999*/ USER_NOT_LOGGED_IN(20001, "用戶未登錄"), USER_LOGIN_ERROR(20002, "帳號不存在或密碼錯誤"), USER_ACCOUNT_FORBIDDEN(20003, "帳號已被禁用"), USER_NOT_EXIST(20004, "用戶不存在"), USER_HAS_EXISTED(20005, "用戶已存在"), /* 業務錯誤:30001-39999 */ //BUSINESS_GROUP_NO_ALLOWED_DEL(30001, "應用分組已經被 {0} 個應用【{1}{2}】使用,不能刪除"), NAME_EXISTED(30001, "{0}名稱已存在"), CODE_EXISTED(30002, "{0}編碼已存在"), BUSINESS_OUTER_DATASOURCE_NO_ALLOWED_DEL(30002, "數據源已經被 {0} 個資源【{1}{2}】使用,不能刪除"), RESOURCE_CATEGORY_EXIST_DEPEND(30003, "當前分類下存在 {0} 個子分類【{1}{2}】,不能刪除"), RESOURCE_CATEGORY_EXIST_RESOURCE_DEPEND(30004, "資源分類已經被 {0} 個資源【{1}{2}】使用,不能刪除"), RESOURCE_CATEGORY_EXIST_TEMPLATE_DEPEND(30005, "資源分類已經被 {0} 個標籤模板【{1}{2}】使用,不能刪除"), LABEL_EXIST_TEMPLATE_DEPEND_NOTALLOW_UPDATE(30006, "標籤已經被 {0} 個數據資源【{1}{2}】使用,不能修改"), LABEL_EXIST_TEMPLATE_DEPEND_NOTALLOW_DELETE(30007, "標籤已經被 {0} 個數據資源【{1}{2}】使用,不能刪除"), DICT_ENGLISH_NOT_BLANK(30006, "標籤值域依賴標籤英文名不能為空"), BUSINESS_IS_TOP(30006, "已經到最頂部"), BUSINESS_IS_BOTTOM(30007, "已經到最底部"), ONLY_ROOT_DEPARTMENT(30009, "組織機構只能存在一個根機構"), DEPART_CODE_EXISTED(30010, "組織機構編碼已存在"), DEPART_CONTAINS_USERS(30011, "該機構下是存在 {0} 個用戶 【{1}{2}】,不允許刪除"), DEPART_CONTAINS_SON(30012, "該機構下是存在子級機構,不允許刪除"), DEPART_PARENT_IS_SELF(30013, "選擇的父機構不能為本身"), DICT_EXIST_DEPEND(30014, "該字典數據存在詳情依賴,不允許刪除"), DICT_DETAIL_LOCK(30015, "該字典數據被鎖定,不允許修改或刪除"), DEPART_CODE_EXISTED_WITH_ARGS(30016, "組織機構編碼【{0}】系統已存在"), USER_GROUP_DEPEND_ROLE(30017, "角色被用戶組關聯,不允許刪除"), ROLE_NAME_EXISTS(30018, "角色名稱已存在"), USER_GROUP_NAME_EXISTS(30019, "用戶組名稱已存在"), USER_GROUP_DEPEND_USER(30020, "用戶組已經分配有 {0} 個用戶【{1}{2}】,不能刪除"), PAGE_EXIST_DEPEND(30021, "系統頁面關聯有功能操作,不能刪除"), APP_EXIST_DEPEND_WITH_ARGS(30022, "當前功能菜單,已分配角色【{0}】不能刪除"), USER_EXISTED_WITH_GROUP(30017, "組織機構編碼【{0}】系統已存在"), USER_IS_ADMIN(30018, "當前用戶為管理員不允許刪除"), PARENT_NODE_IS_SELF(30019, "當前節點父節點不能為自己"), STARTTIME_ENDTIME_NOT_BLANK(30020, "生效時間和失效失效必須同時存在"), ENDTIME_MORETHAN_STARTTIME(30021, "失效失效必須大於生效時間"), CAS_TEMPLATE_NOT_FOUND(30022, "CAS Service 模板丟失,請至少一個CAS註冊模板數據"), LINK_LOGOUT_IP_NOT_EQUALS(30021, "主頁地址和註銷地址IP和埠不一致"), DICT_TYPE_ERROR(30022, "字典類型參數不正確"), DB_TYPE_NOT_SUPPORT(30023, "資料庫類型系統不支援"), /* 系統錯誤:40001-49999 */ SYSTEM_INNER_ERROR(40001, "系統繁忙,請稍後重試"), UPLOAD_ERROR(40002, "系統異常,上傳文件失敗"), /* 數據錯誤:50001-599999 */ RESULT_DATA_NONE(50001, "【{0}】數據未找到"), DATA_YEAR_TO_LARGE(50002, "年份最大支援20年"), DATA_IS_WRONG(50002, "數據有誤"), DATA_ALREADY_EXISTED(50003, "數據已存在"), /* 介面錯誤:60001-69999 */ INTERFACE_INNER_INVOKE_ERROR(60001, "內部系統介面調用異常"), INTERFACE_OUTTER_INVOKE_ERROR(60002, "外部系統介面調用異常"), INTERFACE_FORBID_VISIT(60003, "該介面禁止訪問"), INTERFACE_ADDRESS_INVALID(60004, "介面地址無效"), INTERFACE_REQUEST_TIMEOUT(60005, "介面請求超時"), INTERFACE_EXCEED_LOAD(60006, "介面負載過高"), /* 許可權錯誤 */ PERMISSION_UNAUTHENTICATED(70001,"此操作需要登陸系統!"), PERMISSION_UNAUTHORISE(70002,"許可權不足,無權操作!"), PERMISSION_EXPIRE(401,"登錄狀態過期!"), PERMISSION_LIMIT(70004, "訪問次數受限制"); //操作程式碼 int code; //提示資訊 String message; ResultCode(int code, String message){ this.code = code; this.message = message; } public int code() { return code; } public String message() { return message; } public void setCode(int code) { this.code = code; } public void setMessage(String message) { this.message = message; } }
Result.java 響應結果
package com.pyy.ihrm.common.response; import com.fasterxml.jackson.annotation.JsonInclude; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; /** * ======================== * 統一響應結果集 * Created with IntelliJ IDEA. * User:pyy * Date:2019/6/6 * Time:10:10 * Version: v1.0 * ======================== */ @JsonInclude(JsonInclude.Include.NON_NULL) // 非空數據不顯示 @Setter @Getter @ApiModel(value = "Result",description = "API介面返回值") public class Result<T> { @ApiModelProperty("操作編碼") int code; @ApiModelProperty("響應資訊") String message; @ApiModelProperty("結果數據") T data; @ApiModelProperty("請求響應時間戳") Long timestamp; public Result(ResultCode resultCode){ this.code = resultCode.code(); this.message = resultCode.message(); this.timestamp = System.currentTimeMillis(); } public Result(int code, String msg){ this.code = code; this.message = msg; this.timestamp = System.currentTimeMillis(); } public Result(ResultCode resultCode, T data){ this.code = resultCode.code(); this.message = resultCode.message(); this.data = data; this.timestamp = System.currentTimeMillis(); } public static Result SUCCESS(){ return new Result(ResultCode.SUCCESS); } public static <T> Result SUCCESS(T data){ return new Result(ResultCode.SUCCESS, data); } public static Result FAIL(){ return new Result(ResultCode.FAIL); } }
QueryResult.java 查詢結果
package com.pyy.ihrm.common.response; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.*; import java.util.List; /** * ======================== * 查詢結果 * Created with IntelliJ IDEA. * User:pyy * Date:2019/6/6 * Time:10:10 * Version: v1.0 * ======================== */ @Setter @Getter @NoArgsConstructor @AllArgsConstructor @ApiModel(value = "QueryResult",description = "分頁結果") public class QueryResult<T> { @ApiModelProperty("數據列表") private List<T> list; @ApiModelProperty("數據總數") private Long total; }
(3)新建com.pyy.ihrm.common.utils.SnowflakeId,分散式ID生成器
目前微服務架構盛行,在分散式系統中的操作中都會有一些全局性ID的需求,所以我們不能使用資料庫本身的自增 功能來產生主鍵值,只能由程式來生成唯一的主鍵值。我們採用的是開源的twitter( 非官方中文慣稱:推特.是國外的一個網站,是一個社交網路及微部落格服務) 的snowflake (雪花)演算法。

各個段解析:
分段 |
作用 |
說明 |
---|---|---|
1bit |
保留(不用) |
— |
41bit |
時間戳,精確到毫秒 |
最多可以支援69年的跨度 |
5bit |
機器id |
最多支援2的5次方(32)個節點 |
5bit |
業務編碼 |
最多支援2的5次方(32)個節點 |
12bit |
毫秒內的計數器 |
每個節點每毫秒最多產生2的12次方(4096)個id |
默認情況下41bit的時間戳可以支援該演算法使用到2082年,10bit的工作機器id可以支援1024台機器,序列號 支援1毫秒產生4096個自增序列id . SnowFlake的優點是,整體上按照時間自增排序,並且整個分散式系統內不會產生ID碰撞(由數據中心ID和機器ID作區分),並且效率較高,經測試,SnowFlake每秒能夠產生26萬ID 左右
package com.pyy.ihrm.common.utils; import java.util.Random; public class SnowflakeId { // ==============================Fields=========================================== /** * 開始時間截 (2015-01-01) */ private static final long TWEPOCH = 1420041600000L; /** * 機器id所佔的位數 */ private static final long WORKER_ID_BITS = 5L; /** * 數據標識id所佔的位數 */ private static final long DATA_CENTER_ID_BITS = 5L; /** * 支援的最大機器id,結果是31 (這個移位演算法可以很快的計算出幾位二進位數所能表示的最大十進位數) */ private static final long MAX_WORKER_ID = -1L ^ (-1L << WORKER_ID_BITS); /** * 支援的最大數據標識id,結果是31 */ private static final long MAX_DATA_CENTER_ID = -1L ^ (-1L << DATA_CENTER_ID_BITS); /** * 序列在id中占的位數 */ private static final long SEQUENCE_BITS = 12L; /** * 機器ID向左移12位 */ private static final long WORKER_ID_SHIFT = SEQUENCE_BITS; /** * 數據標識id向左移17位(12+5) */ private static final long DATA_CENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS; /** * 時間截向左移22位(5+5+12) */ private static final long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATA_CENTER_ID_BITS; /** * 生成序列的掩碼,這裡為4095 (0b111111111111=0xfff=4095) */ private static final long SEQUENCE_MASK = -1L ^ (-1L << SEQUENCE_BITS); /** * 工作機器ID(0~31) */ private static long workerId; /** * 數據中心ID(0~31) */ private static long datacenterId; /** * 毫秒內序列(0~4095) */ private static long sequence = 0L; /** * 上次生成ID的時間截 */ private static long lastTimestamp = -1L; //==============================Constructors===================================== public SnowflakeId() { } public static SnowflakeId getInstance(){ int workerId=new Random().nextInt(30); int datacenterId=new Random().nextInt(30); return new SnowflakeId(workerId,datacenterId); } /** * 構造函數 * * @param workerId 工作ID (0~31) * @param datacenterId 數據中心ID (0~31) */ private SnowflakeId(long workerId, long datacenterId) { if (workerId > MAX_WORKER_ID || workerId < 0) { throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", MAX_WORKER_ID)); } if (datacenterId > MAX_DATA_CENTER_ID || datacenterId < 0) { throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", MAX_DATA_CENTER_ID)); } SnowflakeId.workerId = workerId; SnowflakeId.datacenterId = datacenterId; } // ==============================Methods========================================== /** * 獲得下一個ID (該方法是執行緒安全的) * * @return SnowflakeId */ public static synchronized long getId() { long timestamp = timeGen(); //如果當前時間小於上一次ID生成的時間戳,說明系統時鐘回退過這個時候應當拋出異常 if (timestamp < lastTimestamp) { throw new RuntimeException( String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); } //如果是同一時間生成的,則進行毫秒內序列 if (lastTimestamp == timestamp) { sequence = (sequence + 1) & SEQUENCE_MASK; //毫秒內序列溢出 if (sequence == 0) { //阻塞到下一個毫秒,獲得新的時間戳 timestamp = tilNextMillis(lastTimestamp); } } //時間戳改變,毫秒內序列重置 else { sequence = 0L; } //上次生成ID的時間截 lastTimestamp = timestamp; //移位並通過或運算拼到一起組成64位的ID return ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT) | (datacenterId << DATA_CENTER_ID_SHIFT) | (workerId << WORKER_ID_SHIFT) | sequence; } /** * 阻塞到下一個毫秒,直到獲得新的時間戳 * * @param lastTimestamp 上次生成ID的時間截 * @return 當前時間戳 */ protected static long tilNextMillis(long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { timestamp = timeGen(); } return timestamp; } /** * 返回以毫秒為單位的當前時間 * * @return 當前時間(毫秒) */ protected static long timeGen() { return System.currentTimeMillis(); } public static void main(String[] args) { Long i = getId(); System.out.println(i); } }
4.3.2 搭建公共的實體類模組 ihrm_common_model
引入pom.xml
<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.pyy.ihrm</groupId> <artifactId>ihrm-common-model</artifactId> <version>1.0-SNAPSHOT</version> <description>IHRM-公共的實體類模組</description> <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> <java.version>1.8</java.version> <swagger.version>2.9.2</swagger.version> <swagger.model.version>1.5.21</swagger.model.version> <swagger.annotations.version>1.5.21</swagger.annotations.version> <fastjson.version>1.2.58</fastjson.version> </properties> <dependencies> <!-- 引入 ihrm-common --> <dependency> <groupId>com.pyy.ihrm</groupId> <artifactId>ihrm-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> <build> <plugins> <!-- maven 編譯插件 --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
5企業微服務-企業CRUD
5.1模組搭建
(1)搭建企業微服務模組ihrm-company, pom.xml引入依賴
<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.pyy.ihrm</groupId> <artifactId>ihrm-company</artifactId> <version>1.0-SNAPSHOT</version> <description>企業微服務</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.7.RELEASE</version> <relativePath/> </parent> <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> <java.version>1.8</java.version> <druid.version>1.1.16</druid.version> <mysql.version>5.1.16</mysql.version> <tk.mybatis.version>2.1.5</tk.mybatis.version> <pagehelper.version>1.2.10</pagehelper.version> </properties> <dependencies> <!-- 引入 ihrm-common --> <dependency> <groupId>com.pyy.ihrm</groupId> <artifactId>ihrm-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!-- 引入 ihrm-common-model --> <dependency> <groupId>com.pyy.ihrm</groupId> <artifactId>ihrm-common-model</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!-- springboot web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- spring aspects --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </dependency> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>${druid.version}</version> </dependency> <!-- tk mybatis --> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>${tk.mybatis.version}</version> </dependency> <!-- pageHelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>${pagehelper.version}</version> </dependency> </dependencies> <build> <!-- 工程打包名稱--> <finalName>${project.artifactId}-${project.version}</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> <includes> <include>**/*Mapper.xml</include> <include>**/*.yml</include> <include>**/*.properties</include> <include>**/*.html</include> <include>**/*.xml</include> </includes> </resource> </resources> </build> </project>
(2)添加配置文件
application.yml
server: port: 9001 spring: application: name: ihrm-company #指定服務名 profiles: active: dev
application-dev.yml
spring: datasource: #1.JDBC type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/ihrm?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC username: root password: 123456 druid: #2.連接池配置 #初始化連接池的連接數量 大小,最小,最大 initial-size: 5 min-idle: 5 max-active: 20 #配置獲取連接等待超時的時間 max-wait: 60000 #配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒 time-between-eviction-runs-millis: 60000 # 配置一個連接在池中最小生存的時間,單位是毫秒 min-evictable-idle-time-millis: 30000 validation-query: SELECT 1 FROM DUAL test-while-idle: true test-on-borrow: true test-on-return: false # 是否快取preparedStatement,也就是PSCache 官方建議MySQL下建議關閉 個人建議如果想用SQL防火牆 建議打開 pool-prepared-statements: true max-pool-prepared-statement-per-connection-size: 20 # 配置監控統計攔截的filters,去掉後監控介面sql無法統計,'wall'用於防火牆 filter: stat: merge-sql: true slow-sql-millis: 5000 #3.基礎監控配置 web-stat-filter: enabled: true url-pattern: /* #設置不統計哪些URL exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" session-stat-enable: true session-stat-max-count: 100 stat-view-servlet: enabled: true url-pattern: /druid/* reset-enable: true #設置監控頁面的登錄名和密碼 login-username: admin login-password: admin allow: 127.0.0.1 #deny: 192.168.1.100 #分頁插件配置 pagehelper: helperDialect: mysql #分頁合理化參數,默認值為false。當該參數設置為 true 時,pageNum<=0 時會查詢第一頁, pageNum>pages(超過總數時),會查詢最後一頁。默認false 時,直接根據參數進行查詢 reasonable: true #mybatis配置 mybatis: type-aliases-package: com.pyy.ihrm.company.po mapper-locations: 'classpath:mappers/*.xml' configuration: map-underscore-to-camel-case: true
(3)配置啟動類
package com.pyy.ihrm.company; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.transaction.annotation.EnableTransactionManagement; import tk.mybatis.spring.annotation.MapperScan; /** * ======================== * 項目啟動類 * Created with IntelliJ IDEA. * User:pyy * Date:2019/11/11 17:16 * Version: v1.0 * ======================== */ @SpringBootApplication @MapperScan(basePackages = {"com.pyy.ihrm.company.mapper"}) @EnableTransactionManagement @EnableAspectJAutoProxy @EnableScheduling public class CompanyApplication { public static void main(String[] args) { SpringApplication.run(CompanyApplication.class, args); } }
(4)啟動SpringBoot項目訪問druid, http://localhost:tomcat埠號/項目名稱/druid/

通過上面配置的用戶名和密碼登錄:admin/admin,登錄後可以查詢數據源配置資訊

5.2 公共異常處理
為了使我們的程式碼更容易維護,同時給用戶最好的用戶體驗,有必要對系統中可能出現的異常進行處理。spring提供了@ControllerAdvice註解和@ExceptionHandler可以很好的在控制層對異常進行統一處理 (1)添加自定義的異常
package com.pyy.ihrm.company.exception; import com.pyy.ihrm.common.response.ResultCode; import lombok.Getter; import lombok.Setter; import java.text.MessageFormat; /** * ======================== * 自定義異常類 * Created with IntelliJ IDEA. * User:pyy * Date:2019/11/11 17:16 * Version: v1.0 * ======================== */ @Setter @Getter public class CustomException extends RuntimeException { //錯誤程式碼 private ResultCode resultCode; private int code; private String message; public CustomException(ResultCode resultCode){ super(resultCode.message()); this.resultCode = resultCode; } public CustomException(ResultCode resultCode, Object... args){ code = resultCode.code(); message = MessageFormat.format(resultCode.message(), args); } }
(2)配置公共異常處理
package com.pyy.ihrm.company.exception.handler; import com.pyy.ihrm.common.response.Result; import com.pyy.ihrm.common.response.ResultCode; import com.pyy.ihrm.company.exception.CustomException; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.validation.BindException; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import java.util.List; /** * 全局異常處理器 * @author pyy */ @RestControllerAdvice public class GlobalExceptionHandler { private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); /** * 處理自定義異常 */ @ExceptionHandler(CustomException.class) public Result handleException(CustomException e) { if (e.getResultCode() != null) { log.error("### 異常資訊:code={}, msg={} ###", e.getResultCode().code(), e.getResultCode().message()); return new Result(e.getResultCode()); } else { log.error("### 異常資訊:code={}, msg={} ###", e.getCode(), e.getMessage()); return new Result(e.getCode(), e.getMessage()); } } /** * 參數錯誤異常 */ @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class}) public Result handleException(Exception e) { StringBuffer errorMsg = new StringBuffer(); if (e instanceof MethodArgumentNotValidException) { MethodArgumentNotValidException validException = (MethodArgumentNotValidException) e; BindingResult result = validException.getBindingResult(); if (result.hasErrors()) { List<ObjectError> errors = result.getAllErrors(); errors.forEach(p ->{ FieldError fieldError = (FieldError) p; errorMsg.append(fieldError.getDefaultMessage()).append(","); log.error("### 請求參數錯誤:{"+fieldError.getObjectName()+"},field{"+fieldError.getField()+ "},errorMessage{"+fieldError.getDefaultMessage()+"} ###"); }); } } else if (e instanceof BindException) { BindException bindException = (BindException)e; if (bindException.hasErrors()) { log.error("### 請求參數錯誤: {} ###", bindException.getAllErrors()); } } return new Result(ResultCode.PARAM_IS_INVALID.code(), StringUtils.removeEnd(errorMsg.toString(), ",")); } /** * 處理所有不可知的異常 */ @ExceptionHandler(Exception.class) public Result handleOtherException(Exception e){ //列印異常堆棧資訊 e.printStackTrace(); // 列印異常資訊 log.error("### 不可知的異常 e=:{} ###", e.getMessage()); return new Result(ResultCode.SYSTEM_INNER_ERROR); } }
(3)swagger配置
package com.pyy.ihrm.company.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; /** * ======================== * swagger 配置 * Created with IntelliJ IDEA. * User:pyy * Date:2019/10/12 15:00 * Version: v1.0 * ======================== */ @Configuration @EnableSwagger2 //@Profile({"local", "dev", "test"}) public class Swagger2Configuration { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.pyy.ihrm")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("企業管理後台api文檔") .description("企業管理後台api文檔") .version("1.0") .build(); } }
(4)跨域配置 跨域是什麼?瀏覽器從一個域名的網頁去請求另一個域名的資源時,域名、埠、協議任一不同,都是跨域 。我們是採用前後端分離開發的,也是前後端分離部署的,必然會存在跨域問題。
package com.pyy.ihrm.company.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; /** * ======================== * 跨域配置 * Created with IntelliJ IDEA. * User:pyy * Date:2019/10/12 15:00 * Version: v1.0 * ======================== */ @Configuration public class CorsConfig { private CorsConfiguration buildConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); // 1允許任何域名使用 corsConfiguration.addAllowedHeader("*"); // 2允許任何頭 corsConfiguration.addAllowedMethod("*"); // 3允許任何方法(post、get等) return corsConfiguration; } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", buildConfig()); // 4 return new CorsFilter(source); } }
———————————————— 版權聲明:本文為CSDN部落客「小飛俠v科比」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。 原文鏈接:https://blog.csdn.net/kai46385076/article/details/91348949
5.3 企業管理-CRUD
5.3.1 表結構分析

drop table if exists company; /*==============================================================*/ /* Table: company */ /*==============================================================*/ create table company ( id varchar(40) not null comment 'ID', name varchar(255) comment '公司名稱', balance decimal comment '當前餘額', state tinyint comment '狀態', audit_state varchar(255) comment '審核狀態', remarks text comment '備註', industry varchar(255) comment '所屬行業', company_size varchar(255) comment '公司規模', mailbox varchar(255) comment '郵箱', company_phone varchar(255) comment '公司電話', legal_representative varchar(255) comment '法人代表', business_license_id varchar(255) comment '營業執照-圖片ID', company_address varchar(255) comment '公司地址', company_area varchar(255) comment '公司地區', expiration_date datetime comment '到期時間', renewal_date datetime comment '續期時間', version varchar(255) comment '當前版本', manager_id varchar(255) comment '企業登錄帳號ID', create_id varchar(40) comment '創建人ID', create_name varchar(40) comment '創建人名稱', create_time datetime comment '創建時間', update_id varchar(40) comment '更新人ID', update_name varchar(40) comment '更新人名稱', update_time datetime comment '更新時間', is_deleted tinyint comment '刪除標記 0:正常 1:刪除', primary key (id) ); alter table company comment '企業資訊';
5.3.2 完成企業增刪改查操作
(1)在ihrm-company工程下創建 實體PO類
package com.pyy.ihrm.company.po; import lombok.Data; import javax.persistence.Id; import javax.persistence.Table; import java.io.Serializable; /** * --------------------------- * 企業資訊 (Company) * --------------------------- * 作者: * 時間: 2019-11-12 10:10:10 * 版本: v1.0 * --------------------------- */ @Data @Table(name = "company") public class Company implements Serializable{ private static final long serialVersionUID = 8294633490615151005L; /** ID */ @Id private String id; /** 公司名稱 */ private String name; /** 當前餘額 */ private Double balance; /** 狀態 */ private Integer state; /** 審核狀態 */ private String auditState; /** 備註 */ private String remarks; /** 所屬行業 */ private String industry; /** 公司規模 */ private String companySize; /** 郵箱 */ private String mailbox; /** 公司電話 */ private String companyPhone; /** 法人代表 */ private String legalRepresentative; /** 營業執照-圖片ID */ private String businessLicenseId; /** 公司地址 */ private String companyAddress; /** 公司地區 */ private String companyArea; /** 到期時間 */ private java.util.Date expirationDate; /** 續期時間 */ private java.util.Date renewalDate; /** 當前版本 */ private String version; /** 企業登錄帳號ID */ private String managerId; /** 創建人ID */ private String createId; /** 創建人名稱 */ private String createName; /** 創建時間 */ private java.util.Date createTime; /** 更新人ID */ private String updateId; /** 更新人名稱 */ private String updateName; /** 更新時間 */ private java.util.Date updateTime; /** 刪除標記 0:正常 1:刪除 */ private Integer isDeleted; }
(2)在 ihrm-common-model工程中創建 CompanyQueryConditionVO.java, CompanySaveOrUpdateVO.java,CompanyVO.java
這裡之所以將VO類放在model工程中,原因是因為後面整合其他微服務時,會用到這些公共VO類。
CompanyQueryConditionVO.java
package com.pyy.ihrm.domain.company.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.Date; /** * --------------------------- * 模糊查詢條件VO * --------------------------- * 作者: * 時間: 2019-11-12 10:10:10 * 版本: v1.0 * --------------------------- */ @Data @ApiModel(value = "CompanyQueryConditionVO",description = "企業資訊類") public class CompanyQueryConditionVO { @ApiModelProperty("名稱") private String name; }
CompanySaveOrUpdateVO.java
package com.pyy.ihrm.domain.company.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * --------------------------- * 企業資訊 (Company) * --------------------------- * 作者: * 時間: 2019-11-12 10:10:10 * 版本: v1.0 * --------------------------- */ @Data @ApiModel(value = "Company",description = "企業資訊保存和修改VO類") public class CompanySaveOrUpdateVO { @ApiModelProperty("ID") private String id; @ApiModelProperty("公司名稱") private String name; @ApiModelProperty("當前餘額") private Double balance; @ApiModelProperty("狀態") private Integer state; @ApiModelProperty("審核狀態") private String auditState; @ApiModelProperty("備註") private String remarks; @ApiModelProperty("所屬行業") private String industry; @ApiModelProperty("公司規模") private String companySize; @ApiModelProperty("郵箱") private String mailbox; @ApiModelProperty("公司電話") private String companyPhone; @ApiModelProperty("法人代表") private String legalRepresentative; @ApiModelProperty("營業執照-圖片ID") private String businessLicenseId; @ApiModelProperty("公司地址") private String companyAddress; @ApiModelProperty("公司地區") private String companyArea; @ApiModelProperty("到期時間") private java.util.Date expirationDate; @ApiModelProperty("續期時間") private java.util.Date renewalDate; @ApiModelProperty("當前版本") private String version; @ApiModelProperty("企業登錄帳號ID") private String managerId; @ApiModelProperty("操作人ID") private String userId; @ApiModelProperty("操作人名稱") private String username; }
CompanyVO.java
package com.pyy.ihrm.domain.company.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * --------------------------- * 企業資訊 (Company) * --------------------------- * 作者: * 時間: 2019-11-12 10:10:10 * 版本: v1.0 * --------------------------- */ @Data @ApiModel(value = "CompanyVO",description = "企業資訊類") public class CompanyVO { @ApiModelProperty("ID") private String id; @ApiModelProperty("公司名稱") private String name; @ApiModelProperty("當前餘額") private Double balance; @ApiModelProperty("狀態") private Integer state; @ApiModelProperty("審核狀態") private String auditState; @ApiModelProperty("備註") private String remarks; @ApiModelProperty("所屬行業") private String industry; @ApiModelProperty("公司規模") private String companySize; @ApiModelProperty("郵箱") private String mailbox; @ApiModelProperty("公司電話") private String companyPhone; @ApiModelProperty("法人代表") private String legalRepresentative; @ApiModelProperty("營業執照-圖片ID") private String businessLicenseId; @ApiModelProperty("公司地址") private String companyAddress; @ApiModelProperty("公司地區") private String companyArea; @ApiModelProperty("到期時間") private java.util.Date expirationDate; @ApiModelProperty("續期時間") private java.util.Date renewalDate; @ApiModelProperty("當前版本") private String version; @ApiModelProperty("企業登錄帳號ID") private String managerId; @ApiModelProperty("創建人ID") private String createId; @ApiModelProperty("創建人名稱") private String createName; @ApiModelProperty("創建時間") private java.util.Date createTime; @ApiModelProperty("更新人ID") private String updateId; @ApiModelProperty("更新人名稱") private String updateName; @ApiModelProperty("更新時間") private java.util.Date updateTime; @ApiModelProperty("刪除標記 0:正常 1:刪除") private Integer isDeleted; }
(3)持久層Mapper(dao)
package com.pyy.ihrm.company.mapper; import java.util.List; import com.pyy.ihrm.company.po.Company; import com.pyy.ihrm.domain.company.vo.CompanyQueryConditionVO; import tk.mybatis.mapper.common.Mapper; /** * --------------------------- * 企業資訊 (CompanyMapper) * --------------------------- * 作者: * 時間: 2019-11-12 10:10:10 * 版本: v1.0 * --------------------------- */ public interface CompanyMapper extends Mapper<Company>{ List<Company> selectByPageAndParam(CompanyQueryConditionVO queryConditionVO); }
(4)業務邏輯層(service)
CompanyService.java
package com.pyy.ihrm.company.service; import com.pyy.ihrm.common.response.QueryResult; import com.pyy.ihrm.domain.company.vo.CompanyQueryConditionVO; import com.pyy.ihrm.domain.company.vo.CompanySaveOrUpdateVO; import com.pyy.ihrm.domain.company.vo.CompanyVO; import java.util.List; /** * --------------------------- * 企業資訊 (CompanyService) * --------------------------- * 作者: * 時間: 2019-11-12 10:10:10 * 版本: v1.0 * --------------------------- */ public interface CompanyService { /** * 企業資訊保存 * @param companySaveOrUpdateVO */ void save(CompanySaveOrUpdateVO companySaveOrUpdateVO); /** * 企業資訊修改 * @param id * @param companySaveOrUpdateVO */ void update(String id, CompanySaveOrUpdateVO companySaveOrUpdateVO); /** * 企業資訊刪除 * @param id */ void delete(String id, String userId, String username); /** * 根據企業資訊ID查詢 * @param id */ CompanyVO findById(String id); /** * 企業資訊模糊查詢 * @param queryConditionVO * @return */ List<CompanyVO> listByParams(CompanyQueryConditionVO queryConditionVO); /** * 企業資訊分頁模糊查詢 * @param queryConditionVO * @param page * @param size * @return */ QueryResult<CompanyVO> listByPageAndParams(CompanyQueryConditionVO queryConditionVO, Integer page, Integer size); }
CompanyServiceImpl.java
package com.pyy.ihrm.company.service.impl; import com.alibaba.fastjson.JSON; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.pyy.ihrm.common.response.QueryResult; import com.pyy.ihrm.common.response.ResultCode; import com.pyy.ihrm.common.utils.SnowflakeId; import com.pyy.ihrm.company.constants.CommonConstants; import com.pyy.ihrm.company.exception.CustomException; import com.pyy.ihrm.company.mapper.CompanyMapper; import com.pyy.ihrm.company.po.Company; import com.pyy.ihrm.company.service.CompanyService; import com.pyy.ihrm.company.utils.UserUtil; import com.pyy.ihrm.domain.company.vo.CompanyQueryConditionVO; import com.pyy.ihrm.domain.company.vo.CompanySaveOrUpdateVO; import com.pyy.ihrm.domain.company.vo.CompanyVO; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * --------------------------- * 企業資訊 (CompanyServiceImpl) * --------------------------- * 作者: * 時間: 2019-11-12 10:10:10 * 版本: v1.0 * --------------------------- */ @Slf4j @Service @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class) public class CompanyServiceImpl implements CompanyService { @Autowired private CompanyMapper companyMapper; /** * 企業資訊保存 * @param companySaveOrUpdateVO */ @Override public void save(CompanySaveOrUpdateVO companySaveOrUpdateVO) { // 保存企業資訊 Company companyModel = new Company(); BeanUtils.copyProperties(companySaveOrUpdateVO, companyModel); companyModel.setId(SnowflakeId.getId() + ""); companyModel.setCreateId(companySaveOrUpdateVO.getUserId()); companyModel.setCreateName(companySaveOrUpdateVO.getUsername()); companyModel.setCreateTime(new Date()); companyModel.setIsDeleted(CommonConstants.UN_DELETED); companyMapper.insert(companyModel); log.info("### 企業資訊保存成功 ###"); } /** * 企業資訊修改 * @param id * @param companySaveOrUpdateVO */ @Override public void update(String id, CompanySaveOrUpdateVO companySaveOrUpdateVO) { Company companyModel = companyMapper.selectByPrimaryKey(id); if (companyModel == null) { throw new CustomException(ResultCode.RESULT_DATA_NONE, "企業資訊"); } // 修改 BeanUtils.copyProperties(companySaveOrUpdateVO, companyModel); companyModel.setUpdateTime(new Date()); companyModel.setUpdateId(companySaveOrUpdateVO.getUserId()); companyModel.setUpdateName(companySaveOrUpdateVO.getUsername()); companyMapper.updateByPrimaryKey(companyModel); log.info("### 企業資訊修改成功 ###"); } /** * 企業資訊刪除 * @param id * @param userId * @param username */ @Override public void delete(String id, String userId, String username) { Company companyModel = companyMapper.selectByPrimaryKey(id); if (companyModel == null) { throw new CustomException(ResultCode.RESULT_DATA_NONE, "企業資訊,id=" + id); } // 邏輯刪除 companyModel.setId(id); companyModel.setUpdateId(userId); companyModel.setUpdateName(username); companyModel.setUpdateTime(new Timestamp(System.currentTimeMillis())); companyModel.setIsDeleted(CommonConstants.DELETED); companyMapper.updateByPrimaryKeySelective(companyModel); log.info("### 企業資訊邏輯刪除成功 ###"); } /** * 根據企業資訊ID查詢 * @param id */ @Override public CompanyVO findById(String id) { Company companyModel = companyMapper.selectByPrimaryKey(id); if (companyModel == null) { throw new CustomException(ResultCode.RESULT_DATA_NONE, "企業資訊,id=" + id); } log.info("### 企業資訊查詢成功, company={}###", JSON.toJSONString(companyModel)); // model轉換vo CompanyVO companyVO = new CompanyVO(); BeanUtils.copyProperties(companyModel, companyVO); log.info("### 企業資訊Model轉換VO成功, companyVO={}###", companyVO); return companyVO; } /** * 企業資訊模糊查詢 * @param queryConditionVO * @return */ @Override public List<CompanyVO> listByParams(CompanyQueryConditionVO queryConditionVO) { List<Company> companyList = companyMapper.selectByPageAndParam(queryConditionVO); log.info("### 企業資訊Model模糊查詢完畢,總條數:{}條###", companyList.size()); // 企業資訊Model轉換VO數據完畢 List<CompanyVO> companyVOList = new ArrayList<>(); companyList.forEach(company -> { CompanyVO companyVO = new CompanyVO(); BeanUtils.copyProperties(company, companyVO); companyVOList.add(companyVO); }); log.info("### 企業資訊Model轉換VO數據完畢###"); return companyVOList; } /** * 企業資訊分頁模糊查詢 * @param queryConditionVO * @param page * @param size * @return */ @Override public QueryResult<CompanyVO> listByPageAndParams(CompanyQueryConditionVO queryConditionVO, Integer page, Integer size) { // 分頁查詢 PageHelper.startPage(page, size); List<Company> companyList = companyMapper.selectByPageAndParam(queryConditionVO); // 獲取分頁後數據 PageInfo<Company> pageInfo = new PageInfo<>(companyList); log.info("### 企業資訊分頁查詢完畢,總條數:{} ###", pageInfo.getTotal()); List<CompanyVO> companyVOList = new ArrayList<>(); // 補全數據 companyList.forEach(company -> { CompanyVO companyVO = new CompanyVO(); BeanUtils.copyProperties(company, companyVO); companyVOList.add(companyVO); }); log.info("### 企業資訊Model轉換VO數據完畢###"); // 封裝需要返回的實體數據 QueryResult queryResult = new QueryResult(); queryResult.setTotal(pageInfo.getTotal()); queryResult.setList(companyVOList); return queryResult; } }
(5)業務控制層(CompanyController)
package com.pyy.ihrm.company.controller; import com.pyy.ihrm.common.response.QueryResult; import com.pyy.ihrm.common.response.Result; import com.pyy.ihrm.company.service.CompanyService; import com.pyy.ihrm.domain.company.vo.CompanyQueryConditionVO; import com.pyy.ihrm.domain.company.vo.CompanySaveOrUpdateVO; import com.pyy.ihrm.domain.company.vo.CompanyVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.List; /** * --------------------------- * 企業資訊 (CompanyController) * --------------------------- * 作者: * 時間: 2019-11-12 10:10:10 * 版本: v1.0 * --------------------------- */ @Api(tags = "CompanyController", description = "企業資訊相關介面") @RestController @RequestMapping(value = "/v1", produces = MediaType.APPLICATION_JSON_UTF8_VALUE ) public class CompanyController { @Autowired private CompanyService companyService; /** * 保存企業資訊 * @param record * @return */ @ApiOperation(value = "保存企業資訊", notes = "創建新企業資訊") @ApiImplicitParam(name = "record", value = "企業資訊對象", required = true, dataType = "Company", paramType = "body") @PostMapping("/company") public Result save(@Valid @RequestBody CompanySaveOrUpdateVO record) { // 後面集成JWT後完善 String userId = "admin"; String username = "admin"; record.setUserId(userId); record.setUsername(username); companyService.save(record); return Result.SUCCESS(); } /** * 修改企業資訊 * @param id * @param record * @return */ @ApiOperation(value = "修改企業資訊", notes = "根據ID修改企業資訊") @ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "企業資訊ID", required = true, dataType = "String", paramType = "path"), @ApiImplicitParam(name = "record", value = "企業資訊對象", required = true, dataType = "Company", paramType = "body") }) @PutMapping("/company/{id}") public Result update(@Valid @PathVariable(value = "id") String id, @RequestBody CompanySaveOrUpdateVO record) { // 後面集成JWT後完善 String userId = "admin"; String username = "admin"; record.setUserId(userId); record.setUsername(username); companyService.update(id, record); return Result.SUCCESS(); } /** * 刪除企業資訊 * @param id * @return */ @ApiOperation(value = "刪除企業資訊", notes = "根據ID企業資訊") @ApiImplicitParam(name = "id", value = "企業資訊ID", required = true, dataType = "String", paramType = "path") @DeleteMapping("/company/{id}") public Result delete(@Valid @PathVariable(value = "id") String id) { // 後面集成JWT後完善 String userId = "admin"; String username = "admin"; companyService.delete(id, userId, username); return Result.SUCCESS(); } /** * 根據ID查詢企業資訊 * @param id * @return */ @ApiOperation(value = "企業資訊查詢", notes = "根據ID企業資訊查詢") @ApiImplicitParam(name = "id", value = "企業資訊ID", required = true, dataType = "String", paramType = "path") @GetMapping("/company") public Result<CompanyVO> findById(@Valid @PathVariable(value = "id") String id) { CompanyVO queryResult = companyService.findById(id); return Result.SUCCESS(queryResult); } /** * 企業資訊模糊查詢 * @param queryConditionVO * @return */ @ApiOperation(value = "企業資訊模糊查詢", notes = "企業資訊不帶分頁模糊查詢") @GetMapping("/companys") public Result<List<CompanyVO>> listByParams(CompanyQueryConditionVO queryConditionVO) { List<CompanyVO> queryResult = companyService.listByParams(queryConditionVO); return Result.SUCCESS(queryResult); } /** * 企業資訊分頁模糊查詢 * @param queryConditionVO * @param page * @param size * @return */ @ApiOperation(value = "企業資訊分頁查詢", notes = "企業資訊分頁模糊查詢") @ApiImplicitParams({ @ApiImplicitParam(name = "page", value = "當前頁碼", required = true, dataType = "int", paramType = "query"), @ApiImplicitParam(name = "size", value = "分頁尺寸", required = true, dataType = "int", paramType = "query") }) @GetMapping("/companys/page") public Result<QueryResult<CompanyVO>> listByPageAndParams(CompanyQueryConditionVO queryConditionVO, @RequestParam("page") Integer page, @RequestParam("size") Integer size) { QueryResult<CompanyVO> queryResult = companyService.listByPageAndParams(queryConditionVO, page, size); return Result.SUCCESS(queryResult); } }
(6)啟動項目,訪問:http://localhost:9001/swagger-ui.html

源碼:https://github.com/pyygithub/saas-ihrm