티스토리 뷰
TO_DO_LIST :
1. 주문 목록 오류 수정 (OrderController/OrderRESTController 로 나누고 문제 발생)
-> GET 요청만 필요한 페이지라서 HTML + 일반 Controller 로 돌려놨음
2. 주문 목록의 이미지 파일 불러오기
3. 배송조회 페이지로 이동하기
-> HTML + 일반 Controller로 페이지를 요청하고 주문의 paymentId를 포함한 URL로 이동
3. 배송조회 페이지로 이동하기 (delivery.jsp)
orderlist 에서 배송조회 버튼을 클릭하면 paymentId 를 가지고 이동
여기서 고민이
HTML + 일반 Controller 로 페이지를 요청하면서 정보들을 가져오는지 (by paymentId)
JavaScript + ajax + json + RESTController 로 비동기방식으로 데이터를 가져오는지 (by paymentId)
였지만 GET 방식만 사용하면 될 것 같아 첫번째 방식 선택
PUT 및 DELETE와 같은 HTTP 메서드를 사용하는 경우, RESTful API를 사용해야 하므로
JavaScript를 사용하여 AJAX 요청을 이용해야 한다.
orderlist.jsp
: paymentId를 포함한 url 을 사용해서 배송 조회 버튼을 생성하고, EL을 사용하여 주문 객체에서 paymentId를 동적으로 가져온다.
<a href="../Delivery/delivery?paymentId=${order.paymentId}"><button>배송 조회</button></a>
DeliveryController.java
: HTTP 요청 파라미터의 값을 가져오는 어노테이션인 @RequestParam을 이용해서
"paymentId"를 추출하여 메서드의 매개변수인 paymentId에 할당한다.
예) 클라이언트가 "/delivery?paymentId=123"과 같은 URL을 요청을 했을 때,
요청 파라미터 중에서 "paymentId"를 추출하여 Java 메서드의 인수인 paymentId에 할당한다
따라서 위의 예시에서 paymentId에는 123이 할당함.
( 여기서 "paymentId"는 요청 파라미터이며, 해당 값은 123이다. )
@Autowired
DeliveryService deliveryService;
@Autowired
MemberService memberService;
@Autowired
OrderService orderService;
@Autowired
PaymentService paymentService;
// 마이페이지에서 주문목록 > 배송조회 페이지로 이동
@GetMapping("/delivery")
public String deliveryGET(@RequestParam("paymentId") int paymentId, Model model) {
log.info("deliveryGET - paymentId : " + paymentId);
// 배송 예정일 조회
Date date = orderService.getExpectDateByPaymentId(paymentId);
log.info("date : " + date);
model.addAttribute("date", date);
// 송장번호 조회
int getPayment = orderService.getPaymentId(paymentId);
log.info("getPayment : " + getPayment);
model.addAttribute("getPayment", getPayment);
// 주문 조회 by paymentId
List<PaymentVO> paymentList = paymentService.getPaymentByPaymentId(paymentId);
log.info("paymentList : " + paymentList);
model.addAttribute("paymentList", paymentList);
return "/Delivery/delivery"; // delivery.jsp 로 이동
}
PaymentId 로 배송정보 조회하는 메소드 만들기
delivery.jsp
: ${date}, ${getPayment}, 그리고 ${paymentList}는 컨트롤러에서 모델에 추가된 속성들을 참조한다.
EL을 사용하여 이러한 속성들의 값을 가져와서 HTML에 표시한다.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://code.jquery.com/jquery-3.7.1.js"></script>
<title>배송조회</title>
<style type="text/css">
.box {
margin-bottom: 20px;
}
.label {
font-weight: bold;
}
</style>
</head>
<body>
<!-- ${param.paymentId} -->
<h2>배송 조회</h2>
<div>
<p>배송예정일 : ${date}</p>
<p>송장 번호 : ${getPayment}</p>
</div>
<div class="box">
<c:forEach items="${paymentList}" var="payment">
<div class="label">받는 사람:</div>
<div>${payment.receiverName}</div><br>
<div class="label">받는 주소:</div>
<div>${payment.deliveryAddress}</div><br>
<div class="label">배송요청사항:</div>
<div>${payment.requirement}</div>
</c:forEach>
</div>
<script>
$(document).ready(function(){
let expectedDate = new Date("${date}");
let currentDate = new Date();
if (currentDate < expectedDate) {
$("#deliveryStatus").text("배송 예정일 : " + formatDate(expectedDate));
} else {
$("#deliveryStatus").text("배송 완료 되었습니다! 배송 완료일 : " + formatDate(expectedDate) + ")" );
}
});
function formatDate(date){
let formattedDate = new SimpleDateFormat("yyyy-MM-dd").format(date);
return formattedDate;
}
</script>
</body>
</html>
실행화면
배송 상태 업데이트 :
데이터베이스에 스케쥴러를 적용하여 데이터베이스 업데이트
배송 상태 테이블 만들기 :
컬럼 : paymentId(PK) , expectedDeliveryDate(date) , state(int)
paymentId를 Payment 테이블의 paymentId와 외래키로 잡기
테이블 코드 :
CREATE TABLE DELIVERYSTATE (
PAYMENTID NUMBER PRIMARY KEY,
EXPECTEDDATE DATE,
STATE INT,
CONSTRAINT FK_DELIVERYSTATE_PAYMENTID FOREIGN KEY (PAYMENTID) REFERENCES "ORDER" (PAYMENT_ID)
);
테이블에 데이터 집어넣기 :
1) INSERT 문으로 paymentId 넣기,
payment/checkout.jsp 에서 paymentId를 ajax post 요청으로 서버에서 데이터 삽입하기
2) 조인을 사용해서 필요한 정보를 한 번에 가져오기 - > expectDate 만 가능
// Mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.DeliveryMapper">
<insert id="insertDeliveryStateFromOrder" parameterType="int">
INSERT INTO DELIVERYSTATE (PAYMENTID, EXPECTEDDATE, STATE)
SELECT o.PAYMENT_ID, o.EXPECTDELIVERYDATE, 0
FROM "ORDER" o
WHERE o.PAYMENT_ID = #{paymentId}
</insert>
</mapper>
// Mapper 인터페이스
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface DeliveryMapper {
@Insert("INSERT INTO DELIVERYSTATE (PAYMENTID, EXPECTEDDATE, STATE) " +
"SELECT o.PAYMENT_ID, o.EXPECTDELIVERYDATE, 0 " +
"FROM \"ORDER\" o " +
"WHERE o.PAYMENT_ID = #{paymentId}")
void insertDeliveryStateFromOrder(@Param("paymentId") int paymentId);
}
// Service 클래스에서 Mapper 적용
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class DeliveryStateService {
@Autowired
private DeliveryMapper deliveryMapper;
@Transactional
public void updateDeliveryStateFromOrder(int paymentId) {
deliveryMapper.insertDeliveryStateFromOrder(paymentId);
}
}
// Controller에서 서비스 호출
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/api")
public class DeliveryStateController {
@Autowired
private DeliveryStateService deliveryStateService;
@PostMapping("/updateDeliveryState")
public ResponseEntity<String> updateDeliveryState(@RequestBody Map<String, Object> payload) {
int paymentId = (int) payload.get("paymentId");
// DELIVERYSTATE 테이블에 데이터 삽입
deliveryStateService.updateDeliveryStateFromOrder(paymentId);
return ResponseEntity.ok("Delivery state updated successfully");
}
}
DB에서 스케쥴러로 업데이트 :
- PL/SQL 프로시저 작성 :
배송 상태 업데이트
CREATE OR REPLACE PROCEDURE UPDATE_DELIVERY_STATUS AS
BEGIN
UPDATE DELIVERYSTATE
SET STATE = 1
WHERE EXPECTEDDATE < SYSDATE
AND STATE <> 1;
END;
- 스케쥴러 작업 생성 :
DBMS_SCHEDULER을 이용해 주기적으로 이 프로시저를 실행하는 스케쥴러 작업을 만든다
repeat_interval 파라미터를 사용하여 작업이 얼마나 자주 실행될지를 지정할 수 있다.
여기선 10분마다 실행되도록 설정함
BEGIN
DBMS_SCHEDULER.create_job (
job_name => 'UPDATE_DELIVERY_STATUS_JOB',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN UPDATE_DELIVERY_STATUS; END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=MINUTELY; INTERVAL=10', -- 10분마다 실행
enabled => TRUE
);
END;
VIEW(JSP) :
- state 값에 따라 다른 메세지를 표시하는 로직 추가
- 서버 코드와 HTML 수정