LoginSignup
16
14

More than 5 years have passed since last update.

Spring MVCのModel#addAttributeにCollectionを指定した時の属性名は・・・

Last updated at Posted at 2016-07-17

Spring MVCでは、View(ThymeleafやJSPなど)とデータを連携する場合は、org.springframework.ui.Modelインタフェースのメソッド(addAttribute)を使います。

Note: リダイレクト時は?

ちなみに・・・リダイレクト時はorg.springframework.web.servlet.mvc.support.RedirectAttributesインタフェースのメソッド(addFlashAttribute)を使います。

その際に、addAttributeaddFlashAttributeCollectionオブジェクトを指定すると、どんな属性名になるか知っていますか?
答えは・・・Collectionに格納されているオブジェクトのクラス名から生成した属性名に「List」を付与した値が、最終的な属性名になります。

Model#addAttributeの使用

コードで見た方が誤解がないので、コードをみてみましょう :sweat_smile:

@RequestMapping(method = RequestMethod.GET)
public String list(@Validated ApiResponseSearchForm form, BindingResult result, Model model) {
    if (result.hasErrors()) {
        return "response/list";
    }
    List<ApiResponse> apiResponses =
        apiResponseService.findAll(form.getPath(), form.getMethod(), form.getDescription());
    model.addAttribute(apiResponses); // ← ここでModelに追加!!
    return "response/list";
}

View(本投稿ではThymeleaf)からは、以下のようにデータを参照します。

<tr th:each="apiResponse : ${apiResponseList}"> <!-- ← ここでModelに追加したオブジェクトを参照!! -->
    <td>
        <div class="checkbox">
            <label>
                <input type="checkbox" name="ids" th:value="${apiResponse.id}"/>
            </label>
        </div>
    </td>
    <td>
        <a class="btn btn-default" th:href="@{/manager/responses/{id}(id=${apiResponse.id})}">
            <span class="glyphicon glyphicon-edit"></span>
            <span th:text="#{action.edit}"></span>
        </a>
    </td>
    <td th:text="${apiResponse.path}"></td>
    <td th:text="${apiResponse.method}"></td>
    <td th:text="${apiResponse.dataKey}"></td>
    <td th:text="${apiResponse.statusCode}"></td>
    <td th:text="${apiResponse.description}"></td>
</tr>

上の例だと、Listに格納されているクラスがApiResponseなので、apiResponseListが属性名になります。なお、デフォルトの属性名が気に入らない :confused: 場合は、明示的に属性名を指定することもできます!!

List<ApiResponse> apiResponses =
    apiResponseService.findAll(form.getPath(), form.getMethod(), form.getDescription());
model.addAttribute("apiResponses", apiResponses); // ← 属性名を明示的に指定

Note: 配列は?

配列もCollectionと同じ動作になります。

ちなみに・・・
クラス名から生成されるベースの属性名は、「org.springframework.core.Conventions#getVariableName(Object)」を使って生成しているので、細い仕様はソースコード読んでください!! :wink:

@ModelAttriuteの使用

また、Modelにオブジェクトを格納する手段として@ModelAttributeを付与したメソッドがサポートされており、こちらも同様の仕様で属性名が生成されます。こちらは、「org.springframework.core.Conventions#getVariableNameForReturnType(Method, Class<?>, Object)」を使って生成しています。

@ModelAttribute
public List<ApiResponse> getApiResponseList() {
    return apiResponseService.findAll(form.getPath(), form.getMethod(), form.getDescription());
}

こちらもデフォルトの属性名が気に入らない :confused: 場合は、明示的に属性名を指定することもできます!!

@ModelAttribute("apiResponses") // ← 属性名を明示的に指定
public List<ApiResponse> getApiResponseList() {
    return apiResponseService.findAll(form.getPath(), form.getMethod(), form.getDescription());
}

要素が空の時の動作 (追記)

Model#addAttributeRedirectAttributes#addFlashAttributeに指定したCollectionの要素が空の場合は、デフォルトの属性名を生成することができないためModelの中にオブジェクトが格納されません。つまり、Viewからアクセスするとnullとして扱われる点を意識しておきましょう。Thymeleafであれば、#lists.isEmptyメソッドを使えばnullセーフな空判定が可能です。

<button type="button" class="btn btn-default" name="delete" data-toggle="modal"
        data-target="#deleteModal" disabled="disabled" 
        th:if="${not #lists.isEmpty(apiResponseList)}"> <!-- ← これ -->
    <span class="glyphicon glyphicon-trash"></span> 削除
</button>

まとめ

Collectionの要素が空の時の動きはちょっと注意が必要ですが・・・デフォルトの属性名を使おう!!

16
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
14