ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [스프링 인 액션] Chapter 2 - 웹 애플리케이션 개발하기 :: 폼 제출 처리하기
    개발서적읽기/Spring in Action 제 5판 2020. 7. 28. 13:41




    타코 홈페이지의 Submit your taco 버튼에 대한 요청을 처리해보자

    뷰(design.html)의 form 태그를 보면 method 속성이 POST로 설정되어 있는데도 


    form에는 action 속성이 선언되지 않은 것을 알 수 있다.


    이 경우 폼이 제출되면 브라우저가 폼의 모든 데이터를 모아서 


    폼에 나타난 GET 요청과 같은 경로(/design)로 서버에 HTTP POST 요청을 전송한다.


    따라서 이 요청을 처리하는 컨트롤러의 메서드가 있어야 한다.

    @PostMapping
    public String processDesign(Taco design) {
    log.info("Processing design: " + design);
    return "redirect:/orders/current";
    }

    타코 디자인 폼이 제출될 때 이 폼의 필드들은 


    processDesign의 인자로 전달되는 Taco 객체의 속성과 바인딩된다.


    processDesign 메서드에서는 Taco 객체 관련 처리를 아무 것도 하지 않는다.


    폼으로 제출된 Taco 객체를 DB에 저장하는 로직은 3장에서 추가한다.


    showDesignForm 메서드처럼 processDesign 메서드도 String 값을 반환하고 종료한다.


    또한 이 값도 사용자에게 보여주는 뷰를 나타낸다. 그러나 차이점이 있다. 


    processDesign 메서드에서 반환되는 값은 리디렉션 뷰를 나타내는 redirect가 


    제일 앞에 붙는다. 즉, 메소드 실행이 끝난 후 사용자의 브라우저가 


    /orders/current 상대 경로로 재접속되어야 한다는 것을 나타낸다.


    /orders/current 경로의 요청을 처리할 컨트롤러를 생성하자.

    package tacos.web;
    /*
    * @USER JungHyun
    * @DATE 2020-07-04
    * @DESCRIPTION
    */

    import tacos.Order;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;

    @Slf4j
    @Controller
    @RequestMapping("/orders")
    public class OrderController {
    @GetMapping("/current")
    public String orderForm(Model model) {
    model.addAttribute("order", new Order());
    return "orderForm";
    }
    }

    현재의 orderForm 메서드는 orderForm 이라는 이름의 뷰를 반환하는 것만 한다.


    3장에서 모델 데이터를 DB에 저장할 때 주문된 Taco 객체들로 모델을 채우도록 변경한다.


    orderForm 뷰도 만들자


    orderForm.html

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="http://www.thymeleaf.org" lang="en">
    <head>
    <meta charset="EUC-KR">
    <title>Taco Cloud</title>
    <link rel="stylesheet" th:href="@{/styles.css}" />
    </head>

    <body>

    <form method="POST" th:action="@{/orders}" th:object="${order}">
    <h1>Order your taco creations!</h1>

    <img th:src="@{/images/TacoCloud.png}"/>
    <a th:href="@{/design}" id="another">Design another taco</a><br/>

    <div th:if="${#fields.hasErrors()}">
    <span class="validationError">
    Please correct the problems below and resubmit.
    </span>
    </div>

    <h3>Deliver my taco masterpieces to...</h3>

    <label for=" deliveryName">Name: </label>
    <input type="text" th:field="*{deliveryName}"/>
    <span class="validationError"
    th:if="${#fields.hasErrors('deliveryName')}"
    th:errors="*{deliveryName}">Name Error</span>
    <br/>

    <label for="deliveryStreet">Street address: </label>
    <input type="text" th:field="*{deliveryStreet}"/>
    <span class="validationError"
    th:if="${#fields.hasErrors('deliveryStreet')}"
    th:errors="*{deliveryStreet}">Street Error</span>
    <br/>

    <label for="deliveryCity">City: </label>
    <input type="text" th:field="*{deliveryCity}"/>
    <span class="validationError"
    th:if="${#fields.hasErrors('deliveryCity')}"
    th:errors="*{deliveryCity}">City Error</span>
    <br/>

    <label for="deliveryState">State: </label>
    <input type="text" th:field="*{deliveryState}"/>
    <span class="validationError"
    th:if="${#fields.hasErrors('deliveryState')}"
    th:errors="*{deliveryState}">State Error</span>
    <br/>

    <label for="deliveryZip">Zip code: </label>
    <input type="text" th:field="*{deliveryZip}"/>
    <span class="validationError"
    th:if="${#fields.hasErrors('deliveryZip')}"
    th:errors="*{deliveryZip}">Zip Error</span>
    <br/>

    <h3>Here's how I'll pay...</h3>
    <label for="ccNumber">Credit Card #: </label>
    <input type="text" th:field="*{ccNumber}"/>
    <span class="validationError"
    th:if="${#fields.hasErrors('ccNumber')}"
    th:errors="*{ccNumber}">CC Num Error</span>
    <br/>

    <label for="ccExpiration">Expiration: </label>
    <input type="text" th:field="*{ccExpiration}"/>
    <span class="validationError"
    th:if="${#fields.hasErrors('ccExpiration')}"
    th:errors="*{ccExpiration}">CC Num Error</span>
    <br/>

    <label for="ccCVV">CVV: </label>
    <input type="text" th:field="*{ccCVV}"/>
    <span class="validationError"
    th:if="${#fields.hasErrors('ccCVV')}"
    th:errors="*{ccCVV}">CC Num Error</span>
    <br/>

    <input type="submit" value="Submit order"/>
    </form>

    </body>
    </html>

    /orders 경로의 POST 요청을 처리하는 메서드를 OrderController 클래스에 추가해야 한다.

    package tacos.web;
    /*
    * @USER JungHyun
    * @DATE 2020-07-04
    * @DESCRIPTION
    */

    import tacos.Order;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;

    @Slf4j
    @Controller
    @RequestMapping("/orders")
    public class OrderController {
    @GetMapping("/current")
    public String orderForm(Model model) {
    model.addAttribute("order", new Order());
    return "orderForm";
    }

    @PostMapping
    public String processOrder(Order order) {
    log.info("Order submitted: " + order);
    return "redirect:/";
    }
    }

    Order 클래스를 생성하자.


    Order.java

    package tacos;
    /*
    * @USER JungHyun
    * @DATE 2020-07-04
    * @DESCRIPTION
    */
    import lombok.Data;

    @Data
    public class Order {
    private String deliveryName;
    private String deliveryStreet;
    private String deliveryCity;
    private String deliveryState;
    private String deliveryZip;
    private String ccNumber;
    private String ccExpiration;
    private String ccCVV;
    }

    이제는 OrderController와 주문 폼 뷰의 작성이 모두 끝났다.

    http://localhost:8080/design에 접속하여 Submit order 버튼을 눌러보자.


    그러면 주문 처리가 끝나고 타코 홈페이지가 나타난다.


    주문 정보를 보기 위해 로그를 살펴보자.

    2020-07-28 11:38:49.069  INFO 9260 --- [nio-8080-exec-8] tacos.web.OrderController                : Order submitted: Order(deliveryName=123, deliveryStreet=123, deliveryCity=123, deliveryState=123, deliveryZip=123, ccNumber=123, ccExpiration=123, ccCVV=123)

    이 로그 항목을 살펴보면, processOrder 메서드가 실행되어 폼 제출을 처리하는 것은


    잘 되었지만 잘못된 정보의 입력을 허용한다는 것을 알 수 있다.


    필요한 정보에 맞도록 데이터를 검사할 필요가 있다.

    댓글

Designed by Tistory.