2020년 02월 18일
업데이트:
Spring Scheduling
스프링에서 제공하는 스케줄러로써
지정된 시간 또는 특정 간격 마다 작업(job)을 진행하도록 하는 기능.
게시글 등록 시
주기적으로 DB와 서버의 파일을 비교해 데이터 불일치 현상을 없앤다.
- 사용조건
- dispatcher servlet (servlet-context.xml)파일에 task namespace를 추가 +
<task:annotation-driven/>
추가 - 작업이 작성된 클래스를 Bean으로 등록
(Bean 등록 == 스프링 컨테이너가 제어 가능(IOC)
bean 등록 어노테이션 : @Controller, @Service , @Repository, @Component - 지정된 작업이 기록된 메소드를 작성 + 지정된 시간마다 동작하기 위해 @Scheduled 어노테이션 작성
@Scheduled 어노테이션 속성
- fixedDelay : 이전 작업이 끝난 시점으로 부터 고정된 시간(ms)만큼 지난 후 수행
- fixedRate : 이전 작업이 시작된 시점으로 부터 고정된 시간(ms)만큼 지난 후 수행
일정 간격마다 하려면 fixedRate가 더 정확하다 , fixedDelay는 뒤로갈수록 밀릴 수 있음. - cron : UNIX 계열 잡 스케쥴러 표현식
cron=”초 분 시 일 월 요일 [년도]”
(요일: 일요일==1, 토요일==7)
특수문자
*
: 모든 수
-
: 두 수 사이의 값, ex) 10-15 : 10이상 15이하
, : 특정 값 지정. ex) 3,4,7 : 3,4,7 지정
/ : 값의 증가. ex) 0/5 : 0부터 시작해서 5씩 증가할 때 마다.
? : 특별한 값이 없음 (월, 요일만 해당)
EX)
2021년 2월 18일 목요일 10시 20분 30초 -> cron=”30 20 10 18 2 5 2021”
매년 2월 18일 10시 20분 30초 -> cron=”30 20 10 18 2 * [*]”
매일 10시 20분 30초 -> cron=”30 20 10 * * *“
매일 자정(0)시 -> cron=”0 0 0 * * *“
- fixedDelay : 이전 작업이 끝난 시점으로 부터 고정된 시간(ms)만큼 지난 후 수행
- dispatcher servlet (servlet-context.xml)파일에 task namespace를 추가 +
서버와 DB 파일 검사
최근 3일이내 저장된 파일을 제외한 나머지 파일 중 서버에는 있지만 DB에는 존재하지 않는 이미지 파일을 매 시간마다 검사하여 삭제
<!-- servlet-context.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd
">
<!-- 스프링 스케쥴러 : 스케쥴러 관련 어노테이션 활성화 -->
<task:annotation-driven/>
//ImageDeleteScheduling.java
package com.kh.spring.common.scheduling;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.ServletContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.kh.spring.board.model.service.BoardService;
@Component
public class ImageDeleteScheduling {
@Autowired
private ServletContext servletContext;
@Autowired
private BoardService boardService;
//@Scheduled(cron="0 0 * * * *")
@Scheduled(cron="0 * * * * *") // 매 분마다 진행하는 걸로 테스트
public void deleteimage() {
// 최근 3일이내 저장된 파일을 제외한 나머지 파일 중
// 서버에는 있지만 DB에는 존재하지 않는 이미지 파일을 매 시간마다 검사하여 삭제
// 1. 서버와 DB에 있는 파일 리스트를 조회 (최근 3일 이내 데이터만)
// 1) 서버 이미지 파일 리스트
// 이미지 파일이 저장된 실제 경로를 얻어옴
String savePath = servletContext.getRealPath("/resources/infoImages");
// 해당 경로에 있는 모든 파일을 읽어옴
File folder = new File(savePath);
File[] fileList = folder.listFiles(); // savePath 폴더에 있는 모든 이미지 파일이 배열로 반환됨
// fileList에서 최근 3일이내를 제외한 나머지 파일만 새로운 List에 저장
List<File> serverFileList = new ArrayList<File>();
// 3일 전 날짜
Date threeDaysAgo = new Date(System.currentTimeMillis()-(3*24*60*60*1000));
SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHH");
String standard = sdf.format(threeDaysAgo);
// 3일 전 날짜가 진정된 패턴 모양의 문자열 반환
// fileList가 존재하고 파일이 1개 이상 있을 경우
for(File file : fileList) {
// fileList 배열에 반복 접근하여 파일명만 얻어옴
String fileName = file.toString().substring(file.toString().lastIndexOf("\\")+1);
// 가장 마지막 \의 다음칸 부터 자름.
//System.out.println(file.toString());
//System.out.println(fileName);
// 기준(3일 전 시간)보다 더 이전에 만들어진 파일일 경우
// a.compareTo(B) : A가 B보다 크면 양수, A보다 B보다 작으면 음수, A와 B가 같다면 0
if(standard.compareTo(fileName.substring(0,8))>=0){
// 서버 파일 리스트에 추가
serverFileList.add(file);
}
}
// 2) DB 이미지 정보 파일 리스트 조회
List<String> dbFileList = boardService.selectDBFileList();
// 2. 두 리스트를 비교하여 불일치 되는 서버 이미지 파일을 삭제
if(dbFileList!=null && !serverFileList.isEmpty() ) {
// serverfileList 반복 접근
for(File serverFile : serverFileList) {
String fileName = serverFile.toString().substring(serverFile.toString().lastIndexOf("\\")+1);
// indexOf(비교값) : 비교값이 List에 존재하면 해당 index 반환, 없으면 -1 반환
if(dbFileList.indexOf(fileName)<0) {
serverFile.delete();
System.out.println(fileName+"삭제");
}
}
}
}
}
// BoardService.java
/** DB에 저장된 최근 3일이내를 제외한 파일 정보를 조회하는 Service
* @return dbFileList
*/
public abstract List<String> selectDBFileList();
//BoardServiceImpl.java
// DB에 저장된 최근 3일이내를 제외한 파일 정보를 조회하는 Service 구현
@Override
public List<String> selectDBFileList() {
return dao.selectDBFileList();
}
//BoardDAO.java
/** DB에 저장된 최근 3일이내를 제외한 파일 정보를 조회하는 DAO
* @return dbFileList
*/
public List<String> selectDBFileList() {
return sqlSession.selectList("boardMapper.selectDBFileList");
}
/* board-mapper.xml */
<!-- DB에 저장된 최근 3일이내를 제외한 파일 정보를 조회 -->
<!--
<![CDATA[ 부등호 포함 SQL 구문]]>
CDATA : markUp 언어에서 <, > 태그 기호를 태그가 아닌 글자로 인식하게 하는 구문
-->
<select id="selectDBFileList" resultType="string">
SELECT FILE_NAME
FROM ATTACHMENT
<![CDATA[
WHERE TO_DATE(SUBSTR(FILE_NAME,0,8), 'YYMMDDHH24') < SYSDATE -3
]]>
</select>
공유하기
Twitter Google+ LinkedIn
댓글남기기