「Getting Started - フォーム送信を処理する」を読む
引き続きSpring Bootについて調べて回っていて、今回はフォームから送信されたデータを処理する方法について書かれた公式ガイドを見てみます。
このドキュメントは、いわゆる"form-backed object"とか"command object"と呼ばれるオブジェクト──FORM要素の子孫要素であるINPUT要素やSELECT要素などの入力フィールドの値を、みずからのインスタンス・フィールドに格納するオブジェクト──と@ModelAttribute
アノテーションを使用して、フォームに入力されたデータを処理する方法を簡潔に示しています。
原典は、"Getting Started - Handling Form Submission"です(2014/11/25現在)。
* * *
フォーム送信を処理する
このガイドではSpringを使ってWebフォームを作成し送信する処理を見ていきます。
何をつくるのか
このガイドのなかで、あなたはWebフォームをつくります。フォームのページには次のURLでアクセスします:
このページをブラウザで表示するとフォームが表示されます。id
とcontent
の入力欄に値を設定してあいさつ文を送信できます。フォームからの送信がなされると、結果ページが表示されます。
何をする必要があるか
どうすればこのガイドは完了できるか
Springの「Getting Startedガイド」系ドキュメントのご多分に漏れず、このガイドも一からコードを書いてステップごとに完了していくことも、すでに理解している基本的な準備のステップを端折って進むこともできます。
一からはじめる方は「Gradleでビルドする」〔訳注:あるいはその後続のセクション〕に進んでください。
基本をスキップする方は次のステップを踏んでください:
- このガイドのソースコード・リポジトリからZipファイルをダウンロードして解凍するか、Gitコマンドでクローンを行います:
git clone https://github.com/spring-guides/gs-handling-form-submission.git
- cdコマンドで
gs-handling-form-submission/initial
に移動します - 「Webコントローラをつくる」のセクションに移動します
作業が終わったら、gs-handling-form-submission/complete
のコードと比較することで結果をチェックすることができます。.
Gradleでビルドする
(・・・興味がないので中略・・・)
Mavenでビルドする
まず基本的なビルド・スクリプトを準備します。Springでアプリケーションを構築するにあたり、あなたは好みのビルド・システムを使用できます。しかしここで示すコードはMavenでビルドする必要があります。もしMavenについてあまり詳しくないのであれば、「MavenでJavaプロジェクトをビルドする」を参照してみてください。
ディレクトリ構造をつくる
プロジェクトのディレクトリとしてあなたの選んだ場所で、次のサブディレクトリ構造をつくります。例えばUnix/Linux環境であればmkdir -p src/main/java/hello
というコマンドを実行します:
└── src └── main └── java └── hello
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.springframework</groupId> <artifactId>gs-handling-form-submission</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.1.9.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies> <properties> <start-class>hello.Application</start-class> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-releases</id> <url>https://repo.spring.io/libs-release</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-releases</id> <url>https://repo.spring.io/libs-release</url> </pluginRepository> </pluginRepositories> </project>
Spring Boot Mavenプラグインは多くの便利な機能を提供しています:
- クラスパス上のすべてのjarファイルを1つのjarにビルドします。この実行可能な「含み込みのjar」〔"über-jar"。英語的に言えば”over jar”。開発者自身が作成したコードのみならず、そのコードが依存するjarの内容を内包したjarで、それ単体で実行が可能。〕はあなたが開発したアプリケーションの実行と移動をより容易にしてくれます。
- 実行可能クラスの目印として
public static void main()
メソッドを検索します。 - 組み込みの依存性解決メカニズムにより、Spring Bootの依存するライブラリのバージョンを設定します。いずれのバージョンもあなた自身で設定することもできますが、デフォルトではSpring Bootが選択したバージョンが利用されます。
Spring Tool Suiteでビルドする
(・・・興味がないので中略・・・)
Webコントローラをつくる
SpringがWebサイトを構築するアプローチにおいて、HTTPリクエストを処理するのはコントローラの役目です。このコンポーネントは@Controller
アノテーションにより簡単に識別されます。下記のGreetingControllerは/greetingというパスへのGETリクエストを処理して、ビュー〔View〕の名前──ここでは「greeting」を返します。ビューはHTMLコンテンツをレンダリングする役目を持つコンポーネントです:
src/main/java/hello/GreetingController.java
package hello; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @Controller public class GreetingController { @RequestMapping(value="/greeting", method=RequestMethod.GET) public String greetingForm(Model model) { model.addAttribute("greeting", new Greeting()); return "greeting"; } @RequestMapping(value="/greeting", method=RequestMethod.POST) public String greetingSubmit(@ModelAttribute Greeting greeting, Model model) { model.addAttribute("greeting", greeting); return "result"; } }
このコントローラは簡潔でシンプルですが、多くのことをしています。1つずつ見て行きましょう。
@RequestMapping
アノテーションは、HTTPリクエストを特定のコントローラのメソッドに結びつけるものです。このコントローラのなかで宣言されている2つのメソッドはいずれも、/greeting
というパスに結び付けられています。デフォルトでは@RequestMapping
はGETやPOSTその他のあらゆるHTTP操作をパスの一致したメソッドに結びつけます。しかし上記のコードでは、 greetingForm()
メソッドは@RequestMapping(method=GET)
という指定によって、とくに GET
に結び付けられています。対して greetingSubmit()
メソッドは @RequestMapping(method=POST)
という指定によって、とくにPOST
に結び付けられています。このマッピング指定により、コントローラは/greeting
というエンドポイントへのリクエストを分別できるようになるのです。
greetingForm()
メソッドは新しいGreeting
インスタンスをビュー・テンプレートに呈示するために、Model
オブジェクトを使用しています。次のコードでは、Greeting
オブジェクトにid
やcontent
といったフィールドが宣言されていますが、これらはgreeting
ビューのなかのフォームの入力欄に対応しています。そしてこのオブジェクトはフォームから情報を取得するのに使用されます。
src/main/java/hello/Greeting.java
package hello; public class Greeting { private long id; private String content; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } }
メソッドの中側のコードの実装はビュー・テクノロジー次第で変わります。今回のケースではサーバ側でHTMLをレンダリングするのにThymeleafが使用されています。Thymeleafは下記のgreeting.html
テンプレートをパースし、フォームをレンダリングするために種々のテンプレート式を評価します。
src/main/resources/templates/greeting.html
<!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Getting Started: Handing Form Submission</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <h1>Form</h1> <form action="#" th:action="@{/greeting}" th:object="${greeting}" method="post"> <p>Id: <input type="text" th:field="*{id}" /></p> <p>Message: <input type="text" th:field="*{content}" /></p> <p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p> </form> </body> </html>
th:action="@{/greeting}"
という記述はフォームがデータを送信する向き先を /greeting
というエンドポイントに設定します。一方、 th:object="${greeting}"
という記述はフォーム・データをまとめて保持しているモデル・オブジェクトを宣言します。2つのフォームの入力欄には、 th:field="*{id}"
とth:field="*{content}"
という記述があり、このそれぞれが上述のGreeting
オブジェクトのフィールドに対応しています。
これでフォームを表示するためのコントローラ、モデル、そしてビューを説明し終えました。さて、それでは送信されたフォームの情報を処理するところを見て行きましょう。先に述べたとおり、フォームはPOST
メソッドを用いて/greeting
エンドポイントにデータを送信します。 greetingSubmit()
メソッドは、フォームに入力された内容をもとに初期化された Greeting
オブジェクトを受け取ります。そして送信されたデータをresult
ビュー(後述)で画面に表示できるよう、 Greeting
オブジェクトをモデルに追加します。id
は<p th:text="'id: ' + ${greeting.id}" />
という記述のなかで使用されています。同様に、content
は<p th:text="'content: ' + ${greeting.content}" />
という記述のなかで使用されています。
src/main/resources/templates/result.html
<!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Getting Started: Handing Form Submission</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <h1>Result</h1> <p th:text="'id: ' + ${greeting.id}" /> <p th:text="'content: ' + ${greeting.content}" /> <a href="/greeting">Submit another message</a> </body> </html>
この例では明瞭さのため、フォームの画面表示と送信されたデータの表示とに2つの異なるビュー・テンプレートを使用しました。しかし2つの目的のために1つのビューを使用することもできます。
実行可能ファイルをつくる
アプリケーションを独立したアプリケーション・サーバにデプロイするために、伝統的なwarファイルとしてパッケージすることはもちろん可能なのですが、より簡単なアプローチは以下で示すようにスタンドアローンのアプリケーションをつくってしまうというものです。あなたはすべてを1つの、実行可能jarファイル──懐かしのmain()
メソッドにより駆動する──のなかにパッケージ化することができるのです。外部の〔独立した〕サーブレット・コンテナにデプロイする代わりにこの方法をとることで、HTTPランタイムとしての組み込みのTomcatサーブレット・コンテナに対するSpringフレームワークの支援機能が利用できます。
src/main/java/hello/Application.java
package hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; @ComponentScan @EnableAutoConfiguration public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
main()
メソッドは、SpringApplication
ヘルパー・クラスのrun()
メソッドの引数として、 Application.class
を渡して処理を委譲します。このコードは、Springに対して「Applivation
からアノテーション・メタデータを読み取り、それをコンポーネントとして、Springアプリケーション・コンテキストのなかで管理しなさい」と述べていることになります。
@ComponentScan
アノテーションはSpringに対して「hello
パッケージとそのサブパッケージのなかを検索し、直接もしくは間接にSpringの@Component
アノテーションにより印付けされているクラスを見つけ出せ」という指示になります。このディレクティブはSpringが GreetingController
を見つけて〔Springのアプリケーション・コンテキストに〕登録するよう仕向けます。なぜならこのクラスには@Controller
アノテーションが付与されており、このアノテーションには @Component
アノテーションが付与されているからです。
@EnableAutoConfiguration
アノテーションは、クラスパス上に存在するクラス情報に基づき、適切なデフォルトの動作を行うようスイッチを入れます。例えば、アプリケーションが組み込みバージョンのTomcat(tomcat-embed-core.jar)に依存しているので、Tomcatサーバはあなた自身が設定の手間を労せずとも、適切なデフォルトの設定と構成で起動されます。あるいはまた、アプリケーションがSpring MVC(spring-webmvc.jar)に依存しているので、Spring MVCのDispatcherServlet があなたのために設定され登録されます──もはや web.xml
は不要なのです! 自動コンフィギュレーションはパワフルで柔軟性に富むメカニズムです。より詳しい情報についてはJavadocを参照してください。
実行可能jarファイルをつくる
Gradleを使っている場合(・・・興味が無いので中略・・・)。
Mavenを使っている場合、 mvn spring-boot:run
コマンドでアプリケーションを実行することができます。あるいはまた mvn clean package
コマンドでjarファイルをつくり、続いて次のようにタイプしてjarを実行します:
java -jar target/gs-handling-form-submission-0.1.0.jar
[NOTE] 上記の手順では実行可能jarファイルが作成されます。Springはwarファイルをビルドする方法も提供しています。
ログ出力が画面に現れ、コンポーネントが組み立てられて数秒のうちにアプリケーションが起動します。
サービスをテストする
さあ、もうWebサイトは動いています。http://localhost:8080/greeting
にアクセスしてみましょう。次のような入力フォームが表示されるはずです:
IDとメッセージを送信すると結果が表示されます:
まとめ
おめでとうございます! Springを使ってフォームを作成し送信するプログラムができあがりました。
* * *
原典は、"Getting Started - Handling Form Submission"です(2014/11/25現在)。