1. 概要

エンドユーザーにとって、フォーム送信のプロセスは便利であり、ある程度、データを入力して送信ボタンをクリックするのと同じです。 ただし、エンジニアリングの観点からは、バックエンド処理のためにこのデータをクライアント側からサーバー側に確実に送受信するには、エンコードメカニズムが必要です。

このチュートリアルの範囲では、は、SpringWebアプリケーションでそのデータをapplication/x-www-form-urlencodedコンテンツタイプとして送信するフォームの作成に焦点を当てます。

2. フォームデータエンコーディング

フォーム送信に最も一般的に使用されるHTTPメソッドはPOSTです。 ただし、 idempotent フォームの送信には、HTTPGETメソッドを使用することもできます。 また、メソッドを指定する方法は、フォームのメソッド属性を使用することです。

GETメソッドを使用するフォームの場合、フォームデータ全体がクエリ文字列の一部として送信されます。 ただし、POSTメソッドを使用している場合、そのデータはHTTPリクエストの本文の一部として送信されます。

さらに、後者の場合、フォームのenctype属性を使用してデータのエンコードを指定することもできます。これは、 application /x-www-form-urlencodedと2つの値を取ることができます。 multipart /form-data

2.1. メディアタイプapplication/ x-www-form-urlencoded

HTML フォームのデフォルト値は、enctype属性のapplication / x-www-form-urlencodedです。これは、データが完全にテキストである基本的なユースケースを処理するためです。 それでも、ユースケースにファイルデータのサポートが含まれる場合は、 multipart /form-dataの値でオーバーライドする必要があります。

基本的に、フォームデータをアンパサンド(&)文字で区切られたキーと値のペアとして送信します。 また、それぞれのキーと値は等号(=)で区切られます。 さらに、すべての予約文字と英数字以外の文字は、パーセントエンコードを使用してエンコードされます。

3. ブラウザでのフォーム送信

基本を説明したので、次に、SpringWebアプリでフィードバック送信の簡単なユースケースのためにURLエンコードされたフォームデータを処理する方法を見てみましょう。

3.1. ドメインモデル

フィードバックフォームでは、コメントとともに送信者の電子メールIDを取得する必要があります。 それでは、フィードバッククラスドメインモデルを作成しましょう。

public class Feedback {
    private String emailId;
    private String comment;
}

3.2. フォームを作成

単純なHTMLテンプレートを使用して動的Webフォームを作成するには、プロジェクトでThymeleafを構成する必要があります。 この後、フォームのフィードバックビューを提供するGETエンドポイント/フィードバックを追加する準備が整いました。

@GetMapping(path = "/feedback")
public String getFeedbackForm(Model model) {
    Feedback feedback = new Feedback();
    model.addAttribute("feedback", feedback);
    return "feedback";
}

ユーザー入力をキャプチャするためのモデル属性としてfeedbackを使用していることに注意してください。 次に、feedback.htmlテンプレートフィードバックビューを作成しましょう。

<form action="#" method="post" th:action="@{/web/feedback}" th:object="${feedback}">
    <!-- form fields for feedback's submitter and comment info -->
</form>

もちろん、 enctype 属性を明示的に指定する必要はありません。これは、 application /x-www-form-urlencodedのデフォルト値を選択するためです。

3.3. PRGフロー

ブラウザのフィードバックフォームからのユーザー入力を受け付けているため、 POST / REDIRECT / GET(PRG)送信ワークフローを実装して、重複した送信を回避する必要があります

まず、フィードバックフォームのアクションハンドラーとして機能するPOSTエンドポイント / web /Feedbackを実装しましょう。

@PostMapping(
  path = "/web/feedback",
  consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public String handleBrowserSubmissions(Feedback feedback) throws Exception {
    // Save feedback data
    return "redirect:/feedback/success";
}

次に、GETリクエストを処理するリダイレクトエンドポイント / Feedback /successを実装できます。

@GetMapping("/feedback/success")
public ResponseEntity<String> getSuccess() {
    return new ResponseEntity<String>("Thank you for submitting feedback.", HttpStatus.OK);
}

ブラウザでのフォーム送信ワークフローの機能を検証するには、 localhost:8080 /Feedbackにアクセスしてみましょう。

最後に、フォームデータがURLエンコードされた形式で送信されていることを確認することもできます。

emailId=abc%40example.com&comment=Sample+Feedback

4. ブラウザ以外のリクエスト

ブラウザベースのHTTPクライアントがない場合があります。 代わりに、クライアントはcURLPostmanなどのユーティリティである可能性があります。 このような場合、HTMLWebフォームは必要ありません。 代わりに、POST要求を処理する /Feedbackエンドポイントを実装できます。

@PostMapping(
  path = "/feedback",
  consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public ResponseEntity<String> handleNonBrowserSubmissions(@RequestBody Feedback feedback) throws Exception {
    // Save feedback data
    return new ResponseEntity<String>("Thank you for submitting feedback", HttpStatus.OK);
}

データフローにHTMLフォームがない場合、必ずしもPRGパターンを実装する必要はありません。 ただし、リソースがAPPLICATION_FORM_URLENCODED_VALUEメディアタイプを受け入れるように指定する必要があります。

最後に、cURLリクエストでテストできます。

curl -X POST \
  http://localhost:8080/feedback \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'emailId=abc%40example.com&comment=Sample%20Feedback'

4.1. FormHttpMessageConverter基本

application / x-www-form-urlencoded データを送信するHTTPリクエストは、Content-Typeヘッダーでこれを指定する必要があります。 内部的には、Springは FormHttpMessageConverter クラスを使用してこのデータを読み取り、メソッドパラメーターにバインドします。

メソッドパラメーターのタイプがMultiValueMapの場合、@ RequestParamまたは@RequestBodyアノテーションを使用して、HTTPリクエストの本文に適切にバインドできます。これは、サーブレットAPIがクエリパラメーターを組み合わせるためです。データをパラメータと呼ばれる単一のマップに形成します。これにはリクエスト本文の自動解析が含まれます。

@PostMapping(
  path = "/feedback",
  consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public ResponseEntity<String> handleNonBrowserSubmissions(
  @RequestParam MultiValueMap<String,String> paramMap) throws Exception {
    // Save feedback data
    return new ResponseEntity<String>("Thank you for submitting feedback", HttpStatus.OK);
}

ただし、フィードバックドメインオブジェクトなど、MultiValueMap以外のタイプのメソッドパラメーターの場合は、@RequestBodyアノテーションのみを使用する必要があります。

5. 結論

このチュートリアルでは、Webフォームでのフォームデータのエンコードについて簡単に学びました。 また、Spring Boot Webアプリにフィードバックフォームを実装することにより、ブラウザーおよびブラウザー以外のHTTP要求のURLエンコードされたデータを処理する方法についても説明しました。

いつものように、チュートリアルの完全なソースコードは、GitHubから入手できます。