[Spring MVC] [1] 7. Spring MVC-Webページ作成2


[6]商品詳細


製品詳細コントローラとビューの開発

✔️ BasicItemController


itemsでコードを追加
@GetMapping("/{itemId}"`
    public String item(@PathVariable Long itemId, Model model) {
        Item item = itemRepository.findById(itemId);
        model.addAttribute("item", item);
        return "basic/item";
    }
PathVariableに変換された商品IDを使用して、商品をモデルに検索し、ビューテンプレートを呼び出します.

✔️ item


(同様に、コピーされたコードを変更)
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <link th:href="@{/css/bootstrap.min.css}"
          href="../css/bootstrap.min.css" rel="stylesheet">
    <style>
        .container {
            max-width: 560px;
        }
    </style>
</head>
<body>

<div class="container">
    <div class="py-5 text-center">
        <h2>상품 상세</h2>
    </div>

    <div>
        <label for="itemId">상품 ID</label>
    <input type="text" id="itemId" name="itemId" class="form-control"
           value="1" th:value="${item.id}" readonly>
    </div>
    <div>
        <label for="itemName">상품명</label>
        <input type="text" id="itemName" name="itemName" class="form-control"
               value="상품A" th:value="${item.itemName}" readonly>
    </div>
    <div>
        <label for="price">가격</label>
        <input type="text" id="price" name="price" class="form-control"
               value="10000" th:value="${item.price}" readonly>
    </div>
    <div>
        <label for="quantity">수량</label>
        <input type="text" id="quantity" name="quantity" class="form-control"
               value="10" th:value="${item.quantity}" readonly>
    </div>

    <hr class="my-4">

    <div class="row">
        <div class="col">
            <button class="w-100 btn btn-primary btn-lg"
                    onclick="location.href='editForm.html'"
                    th:onclick="|location.href='@{/basic/items/{itemId}/ edit(itemId=${item.id})}'|"
                    type="button">상품 수정</button>
        </div>
        <div class="col">
            <button class="w-100 btn btn-secondary btn-lg"
                    onclick="location.href='items.html'"
                    th:onclick="|location.href='@{/basic/items}'|"
                    type="button">목록으로</button>
        </div>
    </div>

</div> <!-- /container -->

</body>
</html>
ああ、私は先生のコードの200%を信じていません.私はずっと考えています.どうしてそうしないのですか.直接修正して、、、、、

[7]商品登録表


✔️ BasicItemController


コードの追加
    @GetMapping("/add")	// 데이터를 저장하는 것이 아니라 보여만 줌
    public String addForm() {
        return  "basic/addForm";
    }

✔️ addForm


ポストクリスタルを貼り付ける
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <link th:href="@{/css/bootstrap.min.css}"
          href="../css/bootstrap.min.css" rel="stylesheet">
    <style>
        .container {
            max-width: 560px;
        }
    </style>
</head>
<body>

<div class="container">

    <div class="py-5 text-center">
        <h2>상품 등록 폼</h2>
    </div>

    <h4 class="mb-3">상품 입력</h4>

    <form action="item.html" th:action method="post">
        <div>
            <label for="itemName">상품명</label>
            <input type="text" id="itemName" name="itemName" class="form-control" placeholder="이름을 입력하세요">
        </div>
        <div>
            <label for="price">가격</label>
            <input type="text" id="price" name="price" class="form-control" placeholder="가격을 입력하세요">
        </div>
        <div>
            <label for="quantity">수량</label>
            <input type="text" id="quantity" name="quantity" class="form-control" placeholder="수량을 입력하세요">
        </div>

        <hr class="my-4">

        <div class="row">
            <div class="col">
                <button class="w-100 btn btn-primary btn-lg" type="submit">상품 등록</button>
            </div>
            <div class="col">
                <button class="w-100 btn btn-secondary btn-lg"
                        onclick="location.href='items.html'"
                        th:onclick="|location.href='@{/basic/items}'|"
                        type="button">취소</button>
            </div>
        </div>

    </form>

</div> <!-- /container -->
</body>
</html>
formを開くとGet、保存するとPost登録フォームと登録処理を1つのURLで実行

[8]商品登録処理-@ModelAttribute


商品登録表に伝達されたデータを用いて実際の商品を登録処理する.
商品レジストリはPOST-HTMLフォームでサーバにデータを渡します.
  • content-type: application/x-www-form-urlencoded
  • は、クエリパラメータ形式でメッセージ本体
  • に送信する.
    要求パラメータタイプを処理する必要があるため、@RequestParamを使用します.

    ✔勘定科目BasicItemControllerにコードを追加

        @PostMapping("/add")
        public String addItemV1(@RequestParam String itemName,
                           @RequestParam int price,
                           @RequestParam Integer quantity,
                           Model model) {
    
            Item item = new Item();
            item.setItemName(itemName);
            item.setPrice(price);
            item.setQuantity(quantity);
    
            itemRepository.save(item);
    
            model.addAttribute("item", item);   // model에 데이터를 담음
    
            return  "basic/item";
        }
    @RequestParam String itemName:itemName要求パラメータデータがこの変数を受信しました
    Itemオブジェクトの作成→Item Repositoryで保存→Itemをモデルに入れてビューに渡す
    ここでは製品詳細のitemに使用します.htmlビューテンプレートの再使用

    v 2コードの追加

        @PostMapping("/add")
        public String addItemV2(@ModelAttribute("item") Item item, Model model) {
            itemRepository.save(item);
            // model.addAttribute("item", item) // 자동 추가, 생략 가능
            return "basic/item";
        }
    @RequestParamを使用して1つの変数を一度に処理してItemを生成するプロセスは不便です.@ModelAttribute-要求パラメータ処理
    :プロジェクトを作成し、Propertyメソッドとして要求パラメータの値を入力します.@ModelAttribute-モデルの追加
    :@ModelAttributeは、@ModelAttributeとして指定されたオブジェクトを自動的にモデルに入れる重要な機能を有する.
    (コメントしたコードがなくても、正常に動作します)
    モデルにデータを含めるには、@ModelAttributeで指定したname(value)プロパティを使用し、異なる名前を指定した場合は別の名前を使用してモデルに含める名前が必要です.

    Ex.



    v 3コードの追加

        @PostMapping("/add")
        public String addItemV3(@ModelAttribute Item item) {
            itemRepository.save(item);
            return "basic/item";
        }
    @ModelAttributeの名前は省略できます!
    このように名前を省略すると、モデルに格納するときにクラス名が使用されます.クラスの最初の文字のみを小文字に置換

    v 4コードの追加

        @PostMapping("/add")
        public String addItemV4(Item item) {
            itemRepository.save(item);
            return "basic/item";
        }
    @ModelAttribute自体も省略可能!
    ターゲットオブジェクトはモデルに自動的に登録され、残りのオブジェクトは既存のオブジェクトと同じになります.

    」注意事項


    注記@PostMapping(重複マッピングによるエラーを回避)

    [9]商品の修正


    ✔勘定科目BasicItemControllerにコードを追加


    :変更が必要な情報をクエリーし、変更用のフォームビューを呼び出します.
        @GetMapping("/{itemId}/edit")
        public String editForm(@PathVariable Long itemId, Model model) {
            Item item = itemRepository.findById(itemId);
            model.addAttribute("item", item);
            return "basic/editForm";
        }
    
        @PostMapping("/{itemId}/edit")
        public String edit(@PathVariable Long itemId, @ModelAttribute Item item) {
            itemRepository.update(itemId, item);
            return "redirect:/basic/items/{itemId}";
        }
    GETかPOSTかにより、@ModelAttribute@ModelAttributeが処理される.

    📌 リダイレクト


    呼び出しは、ビューテンプレートを呼び出すのではなく、商品詳細にリダイレクトされます.
    スプリングはGET-상품 수정 폼で、直接接続をサポートしています

    ✔️ basic/editForm.html


    editFormレプリケーションの貼り付けによるコードの変更
    <!DOCTYPE HTML>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="utf-8">
        <link href="../css/bootstrap.min.css"
              th:href="@{/css/bootstrap.min.css}"
              rel="stylesheet">
        <style>
            .container {
                max-width: 560px;
            }
        </style>
    </head>
    <body>
    
    <div class="container">
    
        <div class="py-5 text-center">
            <h2>상품 수정 폼</h2>
        </div>
    
        <form action="item.html" th:action method="post">
            <div>
                <label for="id">상품 ID</label>
                <input type="text" id="id" name="id" class="form-control" value="1" th:value="${item.id}" readonly>
            </div>
            <div>
                <label for="itemName">상품명</label>
                <input type="text" id="itemName" name="itemName" class="form-control" value="상품A" th:value="${item.itemName}">
            </div>
            <div>
                <label for="price">가격</label>
                <input type="text" id="price" name="price" class="form-control" th:value="${item.price}">
            </div>
            <div>
                <label for="quantity">수량</label>
                <input type="text" id="quantity" name="quantity" class="form-control" th:value="${item.quantity}">
            </div>
    
            <hr class="my-4">
    
            <div class="row">
                <div class="col">
                    <button class="w-100 btn btn-primary btn-lg" type="submit">저장</button>
                </div>
                <div class="col">
                    <button class="w-100 btn btn-secondary btn-lg"
                            onclick="location.href='item.html'"
                            th:onclick="|location.href='@{/basic/items/{itemId}(itemId=${item.id})}'|"
                            type="button">취소</button>
                </div>
            </div>
    
        </form>
    
    </div> <!-- /container -->
    </body>
    </html>
    📌
    HTMLフォーム転送はPUT、PATCH機能Xをサポートする
    GET、POST
    PUT、PATCHはHTTP API伝送に用いられ、非表示フィールドを介してこれら2つのマッピングを使用することができるが、HTTP要求は表面的にはどうせPOST要求である.

    [10] PRG Post/Redirect/Get


    addItemV 1~4までに商品を登録・更新すると、新規品として登録し続けるという問題が発生します.

    プロセス全体



    POST後リフレッシュ



    POST, Redirect GET


    のように、商品が格納された後、ビューテンプレートではなく商品詳細画面でredirectを呼び出す.
    最後に呼び出されたのはPOSTではなくGETなので、リフレッシュに問題はありません.

    ✔勘定科目BasicItemControllerコード追加

        @PostMapping("/add")
        public String addItemV5(Item item) {
            itemRepository.save(item);
            return "redirect:/basic/items/" + item.getId();
        }
    📌 に注意POST-상품 수정 처리リダイレクトで+item.getId()のようにURLに変数(ハングルで入力すると)を追加するのは危険です.URLを符号化できないからです.
    *RedirectAttributesを使用します.

    [11] RedirectAttributes


    直通電話のようなものはユーザーには向いていません.(お客様は正常に保存されたかどうか分かりません)
    今保存しておけばよかった!高ユーザーに伝える.

    ✔勘定科目BasicItemControllerコード追加

        @PostMapping("/add")
        public String addItemV6(Item item, RedirectAttributes redirectAttributes) {
            Item savedItem = itemRepository.save(item);
            redirectAttributes.addAttribute("itemId", savedItem.getId());
            redirectAttributes.addAttribute("status", true);
            return "redirect:/basic/items/{itemId}";
        }
    さらにredirect:/... を加えると、この値があればredirect:/basic/items/" + item.getId()を吐き出すことができます.

    RedirectAttributes


    :URLエンコーディング、PathVariable、クエリパラメータを処理します.

    ✔️ basic/item.html

    <!DOCTYPE HTML>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="utf-8">
        <link th:href="@{/css/bootstrap.min.css}"
              href="../css/bootstrap.min.css" rel="stylesheet">
        <style>
            .container {
                max-width: 560px;
            }
        </style>
    </head>
    <body>
    
    <div class="container">
        <div class="py-5 text-center">
            <h2>상품 상세</h2>
        </div>
    
        <!-- 추가 -->
        <h2 th:if="${param.status}" th:text="저장 완료"></h2>
    
        <div>
            <label for="itemId">상품 ID</label>
        <input type="text" id="itemId" name="itemId" class="form-control"
               value="1" th:value="${item.id}" readonly>
        </div>
        <div>
            <label for="itemName">상품명</label>
            <input type="text" id="itemName" name="itemName" class="form-control"
                   value="상품A" th:value="${item.itemName}" readonly>
        </div>
        <div>
            <label for="price">가격</label>
            <input type="text" id="price" name="price" class="form-control"
                   value="10000" th:value="${item.price}" readonly>
        </div>
        <div>
            <label for="quantity">수량</label>
            <input type="text" id="quantity" name="quantity" class="form-control"
                   value="10" th:value="${item.quantity}" readonly>
        </div>
    
        <hr class="my-4">
    
        <div class="row">
            <div class="col">
                <button class="w-100 btn btn-primary btn-lg"
                        onclick="location.href='editForm.html'"
                        th:onclick="|location.href='@{/basic/items/{itemId}/ edit(itemId=${item.id})}'|"
                        type="button">상품 수정</button>
            </div>
            <div class="col">
                <button class="w-100 btn btn-secondary btn-lg"
                        onclick="location.href='items.html'"
                        th:onclick="|location.href='@{/basic/items}'|"
                        type="button">목록으로</button>
            </div>
        </div>
    
    </div> <!-- /container -->
    
    </body>
    </html>
  • th:if:条件が真の場合、
  • を実行
  • ${param.status}:時間軸でパラメータを簡単にクエリーできます.
    (
  • は、モデルの値をコントローラから直接取り出すはずでしたが、クエリーパラメータがよく使われているため、時間軸から直接サポートされています)