前回の記事「①要件定義・DB設計編」の続きです。
今回も雑なメモみたいな感じですので、よろしくお願いします。
開発
アーキテクチャ
アプリ構成
レイヤー分割
- プレゼンテーション層(Controller、Form、Validator)
- アプリケーション層(AppSevice)
- ドメイン層(Model、Service)
- インフラ層(Repository)
バリデーション方針
- バリデーションは、主にController(Bean Validationと Spring Validator)層で行い、再入力を促します。Controllerを抜けてきたデータに対しては、アプリケーション層でのバリデーションでチェックし、例外を投げてエラーページに促します。
- 本来であれば、JavaScriptで細かくバリデーションを行いますが、Springの機能を試したかったので、今回は省略しました。
スマートフォン対応
認証フレームワーク
- 認証機能の構築には、Spring Securityを使用します。
その他方針
URL設計
- URLパラメータを活用して、ハンドラを切り替えていきます。
- 例: 会員登録
- 入力画面表示:
GET
+/signup
+?form
- 確認画面表示:
POST
+/signup
+?confirm
- 入力画面に戻る:
POST
+/signup
+?redo
- 登録:
POST
+/signup
+ なし - 完了画面表示:
GET
+/signup
+?complete
- 入力画面表示:
- 例: 会員登録
考慮事項(機能別)
【会員登録】
パスワードはhiddenで引き継がない
画面間のデータの引き継ぎには、基本的にhiddenを使用しています。一方で、会員登録には確認画面があり、パスワードをクライアント側に渡したくないという考えで、パスワードだけ一時的にセッション変数を使用しています。
【メールアドレス変更】
認証情報の更新
Spring Securityが管理する認証情報(Authentication
)のメールアドレスは、会員機能のいろいろな箇所で参照されます。そのため、メールアドレスの変更後は、認証情報(Authentication
)を再設定しています。
【パスワード変更】
変更時に現在のパスワードを確認
セッションハイジャックされた状態でのパスワード変更を防止するため、新しいパスワードの入力とともに、現在のパスワードの確認をしています。
【スケジュール】
スケジュール(カレンダー + API)
- カレンダーには、FullCalendarを使用しました。
- サーバ側は
RestController
でAPIのエンドポイントを作成しています。 next/prev
ボタンの切り替えで、該当月の空き状況だけ取得するように作りました。
「戻る」ボタンを最下部に
スマートフォンから見た場合に、左中央に設置した「戻る」ボタンを最下部に設置する必要がありました。今回はflex-direction: column
とmax-height
を用いて縦並びを折り返したレイアウトとして作り、order
で順番を切り替えることで対応しています。
【予約(会員)】
認証後のリダイレクト先でのリロード対応
会員による予約のため、予約内容の確認画面表示の前に、一旦認証を挟みます。認証が成功すると元のURLにリダイレクトされるのですが、ここでのデータの引き継ぎには通常のセッション変数を使用しています。RedirectAttributes#addFlashAttribute
を使うと確認画面のリロードに対応できないので、この方法を選びました。
消費税変更時の料金計算
料金計算では、せっかくなので消費税変更の考慮を含めました。ホテルやキャンプ場等を予約する場合には、消費税は予約日ではなく宿泊日に対して課されます。なので、サイトを2日間予約する場合に、初日は10%、2日目は15%ということが起こりえます。「端数処理は税率ごとに一回ずつ」というのがルールとのことなので、そのように実装しました。
【予約一覧】
ページネーション
ページネーションは、SQLにlimit
とoffset
を書いて絞り込む方法をとっています。MyBatisでは他に、RowBounds
を用いた方法がありますが、ResultSet
のデータスキップのコストがかかるので、この方法は採用していません。
【予約詳細・キャンセル】
予約者以外のリソースの閲覧、キャンセルを禁止
予約詳細のURLは/member/reservations/{id}
の形式で、id
の値を変えると他人のリソースが閲覧できてしまう恐れがあります。Spring Securityでは、URLでのアクセス制御の他に、メソッドに対するアクセス制御も用意されていて、ここではアプリケーション層のメソッドに@PostAuthorize
を付与し、メソッドの戻り値を評価してアクセス制御を行っています。
考慮事項(その他)
【メッセージ】
リソースファイルによる管理
例外発生時のメッセージは、messages.properties
に集約させています。
【ログ】
手動でのログ出力管理はしない
ログ出力をあちこち手作業で書くのは手間なので、AOPとListener を活用して、ログ出力の記述を集約しています。
ログにはリクエストIDと会員IDを付与
ログの見通しを良くするため、MCDを利用してログにリクエストIDと会員IDを埋め込むようにしました。
【例外】
業務例外とその他の例外
例外には業務例外としてBusinessException
、システム例外としてSystemException
、その他@ResponseStatus
を付与した例外を定義しました。ハンドリングとしては、業務例外が発生した場合はUCの適切なやり直し場所に誘導し、システム例外やその他の例外の場合は、それぞれのHTTPステータスに合ったエラーページを表示するようになっています。
「③デプロイ編」に続きます