動的に生成した異なるURLに対する複数submitの実装
IDなどのパラメータを含めて動的に生成したURLにGETリクエストを送る、のPOST版をどうやって実装したらよいのかについてまとめました。
前提
最近Springの練習用にちょっとしたシステムを作成しています。
その際、よく考えず軽い気持ちで以下のような画面を設計したのですが、これをどう実装したらよいのか悩んでました。
これはデータベースから取得した雑誌の情報を一覧化し、各行にある削除ボタンを押すとその行のデータを削除する機能を持った画面です。
通常、1つのフォームに更新ボタンや削除ボタンのある画面のように複数のsubmitボタンに対応する場合、params属性にbuttonタグのname属性の値を指定した@PostMappingを付加したControllerのメソッドを複数用意することで処理を分けることができます。
しかし、動的に生成したURLの場合、生成したURLの個数分メソッドを作成しなければならず、この方法では対応できません。
そこでGETリクエストの時のようにパラメータを含めたフォーム送信先URLを複数用意し、押下したボタンに対応するURLを送信する方法を思い付き、実装できるかやってみました。
環境
- Java: 11
- Spring Boot: 2.3.3
- Thymeleaf: 3.0.11
実装方法
まず、Thymeleaf側について。
HTML5ではbuttonタグにformactionという属性が用意されています。これはフォームの送信先を指定する属性です。
Thymeleafにも同様にth:formaction属性が用意されています。
他の属性についてはこちらの記事を参照してください。
[ブログ:Thymeleafで用意されている属性の一覧の一次資料]
この属性を使いURLを各ボタンに指定することで、それぞれ異なる送信先URLにリクエストを送れるようになります。
Controller側は@GetMappingの代わりに@PostMappingを指定するだけです。value属性にはGETの時と同様にURLを記載します。
また、メソッドの引数に@PathVariableを付加することでパラメータを取得できます。
実装例
Thymeleaf側で各ボタンに送信先のURLとして/list/delete/{雑誌のID}を指定し、Controller側で雑誌のIDを受け取れるようにしています。
まだ開発中なので、この例ではSTSのコンソールに取得したIDを表示するだけです。
<form method="post">
<table>
<!-- 省略 -->
<tr th:each="magazine : ${magazineListForm.magazineList}">
<!-- 省略 -->
<td role="presentation" sec:authorize="hasRole('ADMIN')">
<button type="submit" th:formaction="@{'/list/delete/' + ${magazine.id}}">削除</button>
</td>
</tr>
</table>
</form>
@PostMapping("/list/delete/{id}")
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
public String postListDelete(Model model, @PathVariable("id") String magazineId) {
System.out.println("magazineId:" + magazineId);
return "redirect:/list";
}