SpringMVCのControllerではHTTPメソッドとしてPUT/DELETEを扱うことが出来ますが、HTML5ではいまだにこれらのHTTPメソッドを扱うことができません。
このギャップを埋めるためにこれまでは、
- ControllerのマッピングではPUT/DELETEメソッドへのマッピングを定義する
@Controller
@RequestMapping("/item")
public class ItemController {
...
@DeleteMapping("{id}")
public String delete(@PathVariable("id") Long id) {
service.delete(id);
return "redirect:/item";
}
}
- thymeleaf側でput/deleteメソッドのフォームを定義するとpostに置き換えて_methodというhiddenパラメータを埋め込む
<form th:action="@{/item/{id}(id=*{id})}" th:method="delete">
<input type="submit" value="delete" />
</form>
<form action="/item/1" method="post">
<input type="hidden" name="_method" value="delete" />
<input type="submit" value="delete" />
</form>
- HiddenHttpMethodFilterというフィルタでこのhiddenパラメータを検知するとリクエストメソッドを差し替える
というアプローチを取っていました。
SpringBoot 2.1 までは、この HiddenHttpMethodFilter がデフォルトの AutoConfiguration で有効化されていたため、特に意識することなく利用できていましたが、SpringBoot 2.2 からデフォルトの挙動が変わり、オフになったようです。
Spring Boot 2.2 Release Notes: HttpHiddenMethodFilter disabled by default
リリースノートによると、
it causes early consumption of a request body if the body may contain parameters.
ということで、early consumption が何を指すのかは理解できなかったのですが、やりたいことに対してフィルタを噛ませるオーバーヘッドのデメリットの方が大きいという感じなのでしょうか。
HTMLでPUT/DELETEがサポートされる気配はないですし、REST APIでもないHTMLなWebサイトから無理にPUT/DELETEメソッド使う必要もないでしょうみたいな話なのかもしれません。
HttpHiddenMethodFilterを使いたい場合は、Configurationで有効にしてあげれば良いとのこと。
spring.mvc.hiddenmethod.filter.enabled: true
これでこれまで通りHTMLからPUT/DELETEメソッドを利用することができます。
ですが、SpringBootのデフォルトでdisabledになったということはあまり使わないほうがいいのでしょうかね。
追記
なぜデフォルトから外されたのか。という点について。
以下のIssueあたりで議論されていました。
https://github.com/spring-projects/spring-boot/issues/16953
https://github.com/spring-projects/spring-boot/issues/18088
ざっくりまとめると
- テンプレートエンジンを使用せずAPIとして利用するなら不要
- MultipartFileがリクエストパラメータに含まれていた場合にフィルタの処理に時間がかかっている
- MaxUploadSizeを超えるエラーが起きた場合にFilterでエラーを投げてしまうためMVCでハンドリングできない
というあたりが理由のようです。
このあたりを踏まえて問題ない場合に有効にするのがよさそう。