hyeonga_code

reProject_19_Spring Scheduler 이용해서 만료된 쿠키에 적용하기 본문

Project_WEATHERWEAR

reProject_19_Spring Scheduler 이용해서 만료된 쿠키에 적용하기

hyeonga 2024. 1. 6. 05:59
반응형

 

reProject_18_Spring Schedular 이용해서 만료된 쿠키에 적용하기 구현 준비

reProject_17_쇼핑몰 상품 재고 반영, 장바구니 수량 변경 적용 구현 reProject_16_ 장바구니 기능 구현 수정, 재고 수량 적용 reProject_15_주문 페이지, 주문 상세 페이지 작업 2024-01-02 주문페이지로 이동

hyeonga493.tistory.com


2024.01.05

스케줄러를 사용하여 매일 자정에 현재 시간과 비교하여 이미 지난 쿠키에 대한 장바구니 데이터를 삭제하는 기능을 작업

 

1. src > main > webapp > WEB-INF > spring > applicationContext.xml

namespace에 task 추가

<!-- Scheduler -->
	<context:component-scan base-package="com.w2.util" />
		<task:scheduler id="w2scheduler" pool-size="10"/>
		<task:annotation-driven scheduler="w2scheduler"/>

 

 

2. com.w2.util 패키지에 Scheduler 클래스 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.w2.util;
 
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
 
@Component
public class Scheduler {
    
    /*
         cron 표현식
          초         | 분     | 시     | 일     | 월     | 요일     | 연도
          0-59      0-59     0-23     1-31     1-12     1-12    (생략가능)
     */
    
    // 매일 자정에 자동으로 실행
    @Scheduled(cron = "0 0 0 * * *")
    public void autoUpdate() {
        System.out.println("자동으로 실행합니다.");
    }
}
 

 

-- 구간별로 모두 선택하고 싶은 경우 ' * '를 작성하면 된다. 서버가 실행되어 있는 경우 그 시간이 되면 자동으로 실행된다.

>> 이를 이용해 만료된 쿠키를 가진 테이블 컬럼을 삭제하려고 한다.

 

>>> Service를 autowired 하려했더니 scheduler가 작동하지 않았다. 전부 static으로 변경해야 하나 싶었는데 스케줄러를 따로 service를 작성하는 방법으로 시도

 

1. applicationContext.xml

> namespace에 util 추가후 내용 수정

<!-- Scheduler -->
	<bean id="schedulerService" class="com.w2.util.SchedulingService" />
	<task:scheduler id="w2Scheduler" pool-size="10" />
	<task:executor id="w2Executor" pool-size="10" />
	<task:annotation-driven scheduler="w2Scheduler" executor="w2Executor" />

 

---- ClientCartDAO를 사용하기 위해서는 빈 등록을 해야한다고 오류가 발생 > applicationContext.xml 파일에 추가

>> 다른 방법은 없을까

	<bean id="cartDAO" class="com.w2.client.cart.ClientCartDAO" />

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:c="http://www.springframework.org/schema/c"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:task="http://www.springframework.org/schema/task"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
        http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
 
<!-- 암호화 -->
    <bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>    
    
<!-- SqlSessionTemplate을 사용하여 DAO 클래스 구현 -->
        <!-- setter 메소드가 없으므로 생성자 인젝션을 사용해야 합니다. -->
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg ref="sqlSessionFactory"/>
    </bean>
 
<!-- MyBatis 연동 : 추가한 라이브러리에서 가져오는 SqlSessionFactoryBean     -->    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:mybatis-config.xml" />
    </bean>
 
<!-- Data Source -->
    <!-- 데이터베이스 정보 -->
    <context:property-placeholder location="classpath:config/webserverdb.properties" />
    
    <!--  <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>
 
<!-- Transaction 관리자 설정 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource" />
 
<!-- Scheduler -->
    <bean id="schedulerService" class="com.w2.util.SchedulingService" />
    <bean id="cartDAO" class="com.w2.client.cart.ClientCartDAO" />
    <task:scheduler id="w2Scheduler" pool-size="10" />
    <task:executor id="w2Executor" pool-size="10" />
    <task:annotation-driven scheduler="w2Scheduler" executor="w2Executor" />
    
<!-- 의존성 주입을 위해 빈 등록 대신 -->
    <context:component-scan base-package="com.w2.util" />
    
</beans>
 
 
 

 

2. com.w2.util 패키지에 SchedulingService.java 클래스 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.w2.util;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
 
import com.w2.client.cart.ClientCartDAO;
 
@Service(value="schedulerService")
public class SchedulingService {
 
    @Autowired
    private ClientCartDAO cartDAO;
 
    /*
         cron 표현식
          초         | 분     | 시     | 일     | 월     | 요일     | 연도
          0-59      0-59     0-23     1-31     1-12     1-12    (생략가능)
     */
    @Scheduled(cron="0 0 0 * * *")
    public void scheduleRun() {
        System.out.println("스케줄러 실행");
        checkCookieLimit();
    }
    
    // 만료된 쿠키 확인
    public void checkCookieLimit() {
        System.out.println("2. [ ClientCartService ] checkCookieLimit");
        cartDAO.checkCookieLimit();
    }
}
 

 

 

3. ClientCartDAO.java 수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package com.w2.client.cart;
 
import java.util.List;
 
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Repository;
 
@Repository
public class ClientCartDAO {
 
    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;
    
    // 장바구니에 상품 추가
    public int clientAddCart(List<ClientCartVO> productList) {
        System.out.println("3. [ CartDAO ] clientAddCart");
        String ckId = null;
        String clientId = null;
        
        for(int i=0; i<productList.size(); i++) {
            if(productList.get(0).getClientId() != null) {
                clientId = productList.get(0).getClientId();
            } else if(productList.get(0).getCkId() != null) {
                ckId = productList.get(0).getCkId();
            }
            
            ClientCartVO cartvo = (ClientCartVO)productList.get(i);
            
            if(i>0) {
                if(clientId != null) {
                    productList.get(i).setClientId(clientId);
                } else if (ckId != null) {
                    productList.get(i).setCkId(ckId);
                }    
            }
            
            int check = sqlSessionTemplate.selectOne("CartDAO.clientCheckCart", cartvo);
 
            // 이미 장바구니에 있는 상품인 경우
            if (check == 1) {
                // 같은 쿠키값 가진 상품 만료시간 업데이트
                if(cartvo.getCkId() != null) {
                    System.out.println(">> 다른 상품 만료시간 업데이트");
                    sqlSessionTemplate.update("CartDAO.clientUpdateCookie", cartvo);
                }
                
                System.out.println(">> 상품 수량 변경");
                sqlSessionTemplate.update("CartDAO.clientUpdateCart", cartvo);
            }else {
                System.out.println(">> 상품 추가");
                sqlSessionTemplate.insert("CartDAO.clientAddCart", cartvo);
            }
        }
        return 1;
    }
 
    // 장바구니 목록 불러오기
    public List<ClientCartVO> getClientCartList(ClientCartVO cartvo) {
        System.out.println("3. [ CartDAO ] getClientCartList");
 
        return sqlSessionTemplate.selectList("CartDAO.getClientCartList", cartvo);
    }
 
    // 장바구니 상품 삭제
    public int clientDeleteCart(String caId) {
        System.out.println("3. [ CartDAO ] clientDeleteCart");
 
        return sqlSessionTemplate.delete("CartDAO.clientDeleteCart", caId);
    }
 
    // 장바구니 상품 수량 변경
    public int clientUpdateCart(ClientCartVO cartvo) {
        System.out.println("3. [ CartDAO ] clientUpdateCart");
        
        return sqlSessionTemplate.update("CartDAO.clientUpdateCart", cartvo);
    }
 
    // 만료된 쿠키 확인
    public void checkCookieLimit() {
        System.out.println("3. [ CartDAO ] checkCookieLimit");
        sqlSessionTemplate.delete("CartDAO.checkCookieLimit");
    }
 
}
 

 

 

4. client-cart-mapping.xml 수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
<?xml version="1.0" encoding="UTF-8"?>
 
<!-- MyBatis 다운 파일 PDF 에서 붙여넣은 내용입니다. -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
                 
<mapper namespace="CartDAO">
    <resultMap type="com.w2.client.cart.ClientCartVO" id="clientCart">
        <id property="caId" column="caId" />
        <result property="proId" column="proId" />
        <result property="clientId" column="cId" />
        <result property="opId" column="opId" />
        <result property="caDate" column="caDate" />
        <result property="caCnt" column="caCnt" />
        <result property="ckId" column="ckId" />
        <result property="ckLimit" column="ckLimit" />
        
        <collection property="provo" resultMap="provoResult" />
        <collection property="opvo" resultMap="opvoResult" />
    </resultMap>
    
    <resultMap type="com.w2.product.ProductVO" id="provoResult">
        <result property="proId" column="proId" />
        <result property="proCate" column="proCate" />
        <result property="proName" column="proName" />
        <result property="proContent" column="proContent" />
        <result property="proRegDate" column="proRegDate" />
        <result property="proSell" column="proSell" />
        <result property="proCnt" column="proCnt" />
        <result property="proView" column="proView" />
        <result property="proLike" column="proLike" />
        
        <collection property="imvo" resultMap="imvoResult" />
        <collection property="pricevo" resultMap="pricevoResult" />
    </resultMap>
    
    <resultMap type="com.w2.product.ProductPriceVO" id="pricevoResult">
        <result property="proId" column="proId" />
        <result property="proPrimeCost" column="proPrimeCost" />
        <result property="proCost" column="proCost" />
        <result property="proPrice" column="proPrice" />
        <result property="proTax" column="proTax" />
        <result property="proMargin" column="proMargin" />
        <result property="proAddCost" column="proAddCost" />
    </resultMap>
    
    <resultMap type="com.w2.util.ImageVO" id="imvoResult">
        <result property="imageId" column="imageId" />
        <result property="imageName" column="imageName" />
        <result property="imageDir" column="imageDir" />
        <result property="imageStatus" column="imageStatus" />
        <result property="imageBy" column="imageBy" />
    </resultMap>
    
    <resultMap type="com.w2.product.OptionVO" id="opvoResult">
        <result property="proId" column="proId" />
        <result property="opColor" column="opColor" />
        <result property="opSize" column="opSize" />
        <result property="opId" column="opId" />
        <result property="stCnt" column="stCnt" />
    </resultMap>
    
<!-- 장바구니 목록 조회 -->
    <select id="getClientCartList" parameterType="clientCart" resultMap="clientCart">
        SELECT pro.proId, pro.proName, ca.opId,
                im.imageDir, im.imageName, 
                op.opColor, op.opSize, pri.proPrice, 
                ca.caCnt, ca.caId,
                <if test="clientId != null">
                    cId
                </if>
                <if test="clientId == null">
                    ckId
                </if>
        FROM cart ca
        LEFT JOIN product pro ON ca.proId = pro.proId
        LEFT JOIN product_image im ON ca.proId = im.imageBy AND im.imageStatus='대표'
        LEFT JOIN option_info op ON ca.opId = op.opId
        LEFT JOIN product_price pri ON ca.proId = pri.proId
        <where>
            <if test="clientId != null">
                cId = #{ clientId }
            </if>
            <if test="clientId == null">
                ckId = #{ ckId }
            </if>
        </where>
    </select>
    
<!-- 장바구니 중복 상품 확인 -->
    <select id="clientCheckCart" parameterType="clientCart" resultType="int">
        SELECT COUNT(*) FROM cart
        <where>
            <if test="clientId != null">
                cId = #{ clientId }
            </if>
            <if test="clientId == null">
                ckId = #{ ckId }
            </if>
            AND proId = #{ proId } AND opId = #{ opId }
        </where>
    </select>
 
<!-- 장바구니에 상품 추가 -->
    <insert id="clientAddCart" parameterType="clientCart">
        INSERT INTO cart (proId, opId, caCnt, 
            <if test="clientId != null">
                cId
            </if>
            <if test="clientId == null">
                ckId
            </if>
        ) VALUES ( #{ proId }, #{ opId }, #{ caCnt },
            <if test="clientId != null">
                #{ clientId }
            </if>
            <if test="clientId == null">
                #{ ckId }
            </if>
        )
    </insert>
    
<!-- 장바구니에 상품 수량 수정 -->
    <update id="clientUpdateCart" parameterType="clientCart">
        UPDATE cart SET caCnt=#{ caCnt }
        <where>
            caId = #{ caId }
            <if test="clientId != null">
                AND cId = #{ clientId }
            </if>
            <if test="clientId == null">
                AND ckId = #{ ckId }
            </if>
        </where>
    </update>
    
<!-- 같은 쿠키 값 가진 장바구니 만료시간 수정 -->
    <update id="clientUpdateCookie" parameterType="clientCart">
        UPDATE cart SET ckLimit = (CURRENT_TIMESTAMP + INTERVAL 2 DAY)
        WHERE ckId = #{ ckId }
    </update>
    
<!-- 장바구니 상품 삭제 -->
    <delete id="clientDeleteCart" parameterType="String">
        DELETE FROM cart WHERE caId=#{ caId }
    </delete>    
    
<!-- 만료된 쿠키 정보 삭제 -->
    <delete id="checkCookieLimit">
        DELETE FROM cart 
        WHERE ckLimit <![CDATA[< CURRENT_TIMESTAMP ]]>
    </delete>
</mapper>

 

 

>> 실행(결과를 바로 확인하기 위해 cron을 */30 * * * * * "로 설정하여 매 30초마다 실행되게 작업함)

>>> 최종적으로는 매 자정에 실행할 것이므로 "0 0 0 * * *"로 지정 

>>> 실행이 잘 되는 것을 볼 수 있음

반응형