プロジェクトの作成 - Spring Initializr

今回は、組み込みデータベースを使用した、デモアプリケーションを作成します。ここでは、Spring Initializr を使用したプロジェクトの作成方法、Spring における基本的な責務の分割方法、およびこれを反映したパッケージの構成を学びます。

Spring Initializr

Spring プロジェクトを作成する場合、現在最も簡単に、目的の依存関係を整える方法が、Spring Initializr を使用したものになります。以下のコマンドを実行することで、プロジェクトのセットアップが完了します。なお以下の例では、groupId や、packageName に、io.github.yo1000 を使用していますが、適宜 yo1000 の部分を、お手持ちの Github アカウントに差替えて指定するようにしてください。

$ curl https://start.spring.io/starter.tgz \
-d dependencies="web,hateoas,thymeleaf,jdbc,hsql,aop" \
-d language="java" \
-d javaVersion="1.8" \
-d packaging="jar" \
-d bootVersion="1.3.0.RELEASE" \
-d type="maven-project" \
-d groupId="io.github.yo1000.sss" \
-d artifactId="self-study-spring" \
-d version="0.0.1-SNAPSHOT" \
-d name="self-study-spring" \
-d description="Self study for Spring Boot" \
-d packageName="io.github.yo1000.sss" \
-d baseDir="self-study-spring" \
-d applicationName="SelfStudySpringApplication" \
| tar -xzvf -

使用可能なすべてのオプションは、以下のコマンドで確認できます。

$ curl start.spring.io

お手持ちの環境で、 curl が使用できない場合、https://start.spring.io/ へアクセスすることでも、同様のプロジェクト作成を行うことができます。

プロジェクトが作成できたら、以下のコマンドを使用して、起動を確認します。なお、Spring Boot では、デフォルトで 8080 ポートが使用されます。もしすでに 8080 ポートが使用されている場合は、./mvnw spring-boot:run の後ろにスペースを空けて、--server.port={任意のポート番号} オプションをつけてください。

$ cd self-study-spring
$ ./mvnw spring-boot:run

起動が確認できたら、Ctrl+C キーでプロセスを終了してください。

Spring Initializr で作成したプロジェクトには mvnw が同梱されており、これを使用すると、環境へ事前に Maven を用意しておくことなく、Maven によるビルドが可能になります。なお、Windows を使用している場合は、mvnw.cmd が使用できます。

mvnw の実行モジュール本体は、同じく同梱されている .mvn/wrapper/maven-wrapper.jar になります。GitHub で作成される .gitignore には、デフォルトで *.jar が含まれているため、プロジェクトを公開する場合などには、.mvn/wrapper/maven-wrapper.jar もバージョン管理されるように、.gitignore を適宜編集するようにしてください。

Spring における責務の分割

Spring では、責務に応じていくつかのアノテーションが用意されています。これらを適切に使用することで、自然と責務の分割が進み、見通しや、テストの書きやすさに優れた、保守性の高いコードとなっていきます。Spring を使用した開発を行うにあたって、この考え方の把握は最も重要なステップのひとつです。次章以降で実際にコードを書き始める前に、必ず押さえておくようにしてください。

下図は、各責務レイヤー間がどのように連携しあうかを、簡単に俯瞰できるようにしたものです。

それぞれにどのような責務があり、どのようなアノテーションが対応しているか、見ていきます。

Configuration

コンフィグレーションレイヤーを担当し、構成管理や設定などを表現します。アノテーションは、@Configuration が対応します。

View

ビューレイヤーを担当し、リクエスト元へのレスポンスを表現します。

Spring では、リクエスト元にレスポンスされるものは、いずれもビューとみなされます。HTML 書式のものだけでなく、JSON、XML、CSV、PDF、他も、等しくビュー表現のひとつとして扱われます。

Controller

コントローラーレイヤーを担当し、エンドポイント、サービス、ビューの紐付けを表現します。アノテーションは、@Controller、および @RestController が対応します。

コントローラーレイヤーでは、リクエスト、およびレスポンスのハンドリングのみを行います。共通的な例外レスポンスや、レスポンス書式の変換処理については、後述する @ContorollerAdvice を併せて利用します。

Service

サービスレイヤーを担当し、業務処理や、業務の流れを表現します。アノテーションは、@Service が対応します。

リクエスト、レスポンスに依存したような処理や、永続化処理は、このレイヤーで表現すべきではありません。これら、他責務の処理記述が混在しはじめると、テストの難易度は著しく向上していきます。

Repository

リポジトリーレイヤーを担当し、永続化を表現します。アノテーションは、@Repository が対応します。

実装に際しては、具象クラスの他に、抽象化されたインターフェースを定義しておくことを強く推奨します。抽象化しておくことで、例えばデータソースが、RDB から、KVS に変更された場合など、他責務レイヤーへの影響が最小化され、変更をリポジトリーレイヤーのみに閉じることができます。

Template

テンプレートレイヤーを担当し、データソースの直接的な操作を表現します。

テンプレートは、各データソースと、その永続化方法に応じた、直接的な永続化操作を表現するため、サポートされうる限り、その組み合わせの分だけ種類があります。(テンプレート = データソースタイプ x 永続化手法)

例えば、RDB をデータソースとした、JDBC による永続化手法を表現するテンプレートには JdbcTemplate が存在し、同じく RDB をデータソースとした MyBatis による永続化手法を表現するテンプレートには SqlSessionTemplate が存在します。一方、MongoDB をデータソースとした場合には MongoTemplate が存在するなど、様々なデータソース、永続化手法に応じてテンプレートが用意されています。

Model

データモデルレイヤーを担当します。アノテーションは、必ずしも必要ではありませんが、永続化手法に応じて、@Entity や、@Document が必要となる場合があります。

アノテーションによるフィールドバリデーション等の表現を除き、原則 POJO であることが望ましいです。

Advice (AOP)

AOP レイヤーを担当します。アノテーションは、@Aspect、および @ControllerAdvice が対応します。

@Aspect は、それ単体では DI コンテナに登録されないため、@Component@Bean と組み合わせて使用します。また、ビューレイヤー、コントローラレイヤー間における処理の多くは、@Aspect で、割り込みを行うことができないため、この箇所への割り込みには @ControllerAdvice を利用します。

AOP は、メソッドの前や後、または前後に共通的な処理を後付けすることができ、同じような処理を何度も記述するのを抑制したり、本来の責務とは直接関係のない処理を、各責務から分離したりするのに非常に役立ちます。

例えば、パフォーマンスログの出力や、トランザクション境界の定義などを AOP に分離することができます。

パッケージ構成

ここまでで紹介した責務の分割を考慮したうえで、パッケージを構成してみます。yo1000 となっている部分については、適宜ご自身の環境に応じて、読み替えてください。

$ PACKAGE_BASEDIR='src/main/java/io/github/yo1000/sss'; \
mkdir -p ${PACKAGE_BASEDIR}/aspect; \
mkdir -p ${PACKAGE_BASEDIR}/config; \
mkdir -p ${PACKAGE_BASEDIR}/controller/api/v1; \
mkdir -p ${PACKAGE_BASEDIR}/controller/page; \
mkdir -p ${PACKAGE_BASEDIR}/model; \
mkdir -p ${PACKAGE_BASEDIR}/repository/jdbc; \
mkdir -p ${PACKAGE_BASEDIR}/service; \
mkdir -p ${PACKAGE_BASEDIR}/util; \
mkdir -p src/main/resources/db/migration; \
touch ${PACKAGE_BASEDIR}/aspect/.gitkeep; \
touch ${PACKAGE_BASEDIR}/config/.gitkeep; \
touch ${PACKAGE_BASEDIR}/controller/api/v1/.gitkeep; \
touch ${PACKAGE_BASEDIR}/controller/page/.gitkeep; \
touch ${PACKAGE_BASEDIR}/model/.gitkeep; \
touch ${PACKAGE_BASEDIR}/repository/jdbc/.gitkeep; \
touch ${PACKAGE_BASEDIR}/service/.gitkeep; \
touch ${PACKAGE_BASEDIR}/util/.gitkeep; \
touch src/main/resources/db/migration/.gitkeep; \
touch src/main/resources/static/.gitkeep; \
touch src/main/resources/templates/.gitkeep; \
mv src/main/resources/application.properties src/main/resources/application.yml
$ pwd; find . | grep -v '/target' | grep -v '/.git' | sort | sed -E '1d; s/^.//; s/\/([^/]*)$/|__ \1/; s/\/[^/|]*/|   /g'
~/self-study-spring
|__ .mvn
|   |__ wrapper
|   |   |__ maven-wrapper.jar
|   |   |__ maven-wrapper.properties
|__ mvnw
|__ mvnw.cmd
|__ pom.xml
|__ src
|   |__ main
|   |   |__ java
|   |   |   |__ io
|   |   |   |   |__ github
|   |   |   |   |   |__ yo1000
|   |   |   |   |   |   |__ sss
|   |   |   |   |   |   |   |__ SelfStudySpringApplication.java
|   |   |   |   |   |   |   |__ aspect
|   |   |   |   |   |   |   |__ config
|   |   |   |   |   |   |   |__ controller
|   |   |   |   |   |   |   |   |__ api
|   |   |   |   |   |   |   |   |   |__ v1
|   |   |   |   |   |   |   |   |__ page
|   |   |   |   |   |   |   |__ model
|   |   |   |   |   |   |   |__ repository
|   |   |   |   |   |   |   |   |__ jdbc
|   |   |   |   |   |   |   |__ service
|   |   |   |   |   |   |   |__ util
|   |   |__ resources
|   |   |   |__ application.yml
|   |   |   |__ static
|   |   |   |__ templates
|   |__ test
|   |   |__ java
|   |   |   |__ io
|   |   |   |   |__ github
|   |   |   |   |   |__ yo1000
|   |   |   |   |   |   |__ sss
|   |   |   |   |   |   |   |__ SelfStudySpringApplicationTests.java

以上で、プロジェクトの作成は完了です。次章からは、責務の分割図の左側 (リクエストに最も近い側) から順に、実際にクラスを作成していきます。

参考

サンプル

ここまでのコードサンプルは、以下より入手できます。

$ git clone -b chapter/1 https://github.com/yo1000/self-study-spring.git

results matching ""

    No results matching ""