주문 처리를 위한 웹 플로우 페이지 작성하기
앞서 작성한 웹 플로우 정의 파일 order-flow.xml의 <view-state> 요소에 설정한 뷰 페이지를
작성해보도록 하겠습니다.
orderCustomer.jsp
WEB-INF/flows/order 폴더에 다음과 같이 작성해 줍니다.
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<link href="<c:url value="/resources/css/bootstrap.min.css"/>" rel="stylesheet">
<title>Customer</title>
</head>
<body>
<nav class="navbar navbar-expand navbar-dark bg-dark">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="./home">Home</a>
</div>
</div>
</nav>
<div class="jumbotron">
<div class="container">
<h1 class="display-3"> 고객정보</h1>
</div>
</div>
<div class="container">
<form:form modelAttribute="order.customer" class="form-horizontal">
<fieldset>
<legend>고객 세부 사항</legend>
<div class="form-group row">
<label class="col-sm-2 control-label" >고객 ID</label>
<div class="col-sm-3">
<form:input path="customerId" class="form-control" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label" >성명</label>
<div class="col-sm-3">
<form:input path="name" class="form-control" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label" >전화번호</label>
<div class="col-sm-3">
<form:input path="phone" class="form-control" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label" >국가명</label>
<div class="col-sm-3">
<form:input path="address.country" class="form-control"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label" >우편번호</label>
<div class="col-sm-3">
<form:input path="address.zipCode" class="form-control" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label" >주소</label>
<div class="col-sm-5">
<form:input path="address.addressName" class="form-control" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label" >세부주소</label>
<div class="col-sm-3">
<form:input path="address.detailName" class="form-control" />
</div>
</div>
<input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}"/>
<div class="form-group row">
<div class="col-sm-offset-2 col-sm-10 " >
<input type="submit" class="btn btn-primary" value="등록" name="_eventId_customerInfo" />
<button class="btn btn-default" name="_eventId_cancel">취소</button>
</div>
</div>
</fieldset>
</form:form>
</div>
</body>
</html>
고객 정보 폼 페이지에서 입력 데이터를 바인딩하기 위해 modelAttribute 속성을 사용해서
커맨드 객체 order.customer로 설정합니다.
고객의 세부 사항으로 고객 ID, 성명, 전화번호, 국가명, 우편번호, 주소, 세부 주소 등을 입력받습니다.
_flowExecutionKey는 웹 플로우에서 플로 순번 키 값입니다.
예를 들어 URL이 /checkout?execution=els1이라면 _flowExecutionKey 값이 els1이 됩니다.
등록 버튼을 누르면 이벤트 ID가 customerInfo로 되면서 orderShippingInfo 뷰 페이지가 출력됩니다.
취소 버튼을 누르면 이벤트 ID가 cancel이 되면서 orderCancelled 뷰 페이지가 출력됩니다.
orderShippingInfo.jsp
WEB-INF/flows/order 폴더에 다음과 같이 작성해 줍니다.
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<link href="<c:url value="/resources/css/bootstrap.min.css"/>" rel="stylesheet">
<title>Shipping</title>
</head>
<body>
<nav class="navbar navbar-expand navbar-dark bg-dark">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="./home">Home</a>
</div>
</div>
</nav>
<div class="jumbotron">
<div class="container">
<h1 class="display-3">배송정보</h1>
</div>
</div>
<div class="container">
<form:form modelAttribute="order.shipping" class="form-horizontal">
<fieldset>
<legend>배송 세부 사항</legend>
<div class="form-group row">
<label class="col-sm-2 control-label">성명</label>
<div class="col-sm-3">
<form:input path="name" class="form-control"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">배송일</label>
<div class="col-sm-3">
<form:input path="date" class="form-control"/> (yyyy/mm/dd)
</div>
<div class="col-sm-6">
<form:errors path="date" cssClass="text-danger"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">국가명</label>
<div class="col-sm-3">
<form:input path="address.country" class="form-control"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">우편번호</label>
<div class="col-sm-3">
<form:input path="address.zipCode" class="form-control"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">주소</label>
<div class="col-sm-5">
<form:input path="address.addressName" class="form-control"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">세부주소</label>
<div class="col-sm-3">
<form:input path="address.detailName" class="form-control"/>
</div>
</div>
<input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey }"/>
<div class="form-group row">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-default" name="_eventId_backToCustomerInfo">이전</button>
<input type="submit" class="btn btn-primary" value="등록" name="_eventId_shippingInfo"/>
<button class="btn btn-default" name="_eventId_cancel">취소</button>
</div>
</div>
</fieldset>
</form:form>
</div>
</body>
</html>
배송 정보 폼 페이지에서 입력 데이터를 바인딩 하기 위해서 modelAttribute 속성을 사용해서
커맨드 객체 order.shipping으로 설정합니다.
배송의 세부 사항으로 성명, 배송일, 국가명, 우편번호, 주소, 세부 주소 등을 입력받습니다.
배송일 입력 시 유효성 검사를 진행하여 오류 발생하면 메시지가 출력됩니다.
_flowExecutionKey는 웹 플로우에서 플로 순번의 키 값을 가집니다.
이전 버튼을 누르면 이벤트 ID가 backToCustomerInfo가 되면서 orderCustomerInfo 뷰 페이지가 출력되며
취소 버튼을 누르면 이벤트 ID가 cancel이 되면서 orderCancelled 뷰 페이지가 출력됩니다.
messages.properties
orderShippingInfo 뷰 페이지에서 배송일 필드의 유효성 검사 시 오류 메시지를 작성해줍니다.
Pattern.NewBook.bookId = \uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uB3C4\uC11CID\uC785\uB2C8\uB2E4(\uC22B\uC790\uB85C \uC870\uD569\uD558\uACE0 ISBN\uC73C\uB85C \uC2DC\uC791\uD558\uC138\uC694).
Size.NewBook.name = \uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uB3C4\uC11C\uBA85\uC785\uB2C8\uB2E4(\uCD5C\uC18C 4\uC790\uC5D0\uC11C \uCD5C\uB300 50\uC790\uAE4C\uC9C0 \uC785\uB825\uD558\uC138\uC694).
Min.NewBook.unitPrice = \uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uAC00\uACA9\uC785\uB2C8\uB2E4(0\uC774\uC0C1\uC758 \uC218\uB97C \uC785\uB825\uD558\uC138\uC694).
Digits.NewBook.unitPrice = \uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uAC00\uACA9\uC785\uB2C8\uB2E4(\uC18C\uC218\uC810 2\uC790\uB9AC\uAE4C\uC9C0, 8\uC790\uB9AC\uAE4C\uC9C0 \uC785\uB825\uD558\uC138\uC694).
NotNull.NewBook.unitPrice = \uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uAC00\uACA9\uC785\uB2C8\uB2E4(\uAC00\uACA9\uC744 \uC785\uB825\uD558\uC138\uC694).
BookId.NewBook.bookId = \uB3C4\uC11CID\uAC00 \uC774\uBBF8 \uC874\uC7AC\uD569\uB2C8\uB2E4.
UnitsInStockValidator.message = \uAC00\uACA9\uC774 10000\uC6D0 \uC774\uC0C1\uC778 \uACBD\uC6B0\uC5D0\uB294 99\uAC1C \uC774\uC0C1\uC744 \uB4F1\uB85D\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
typeMismatch = \uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uB0A0\uC9DC\uC785\uB2C8\uB2E4. (yyyy/mm/dd \uD615\uC2DD\uC73C\uB85C \uC785\uB825\uD558\uC138\uC694.)
orderConfirmation.jsp
WEB-INF/flows/order 폴더에 다음과 같이 작성해 줍니다.
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<link href="<c:url value="/resources/css/bootstrap.min.css"/>" rel="stylesheet">
<title>Order</title>
</head>
<body>
<nav class="navbar navbar-expand navbar-dark bg-dark">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="./home">Home</a>
</div>
</div>
</nav>
<div class="jumbotron">
<div class="container">
<h1 class="display-3">주문정보</h1>
</div>
</div>
<div class="container">
<form:form modelAttribute="order" class="form-horizontal">
<div class="well col-md-9 col-md-offset-2" style="background:#fafafe; padding:20px">
<div class="text-center">
<h1>영수증</h1>
</div>
<div class="row">
<div class="col-md-6">
<address>
<strong>배송 주소</strong><br>
성명 : ${order.shipping.name }<br>
우편번호 : ${order.shipping.address.zipCode }<br>
주소 : ${order.shipping.address.addressName } ${order.shipping.address.detailName } (${order.shipping.address.country })<br>
</address>
</div>
<div class="col-md-6 text-right">
<p><em>배송일 : <fmt:formatDate type="date" value="${order.shipping.date }"/></em></p>
</div>
</div>
<div class="row">
<div class="col-md-9">
<address>
<strong>청구주소</strong>
성명 : ${order.customer.name }<br>
우편번호 : ${order.customer.address.zipCode }<br>
주소 : ${order.customer.address.addressName } ${order.customer.address.detailName } (${order.customer.address.country })<br>
HP : ${order.customer.phone }<br>
</address>
</div>
</div>
<div class="row">
<table class="table table-hover">
<thead>
<tr><th>도서</th>
<th>#</th>
<th class="text-center">가격</th>
<th class="text-center">소계</th>
</tr>
</thead>
<tbody>
<c:forEach var="cartItem" items="${order.cart.cartItems }">
<tr>
<td><em>${cartItem.value.book.name }</em></td>
<td style="text-align:center">${cartItem.value.quantity }</td>
<td class="text-center">${cartItem.value.book.unitPrice }원</td>
<td class="text-center">${cartItem.value.totalPrice }원</td>
</tr>
</c:forEach>
<tr>
<td> </td>
<td> </td>
<td class="text-right"><h5><strong>총액 : </strong></h5></td>
<td class="text-center text-danger"><h4><strong>${order.cart.grandTotal }</strong></h4></td>
</tr>
</tbody>
</table>
<input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey }"/>
<button class="btn btn-default" name="_eventId_backToShippingInfo">이전</button>
<button type="submit" class="btn btn-success" name="_eventId_orderConfirmed">주문완료</button>
<button class="btn btn-default" name="_eventId_cancel">취소</button>
</div>
</div>
</form:form>
</div>
</body>
</html>
저장된 주문 관련 정보 데이터를 바인딩 하기 위해 modelAttribute 속성을 사용해서
커맨드 객체 order로 설정합니다.
배송 정보에 대해 저장된 세부 사항인 성명, 우편번호, 주소, 국가명, 배송일 등을 출력합니다.
고객 정보에 대해 저장된 세부 사항인 성명, 우편번호, 주소, 국가명, 전화번호 등을 출력합니다.
주문한 도서 정보로 도서명, 주문 수, 가격, 소계, 총액 등을 출력합니다.
_flowExecutionKey는 웹 플로우에서 플로 순번의 키 값을 가집니다.
이전 버튼을 누르면 이벤트 ID가 backToShippingInfo로 orderShippingInfo 뷰 페이지가 출력됩니다.
주문완료 버튼을 누르면 이벤트 ID가 orderConfirmed로 confirmOrder() 메소드를 호출하고
취소 버튼을 누르면 이벤트 ID가 cancel로 되면서 orderCancelled 뷰 페이지가 출력됩니다.
orderFinished.jsp
WEB-INF/flows/order 폴더에 다음과 같이 작성해 줍니다.
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<link href="<c:url value="/resources/css/bootstrap.min.css"/>" rel="stylesheet">
<title>Thank you</title>
</head>
<body>
<nav class="navbar navbar-expand navbar-dark bg-dark">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="./home">Home</a>
</div>
</div>
</nav>
<div class="jumbotron">
<div class="container">
<h1 class="display-3">주문완료</h1>
</div>
</div>
<div class="container">
<h2 class="alert alert-danger">주문해 주셔서 감사합니다.</h2>
<p>주문은 <fmt:formatDate type="date" value="${order.shipping.date }"/>에 배송될 예정입니다!</p>
<p>주문번호 : ${order.orderId }</p>
</div>
<div class="container">
<p>
<a href="<c:url value="/books"/>" class="btn btn-primary">« 도서목록</a>
</p>
</div>
</body>
</html>
orderCartWarning.jsp
WEB-INF/flows/order 폴더에 다음과 같이 작성해 줍니다.
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<link href="<c:url value="/resources/css/bootstrap.min.css"/>" rel="stylesheet">
<title>Thanks you</title>
</head>
<body>
<nav class="navbar navbar-expand navbar-dark bg-dark">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="./home">Home</a>
</div>
</div>
</nav>
<div class="jumbotron">
<div class="container">
<h1 class="display-3">주문취소</h1>
</div>
</div>
<div class="container">
<h2 class="alert alert-danger">주문을 취소하였습니다.</h2>
</div>
<div class="container">
<p><a href="<c:url value="/books"/>" class="btn btn-primary">« 도서목록</a></p>
</div>
</body>
</html>
cart.jsp
[주문하기] 버튼을 웹 플로우 액션과 연결해 줍니다.
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<title>Cart</title>
<link href="<c:url value="/resources/css/bootstrap.min.css"/>" rel="stylesheet">
<script src="<c:url value="/resources/js/controllers.js"/>"></script>
</head>
<body>
<nav class="navbar navbar-expand navbar-dark bg-dark">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="../">Home</a>
</div>
</div>
</nav>
<div class="jumbotron">
<div class="container">
<h1 class="display-3">장바구니</h1>
</div>
</div>
<div class="container">
<div>
<form:form name="clearForm" method="delete">
<a href="javascript:clearCart()" class="btn btn-danger pull-left">삭제하기</a>
</form:form>
<a href="<c:url value="/order?cartId=${cartId }"/>" class="btn btn-success float-right">주문하기</a>
</div>
<div style="padding-top:50px">
<table class="table table-hover">
<tr>
<th>도서</th>
<th>가격</th>
<th>수량</th>
<th>소계</th>
<th>비고</th>
</tr>
<form:form name="removeForm" method="put">
<c:forEach items="${cart.cartItems }" var="item">
<tr>
<td>${item.value.book.bookId }-${item.value.book.name }</td>
<td>${item.value.book.unitPrice }</td>
<td>${item.value.quantity }</td>
<td>${item.value.totalPrice }</td>
<td><a href="javascript:removeFromCart('../cart/remove/${item.value.book.bookId }')"
class="badge badge-danger">삭제</a></td>
</tr>
</c:forEach>
</form:form>
<tr>
<th></th>
<th></th>
<th>총액</th>
<th>${cart.grandTotal }</th>
<th></th>
</tr>
</table>
<a href="<c:url value="/books"/>" class="btn btn-secondary">« 쇼핑 계속하기</a>
</div>
<hr>
<footer>
<p>© BookMarket</p>
</footer>
</div>
</body>
</html>
실행 결과
/books를 입력 후 장바구니에 도서를 추가하고 장바구니 화면에서 주문하기 버튼을 눌러보겠습니다.
'SPRING' 카테고리의 다른 글
[SPRING]#70 도서 쇼핑몰 구현 (타일즈 2) (0) | 2024.02.25 |
---|---|
[SPRING]#69 도서 쇼핑몰 구현 (타일즈 1) (0) | 2024.02.25 |
[SPRING]#67 도서 쇼핑몰 구현 (스프링 웹 플로우 6) (0) | 2024.02.23 |
[SPRING]#66 도서 쇼핑몰 구현 (스프링 웹 플로우 5) (0) | 2024.02.23 |
[SPRING]#65 도서 쇼핑몰 구현 (스프링 웹 플로우 4) (0) | 2024.02.23 |