1. 程式人生 > >JHipster中文文件(一)

JHipster中文文件(一)

介紹

技術棧

客戶端技術棧

單頁面應用:

  • Angular4 or AngularJS v1.x
  • Bootstrap
  • HTML5
  • 國際化支援
  • Sass
  • Spring Websocket

良好的開發流程:

  • 通過Yarn或Bower易於安裝JavaScript類庫
  • 通過webpack或gulp構建、優化、實時過載
  • 使用Karma headless Chrome 或者 Protractor進行測試
  • 支援Thtmeleaf模板引擎

服務端技術棧

一個完整的Spring應用:

  • Spring-Boot:易於配置
  • Maven或Gradle:構建、測試、執行應用
  • Spring Security
  • Spring MVC REST + Jackson
  • Spring Data JPA + Bean Validation
  • Liquibase: 資料庫管理(資料庫變更等記錄)
  • Elasticsearch支援
  • MongoDB支援
  • Cassandra支援
  • Kafka 支援
  • Spring WebSocket支援

微服務技術棧

微服務是可選的並且完全支援服務端技術棧,除此之外還支援:

  • 使用Netflix Zuul或者Traefik進行HTTP路由
  • 使用Netflix Eureka或者Consul進行服務發現

生產環境支援

  • 監控:使用Metrics和ELK
  • 快取:ehcache本地快取、hazelcast等分散式快取
  • 靜態資源優化(gzip、http cache header)
  • 日誌管理
  • 使用資料庫連線池HikariCP提升效能
  • 可建立標準的war或者可執行的jar
  • Docker以及Docker Compose完全支援
  • 支援主流雲服務提供商,如k8s docker aws 等

環境設定

安裝JHipster

安裝方式

Jhipster提供了6中方式以便使用JHipster,主要有:

  • 線上安裝
  • 使用Yarn進行本地安裝
  • 使用NPM進行本地安裝
  • 使用包管理器安裝,僅支援Max OS X和Windows
  • 基於ubuntu development box安裝
  • 基於docker的輕量級容器安裝

官方推薦選擇第二種安裝方式,即:使用Yarn進行本地安裝。

使用Yarn進行本地安裝

當使用Angular時的快速配置
  1. 安裝JDK8
  2. 安裝Node.js
  3. 安裝Yarn(配置淘寶映象:yarn config set registry https://registry.npm.taobao.org
  4. 如果要使用JHipster商城,需要安裝Yeoman:yarn global add yo
  5. 安裝JHipster:yarn global add generator-jhipster
當使用AngularJS 1.x時的快速配置
  1. 安裝JDK8
  2. 安裝Node.js
  3. 安裝Yarn
  4. 安裝Bower: yarn global add bower
  5. 安裝gulp: yarn global add gulp-cli
  6. 如果需要使用JHipster商城,安裝Yeoman:yarn global add yo
  7. 安裝JHipster:yarn global add generator-jhipster
其他元件安裝
  1. 安裝Java構建工具:Maven或者Gradle,如果使用Maven需要配置環境變數 M2_HOME=/maven-home
  2. 安裝git進行版本管理
其他問題

如果使用Yarn有問題,請檢查$HOME/.config/yarn/global/node_modules/.bin 有沒有此路徑。 在Mac或者Linux下,需要
export PATH="$PATH:`yarn global bin`:$HOME/.config/yarn/global/node_modules/.bin"

Jhipster核心任務

建立一個應用

快速入門

開始之前為你的應用建立一個空資料夾:mkdir myapplication

進入到此資料夾中 cd myapplication

生成你的應用,執行jhipster

回答你看到的問題,這些問題用於定製你的應用,稍後詳細解釋每個問題。

當一個應用生成好之後,你可以使用./mvnw或者./mvnw.bat來啟動,(也可以使用yarn && mvn spring-boot:run來啟動)

生成應用時的問題

你選擇的問題答案不同可能會影響到接下來的問題顯示,如:你不想使用hibernate的快取那麼就不能選擇sql資料庫。

Q1. Which type of application would you like to create?
  • Monolithic application: 單體應用
  • Microservice application: 微服務架構的service
  • Microservice gateway: 微服務閘道器,為微服務請求進行路由和安全
  • JHipster UAA server: 基於OAuth2的安全認證微服務,後文詳細解釋
Q2. What is the base name of your application?

你期望的應用的名稱

Q3. What is your default Java package name?

應用使用的預設包名,使用Yeoman的時候此值會被儲存,當下次使用的時候此值會成為預設值,可覆寫此值

Q4. Do you want to use the JHipster Registry to configure, monitor and scale your application?

JHipster Registry是一個開源的工具,用於管理你正在執行的應用(微服務註冊中心和統一配置中心),只有在微服務架構時才會使用

Q5. Which type of authentication would you like to use?

所有可能的答案:

  • JWT authentication: 使用JSON Web Token
  • HTTP Session Authentication:經典的基於session認證的機制
  • OAuth 2.0 / OIDC Authentication: 使用OpenID連線服務,類似於Keycloak或者Okta
  • Authentication with JHipster UAA server: 此種方式必須提前生成JHipster UAA Server (Q1的選項),它是基於OAuth2的驗證服務
Q6. Which type of database would you like to use?

你可以選擇的選項:

  • No database,僅使用微服務架構時可用
  • An SQL database: 使用關係型資料庫,將會採用Spring data jpa
  • MongoDB
  • Cassandra
  • Couchbase
Q7. Which production database would you like to use?

選擇你線上環境使用的資料庫,此選項決定src/main/resources/config/application-prod.yml的配置

Q8. Which development database would you like to use?

此選項決定你src/main/resources/config/application-dev.ymlprofile的資料庫配置項,你可以選擇:

  • H2,running in-memory,資料儲存在記憶體中,服務停掉資料消失
  • H2,with its data stored on disk,資料儲存在硬碟,當前只是BETA測試且不能在Windows機器上工作
  • 可以和Q7的選項一致
Q9. Do you want to use the Spring cache abstraction?

由於Spring對於Cache的允許使用者使用不同的cache實現,你可以使用chcache(本地快取),Hazelcast(分散式快取)或者Infinispan(另一種分散式快取),此選項可以提升你的應用的效能

Q10. Do you want to use Hibernate 2nd level cache?

此選項僅當你選擇SQL資料庫並且在Q9選擇了一個快取實現。Hibernate使用二級快取可以更好的提升它的效能

Q11. Would you like to use Maven or Gradle?

構建此專案時將要使用的工具,Maven或者Gradle

Q12. Which other technologies would you like to use?

多選,你可以為你的應用新增多種技術,如:

  • Social login,社交登入功能
  • API first development using swagger-codegen:通過成swagger-codegen而使你的應用採用API優先的開發模式
  • Search engine using ElasticSearch: 對於ES的支援(Spring Data Elasticsearch)
  • Clustered HTTP sessions using Hazelcast,預設情況下,JHipster只是用Http Session來儲存Spring Security的身份驗證和授權資訊。如果你在叢集中執行,使用HTTP Session將會導致一些資料一致的問題,如果你想在叢集中複製session,請選擇此項
Q13. WebSockets using Spring Websocket

啟用Websockets支援,將使用Spring WebSocket,JHipster提供了簡單的例子展示如和高效的使用

Q14. Asynchronous messages using Apache Kafka

是否使用Kafka來發布和訂閱訊息

Q15. Which Framework would you like to use for the client?

選擇使用那種客戶端技術:

  • Angular version 4+
  • AngularJS version 1.x
Q16. Would you like to use the LibSass stylesheet preprocessor for your CSS?

Node-sass對於設計CSS是一個優秀的解決方案,便於高效使用,你需要執行一個Gulp服務,jhipster會自動配置

Q17. Would you like to enable internationalization support?

JHipster對於國際支援非常友好,你可以在客戶端和服務端使用。但一般對於國際化要求不多的場景,可以不選擇。

Q18. Which testing frameworks would you like to use?

預設Jhipster提供了Java單元/整合測試(spring`s Junit)和JavaScript單元測試(Karma.js),你也可以選擇:

  • Performance tests using Gatling,效能測試 Gatling
  • Behaviour tests using Cucumber,行為測試 Cucumber
  • Angular integration tests with Protractor, angular整合測試Protractor
Q19. Would you like to install other generators from the JHipster Marketplace?

是否需要去JHipster商城安裝第三方外掛模組

命令列選項

你可以使用JHipster的一些可選命令列選項,使用jhipster app --help檢視詳細說明。

  • --skip-cache 忽略之前記住的答案
  • --skip-git 不自動生成git專案
  • --skip-install不自動安裝依賴
  • --skip-client 跳過客戶端的生成,只生成後臺服務,也可以使用jhipster server代替
  • --skip-client 跳過生成服務端程式碼,只生成客戶端程式碼jhipster clinet代替
  • --skip-user-management跳過生成使用者管理程式碼,包含前端和後端
  • --i18n 當跳過客戶端程式碼生成時禁用或啟用i18n,否則沒應用
  • --auth 當跳過服務端程式碼生成時指定認證型別
  • --db 當跳過服務端程式碼生成時指定資料庫
  • --with-entities 如果已經生成了實體則重新生成一次
  • --skip-checks 跳過需要工具的檢查
  • --jhi-prefix 新增服務、元件或路由的字首,預設jhi
  • --npm 使用npm代替Yarn
  • --eperimental 啟用實驗特性,請注意這些特性可能不穩定
  • --force 強制覆蓋以存在的檔案

建立一個實體

介紹

當你剛建立完應用時,你可能想要建立一些實體類。例如你也許想要建立一個Book和Author實體類。對於每個實體,你需要:

  • 一個數據庫表
  • 一個Liquibase變更set
  • 一個JPA實體
  • 一個Spring data jpa repository
  • 一個帶有基礎增刪改查的rest controller
  • 一個angular路由、元件以及服務
  • 一個HTML檢視
  • 整合測試
  • 效能測試

如果你有多個實體,你可能還想建立他們之間的關係,比如這個例子,你需要:

  • 一個數據庫外來鍵
  • 指定Javascript和HTML程式碼管理此關係

實體sub-generator(子生成器)將會為每個實體建立所有需要的檔案並且提供增刪改查後端,sub-generator通過jhipster entity <entityName> --[options]執行

它支援的選項有:

  • --table-name <table_name> 通過JHipster會生成一個表,他的名稱基於你的實體名稱,如果你想要修改為不同的名稱使用此選項
  • --angular-suffix <suffix> 如果你想所有的都帶有自定義的字尾,可使用此選項
  • --regenerate 將會不做任何詢問生成已存在的實體
  • --skip-server 不會服務端程式碼
  • --skip-client不會生成客戶端程式碼
  • --db 跳過服務端程式碼生成時指定資料庫

JHipster UML AND JDL Studio

此章節描述如何使用JHipster的標準命令列介面建立實體類。如果你想建立多個實體,你也許要使用一些圖形工具。

如果你使用JDL Studio:

  • 你已使用import-jdl子生成器從JDL 檔案生成實體,jhipster import-jdl your-jdl-file.jh

    • 當匯入的時候如果你不想重新生成實體,你可以使用--json-only標誌,跳過實體生成僅建立json檔案於.jhipster資料夾中
    • 預設使用import-jdl僅會重新生成被改變的實體,如果你想所有的實體被重新生成,則通過--force生成
  • 如果你使用JhipsterUML代替import-jdl子生成器,你需要安裝npm install -g jhipster-uml然後執行jhipster-uml youFileName.jh

實體欄位

對於每個實體,你可以新增很多欄位。你需要輸入欄位名稱和型別,JHipster將會生成你所需的程式碼和配置。這些欄位名稱不能包含關鍵字

欄位型別

JHipster支援很多欄位型別,這些支援依賴於你的後臺資料庫,所有我們使用Java型別去描述他們:一個Java String在Oracle和Cassandra中不同,這是Jhipster生成健壯和正確的資料庫程式碼的一種方式。

  • String 它的預設長度取決於後端,如果你使用JPA預設長度255,你可以通過檢驗規則來修改它
  • Integer
  • Long
  • Float
  • Double
  • BigDecimal
  • LocalDate 用於在Java中正確的管理日期
  • Instant 用於時間戳
  • ZoneDateTime 給定時區的本地時間
  • Enumeration 列舉物件,當選擇此型別時,子生成器將會詢問你對應的列舉值並建立enum類
  • Blob 用於儲存二進位制資料,當被選中時,子生成器會詢問你儲存的資料型別,是圖片物件還是CLOB

校驗

可以對每個欄位設定校驗,不同的欄位具有不同校驗選項

校驗將會被自動的生成在:

  • Html views,使用the AngularJS validation mechanism

當物件被以下面的方式使用時,會自動的對領域物件進行校驗:

  • Sptring MVC/REST controllers(使用@Valid註解時)
  • Hibernate/JPA(實體在儲存之前自動校驗)

校驗資訊將盡可能清晰的使用資料庫列的元資料描述:

  • 必填欄位將被標記為non-nullable
  • 唯一欄位將建立唯一約束
  • 有最大長度的欄位與資料庫中的長度相同

校驗功能會有一些限制:

  • 不支援AnjularJS和Bean Validation的所有校驗選項,只支援具有共同API的選項
  • Java和Javascript的正則表示式不一定能同時工作,當你配置其中一個時,你需要略微的修正另一個
  • JHipster生成的單元測試用例並不知道你的校驗規則,這可能導致生成的單元測試用例不能通過校驗規則,這時候你需要更新單元測試用例的值以使他們符合規則

實體關係

實體關係僅支援關係型資料庫,稍後有章節詳細說明

為你的業務邏輯生成單獨的service class

相對於rest controller,單獨的service類中允許有多種邏輯組合。業務層允許使用DTO。

相同邏輯使用spring service sub-generator,後續將由章節詳細說明

Data Thransfer Objects(DTOs)

預設JHipster實體不使用DTOs,但是如果使用業務層時,DTOs是一中可用的資料傳輸方式,具體用法後續章節詳細說明

Filtering(過濾或者查詢)

可選,實體儲存在資料庫中可以使用JPA過濾。

分頁

當你的應用使用Cassandra建立的時候,是不能使用分頁的。當然這個特性將會被新增。

JHipster在服務端和客戶端提供了依照標準規則的實現

當實體被生成時,JHipster提供了4中分頁選項:

  • 不分頁
  • 簡單分頁,基於bootstrap pager
  • 完成分頁系統,基於Bootstrap pagination component
  • 滾動分頁,基於infinite scroll directive

更新已存在的實體

實體配置儲存在~/.jhipster/*.json檔案中,如果你再次使用已存在的實體類名執行子生成器,你就可以更新或者重新生成實體

當你對一個已存在的實體執行子生成器時,將會詢問’Do you want to update the entity? This will replace the existing files for this entity, all your custom code will be overwritten’(你想更新實體嗎?這將會替換已存在的實體檔案和實體相關的所有的程式碼將會被覆蓋),有兩種答案:

  • Yes, re generate the entity,這將重新生成你的實體
  • Yes, add more fields and relationships詢問你以新增更多欄位和關係
  • Yes, remove fields and relationships浙江詢問你是否移除已存在的欄位和關係
  • No, exit

你更新實體的理由可能如下:

  • 你想對已存在的實體新增或者移除欄位及關係
  • 你想重置你的實體程式碼
  • 你更新了JHipster,想使用新的模板生成你的實體
  • 你修改了.json檔案,所以你需要有一個新版本的實體
  • 你貼上複製了.json檔案,然後想生成此實體

快速生成多個實體:

  • linux & mac :
for f in `ls .jhipster`; do jhipster entity ${f%.*} --force ; done
  • Windows:
for %f in (.jhipster/*) do jhipster entity %~nf --force

指導

這是一個簡短的引導以建立兩個具有one-to-many的實體(Author 和 Book)

一個Author包含多個Book的關係,所以我們需要首先建立Author,在資料庫級別Jhipster將會建立一個外來鍵在Book表上,這外來鍵指向Author表

jhipster entity author

輸入關於這個實體欄位的問題的答案:

  • a “name” of type “String”
  • a “birthDate” of type “LocalDate”

輸入關於這個實體關係的問題答案:

  • one-to-many with the “book” entity(當前Book還不存在)
生成Book實體

jhipster entity book

回答接下來關於book欄位的的問題 :

  • title型別為String
  • description型別為String
  • publicationDate型別為LocalDate
  • price型別為BigDecimal

回答關於關係的問題:

  • 擁有與author的many-to-one的關係
  • 關係中使用name欄位顯示author
檢查生成的程式碼

執行生成的測試用例mvn test,此測試用例測試Author和Book實體

啟動應用,登入後點擊- entities > Author

修改生成的程式碼

生成的檔案包含了基礎的CURD操作。如果你的需求比較簡單的話,都不用進行任何修改。

如果你想修改生成的程式碼或者資料庫表,你應該閱讀後續的“開發指導”章節

如果你有一些組合的業務行為,你也許需要新增Spring的@Service類,請使用 service生成器

建立Controller

介紹

controller生成器相對實體生成器而言,簡單的多。此生成器用於生成Spring MVC REST controller,如:jhipster spring-controller Foo,簡單的回答完問題後,即可生成

可以使用swagger記錄這個rest介面嗎?

在dev模式下,點選aministration > API 即可看到。

可以為此介面新增安全控制嗎?

只需要新增@Secured註解在你的類或者方法上,就可以限定使用者的許可權。

可以監控這個介面嗎?

值需要新增@Timed註解就可以監控

建立Spring service

介紹

此生成器相對於實體類生成器簡單的多。

此生成器生成你應用程式的業務邏輯的spring service物件,如:

jhipster spring-service Bar

這將會生成BarService.生成的程式碼行數很少,但通常會有一些問題。

為什麼service class不通過實體類生成器生成?

我們這裡有兩個主要的架構原則:

  • 我們不想推廣無用的服務,如果你僅需要一個基礎的CURD操作,那麼是不需要service物件的,這也是為什麼Jhipster不生成他們的原因
  • 我們認為service bean 應該比repository的粒度更粗,service bean使用多個repository來實現他們的業務價值,所以Service沒有和實體類一起生成

我們Service應該使用interface嗎?

簡單的說:不需要!

如果需要詳細的解釋,那麼:

一個主要的興趣點是使用Spring AOP,這個技術允許Spring新增一些行為在你的Bean之上:對於實力而言,提供了諸如事務控制、安全的工作等。

為了增加這寫行為,spring需要為你累建立一個代理,一般由兩種方式建立代理:

  • 如果你使用的介面,spring將會使用Java提供的標準機制來建立動態代理
  • 如果你沒有使用介面,Spring將會使用CGLIB來生成一個新的類:這不是Java的標準機制,但是它比標準機制工作的要好

很多人的爭論點之一是使用介面易於編寫測試用例,但是我們詳細我們不應該為了測試用例兒修改我們的產品程式碼,並且還有一些新的mock框架(如EasyMock)允許我們不用介面建立一些有些的單元測試用例。

因此,最終我們發現介面對於我們的Service Bean通常是無用的,所以我們不推薦使用(但我們任務提供了生成介面的選項)

為什麼我們應該使用事務來延遲載入JPA的關係?

預設JPA使用延遲載入一對多和多對多的實體關係,如果你使用預設配置,你將很可能看到LazyInitializationException:這意味著你嘗試在事務外使用未初始化的關係。

由於生成的service class預設使用了@ Transactional註解,所有的方式都具有事務性,這意味著你可以再方法內獲取所需的延遲載入的關係了,不用擔心出現LazyInitializationException

提示:如果你不修改資料時在方法上使用@Transactional(readOnly = true)。這是一個比較好的效能優化方式(hibernate不需要重新整理一級快取,因為我們沒有修改任何資料)以及使用一些JDBC驅動時質量的提升(Oracle不允許傳送INSERT/UPDATE/DELETE命令)

可以給Service Bean新增許可權控制嗎?

僅需要在類或者方法上新增@Secured註解即可限制使用者的訪問許可權。

可以監控Service Bean嗎?

僅需在方法上添加註解@Timed即可。

建立DTOs

警告這是一個比較新的特性,目前處於測試階段,使用它有一定的風險,非常歡迎反饋。

介紹

Jhipster預設在REST端點使用領域模型物件(典型的JPA實體)。這樣做有很多好處,如易於使用、便於理解和擴充套件。

但是在一些複雜的場景,你也許想在REST的端點暴露出資料傳輸物件(DTOs)。這些物件將在domain物件上新增一些額外的東西,並專門針對REST進行優化:他們最大的好處就是可以將多個domain物件聚合起來使用。

DTOs在JHipster中如何工作

在生產JHipster實體的時候,你擁有一個新增Service層的選項:只有當你選擇一個需要進行對映的Service層時DTOs選線才可以使用(當你使用的是JPA,由於service層具有事務,所以延遲載入會起作用)。

當你選擇擁有service層時,你將會擁有從實體生成DTO的選項,如:

  • 一個基於當前實體對映的DTO將會被生成
  • 它將聚合多對一關係,僅使用ID和一個用於在客戶端(如angular)顯示的欄位,因此,在一個基於User實體的多對一關係中將會新增一個userId和userLogin到DTO中。
  • 忽略一對多和多對多關係:這與實體的工作方式相似(在這些欄位上具有一個@JsonIgnore
  • 對於所有者的多對多關係:它將使用來自其他實體的DTO,並將他們放在Set中,因此,只有在另一個實體也是用DTO的時候才能起作用。

使用MapStruct對映實體與DTOs

DTOs看起來很像一個實體,因此需要一個自動對映他們的解決方案。

JHipster選擇的解決方案是使用MapStruct,它是一個註解處理器,在Java編譯的時候自動的生成需要的對映。

我們發現,相對於反射而言,它乾淨而且高效。(使用反射進行對映的時候,對於效能而言比較糟糕)

在IDE中配置MapStruct

MapStruct是一個註解處理,當IDE編譯專案的時候應該將它設定為自動執行。

如果你使用的士Maven,你需要在IDE中啟用profile,gradle使用者不需要進行任何設定。

如何啟用Profile在“配置IDE”章節說明。

MapStruct的高階使用

MapStruct對映可以被配置為一個SpingBeans,並且支援依賴注入。你可以將Repository注入到對映中,就可以使用ID在Mapper中獲取JPA實體。 如:

@Mapper
public abstract class CarMapper {

    @Inject
    private UserRepository userRepository;

    @Mapping(source = "user.id", target = "userId")
    @Mapping(source = "user.login", target = "userLogin")
    public abstract CarDTO carToCarDTO(Car car);

    @Mapping(source = "userId", target = "user")
    public abstract Car carDTOToCar(CarDTO carDTO);

    public User userFromId(Long id) {
        if (id == null) {
            return null;
        }
        return userRepository.findOne(id);
    }
}

關係管理

當使用JPA的時候,實體生成器可以建立實體之間的關係。

簡述

只有使用JPA的時候關係才會工作,如果你選擇 Cassandra, MongoDB of Couchbase的話關係是不可用的。

一個關係產生於兩個實體之間,JHipster會生成如下程式碼:

  • 生成實體時通過JPA管理關係
  • 生成正確的Liquibase changelog,以便在已有的資料庫中維護關係。
  • 生成angular的前端,你就可以通過圖形使用使用者介面管理關係。

JHipster UML 以及 JDL studio

這個章描述瞭如何通過Jhipster標準命令列介面生成關係。如果你需要常見比較多的實體和關係的時候,更好使用一些圖形工具。

  • JHipster UML: 允許使用UML編輯器
  • JDL Studio:線上工具,使用我們特定的語言建立實體和關係

你可以通過import-jdl子生成器使用JDL檔案生成實體和關係jhipster import-jdl you-jdl-file.jh

可用的關係

我們使用JPA,通常可用的關係有:one-to-many,many-to-one,many-to-many,以及one-to-one:

  1. 雙向一對多
  2. 單向多對一
  3. 單向一對多
  4. 同一實體上的兩個多對一關係
  5. 多對多關係
  6. 一對一關係
  7. 單向一對一關係

請注意通過jhipster生成的User實體,你可以:

  • 給此實體新增many-to-one關係(一個Carmany-to-oneUser),這將會在你的新的實體Repository中生成一個特定的查詢,然後你參考一使用當前的認證使用者查詢實體。在生成的angular介面,你可以通過下拉選擇Car來選中一個使用者。

  • many-to-manyone-to-one關係在User實體中,另一個實體必須是關係的所有者(一個TeamUser是many-to-many關係,但是Team能增刪User,但是User不能增刪Team).在angular介面,你可以在多選框中選擇User.

單向一對多關係

讓我們從兩個實體開始吧,OwnerCar。一個owner可以多輛car,一個car只能屬於一個owner。

因此在owner這邊是一個簡單的一對多關係,而在另一邊是一個多對一的關係。

Owner (1) <------> (*) Car

首先我們來建立Owner,這有幾個關係Owner的問題:

jhipster entity Owner
...
Generating relationships with other entities
? Do you want to add a relationship to another entity? Yes
? What is the name of the other entity? Car
? What is the name of the relationship? car
? What is the type of the relationship? one-to-many
? What is the name of this relationship in the other entity? owner

請注意我們選擇預設的關係名稱。接下來,我們生成Car:

jhipster entity Car
...
Generating relationships with other entities
? Do you want to add a relationship to another entity? Yes
? What is the name of the other entity? Owner
? What is the name of the relationship? owner
? What is the type of the relationship? many-to-one
? When you display this relationship with AngularJS, which field from 'Owner' do you want to use? id

使用下邊的JDL也可以實現:


entity Owner
entity Car

relationship OneToMany {
  Owner{car} to Car{owner}
}

這樣,你現在就擁有了一個一對多的關係在兩個實體之間。在angular介面你可以通過Car下拉框選中一個User.

單向對多一關係

在前邊的例子中我們有一個雙向關係:通過Car例項可以發現他的Owner,通過Owner可以找到他的所有Car

一個單向多對一的關係意味著Car可以知道他們的Owner,但是不能反過來:

Owner (1) <------ (*) Car

擁有這樣的關係可能有兩個原因:

  • 從業務的角度來講,你僅需要通過這種方式使用實體,因此不希望有其他的API允許開發者做一些沒有意義的事情
  • 期望使用Owner時效能提升(因為你不用哪個維護一個Car的集合)

在這個例子中,你仍然需要先建立Owner,但這次沒有生成關係:

jhipster entity Owner
...
Generating relationships with other entities
? Do you want to add a relationship to another entity? No

接下來生成Car實體,和前邊的例子相似:

jhipster entity Car
...
Generating relationships with other entities
? Do you want to add a relationship to another entity? Yes
? What is the name of the other entity? Owner
? What is the name of the relationship? owner
? What is the type of the relationship? many-to-one
? When you display this relationship with AngularJS, which field from 'Owner' do you want to use? id

這將會和前邊的例子一樣正常公國,但是我們不能通過Owner來新增和刪除Car。在angular你將會通過Car的下來框選中一個Owner。下邊是相關的JDL:

entity Owner
entity Car

relationship ManyToOne {
  Car{owner} to Owner
}

單向一對多關係

單向一對多關係意味著Owner例項可以獲取一個Car集合,但不反過來不能。這個和前邊的例子是相反的:

Owner (1) ------> (*) Car

目前,這種關係型別Jhipster預設是不提供的。原因檢視#1569

你有兩種解決方式:

  • 使用一個雙向對映不用修改,這也是我們推薦的,相對比較簡單
  • 使用一個雙向對映,然後將西修改成單向對映:
    • @OneToMany註解上移除mappedBy屬性
    • 生成所需要的表:你可以使用mvn liquibase:diff生成表。

在JHipster中不支援通過JDL生成這種關係。

同一實體的一對多關係

在這個例子中,一個Person可以成為多個Car的擁有者,當然他也可以駕駛多輛Car:

Persion (1) <---owns---> (*) Car
Persion (1) <---drivers---> (*) Car

為此我們需要使用我們之前的例子中保留的預設關係名稱。

生成Persion實體,它具有到Car的一對多關係:

jhipster entity Person
...
Generating relationships with other entities
? Do you want to add a relationship to another entity? Yes
? What is the name of the other entity? Car
? What is the name of the relationship? ownedCar
? What is the type of the relationship? one-to-many
? What is the name of this relationship in the other entity? owner
...
Generating relationships with other entities
? Do you want to add a relationship to another entity? Yes
? What is the name of the other entity? Car
? What is the name of the relationship? drivedCar
? What is the type of the relationship? one-to-many
? What is the name of this relationship in the other entity? driver

生成Car實體,使用在Person中的相同的關係名稱:

jhipster entity Car
...
Generating relationships with other entities
? Do you want to add a relationship to another entity? Yes
? What is the name of the other entity? Person
? What is the name of the relationship? owner
? What is the type of the relationship? many-to-one
? When you display this relationship with AngularJS, which field from 'Person' do you want to use? id
...
Generating relationships with other entities
? Do you want to add a relationship to another entity? Yes
? What is the name of the other entity? Person
? What is the name of the relationship? driver
? What is the type of the relationship? many-to-one
? When you display this relationship with AngularJS, which field from 'Person' do you want to use? id

也可以通過如下的JDL實現:

entity Person
entity Car

relationship OneToMany {
  Person{ownedCar} to Car{owner}
}

relationship OneToMany {
  Person{drivedCar} to Car{driver}
}

現在,一個Car擁有一個driver和一個owner,他們都是Person實體。在生產的angular的介面我們可以下拉Carownerdriver選中一個Person.

多對多關係

一個Driver可以駕駛多輛汽車,但是一輛Car也可以有被多個司機。

Driver (*) <------> (*) Car

在資料庫級別,這意味著DriverCar會有一張關聯表。

對於JPA,這兩個實體中一個將負責管理關係:在我們的例子中,將有Car來負責增刪Driver.

讓我們在沒有關係所有權的一方生成多對多關係:

jhipster entity Driver
...
Generating relationships with other entities
? Do you want to add a relationship to another entity? Yes
? What is the name of the other entity? Car
? What is the name of the relationship? car
? What is the type of the relationship? many-to-many
? Is this entity the owner of the relationship? No
? What is the name of this relationship in the other entity? driver

接下來生成具有多對多關係所有權的一方Car:

jhipster entity Car
...
Generating relationships with other entities
? Do you want to add a relationship to another entity? Yes
? What is the name of the other entity? Driver
? What is the name of the relationship? driver
? What is the type of the relationship? many-to-many
? Is this entity the owner of the relationship? Yes
? When you display this relationship with AngularJS, which field from 'Driver' do you want to use? id

也可以通過JDL實現相同的目的:

entity Driver
entity Car

relationship ManyToMany {
  Car{driver} to Driver{car}
}

這樣,你就擁有了兩個實體之間的多對多關係。在生成的angular介面,你可以通過一個Car的複選下拉框來選擇屬於這個Car的多個Driver了。

一對一關係

接著我們之前的例子,一個一對一關係意味著一個Driver只能駕駛一輛Car,一輛Car只能有一個Driver

Driver (1) <------> (1) Car

首先我們建立沒有關係所有權的一方,Driver:

jhipster entity Driver
...
Generating relationships with other entities
? Do you want to add a relationship to another entity? Yes
? What is the name of the other entity? Car
? What is the name of the relationship? car
? What is the type of the relationship? one-to-one
? Is this entity the owner of the relationship? No
? What is the name of this relationship in the other entity? driver

接下來我們建立擁有關係所有權的一方Car:

jhipster entity Car
...
Generating relationships with other entities
? Do you want to add a relationship to another entity? Yes
? What is the name of the other entity? Driver
? What is the name of the relationship? driver
? What is the type of the relationship? one-to-one
? Is this entity the owner of the relationship? Yes
? What is the name of this relationship in the other entity? car
? When you display this relationship with AngularJS, which field from 'Driver' do you want to use? id

通過JDL可以實現相同的目的:

entity Driver
entity Car

relationship OneToOne {
  Car{driver} to Driver{car}
}

單向一對一關係

單向一對一關係意味著可以通過citizen獲取到passport,但不能通過passport獲取citizen

Citizen (1) -----> (1) Passport

首先我們生成沒有任何所屬關係的一方Passport:

jhipster entity Passport
...
Generating relationships with other entities
? Do you want to add a relationship to another entity? No

接下來,生成Citizen實體:

jhipster entity Citizen
...
Generating relationships with other entities
? Do you want to add a relationship to another entity? Yes
? What is the name of the other entity? Passport
? What is the name of the relationship? passport
? What is the type of the relationship? one-to-one
? Is this entity the owner of the relationship? Yes
? What is the name of this relationship in the other entity? citizen
? When you display this relationship with AngularJS, which field from 'Passport' do you want to use? id

做完這些,一個Citizen擁有一個護照,但是在Passport上沒有定義Citizen例項。生產的angular介面上,你可以下拉Citizen來選中一個Passport

相應的JDL如下:

entity Citizen
entity Passport

relationship OneToOne {
  Citizen{passport} to Passport
}

國際化

介紹

在生成一個新專案的時候,你將會被詢問是否需要啟用國際化的支援。

如果啟用,你需要為你的應用選擇一個原生語言。然後你可以選擇你需要新增的其他語言。如果你一開始沒有選擇支援或者新增語言,那麼稍後你可以通過語言生成器新增語言。

如果你確認你的應用不需要翻譯成其他語言,你就可以不啟用國際化。

支援的語言

  • Arabic (Libya)
  • Armenian
  • Indonesian
  • Catalan
  • Chinese (Simplified)
  • Chinese (Traditional)
  • Czech
  • Danish
  • Dutch
  • English
  • Estonian
  • Farsi
  • French
  • Galician
  • German
  • Greek
  • Hindi
  • Hungarian
  • Italian
  • Japanese
  • Korean
  • Marathi
  • Polish
  • Portuguese
  • Portuguese (Brazilian)
  • Romanian
  • Russian
  • Slovak
  • Serbian
  • Spanish
  • Swedish
  • Turkish
  • Tamil
  • Thai
  • Turkish
  • Ukrainian
  • Vietnamese

在專案生成之後如何新增語言?

可以通過以下命令來進行新增:

jhipster languages

Languages configuration is starting
? Please choose additional languages to install (Press <space> to select, <a> to toggle all, <i> to inverse selection)
❯◯ Arabic (Libya)
 ◯ Armenian
 ◯ Catalan
 ◯ Chinese (Simplified)
 ◯ Chinese (Traditional)
 ◯ Czech
 ◯ Danish
(Move up and down to reveal more choices)

如何新增支援列表之外的語言

所有的語言檔案儲存於這些資料夾:客戶端src/main/webapp/i18n,服務端src/main/resources/i18n

下邊是一個叫做new_lang的語言的安裝步驟:

  1. 複製src/main/webapp/i18/ensrc/main/webapp/i18/new_lang(這是所有前端檔案儲存的地方)
  2. 翻譯儲存在src/main/webapp/i18/new_lang所有檔案
  3. 為AngularJs 1 新增語言的常量定義程式碼,此常量位於src/main/webapp/app/components/language/language.constants.js

    .constant('LANGUAGES', [
        'en',
        'fr',
        'new_lang'
        // jhipster-needle-i18n-language-constant - JHipster will add/remove languages in this array
    ]
  4. src/main/resources/i18n資料夾中,拷貝messages_en.properties檔案為messages_new_lang.properties(服務端所有的翻譯檔案儲存在這兒)
  5. 翻譯messages_new_lang.properties檔案中的所有鍵
  6. src/main/webapp/app/components/language/language.filter.js檔案的函式filter('findLanguageFromKey')為Angular JS 1新增新的語言名稱。在src/main/webapp/app/shared/language/find-language-from-key.pipe.ts檔案的變數FindLanguageFromKeyPipelanguages新增新的語言名稱。
  7. webpack.common.js檔案中為Angular 2+新增新的語言繫結

    new MergeJsonWebpackPlugin({
        output: {
            groupBy: [
                { pattern: "./src/main/webapp/i18n/en/*.json", fileName: "./i18n/en.json" },
                { pattern: "./src/main/webapp/i18n/new_lang/*.json", fileName: "./i18n/new_lang.json" }
                // jhipster-needle-i18n-language-webpack - JHipster will add/remove languages in this array
            ]
        }
    })

現在,新的語言new_lang就出現在了語言選單的下來框中,並且前端和後端應用都可用。

如何移除已存在的語言?

通過以下步驟移除叫做old_lang的語言:

  1. 移除資料夾src/main/webapp/i18/old_lang
  2. 進入檔案src/main/webapp/app/components/language/language.constants.js或者 src/main/webapp/app/shared/language/language.constants.tswebpack.common.js移除定義的常量
  3. 移除檔案src/main/resources/i18n/messages_old_lang.properties

升級應用

當新版本的Jhipster被髮布時,使用JHipster upgrade生成器幫助升級已存在的應用到最先進的版本。升級有益於以下幾點:

  • 在應用中需要使用新的特性
  • 獲取重要的BUG修正或者安全更新
  • 保留你的程式碼,與新版本易於合併

在升級之前一定要仔細的閱讀這個章節,並且理解升級過程的工作。

必要條件

這個子生成器工作必須使用git

執行升級子生成器

進入應用的根目錄:cd myapplication/

升級你的應用: jhipster upgrade

執行此命令時有以下幾個選項:

  • --verbose 列印每一步驟的詳細日誌
  • --target-version=4.2.0 升級至指定的版本
  • --force 如果沒有新的版本可用也可以強制升級

升級過程示意圖

下邊的圖展示了升級過程:
升級流程

請注意:jhipster upgrade會在你的專案中建立一個沒有歷史資訊的分支,儘管在此圖中沒有正確的顯示出來。

一步一步的說明升級流程

jhister通過下邊的步驟來進行升級:

  1. 檢查是否有新版本可用
  2. 檢查專案是否是一個git專案,如果不是jhipster將初始化你的專案為git專案,並將當前程式碼提交到主分支
  3. 檢車確保沒有未提交的程式碼在倉庫中,如果有未提交的程式碼,升級程式將會退出