源碼連接: https://github.com/samt007/xygerp-api-demohtml
這是用Spring Cloud微服務架構搭建的一套基於EBS的API服務系統前端
如對本文有任何的疑問,請聯繫我:samt007@qq.comjava
這是一篇傳統ERP系統和基於Java的微服務架構有效結合的技術文檔。git
傳統ERP關注的是企業內部的信息化管理。當ERP系統能將其服務發佈出去以後(結合微服務架構),就能夠很好實現與第三方系統的無縫對接,同時也能夠實現擴展ERP自己的功能。 目標是:讓ERP的服務更開放!github
簡單來講,就是:web
至關於作一箇中間服務平臺,把ERP的API作成Web Service與其它系統集成。docker
下面具體說明它的做用。數據庫
若是沒有一個統一的API對接平臺,那麼ERP和第三方系統作對接,那會是下圖所示的結構: 後端
從上圖能夠看出,各個第三方系統分別和ERP作對接,不管是DBLINK仍是經過本身的Web Service, 都是雜亂的,沒能統一管理的。簡單來講就是各自爲政,爲對接而須要作的事情都是零碎的。api
當第三方系統愈來愈多的時候,那對於平常的運維將會是一個災難的問題。舉個例子,就一個簡單的運維:密碼修改,須要調整的地方就會不少,也很容易遺漏。
特別指出的是,接口功能的複用方面也是個難題。假設一個查詢庫存的接口,CRM系統和在線下單系統均可以用的,須要開發2次。
有了這套統一的API系統以後,ERP系統和別的系統之間的對接就變成了這個結構:
因此,有了它,至關於ERP的API均可以經過這服務平臺給開發出去,基本上全部的接口能夠完成的業務,均可以經過這套服務平臺來完成。
能夠實現:
舉個例子:
大概這個需求: 成品入庫的時候,直接能夠用條碼槍掃條碼或者二維碼就能夠入庫;銷售出庫的時候,也能夠經過刷成品的條碼直接進行出庫。JIT管理。
經過這個系統的實現邏輯是: 經過EBS的用戶名和密碼能夠登入條碼槍上的APP系統。而後,刷條碼的時候,經過該Web Service能夠產生對應的事務處理!例如完工入庫,處理物料搬運單等。
下面是該系統的一些截圖
注意:該功能後臺API由該微服務提供,前臺是安卓的APP
每一個企業內部都有各類第三方系統,這些系統或多或少都須要和EBS進行集成。傳統的集成方法是經過DBLINK。
可是有這套Web Service系統以後,就能夠統一經過該Web Service做爲中介,和EBS進行數據的集成交互!
關於它的解析,網上資料不少。 這裏引用某位大神的總結(引用:http://blog.51cto.com/ityouknow/1974080),解析得比較到位:
微服務的概念源於2014年3月Martin Fowler所寫的一篇文章「Microservices」。
微服務架構是一種架構模式,它提倡將單一應用程序劃分紅一組小的服務,服務之間互相協調、互相配合,爲用戶提供最終價值。每一個服務運行在其獨立的進程中,服務與服務間採用輕量級的通訊機制互相溝通(一般是基於HTTP的RESTful API)。每一個服務都圍繞着具體業務進行構建,而且可以被獨立地部署到生產環境、類生產環境等。另外,應儘可能避免統一的、集中式的服務管理機制,對具體的一個服務而言,應根據業務上下文,選擇合適的語言、工具對其進行構建。
微服務是一種架構風格,一個大型複雜軟件應用由一個或多個微服務組成。系統中的各個微服務可被獨立部署,各個微服務之間是鬆耦合的。每一個微服務僅關注於完成一件任務並很好地完成該任務。在全部狀況下,每一個任務表明着一個小的業務能力。
微服務架構優點
複雜度可控:在將應用分解的同時,規避了本來複雜度無止境的積累。每個微服務專一於單一功能,並經過定義良好的接口清晰表述服務邊界。因爲體積小、複雜度低,每一個微服務可由一個小規模開發團隊徹底掌控,易於保持高可維護性和開發效率。
獨立部署:因爲微服務具有獨立的運行進程,因此每一個微服務也能夠獨立部署。當某個微服務發生變動時無需編譯、部署整個應用。由微服務組成的應用至關於具有一系列可並行的發佈流程,使得發佈更加高效,同時下降對生產環境所形成的風險,最終縮短應用交付週期。
技術選型靈活:微服務架構下,技術選型是去中心化的。每一個團隊能夠根據自身服務的需求和行業發展的現狀,自由選擇最適合的技術棧。因爲每一個微服務相對簡單,故須要對技術棧進行升級時所面臨的風險就較低,甚至徹底重構一個微服務也是可行的。
容錯:當某一組建發生故障時,在單一進程的傳統架構下,故障頗有可能在進程內擴散,造成應用全局性的不可用。在微服務架構下,故障會被隔離在單個服務中。若設計良好,其餘服務可經過重試、平穩退化等機制實現應用層面的容錯。
擴展:單塊架構應用也能夠實現橫向擴展,就是將整個應用完整的複製到不一樣的節點。當應用的不一樣組件在擴展需求上存在差別時,微服務架構便體現出其靈活性,由於每一個服務能夠根據實際需求獨立進行擴展。
從上面的解析得知:微服務是一種技術架構,將一個龐大的服務體系拆分爲若干個子服務執行。 問題來了,應該如何拆分呢?就是服務的拆分原則是什麼。
這個問題就像是一個大表如何進行分區同樣,其實我以爲是具體問題具體分析。 因爲我開發的是基於EBS的微服務系統,正常來講,比較合理的劃分規則應該是以EBS的模塊來分。
至關於每一個模塊都劃分爲一個單獨的微服務。例如FND模塊,INV模塊,WIP模塊等等。
有時候,爲了某個目的,可能有些功能是定製的,須要提取幾個模塊的數據來用,並且被別的模塊重用的機率很低。因此,實際上也能夠以定製的功能來劃分微服務。
目前來講,該系統包括2個子服務:
這個是整個微服務API的核心ald模塊。這個模塊的主要功能是驗證用戶的登陸,爲全部的api模塊提供統一的token認證。至關於ebs的FND模塊。
這個項目是屬於微服務的API模塊之一:條碼管理系統提供數據以及數據處理的API。 主要是爲條形碼傳輸系統用。
固然,將來能夠添加若干個服務。微服務架構的優點是有很好的橫向擴展能力!
該系統的架構圖以下所示。
注意:
1.Spring Cloud模塊中,實際上Spring Security並非單獨的一個模塊,而是融入到每個業務微服務模塊中! 每一個微服務都必需要有token認證才容許訪問API,它很是重要! 因此我將它給列到Spring Cloud模塊中。
2.圖中有些模塊目前尚未實現。 目前實現了架構總體,包括如下的服務(下一個章節會具體說明每一個模塊的用途):
xygerp-ald
xygerp-albc
xygerp-server-eureka
xygerp-server-zuul
注意: 之後會按需添加別的模塊。
接下來是一步一步來開發一套這個基於Spring Cloud的微服務系統。
開發系統都必需要打好基礎。因此,這裏列出了開發基於Spring Cloud的微服務系統須要掌握的開發技術。
下面我不會具體解說每個開發技術如何學習,由於這並非本文的重點。工欲善其事必先利其器,基礎仍是必需要打好。
必需要熟悉java,不然基本不用看文檔了。先打好基礎吧!
系統開發的項目都是以maven作項目管理的,因此必需要先安裝並掌握maven工具。
數據庫端的開發技術。這裏選用Oracle數據庫,由於EBS就是基於Oracle數據庫的ERP系統。
Java技術發展到如今,已經出現了許多很是優秀的開源框架,咱們能夠藉助這些框架來快速開發系統。
Spring是目前開源的主流的技術包。 該系統主要用到的技術棧是:Spring boot,Spring Security以及Spring Cloud。
系統基於SpringBoot快速開發。選擇目前熱度很高的SpringBoot,最大限度地下降配置複雜度,把大量的精力投入到業務開發中來。
利用Spring MVC框架處理全部的url請求,簡單易用。
Spring security是一個強大的和高度可定製的身份驗證和訪問控制框架。它是確保基於Spring的應用程序的標準。 這裏主要是用Spring Security框架處理Token機制。
Spring Cloud是一系列框架的有序集合。 它利用Spring Boot的開發便利性巧妙地簡化了分佈式系統基礎設施的開發,如服務發現註冊、配置中心、消息總線、負載均衡、斷路器、數據監控等,均可以用Spring Boot的開發風格作到一鍵啓動和部署。 注意:本系統目前使用Spring Cloud的2個模塊
ORM框架選用MyBatis。
主要是考慮到它可以很好支持SQL語句:MyBatis是支持普通SQL查詢,存儲過程和高級映射的優秀持久層框架。 另外,還用到了MyBatis的一些提升開發效率的插件,特別是通用Mapper和PageHelper分頁插件!
DRUID是阿里巴巴開源平臺上一個數據庫鏈接池實現。它結合了C3P0、DBCP、PROXOOL等DB池的優勢,同時加入了日誌監控,能夠很好的監控DB池鏈接和SQL的執行狀況。
前端和後端的惟一聯繫,變成了API接口。
API文檔變成了先後端開發人員聯繫的紐帶,變得愈來愈重要,swagger就是一款讓你更好的書寫API文檔的框架。
目前用Redis的主要做用是存取token,以配合實現Spring Security完成api訪問的安全機制。
之後能夠考慮作緩存或者消息隊列等高級功能。
基於Docker的容器化部署。
因爲使用了微服務架構後,咱們的系統將會由不少子系統構成。 爲了達到多個系統之間環境隔離的目的,咱們能夠將它們部署在多臺服務器上,可這樣的成本會比較高,並且每臺服務器的性能可能都沒有充分利用起來。
因此咱們很天然地想到了虛擬機,在同一臺服務器上運行多個虛擬機,從而實現環境的隔離,每一個虛擬機上運行獨立的服務。
然而虛擬機的隔離成本依舊很高,由於它須要佔用服務器較多的硬件資源和軟件資源。 因此,在微服務結構下,要實現服務環境的隔離,Docker是最佳選擇。它比虛擬機更加輕量級,佔用資源較少,並且可以實現快速部署。
備註:後面有專題說明這個工具如何安裝使用。因爲篇幅緣由,本文檔暫時不講解容器化部署。
Jenkins自動化構建工具。
當咱們採用了微服務架構後,咱們會發現這樣一個問題。整個系統由許許多多的服務構成,這些服務都須要運行在單獨的容器中,那麼每次發佈的複雜度將很是高。
首先你要搞清楚這些服務之間的依賴關係、啓動的前後順序,而後再將多個子系統挨個編譯、打包、發佈。這些操做技術難度低,卻又容易出錯。
那麼有什麼工具可以幫助咱們解決這些問題呢?答案就是——Jenkins。
它是一款自動化構建的工具,簡單的來講,就是咱們只須要在它的界面上按一個按鈕,就能夠實現上述一系列複雜的過程。
備註:後面有專題說明這個工具如何安裝使用。因爲篇幅緣由,本文檔暫時不講解自動化構建。
如今開始手把手來搭建一套這樣子的系統。
先建立一個微服務系統的父級項目:xygerp-api
再在這個項目下面分別建立下面幾個子項目:
項目名稱 | 說明 |
---|---|
xygerp-ald | ald模塊,端口:8180。這個是整個微服務API的核心ald模塊。這個模塊的主要功能是驗證用戶的登陸,爲全部的api模塊提供統一的token認證。至關於ebs的FND模塊。 |
xygerp-albc | albc子模塊,端口:8181。這個項目是屬於微服務的API模塊之一:條碼管理系統提供數據以及數據處理的API。主要是爲條形碼傳輸系統用。 |
xygerp-comm | comm模塊這個項目是全部API項目的核心依賴項目。說白了就是將API微服務架構的全部項目的公用代碼能夠抽取在這裏。 |
xygerp-basic-support | 核心基礎支撐模塊這個項目是全部API項目的基礎數據支撐項目。這裏統一歸集了全部的Entity!由於對於Entity來講,應該是整個微服務都公用的。 |
xygerp-server-eureka | Spring Cloud的服務與發現的服務中心。端口:8101。這個模塊是Spring cloud的最核心的模塊了,用來處理各個微服務之間的服務調用的。 |
xygerp-server-zuul | Spring Cloud服務網關。端口:8102。在Spring Cloud架構體系內的全部微服務都經過Zuul來對外提供統一的訪問入口,全部須要和微服務架構內部服務進行通信的請求都走統一網關。 |
注意: 關於xygerp-basic-support:核心基礎支撐模塊
可能您會有疑問:爲何不將entity歸併在它所屬的模塊?實際上是這樣的,我主要是考慮到服務之間的互相調用的問題。
微服務雖然客觀上是一個單獨的服務,可是,實際上大部分的功能確定是互相調用的。舉個例子,銷售訂單模塊調用庫存模塊的功能查詢個庫存是很正常的業務吧?
若是entity不共用的話,至關於銷售模塊獲得的庫存模塊的結果沒法歸集爲bean來處理,這樣子對於後臺的處理會帶來極大的不便!
接着須要經過pom文件來指定它們之間的依賴關係,依賴關係以下圖所示。
而xygerp-comm和xygerp-basic-support只是爲各個微服務提供基礎代碼支撐,因此是jar部署便可。
此外,爲了簡化各個模塊的配置,咱們將全部模塊的通用依賴放在Project的pom文件中,而後讓全部模塊做爲Project的子模塊。 這樣子模塊就能夠從父模塊中繼承全部的依賴,而不須要本身再配置了。
在父pom中指定子模塊
modules標籤指定了當前模塊的子模塊是誰,可是僅在父模塊的pom文件中指定子模塊還不夠,還須要在子模塊的pom文件中指定父模塊是誰。
<modules>
<module>xygerp-comm</module> <!--核心Comm模塊 -->
<module>xygerp-basic-support</module> <!--核心基礎支撐模塊 -->
<module>xygerp-server-eureka</module> <!--Eureka服務治理模塊 -->
<module>xygerp-server-zuul</module> <!--zuul動態路由模塊 -->
<module>xygerp-ald</module> <!--核心ald模塊 -->
<module>xygerp-albc</module> <!--子模塊:albc模塊,提供條碼對接API服務 -->
</modules>
複製代碼
須要在子模塊中指定父模塊
<parent>
<artifactId>xygerp</artifactId>
<groupId>com.xygerp</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
複製代碼
備註:具體代碼直接看源碼吧。這裏只是說起了一些重點設置而已。
因此,到此爲止,模塊的依賴關係配置完畢!但要注意模塊打包的順序。
因爲全部模塊都依賴於xygerp-comm模塊和xygerp-basic-support模塊,所以在構建模塊時,首先須要編譯、打包、安裝xygerp-comm模塊和xygerp-basic-support模塊,將它打包進本地倉庫中,這樣上層模塊才能引用到。當該模塊安裝完畢後,再構建上層模塊。 不然在構建上層模塊的時候會出現找不到xygerp-comm模塊中類庫的問題。
Tips: 其實,若是是在父級目錄直接用mvn package總體打包的話,那打包構建的順序在父pom中是直接指定了!
xygerp-server-eureka:Spring Cloud服務註冊和發現。就是處理服務之間的治理。
xygerp-server-zuul:Spring Cloud的統一API網關服務。
Tips: 這2個項目是爲了實現微服務架構而用到的核心服務。因此,它們是相對獨立的。不須要依賴父pom。
上面的項目都創建好以後,再添加全部項目都須要用到的依賴(具體代碼能夠參考個人源碼)。
都沒問題的話,就能夠用mvn命令進行打包項目了:
mvn clean install -Dmaven.test.skip=true -P dev
這裏簡單解析一下指令:
mvn:Maven的統一指令。
clean install:表示要構建該項目。
-Dmaven.test.skip=true:表示構建的時候要跳過測試模塊。
-P dev:表示構建的時候,啓用 dev 的Spring boot參數運行系統。
若是一切都OK,那正常的結果以下:
代碼搞定了,接下來須要考慮的事情應該是如何測試。 畢竟全部的系統都必需要通過測試,特別是這種配置多,涉及範圍廣的系統。
這個就不得不說一下Spring boot的優點了。Spring boot的打包應用默認內置了tomcat服務。 換句話說,只須要java命令執行一下Spring boot打包的target結果,就能夠啓動一個tomcat服務啦!真挺方便測試的!
假設個人xygerp-api項目在這裏:D:\JSP_MyEclipse\xygerp-api
而後分別打開4個cmd命令窗口,執行:
D:\JSP_MyEclipse\xygerp-api\xygerp-server-eureka\target>java -jar xygerp-server-eureka-1.0-SNAPSHOT.war
D:\JSP_MyEclipse\xygerp-api\xygerp-server-zuul\target>java -jar xygerp-server-zuul-1.0-SNAPSHOT.war
D:\JSP_MyEclipse\xygerp-api\xygerp-ald\target>java -jar xygerp-ald-1.0-SNAPSHOT.war
D:\JSP_MyEclipse\xygerp-api\xygerp-albc\target>java -jar xygerp-albc-1.0-SNAPSHOT.war
複製代碼
以下圖:
本地測試環境的服務啓動起來了,接着就是進行具體的數據測試。
首先測試Eureka的服務註冊以及發現,確認服務是否都已經註冊到系統中:
而後,用swagger測試用戶登陸的功能: http://127.0.0.1:8102/xygerp/ald/swagger-ui.html 目前是測試是否能夠正常產生token。
說明已經登陸成功,而且產生了本次訪問的token!將token記錄下來,接着測試。 繼續測試一個查詢的功能: http://127.0.0.1:8102/xygerp/albc/swagger-ui.html
注意,這裏用了Spring Security框架,因此的API請求頭都必須攜帶token信息。不然請求會返回401。
若是測試OK,那說明基本上系統已經成功搭建好了。 下一步就是如何在測試環境或者正式環境部署它,以及如何一鍵構建項目的問題了。
簡單來講,系統的部署是用 docker工具 ,一鍵部署項目用的是 Jenkins工具。後面將會用專題來講明這2個工具的使用。
關於這個問題,目前我用的辦法可能不必定是最優的,若是有別的兄臺有更好的解決辦法,請留言給我,十分感謝!
問題來源:
熟悉EBS開發的兄臺都應該知道,登陸ERP以後,咱們每次打開Form,系統就會申請一個新的數據庫Session,這時候,EBS系統會 自動幫咱們初始化該Session的環境變量 :例如基本的語言環境,用戶環境,業務實體等等。
這時候,咱們在包裏面能夠直接用FND_GLOBAL.USER_ID之類的函數就能夠很是方便獲取環境變量的信息。
可是,在Java Web開發裏面就不同了!
在Java訪問數據庫的理念中,Session的申請是一個極耗資源的動做!因此,大部分鏈接數據庫的Java軟件都提出了一個 數據庫鏈接池 的概念(例如DRUID數據庫鏈接池)。簡單來講就是session共用!
Session公用就會帶來一個併發問題:A用戶使用系統,並初始化了該Session的環境變量爲A用戶;當A用戶不用系統的時候,Session會閒置並放回鏈接池裏面等待別的用戶使用。
這時候若是B的用戶極可能會使用該Session,若是不從新初始化環境變量的話,那B用戶使用系統的Session的環境變量仍是A用戶,就會致使數據的bug! 如何處理該問題是開發該系統碰到的一個難題。
問題解決:
我目前的處理辦法是:在Service層,用AOP統一自動監控Service層的這個參數AuthUser user
只要在Service層將參數AuthUser user放在最後,AOP會自動初始化Session的環境變量。(須要注意的是,我這個系統的數據庫Transaction在Service層啓用!)
另外,語言環境變量,登陸ID環境變量等,會一併自動初始化。由於AuthUser會攜帶該定義!
核心處理代碼以下:
private static final String SQL_GLOBAL_INIT
= " DECLARE "
+ " L_session_id NUMBER;L_user_id NUMBER;L_login_id NUMBER;L_LANG VARCHAR2(10); "
+ " BEGIN "
+ " L_user_id:=:P_USER_ID; L_login_id:=:P_LOGIN_ID; L_LANG:=:P_LANG;"
+ " APPS.fnd_global.INITIALIZE("
+ " session_id=>L_session_id, user_id =>L_user_id, resp_id =>NULL, "
+ " resp_appl_id=>NULL, security_group_id=>NULL, site_id=>NULL, login_id =>L_login_id, "
+ " conc_login_id=>NULL, prog_appl_id=>NULL, conc_program_id=>NULL, conc_request_id=>NULL, "
+ " conc_priority_request=>NULL"
+ " ); "
+ " IF NVL(L_LANG,'US') <> USERENV('LANG') THEN "
+ " IF L_LANG='ZHS' THEN "
+ " APPS.fnd_global.set_nls_context(p_nls_language => 'SIMPLIFIED CHINESE'); "
+ " ELSE "
+ " APPS.fnd_global.set_nls_context(p_nls_language => 'AMERICAN'); "
+ " END IF;"
+ " END IF;"
+ " END; ";
/***
* service層調用以前先自動初始化環境變量
* 須要注意的是,用戶變量必須的參數放在最後!
* 只要在Service層將參數AuthUser user放在最後,AOP會自動初始化Session的環境變量。
* @throws Exception
*/
@SuppressWarnings("static-access")
@Before("execution(* com.jebms.*.service..*.*(..)) && args(..,user)")
public void oracleDBInit(JoinPoint joinPoint,AuthUser user) throws Exception{
Long dbLoginId=devDao.getJdbcTemplate().queryForObject("SELECT FND_GLOBAL.LOGIN_ID FROM DUAL", Long.class);
if(user.getLoginId()!=null&&user.getLoginId()>0&&!user.getLoginId().equals(dbLoginId)){
Map<String,Object> inParamMap=new HashMap<String,Object>();
inParamMap.put("P_USER_ID", user.getUserId());
inParamMap.put("P_LOGIN_ID", user.getLoginId());
inParamMap.put("P_LANG", user.getLanguage());
devDao.getDevJdbcTemplate().execute(this.SQL_GLOBAL_INIT, inParamMap);
}
}
複製代碼
源代碼在:com.jebms.comm.utils. AopUtil
問題描述:
因爲我這個是第三方的API系統,因此,用戶名和密碼信息實際上並非該API系統須要管理的事情。
至關於說,API系統沒法按照正常的流程來驗證用戶名和密碼:輸入用戶名和密碼,系統驗證後臺數據庫的用戶名和密碼,再返回驗證結果。
而是:輸入用戶名和密碼,系統 調用ERP的用戶名密碼驗證包 進行驗證,再返回結果。 簡單來講:須要添加自定義驗證的邏輯。
還好Spring Security框架支持靈活的驗證邏輯。
添加步驟:
首先,寫一個自定義驗證的類:MyAuthenticationProvider
接着,在Spring Security框架的定義中,添加這個自定義的驗證。
AbstractWebSecurityConfig
private MyAuthenticationProvider provider;//自定義驗證 auth.authenticationProvider(provider);
便可以完美實現這個效果
核心代碼:
/**
* 自定義驗證方式
*/
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = (String) authentication.getCredentials();
AuthUser user = (AuthUser) userService.loadUserByUsername(username);
System.out.println("username:"+username+",password:"+password);
if(user == null){
throw new BadCredentialsException("Username not found.");
}
//加密過程在這裏體現
if (!sysService.xygErpValidateLogin(username, password)) {
throw new BadCredentialsException("Wrong password.");
}
user.setPassword(passwordEncoder.encode(password));
Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
return new UsernamePasswordAuthenticationToken(user, password, authorities);
}
複製代碼
1.Entity基類封裝。
封裝了5who欄位,以及相似Form的FND_SET_WHO的方法,能夠很方便進行開發。
另外,爲了防止丟失更新,這邊每次更新前實際上會先檢測數據的一致性,對應的動做也有作了封裝。
2.查詢邏輯的封裝。
查詢功能相對來講仍是會不少,對於複雜的查詢條件如何傳值是一個難題。
這裏封裝了一個SearchInfo積累,能夠統一將全部的查詢條件都放在這個類,而後在java的Controller層定義好查詢條件對應匹配欄位,系統就能夠自動產生對應的and條件。
例如:
@GetMapping(value = "/getPageLocator")
@ApiOperation(value = "貨位分頁列表接口")
public ResultEntity<PageInfo<EslipLocatorRE>> getPageLocator(
@ApiParam(value = "庫存組織ID",required = true) @RequestParam(required = true) int organizationId,
@ApiParam(value = "庫別代碼",required = true) @RequestParam(required = true) String subinventoryCode,
@ApiParam(value = "貨位代碼",required = false) @RequestParam(required = false) String locatorCode,
SearchInfo searchInfo) throws Exception {
searchInfo.getConditionMap().put("organizationId", organizationId);
searchInfo.getConditionMap().put("subinventoryCode", subinventoryCode);
searchInfo.getConditionMap().put("locatorCode", locatorCode);
searchInfo.setAuthUser(this.authUser);
searchInfo.initSqlCondition();
searchInfo.andSqlCondition("MIL.ORGANIZATION_ID","organizationId");
searchInfo.andSqlCondition("MIL.SUBINVENTORY_CODE","subinventoryCode");
searchInfo.andSqlCondition("MIL.SEGMENT1","locatorCode");
return eslipService.selectForPageLocator(searchInfo);
}
複製代碼
3.統一的處理結果的封裝。
基本上任何一個處理,要不成功,要不失敗(警告其實也算失敗)。
這裏封裝了一個返回結果的基類ResultEntity<T>,能夠進行有效的應用端或者java端的交互。
@ApiModelProperty(value = "狀態碼,0表示成功 其餘表示失敗", example = "0",position = 1)
private String code;
複製代碼
特別須要指出的是,前端獲取或者處理數據,也是統一要用這個處理結果基類的返回。
簡單來講,就是數據處理成功/失敗,會有一個統一的返回結果標識。注意,這個標識和請求的響應結果標識(200)是有所不一樣的!
請求響應標識只是說明web服務器的響應是正常,但,具體的處理結果多是處理失敗。
下面是一個具體的例子(到時候實際開發處理的接口處理結果也是這樣子):
{
"code": "0",
"message": "",
"description": "",
"obj": [{
"createdBy": -1,
"creationDate": "2017-10-10 09:37:03",
"lastUpdatedBy": 10,
"lastUpdateDate": "2017-11-16 14:47:48",
"lastUpdateLogin": 96,
"valueUUID": null,
"id": 2,
"applId": 1,
"respCode": "BASIC_SET",
"menuId": 2,
"startDate": "2017-10-10 09:37:03",
"endDate": null,
"respName": "系統設置職責",
"description": "系統設置職責",
"menuCode": "SYSTEM_SET",
"menuName": "系統設置菜單",
"enabled": true
}],
"param1": null,
"param2": null,
"param3": null,
"param4": null,
"param5": null,
"ok": true
}
複製代碼
文檔參考連接: https://juejin.im/entry/5a7812906fb9a0635014f19a http://blog.51cto.com/ityouknow/1974080