Thymeleafのth:hrefとSpring BootのControllerの@RequestMappingでハマった件

タイトルそのまんまなんですが、むちゃくちゃハマったのでメモメモ。

Thymeleafのth:href、リンクURL

まずは、Thymeleaf側なのですが、th:hrefでgetパラメーターを渡す書き方がいろいろあるのを知らなかったのですが、 

Thymeleaf version 2.1.4の機能メモ - Qiita

⇧  上記サイト様によると、リンクURL式(th:hrefのこと)には大きく分けて、

  • クエリ形式
  • REST形式

の2つが存在し、SpringのController側の@RequestMappingでURLとして受け取る場合は「Rest形式」を使わないといけないようです。

知らずに、ずっとクエリ形式で実装していてgetパラメーターは送れてるのにController側のメソッドの処理が実装されない、なんでや!って1日中やってました(涙)。

上記サイト様のものを引用させてもらいましたが、

クエリ形式

変数の値をクエリのパラメータ値にするには(パラメータ名=${'変数名'})とします。パラメータが複数ある場合はカンマで区切って記述します。

template
<a href="/user/profile" th:href="@{/user/profile(id=${'ab123'})}">profile</a>
<a href="/user/profile" th:href="@{/user/profile(id=${'ab123'},role=${'admin'})}">profile</a>
render
<a href="/user/profile?id=ab123">profile</a>
<a href="/user/profile?id=ab123&amp;role=admin">profile</a>

 REST形式

変数の値をURLの一部として組み立てるにはプレースホルダ{プレースホルダ名}で定義し、そこへ差し込む値を(プレースホルダ名=${'変数名'})とします。

template
<a href="index.html" th:href="@{/user/profile/{id}/{role}(id=${'ab123'},role=${'admin'})}">profile</a>
render
<a href="/user/profile/ab123/admin">profile</a>

とThymeleaf側で記述した場合、Spring BootのController側で@RequestMappingのvalue属性(マッピング対象にするリクエストパスを指定する属性)としてid、roleを含めることができるのは、REST形式の書き方だけということです。

つまり、Thymeleaf側でREST形式で記述したときにだけ、

@RequestMapping(value="/user/profile/{id}/{role}")
public String userRecieve(@PathVariable("id") String id, @PathVariable("role") String role) {
  // 「src/main/resources」>「templates」フォルダに「user.html」があり、thymeleafを使用してる場合
  return "user";
}

といったマッピングが可能のようです。これを知らずに、getパラメーターを渡せばSpringのController側で、getパラメーター付きのURLを勝手に判定してくれるもんだと思い込んで、ずっとクエリ形式で実装してました(泣)

ちなみに、<form>のth:action属性でも同じく、「クエリ形式」「REST形式」の2パターンが使えるみたいですね。

ThymeleafとSpring Bootの連携の仕方で何ができるのかいまいち分からずですね。少しづつ発見していきたいと思います。

 

ちなみに、最近、PHPのテンプレートエンジンにTwigというものがあるのを初めて知りました。Smartyしか知らなんだ~。