ねこじゃすり
猫を魅了する魔法の装備品!
Anker PowerCor
旅行には必須の大容量モバイルバッテリー!
[ノースフェイス] THE NORTH FACE メンズ アウター マウンテンライトジャケット
防水暴風で耐久性抜群なので旅行で大活躍です!
レッドブル エナジードリンク 250ml×24本
翼を授けよう!
ドラゴンクエスト メタリックモンスターズギャラリー メタルキング
みんな大好き経験値の塊をデスクに常備しておこう!
Bauhutte ( バウヒュッテ ) 昇降式 L字デスク ブラック BHD-670H-BK
メインデスクの横に置くのにぴったりなおしゃれな可動式ラック!
サンディスク microSD 128GB
スマホからSwitchまで使える大容量MicroSDカード!
スポンサーリンク
目次
お勉強のためのシステムを作ってみようと思った今日この頃
新鮮な知識を求めて
筆者は普段はJava+SpringBoot(1系)
を取り扱ったシステム開発を行っています。
Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”.
We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need very little Spring configuration.Spring Boot
上記の環境については、それなりに知識がついてきていると思っています。
しかし、日々進化するIT業界。。。
いつまでも同じ技術だけで生きていけるはずはありません。
個人事業主なら尚更です・・・!ガクガク((( ;゚Д゚)))ブルブル
Spring Boot2系を覚えよう
とはいえ、今後もJava
を武器にしていきたい気持ちは変わりません。
なんだかんだでメジャーな言語ですしね!
そして、Javaのサーバーサイド開発といえば、今やSpringフレームワークが一強となってきているのもまた事実。
そんな中SpringBoot2が最近リリースされまして、触ったことがなかったので勉強とアウトプットの目的を兼ねて、いろいろと個人開発をしながらやったことを記事にまとめていこうと思います!
ゆくゆくはサーバーサイドKotlinやフロントエンドの勉強、AWSやGCPなどへのデプロイなどもご紹介していければなと思います♪
そんなわけで、今回はSpringBoot2+Gradle
を取り扱ったマルチプロジェクト開発の土台作りをご紹介していこうと思います♪
手順
注意
今回は筆者の好みを踏まえたマルチプロジェクトの設定をご紹介していきます。
筆者の理想の開発思想としては以下の点を念頭におくようにしています。
- DDD(ドメイン駆動設計)
- マイクロサービス
- 極力疎結合
- ソース=ドキュメント
- MVCレイヤー思想
こんな感じですね。
ですので、あくまで皆さんの理想の開発環境構築を手助けするための参考程度に捉えて頂ければなと思います!!!
Spring Initializrでプロジェクトの作成
今回はSpring Initializrを使ってプロジェクトの雛壇を作ろうと思います。
Spring InitializrBootstrap your application · Github | Twitter. Help us improve the site! Take a quick survey. Project. Maven Project. Gradle Project. Language. Java. Kotlin. Groovy. Spring Boot. Spring Initializr
今回は以下の通りのアーキで作成しました。
Project | Gradle Project |
---|---|
Language | 2.1.3 |
Packaging | Jar |
Java Version | 8 |
Dependencies | 一旦無し(必要な時に理解しながら追加していく) |
ダウンロードしたzip
を展開して、api
というフォルダ名に変更して作業ディレクトリに移動しました。
確認
まずはこの状態でapi
フォルダにディレクトリに入って以下のコマンドで動作確認をしてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
> Task :bootRun . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.3.RELEASE) 2019-04-01 17:35:35.376 INFO 43476 --- [ main] t.b.service.account.AccountApplication : Starting AccountApplication on xxx.xxx.xxx.xxx.static.zoot.jp with PID XXXXX (/Users/blogenist/develop/git/github/service-account/api/build/classes/java/main started by blogenist in /Users/blogenist/develop/git/github/service-account/api) 2019-04-01 17:35:35.381 INFO 43476 --- [ main] t.b.service.account.AccountApplication : No active profile set, falling back to default profiles: default 2019-04-01 17:35:36.854 INFO 43476 --- [ main] t.b.service.account.AccountApplication : Started AccountApplication in 2.342 seconds (JVM running for 3.301) BUILD SUCCESSFUL in 32s 3 actionable tasks: 3 executed |
正しくビルド及び実行が出来ましたね。
devtoolsプロジェクトの作成
では、次にdevtools
のプロジェクトを作りましょう。
apiプロジェクト内部で各コマンドを行っても良いですが、筆者の好みとしてapiプロジェクトはapiの事だけに専念してもらって、開発における操作をするためのdevtoolsプロジェクトを作るようにしています。
ローカル開発でのコマンドやFlyway
などを使ったマイグレーとなどもdevtools
プロジェクトにてシェルなどにして管理すれば、開発スピードも上がるし、ファイルが混在するのも避けれますしね♪
まずは作業ディレクトリに移動して、cp -R api devtools
コマンドでapiディレクトリをdevtools
として再帰的にコピーしましょう。
コピーが出来たら、まずapi
ディレクトリからは以下のファイルを削除します。
- gradleディレクトリ
- gradlew
- gradlew.bat
- settings.gradle
次は、devtools
ディレクトリからは以下のファイルを削除します。
- srcディレクトリ
- gradlew
- gradlew.bat
次に、api/build.gradle
の内容を以下のように変更してください。
1 2 3 4 5 6 7 8 9 |
springBoot { mainClassName = 'xxx.yyy.zzz.XXXApplication' } repositories { } dependencies { } |
次に、devtools/settings.gradle
を以下のようにしてください。
1 2 3 4 5 6 7 8 |
pluginManagement { repositories { gradlePluginPortal() } } rootProject.name = 'devtools' //書き換え includeFlat 'api' // 追加 |
そして、最後にdevtools/build.gradle
の内容を以下のように変更してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
buildscript { ext { springBootVersion = "2.1.3.RELEASE" } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } allprojects { } subprojects { apply plugin: "java" apply plugin: "org.springframework.boot" apply plugin: "io.spring.dependency-management" group = 'xxx.yyy.zzz' version = '0.0.1-SNAPSHOT' sourceCompatibility = '1.8' repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter' testImplementation 'org.springframework.boot:spring-boot-starter-test' } } |
確認
では、この状態でdevtoolsディレクトリに移動し、もう一度アプリケーションを実行してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
> Task :api:bootRun . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.3.RELEASE) 2019-04-01 18:37:16.982 INFO 47670 --- [ main] t.b.service.account.AccountApplication : Starting AccountApplication on xxx.xxx.xxx.xxx.static.zoot.jp with PID XXXXX (/Users/blogenist/develop/git/github/service-account/api/build/classes/java/main started by blogenist in /Users/blogenist/develop/git/github/service-account/api) 2019-04-01 18:37:16.986 INFO 47670 --- [ main] t.b.service.account.AccountApplication : No active profile set, falling back to default profiles: default 2019-04-01 18:37:17.734 INFO 47670 --- [ main] t.b.service.account.AccountApplication : Started AccountApplication in 1.154 seconds (JVM running for 1.592) BUILD SUCCESSFUL in 2s 3 actionable tasks: 1 executed, 2 up-to-date |
Task :api:bootRun
となっているため、正常にdevtools
プロジェクトからapi
プロジェクトのアプリケーションを起動出来るようになりましたね♪
gradleプロパティ値の外部ファイル化
システムを開発していると、依存関係のあるライブラリやビルド情報などの設定値を設けるようになります。
これらの値をdevtools/build.gradle
に直接定義しても良いのですが、せっかくなので設定値のみをまとめたプロパティファイルを用意してそちらから読み込むようにしてみましょう。
まず、devtools
プロジェクトにproperty.gradle
を作成しましょう。
1 2 3 4 5 6 7 |
ext { accountService = [:] accountService.springBootVersion = '2.1.3.RELEASE' accountService.sourceCompatibility = 1.8 accountService.group = 'xxx.yyy.zzz' accountService.version = '0.0.1-SNAPSHOT' } |
これは、Groovy
の書き方で、空の連想配列を用意した上で各キーに対して設定値を定義している形になります。
そして、devtools/build.gradleを
以下のように修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
buildscript { apply from: 'property.gradle' // プロパティファイルの読み込み ext { //定義不要になる } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${accountService.springBootVersion}") // 読み込んだ変数を展開 } } allprojects { apply plugin: 'eclipse' } subprojects { apply plugin: "java" apply plugin: "org.springframework.boot" apply plugin: "io.spring.dependency-management" group = accountService.group// 読み込んだ変数を展開 version = accountService.version// 読み込んだ変数を展開 sourceCompatibility = accountService.sourceCompatibility// 読み込んだ変数を展開 repositories { mavenCentral() } dependencies { implementation "org.springframework.boot:spring-boot-starter:${accountService.springBootVersion}"// マシン毎のバージョン差異が出ないように指定追加 testImplementation "org.springframework.boot:spring-boot-starter-test:${accountService.springBootVersion}"// マシン毎のバージョン差異が出ないように指定追加 } } |
確認
ではもう一度確認してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
> Task :api:bootRun . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.3.RELEASE) 2019-04-01 18:51:29.148 INFO 48393 --- [ main] t.b.service.account.AccountApplication : Starting AccountApplication on xxx.xxx.xxx.xxx.static.zoot.jp with PID 48393 (/Users/blogenist/develop/git/github/service-account/api/build/classes/java/main started by blogenist in /Users/blogenist/develop/git/github/service-account/api) 2019-04-01 18:51:29.151 INFO 48393 --- [ main] t.b.service.account.AccountApplication : No active profile set, falling back to default profiles: default 2019-04-01 18:51:29.958 INFO 48393 --- [ main] t.b.service.account.AccountApplication : Started AccountApplication in 1.205 seconds (JVM running for 1.628) BUILD SUCCESSFUL in 2s 3 actionable tasks: 1 executed, 2 up-to-date |
こちらも問題なく動きましたね。
アプリケーションプロパティファイルの整理
次に、アプリケーションプロパティファイルを整理しましょう。
デフォルトではapi/src/main/resrouces/application.properties
が用意されています。
もちろん、このままでもよいのですがSpringBootはyml形式のプロパティファイルをサポートしています。
xml形式より格段に可読性が高く記述方法が簡単なのでyml形式がオススメです!
また、本番/検証/開発/ローカルごとに接続情報等は変わるので、その辺にも対応出来るような構造にしておきましょう。
まずは、application.properties
をapplication.yml
にリネームして、以下の記述を追記してください。
また、環境ごとに差分がない設定値を定義するためのapplication-common.yml
を用意してください。
今回の作業では特に内容は指定しませんが、今後こちらにも定義をしていこうと思っています。
1 2 3 4 5 |
#profileの指定が無い場合のデフォルトのprofile指定 spring: profiles: active: local include: common |
これはプロファイル指定を忘れた際に間違えて開発や検証、本番に向き先が行く事故を防ぐための設定となります。
次に、api/src/main/resources
ディレクトリにapplication-local.yml
とapplication-local.yml.tmp
を作成します。
Springでは、application-{profile名}.yml
を用意しておく事でそれぞれの環境にあったプロパティファイルを読み込んでくれます。
また、ローカル用のprofileに関しては設定が異なると思うので、application-local.yml.tmp
をgit管理して、各自はそれをapplication-local.yml
にリネームコピーして設定を変えるようにしています。
ファイルの中身は一旦は空で良いです。
確認(profile未指定)
ではもう一度確認してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
> Task :api:bootRun . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.3.RELEASE) 2019-04-01 18:57:39.148 INFO 48393 --- [ main] t.b.service.account.AccountApplication : Starting AccountApplication on xxx.xxx.xxx.xxx.static.zoot.jp with PID 48393 (/Users/blogenist/develop/git/github/service-account/api/build/classes/java/main started by blogenist in /Users/blogenist/develop/git/github/service-account/api) 2019-04-01 18:57:39.151 INFO 48393 --- [ main] t.b.service.account.AccountApplication : The following profiles are active: common,local 2019-04-01 18:57:39.958 INFO 48393 --- [ main] t.b.service.account.AccountApplication : Started AccountApplication in 1.205 seconds (JVM running for 1.628) BUILD SUCCESSFUL in 2s 3 actionable tasks: 1 executed, 2 up-to-date |
ログにThe following profiles are active: local
と出ているので、未指定時はデフォルトのプロパティファイルに指定したlocal
が適用されるようになりましたね♪
確認
上記で未指定時にはデフォルトのlocalが適用されるようになりましたが、本来はデプロイミス等を防ぐために、意図してprofileを指定する癖をつけておいたほうが良いでしょう。
実行時に-Pargs="--spring.profiles.active={profile名}"
をつける事でプロファイルを指定する事が可能になります。
以下のコマンドで確認しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
> Task :api:bootRun . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.3.RELEASE) 2019-04-03 15:20:17.595 INFO 34962 --- [ main] t.b.service.account.AccountApplication : Starting AccountApplication on xxx.xxx.xxx.xxx.static.zoot.jp with PID 34962 (/Users/blogenist/develop/git/github/service-account/api/build/classes/java/main started by blogenist in /Users/blogenist/develop/git/github/service-account/api) 2019-04-03 15:20:17.599 INFO 34962 --- [ main] t.b.service.account.AccountApplication : The following profiles are active: common,local 2019-04-03 15:20:18.439 INFO 34962 --- [ main] t.b.service.account.AccountApplication : Started AccountApplication in 1.804 seconds (JVM running for 2.488) BUILD SUCCESSFUL in 3s 3 actionable tasks: 1 executed, 2 up-to-date |
以上のように、問題なくprofile指定がlocalに有効な状態で起動出来ましたね♪
ちなみに、hogeのような存在しないprofileを指定するとエラーにならずにデフォルトのprofileが読み込まれます。
今回の場合は内部的にはlocalが適用されます。
起動用シェルの作成
最後に、ローカル開発用の起動用ファイルを作成しましょう。
devtools
プロジェクトにapi
ディレクトリを作成し、その中にbootrun.sh
と言うファイルを作成します。
中身は単純で、ディレクトリ移動して先ほど打っていたコマンドを実行するだけのものです。
1 2 3 4 5 |
#!/bin/bash pushd ../ ./gradlew bootRun -Pargs="--spring.profiles.active=local" popd |
確認
では、実際に起動用シェルからアプリケーションを動かしてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
~/develop/git/github/service-account/devtools ~/develop/git/github/service-account/devtools/api > Task :api:bootRun . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.3.RELEASE) 2019-04-01 19:02:04.487 INFO 48649 --- [ main] t.b.service.account.AccountApplication : Starting AccountApplication on xxx.xxx.xxx.xxx.static.zoot.jp with PID 48649 (/Users/blogenist/develop/git/github/service-account/api/build/classes/java/main started by blogenist in /Users/blogenist/develop/git/github/service-account/api) 2019-04-01 19:02:04.490 INFO 48649 --- [ main] t.b.service.account.AccountApplication : The following profiles are active: common,local 2019-04-01 19:02:05.171 INFO 48649 --- [ main] t.b.service.account.AccountApplication : Started AccountApplication in 1.088 seconds (JVM running for 1.489) BUILD SUCCESSFUL in 2s 3 actionable tasks: 1 executed, 2 up-to-date ~/develop/git/github/service-account/devtools/api |
無事に起動シェル経由でprofileがlocalの状態で動きましたね♪
完成ディレクトリ構造
最終的にはこのようなディレクトリ構造になりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
. ├── README.md ├── api │ ├── build │ ├── build.gradle │ └── src │ ├── main │ │ ├── java │ │ │ └── tech │ │ │ └── blogenist │ │ │ └── service │ │ │ └── account │ │ │ └── AccountApplication.java │ │ └── resources │ │ ├── application-common.yml │ │ ├── application-develop.yml │ │ ├── application-local.yml │ │ ├── application-local.yml.tmp │ │ ├── application-production.yml │ │ ├── application-staging.yml │ │ └── application.yml │ └── test │ └── java │ └── tech │ └── blogenist │ └── service │ └── account │ └── AccountApplicationTests.java └── devtools ├── api │ └── bootrun.sh ├── build │ ├── classes │ │ └── java │ ├── generated │ │ └── sources │ │ └── annotationProcessor │ │ └── java │ ├── resources │ └── tmp │ └── compileJava ├── build.gradle ├── gradle │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── property.gradle └── settings.gradle |
終わりに
これでSpring Boot2 + Gradle
でのマルチプロジェクトの土台が出来ました。
次は実際にAPI
として動くように手を加えていこうと思います♪