Spring Bootの基本的な処理の流れ

Webアプリケーションを作るうえでの基礎知識

ここまででSpring Bootの基本概念を学びましたが、このページでは実際にSpring Boot開発での具体的な処理を実践していきます!
実践の前に、まずはWebアプリケーションを作るうえで最低限必要になる通信の知識から学習しましょう。

Webサービスにおける通信の基本

まず、クライアントとサーバがどうやってやりとりをしているのかについて話します。
Webにおいてサーバとクライアント間のやりとりは、基本的にHTTPというプロトコルを用います。

  • クライアントからサーバへの要求することをリクエストといいます。
  • サーバからブラウザへ応答することをレスポンスといいます。

Webの世界でのやりとりは基本的にリクエスト/レスポンスで成立しています

例えば、Googleなどの検索エンジンで検索をする場合では、
…クライアントはサーバに検索内容に該当するサイトを教えてくださいと要求します(リクエスト)
…サーバは要求に対して、必要な処理をして、その結果を返答します(レスポンス)
この結果、クライアントはレスポンスを元に検索結果を表示します。

※ HTTPにもHTTP/1.1やHTTP/2やHTTP/3が存在したり、キャッシュなど…他にも学んだ方が良いことはたくさんありますが、一度に多くのことを学ぶことは大変です。まだプログラミングが手に馴染んでいなければ、慣れることの方が大切な時期です。今は簡単にざっくりと上記の例のような粒度で、通信がどうやって行われているかのイメージが持てればOKです!
参考サイト:
クライアントサイドとサーバーサイドの意味とは?| クライアントサイドとサーバーサイドの違い
HTTPとは?HTTPSとの違いをサイト移行で実施するリダイレクト設定などをもとに解説

GET、POSTとは ~HTTPメソッド~

クライアントとサーバがやり取りするHTTP通信には、いくつかの仕様が取り決められています。
GET/POSTというのはその仕様で取り決められた、HTTPメソッドの一種です。今回は説明しませんが、他にもHEAD/OPTIONS/PUT/DELETEなどが定義されています。

実装したい機能は表面上はGETでもPOSTでも動くかもしれませんが、セキュリティなどいくつかの観点から、この取り決められた仕様に則って実装することが推奨されます。つまり実装する機能が実現したいことに対して、GETとPOSTでより適している方を選ぶ必要があります。

次はGETとPOSTの違いを大まかに噛み砕いて説明します。
機能を実装したい時に、ある程度適切にGETかPOSTを選べるようになりましょう!

GET送信

GETは指定したリソースの表現を転送するようにリクエストするメソッドです。
つまり、何か情報を検索したり取得するために使うためのメソッドになります。

例えば、ブラウザでURLを入力し検索するとき、あなたは無意識にGETメソッドを使っています。
また仕様で安全かつ冪等(べきとう、同じ操作を何度行っても同じ結果が得られる性質)であると定義されているため、基本的に読み取り専用な機能に対して使うべきメソッドになります。

GETを使うとどのような処理をしていたとしてもクライアントには安全なAPIだと見なされます。
これは、クライアントからはサーバがどのような処理をやっているかを知ることはできないためです。

なお、以下のアクセスパターンはすべてGET送信にあたりますので覚えておきましょう。

  • URL(アドレスバー)に直接アドレスを入力する
  • <a>タグによるアクセス
  • <form>タグでmethod=”GET”に設定している場合の送信

大きな特徴として、GET通信では、パラメータ(送信するデータ)がURLに付与されます
下記の「?」以降が送信したデータです。このようにURLに目に見える形でデータが送られます。(クエリパラメータと言います)

反対に、POST通信では、URL上は見えない形で送信されます。

POST送信

POSTは指定したリソースを実装した機能に従って処理をする機能になります。
主に登録処理や更新処理などの、書き込みがありリソースが更新される可能性のある処理に対して使うメソッドになります。

例えば、以下のような例があります。

  • ブログの記事を投稿する
  • 新しいユーザを登録する
  • 既存のデータに新しい情報を付加する

POST送信にあたるのは以下のパターンです。

  • <form>タグでmethod=”POST”に設定している場合

また、GETとは反対に冪等でないかつ安全でないと定義されています。

※余談
POSTは目に見えないから安全だという話が稀にあがりますが、半分は間違っています。
URL上から見えないだけで通信を盗聴すれば見ることができます。安全性を担保するには通信を暗号化をしなければいけません。(目に見えてしまう以外の理由もありますが、)セキュリティ観点から、機密性の高いデータの送信にGETを使うべきではないというのが正しい解釈になります。

GET、POST通信のまとめ

・以下のように使い分けるといいでしょう。
GET通信→単純なページの表示や、検索結果の表示
POST通信→データの新規編集削除といった変更を含む場合や、保護したい情報を送信する場合

GETPOST
パラメータの格納場所URLメッセージボディ(URLでない)
セキュリティURLなので見られやすいボディなので見えづらい
パラメータの長さ古いソフトウェアでは制限あり(255文字)制限なし

続いて、本題のSpring Bootの処理の話になります!

Spring Bootのクラス分類と主な役割

Spring Bootでのクラス分類と主な役割を簡潔にまとめます。(JPAを使用する前提。JPAについては別の単元で解説)

  • Controller: リクエストを受け取り、戻ってきた結果をレスポンスに変換して返す
  • Service: 部分的な処理を行い結果を返す。Controllerからビジネスロジックを取り出し集中管理する役割。
  • Entity: DBと送受信するデータを受け渡しする入れ物。Modelにあたる
  • Repository:Service 内で生成され、部分的な処理を行い結果を返す。Modelにあたる

仕組み・流れについて

会社やシステム規模により流れは変わりますが、研修中は下記の流れで実装していきます。
「リクエスト → Controller → Service → Repository → Entity→View(レスポンス)」

Service、Repository、Entityに関しては別の単元で説明いたしますので、
とりあえずここでは「リクエスト → Controller →Viewレスポンス)」の流れの説明をいたします。

実践①(@RequestParam Ver.)

「初期表示画面」のフォームに入力した値をControllerで受け取り、次の「確認画面」に渡す処理を学びます。
初期画面の表示、確認画面に表示 の2段階で作成していきます。

初期表示画面

Controller

「com.cmps.spring.controller」パッケージに「ManualController」クラスを作成します。

なお、Controller名には意味の分かる名前を付けましょう!例えば商品の操作を行うコントローラーであれば「ItemController」、ログイン関連であれば「LoginController」、メール送信関連であれば「MailSendController」という風にしましょう。

そしてメソッド名には機能がわかる名前を付けましょう!下記に一般的な例を記載いたします。
・「index」…初期処理、初期表示 ・「insert」「regist」…登録       ・「update」「edit」…更新、編集
・「conf」「check」…確認    ・「delete」…削除  ・「send」…送信  ・「complete」…完了

Controllerファイルに下記のコードを記述します。
【com/cmps/spring/controller/ManualController.java】

package com.cmps.spring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class ManualController {

	/**
	 * 初期画面の表示(フォーム①RequestParam)
	 * 
	 * @param model Model Model情報
	 * @return "manual/index" String viewファイル
	 */
	@GetMapping("/manual/index")
	public String index(Model model) {

		String pageTitle = "Spring Bootの基本的な処理の流れ";

		// Viewに渡すデータを登録
		model.addAttribute("pageTitle", pageTitle);
		model.addAttribute("manualText", "サーバー側から渡した文字列");
		
		// 表示するViewを指定
		return "manual/index";
	}
}

@Controller
@Controllerアノテーションは、このクラスがControllerであることを示します。
Controllerのメソッドでは、原則、戻り値としてViewを返します(Viewに遷移する)。
indexメソッドの最終行で返している文字列“manual/index”がViewファイルと対応しています。
「src/main/resources/templates」フォルダ配下のパスを指定するのが基本のルールで、今回はその中のmanualフォルダのindex.htmlを指しています。
このように指定することで「index.htmlというテンプレートファイルを使用してブラウザに画面出力する」という動作を行います。

@GetMapping("/manual/index")
@GetMappingアノテーションは、
GET送信でURL「/manual/index」にアクセスすると、アノテーション直後のindexメソッドを実行する
といった機能をします。

public String index(Model model) {
indexメソッドの引数で指定している「Model」とは、Controllerで用意したデータ(オブジェクト)を入れて、View(テンプレート)に渡すための「箱」のようなものです。
ModelのaddAttributeメソッドでデータを格納できます。第1引数に文字列を指定し、これがViewファイル上でオブジェクト名として使用できます。第2引数にはオブジェクトのデータを設定します。
model.addAttribute("pageTitle", pageTitle); の例で言えば、View側で扱える変数名が第1引数、その中身が第2引数です。

View

「src/main/resources/templates/manual」フォルダを作成し、フォルダ内に「index.html」ファイルを作成します。

Viewファイルは、「src/main/resources/templates」フォルダ配下に保存します。
「manual」フォルダは作成せずtemplatesフォルダ直下に置くことも可能ですが、templatesフォルダ配下を整理するために作成しています。
ManualController内で呼び出すViewファイルは、同名のmanualフォルダに用意する、という風に今後もフォルダを作成しましょう!

index.htmlに下記のコードを記述します。
【src/main/resources/templates/manual/index.html】

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="ja">
<head>
	<meta charset="UTF-8">
	<title th:text="${pageTitle}"></title>
	<style>
		.formParts {
			width: 300px;
		}
		li {
			list-style-type: none;
			padding-top: 5px;
		}
	</style>
</head>
<body>
	<h1>[[${pageTitle}]]</h1>
	<form method="post" th:action="@{/manual/check}" accept-charset="UTF-8">
		<h2>フォーム①(RequestParam)</h2>
		<ul>
			<li>名前:
				<input class="formParts" type="text" name="userName" th:value="${manualText}">
			</li>
			<li>出身:
				<select class="formParts" name="comeFrom">
					<option value="Japan" selected>日本</option>
					<option value="other">日本以外</option>
				</select>
			</li>
			<li>年齢:
				<input class="formParts" type="text" name="age">
			</li>
			<li>
				<input type="submit" value="送信ボタン">
			</li>
		</ul>
	</form>
</body>
</html>

Java、Springの代表的なテンプレートエンジン(変数などをサーバー側で埋め込んで初めてHTMLとして完成されるテンプレート)として、本マニュアルではThymeleafを使用します。
Thymeleafの詳細は別の単元で扱いますが、使用する上で最低限必要なことは、
 ①プロジェクト構成ファイルに依存関係を追加する(プロジェクト作成時に導入済。pom.xmlに記述されている)
 ②<html>タグにxmlns:th="http://www.thymeleaf.org"を記述する(上記コードに記述済み)

です。
大枠の記述はHTMLと同じで、
そのほかThymeleafの記述ルールに則って記述すると、Controllerから渡した変数を出力したり、繰り返し処理をしたり、オブジェクトのメンバの値を簡単に取り出せたりと、様々なことが出来ます。
別の単元でまた詳しく説明します。

上記のコードにおけるThymeleafの記述を解説します。
<title th:text="${pageTitle}"></title> 左記の属性に付与されている「th:」が、Thymeleafによって処理される記述です。「th:text」に指定した値がそのタグの中身に置き換わります。${~}」は基本型・文字列型の変数を出力する記述で、ここではpageTitleという変数を出力しようとしています。
結果、この行で生成されるHTMLは右記のようになります。 <title>Spring Bootの基本的な処理の流れ</title>
・また、<h1>[[${pageTitle}]]</h1>の記述も、変数を出力する記述です。「[[~]]」の中に変数名を指定するとインラインで出力できます。

以下の2つの「th:」については、th:を除いた部分の属性名に整理されます。
<form method="post" th:action="@{/manual/check}" accept-charset="UTF-8">こちらはaction属性に指定するURLとして整理されます。「@{~}」はURLを処理する記述で、特にPOST通信の際はこの指定の仕方が必須になります。理由としてはCSRF対策も同時にしてくれるからで、Springでは、POST通信はCSRF対策がなされていないとエラーとみなされます。
CSRF トークンとは何ですか? 意味と例 – Wallarm
<input class="formParts" type="text" name="userName" th:value="${manualText}">inputタグのvalue値に設定されています。これにより、manualTextの値がテキストボックスの初期入力値になります。

ここまでで初期表示画面が表示できるようになりました!
Spring Bootアプリケーションを実行し、GetMappingで設定したURLにアクセスしてViewが表示できることを確認しましょう。
URL:http://localhost:8080/manual/index

入力内容の確認画面

続いて入力内容の確認処理を作成します。

Controller

Manualontrollerに下記のコードを追記します。
・import文の追記
・checkメソッドを追記
【com/cmps/spring/controller/ManualController.java】

package com.cmps.spring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;////追記
import org.springframework.web.bind.annotation.RequestParam;////追記

@Controller
public class ManualController {

	/**
	 * 初期画面の表示(フォーム①RequestParam)
	 */
	@GetMapping("/manual/index")
	public String index(Model model) { // ・・略
	}

	////以下を追記
	/**
	 * 入力内容の確認(フォーム①RequestParam)
	 * 
	 * @param model Model 
	 * @param userName String 名前
	 * @param comeFrom String 出身
	 * @param age String 年齢
	 * @return "manual/check" String viewファイル
	 */
	@PostMapping("/manual/check")
	public String check(Model model, @RequestParam String userName,
			@RequestParam String comeFrom, @RequestParam(required=false) Integer age) {

		// Viewに渡すデータを登録
		model.addAttribute("userName", userName);
		model.addAttribute("comeFrom", comeFrom);
		model.addAttribute("age", age);
		// 表示するViewを指定
		return "manual/check";
	}
}

checkメソッドの記述を解説します。
@PostMappingアノテーションでは、引数に指定した「/manual/check」にPOST通信でアクセスすると、checkメソッドが実行されます。
先ほどのindex.htmlのformタグの送信先(action属性)と一致するようになっています。

@RequestParamを付けてメソッドの引数に指定すると、名前の通り、送信されたパラメータを受け取ることができます。変数名をフォーム部品(inputタグなど)のname属性と一致させると、自動で割り当てされます。今回の場合も、index.htmlの各フォーム部品のname属性と一致するuserName、comeFrom、ageを変数としています。
@RequestParamの設定の1つとして、デフォルトでは送信が必須になっています。つまり、送信データ(入力値)が空であることを許容していません。
この設定は変えることができ、@RequestParam(required=false) と指定すると空を許容できます。

・残りの記述は、indexメソッドと同じような流れで、
確認画面で入力内容を表示するために、リクエストから受け取ったパラメータをmodelに登録し、Viewに返しています。

View

「src/main/resources/templates/manual」フォルダに「check.html」ファイルを作成し、下記のコードを記述します。
【src/main/resources/templates/manual/check.html】

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="ja">
<head>
	<meta charset="UTF-8">
	<title>check | Spring Bootの基本的な処理の流れ</title>
	<style>
		.outputArea {
			background-color: #FFFFDD;
		}
	</style>
</head>
<body>
	<h1>Spring Bootの基本的な処理の流れ</h1>
	<h2>フォーム①(RequestParam)</h2>
	<div class="outputArea">
		<p>↓↓ここに送信されたデータを表示</p>
		<p th:text="'名前:' + ${userName}"></p>
		<p th:text="'出身:' + ${comeFrom}"></p>
		<p th:text="'年齢:' + ${age}"></p>
		<p>↑↑ここに送信されたデータを表示</p>
	</div>
</body>
</html>

こちらは単純で、使っている知識はindex.htmlと大きく変わりません。
Controllerから受け取ったオブジェクトを、「th:text」の値に指定して出力しています。
上の例のように、th:textの中に’名前:’のように文字列を含めて、+で変数と連結することもできます。

これで確認処理も完成しましたので、「/manual/index」のページからフォームを送信してみてください!
テキストボックスやセレクトボックスの値を変更して、入力内容が送信されることを確認してみましょう。

実践②(Formクラス Ver.)

@RequestParam以外に、Formクラスを作成してパラメータを受け渡しする方法もあります。こちらのパターンも見ていきましょう!
Controller、Viewファイルの大まかな作りは変わりませんので、まとめて紹介します。

初期表示画面、入力内容の確認画面

Form

「com.cmps.spring」パッケージに「form」パッケージを作成し、パッケージ内に「ManualForm」クラスを作成します。

ManualFormに下記のコードを記述します。
【com/cmps/spring/form/ManualForm.java】

package com.cmps.spring.form;

import java.io.Serializable;
import lombok.Data;

@Data
public class ManualForm implements Serializable {

	// 名前
	private String userName;
	
	// 出身
	private String comeFrom;
	
	// 年齢
	private Integer age;
}

Formクラスは、フォームに入力された入力値を受け渡しするためのクラスです。オブジェクトのメンバ変数をフォームの項目と対応させ、データを格納します。フォーム部品に対応するメンバ変数を宣言しています。「クラスとオブジェクト」の単元で扱ったカプセル化をして、getter/setterで値を管理します。

@Dataアノテーションはlombok(ロンブック)というライブラリから利用しているもので(プロジェクト作成時に導入済み)、クラス内の各フィールド変数に対するアクセサメソッド(Getterメソッド・Setterメソッド)をプログラム側で作成してくれるので、自分で書く必要がなくなります。もちろんこれらのアノテーションを使用しない場合は、アクセサメソッドを自分で記述する必要があります。なお、@DataにはGetter・Setterの他にも機能が含まれていますが、ここでは割愛します。

・Formクラスではよくjava.io.Serializableインタフェースを実装(implements)します。
Serializableを実装することにより、オブジェクト(データ)をシリアライズ(Byte配列に変換)/デシリアライズ可能になります。Byte配列化することにより、ファイルに保存したり、ネットワーク越しに送信したり、または他の形式に変換して保存・復元ができます。今回の場合であれば付けなくても処理に影響しませんが、拡張性のために原則付けるようにしておいた方がいいでしょう。

Controller

Manualontrollerに下記のコードを追記します。
・import文の追記
・index2、check2メソッドを追記
【com/cmps/spring/controller/ManualController.java】

package com.cmps.spring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ModelAttribute;////追記

import com.cmps.spring.form.ManualForm;////追記

@Controller
public class ManualController {

	/**
	 * 初期画面の表示(フォーム①RequestParam)
	 */
	@GetMapping("/manual/index")
	public String index(Model model) { //・・ 略
	}

	/**
	 * 入力内容の確認(フォーム①RequestParam)
	 */
	@PostMapping("/manual/check")
	public String check(Model model, @RequestParam String userName, //・・ 略	
	}

	////以下を追記
	/**
	 * 初期画面の表示(フォーム②Formクラス)
	 * 
	 * @param model Model
	 * @return "manual/index2" String viewファイル
	 */
	@GetMapping("/manual/index2")
	public String index2(Model model) {

		// 表示するViewを指定
		return "manual/index2";
	}

	/**
	 * 入力内容の確認(フォーム②Formクラス)
	 * 
	 * @param model Model
	 * @param form ManualForm form入力データ
	 * @return "manual/check2" String viewファイル
	 */
	@PostMapping("/manual/check2")
	public String check2(Model model, @ModelAttribute("form") ManualForm form) {

		// 表示するViewを指定
		return "manual/check2";
	}
}

今回のindex2メソッドはViewに渡す変数がないため、Viewファイルを指定する記述のみです。
check2メソッドの記述を解説します。
・メソッドの引数には @ModelAttribute("form") ManualForm form と記述されています。check1メソッドの引数と比較していただくと、3つの@RequestParamの代わりにこちらが記述されているのが分かると思います。Formクラスの説明と被りますが、フォーム送信されたデータ(リクエストパラメータ)をFormオブジェクトで受け取っているのです。
・また、index2メソッドと同様にメソッド内の記述はView返却のみです。これは、@ModelAttributeという名前の通り、既にmodelにattribute(属性)として変数formが追加されているからです。なお、Viewで使用できる変数名(Modelに詰める際のキー)は、デフォルトではクラス名の1文字目を小文字にしたものになります。ここでは”form”と明示的に指定しています。
キーの指定の記述例を下記に示します。
@ModelAttribute ManualForm form(デフォルト)  → manualForm
@ModelAttribute("form") ManualForm form     → form
@ModelAttribute(name = "form") ManualForm form  → form
公式:ModelAttribute (Spring Framework API) – Javadoc

View

「src/main/resources/templates/manual」フォルダに「index2.html」「check2.html」ファイルを作成し、それぞれ下記のコードを記述します。
【src/main/resources/templates/manual/index2.html】

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="ja">
<head>
	<meta charset="UTF-8">
	<title>Spring Bootの基本的な処理の流れ</title>
	<style>
		.formParts {
			width: 300px;
		}
		li {
			list-style-type: none;
			padding-top: 5px;
		}
	</style>
</head>
<body>
	<h1>Spring Bootの基本的な処理の流れ</h1>
	<form method="post" th:action="@{/manual/check2}" accept-charset="UTF-8">
		<h2>フォーム②(Formクラス)</h2>
		<ul>
			<li>
				名前:
				<input class="formParts" type="text" name="userName" value="名前">
			</li>
			<li>出身:
				<select class="formParts" name="comeFrom">
					<option value="" selected>選択してください</option>
					<option value="Japan">日本</option>
					<option value="other">日本以外</option>
				</select>
			</li>
			<li>年齢:
				<input class="formParts" type="text" name="age" value="20">
			</li>
			<li>
				<input type="submit" value="送信ボタン">
			</li>
		</ul>
	</form>
</body>
</html>


【src/main/resources/templates/manual/check2.html】

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="ja">
<head>
	<meta charset="UTF-8">
	<title>check2 | Spring Bootの基本的な処理の流れ</title>
	<style>
		.outputArea {
			background-color: #FFFFDD;
		}
	</style>
</head>
<body>
	<h1>Spring Bootの基本的な処理の流れ</h1>
	<h2>フォーム②(Formクラス)</h2>
	<div class="outputArea" th:object="${form}">
		<p>↓↓ここに送信されたデータを表示</p>
		<p th:text="'名前:' + *{userName}"></p>
		<p th:text="'出身:' + *{comeFrom}"></p>
		<p th:text="'年齢:' + *{age}"></p>
		<p>↑↑ここに送信されたデータを表示</p>
	</div>
</body>
</html>

・Viewに関して違いがあるのは、check2.htmlの <div class="outputArea" th:object="${form}"> 以降の記述でしょう。
th:object」は、オブジェクトを指定することが出来ます。${form}はcheck2メソッドのModelから受け取ったオブジェクト・formです。「th:object」のみでは、特に見かけ上やHTML上には何も出力されません。これを指定した子クラス(ここで言うdivタグ配下にあるpタグ)に影響します。
「th:text=~*{userName}」の記述で、オブジェクトのメンバ変数userNameに対してgetterメソッドを実行して値を取り出しています。
「th:object」を指定したブロック内では、「*{~}」でメンバ変数を取り出せるということです。

以上でコードは完成したので、ブラウザ上で挙動を確認してみましょう。
@RequestParamの時と同じように実装できたことを確認してください。
URL:http://localhost:8080/manual/index2

@RequestParamを使用する場合も、@ModelAttributeとFormクラスを使用する場合も、同様に実装できますが、@RequestParamは受け取るパラメータの数が増えるほど、Controllerの記載量も増えてしまいます。
一般的なWeb上の入力フォームを想像していただくと、項目数は3個どころかもっと多いことと思います。すなわち、今後主に使っていくのはFormクラスの形になります!

Spring Bootにおけるパラメータの渡し方として、上記の2パターンは必ず習得しておきましょう!

@RequestMappingの応用

ここまでのコードで@GetMapping、@PostMappingを用いてきましたが、これらは本来@RequestMappingから派生したものです。
RequestMapping (Spring Framework API) – Javadoc

@RequestMappingでは、どのHTTP リクエストメソッドであるかを指定する必要があります。転じて、どのメソッドにも適用出来得るものです。
この考えを応用すると、URLをネストして短縮することができます。

今回のManualControllerに適用すると以下のようになります。

package com.cmps.spring.controller;

import org.springframework.stereotype.Controller; //・・ 以下略

import org.springframework.web.bind.annotation.RequestMapping;//// (1)

@RequestMapping("/manual")//// (1)
@Controller
public class ManualController {

	/**
	 * 初期画面の表示(フォーム①RequestParam)
	 */
	@GetMapping("/index")//// (2)
	public String index(Model model) { //・・ 略
	}

	/**
	 * 入力内容の確認(フォーム①RequestParam)
	 */
	@PostMapping("/check")//// (2)
	public String check(Model model, @RequestParam String userName, //・・ 略	
	}

	/**
	 * 初期画面の表示(フォーム②Formクラス)
	 */
	@GetMapping("/index2")//// (2)
	public String index2(Model model) { //・・ 略	
	}

	/**
	 * 入力内容の確認(フォーム②Formクラス)
	 */
	@PostMapping("/check2")//// (2)
	public String check2(Model model, @ModelAttribute("form") ManualForm form) { //・・ 略	
	}
}

変更点は以下
(1)クラスに対してアノテーション @RequestMapping(“/manual”) を追加
(2)各~Mappingアノテーションを短縮

Controller自体に”/manual”というURLのMappingを付与することで、
Controller内のすべてのメソッドのMappingの接頭辞に”/manual”を付けることを設定できるのです。

上記のように変更しても、ページへのアクセスを始めとした各処理は変わらず実行できることを確認できるでしょう。
記述が短くなり、ミスタイプの削減にも繋がりますので、今後はこの形式でMappingを作成しましょう!

☆Mappingの注意点として・・
Mappingの値(URL)が重複するとエラーになります。
プロジェクト全体を通して一意なURLになるように気を付けましょう。

練習問題

問1: 実践①(RequestParam Ver.)を改変し、「点数」を入力するテキストボックスを作成します。点数に入力された値が80以上の場合、「おめでとうございます!」、それ以外の場合は「残念」とviewに表示してください。
(参考)下記の赤枠部分の 入力欄および出力 を追加するイメージです。


問2: 「様々な入力項目について」の練習問題で作成したフォームを使用し、フォームから送信されたデータを確認用Viewに表示してください。
・【チェックボックス、セレクトボックス(複数)、ファイルアップロード】については省略してください。
・ここでは未入力・未選択の場合は考えなくてよく、全て入力されたときに次のViewが表示できればよいです。

ヒント
問1:
・初期表示のView(HTML)に入力欄を追加する。
・確認処理のメソッドにて、受け取った値が80以上かそうでないかを判定し、結果に応じてString型の変数に文字列を格納する。
・前述の変数をmodelのattributeに追加する。
・確認用のViewを編集し、文字列を表示する記述を追加する。

問2:本単元を参考に、新たにFormクラスや必要なクラス・ファイルを作成しましょう。
・初めに「様々な入力項目」で作成したHTMLファイルをコピーしてSpringプロジェクトに配置し、GetMappingで表示できるようにします。

問2-2: <<発展(任意実施)>>
チェックボックス、セレクトボックス(複数)、ファイルアップロードについて実践する場合(先の単元の内容を含みます)
■Formクラスについて
 ・チェックボックス、セレクトボックス(複数)は、string[]やInteger[]といった配列型でフィールド変数として定義する
 ・ファイルアップロードは、org.springframework.web.multipart.MultipartFile 型で定義する
(↓例)


■Viewについて
 ・チェックボックスなどの配列データの表示については、th:eachという繰り返し属性を用いてすべてのデータを出力する。(詳細は次の「Thymeleaf」の単元にて)
(↓例)

 ・ファイルアップロードについては、MultipartFile クラスに規定のgetOriginalFilename()メソッドを使用して、ファイル名を表示しましょう
(↓例)

タイトルとURLをコピーしました