본문 바로가기

카테고리 없음

Spring 14. Scheduler(1)

▶ Scheduler 

: 매일, 매분, 매초, 매주, 매달, .. 등 반복적으로 실행시켜야 하는 작업(프로세스)가 있는 경우 스프링 스케쥴러를 사용하면 간편하게 셋팅 가능하다.

▶ Spring Scheduler 작업순서

1. xml파일 만들고 task, context 스키마를 등록(하단 namespace탭을 이용)
2. 스케쥴링 관련 annotation 활성화 <task:annotation-driven/>
3. 스케쥴러로 사용할 클래스들을 bean객체로 등록
4. web.xml에 프로그램 구동시 현재 xml이 읽혀지도록 등록 -> *-context.xml로 등록
5. 스케쥴링을 원하는 메서드에서 schedule어노테이션 추가(#2가 되어있어야 함) -> ScheduleController.java에 추가함

 

// scheduler-context.xml

<?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:context="http://www.springframework.org/schema/context"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="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">

    
	<!-- #2. -->
	<task:annotation-driven scheduler="khScheduler"  />
	<!-- <task:scheduler id="khScheduler"/>의 id값을 넣어줌 -->
	
	<!-- #3. -->
	<context:component-scan base-package="com.kh.spring.common.scheduling" />
	
	<task:scheduler id="khScheduler" pool-size="10"/>
	<!-- pool-size : 쓰레드풀 개수 지정(기본값1) -->
	
	<task:scheduled-tasks scheduler="khScheduler">
		<task:scheduled ref="scheduleController" method="testCron" cron="1 * * * * *"/>
		<!-- 
			ref : bean 클래스의 변수명(Beans Graph) 
			method : bean클래스의 스케쥴링할 메서드명
			cron : 
				* * * * * * (*) 
				초 분 시 일 월 요일 년도(생략가능)(7개)
				* : 모든 값(매시 매분 매주 매초)
				? : 어떤 값이든 상관없다.
				- : 범위지정(1-2초) 1에서 2초
				, : 여러 값을 지정(1, 5) 1초랑 5초
				/ : 증분 값 (0/2) 0초부터 매 2초마다 (증가치 설정가능)
				L : 지정할 수 있는 범위의 마지막 값(매달 말일)
				W : 가장 가까운 "평일"을 설정할 때
				# : N번째 특정 요일을 설정할 때
			cron="1 * * * * *" :  요일 매월 매일 매시 매분 1초에 실행
			
			ex)매시간 30분에 특정 작업을 실행시키고 싶다?
			0 30 * * * * (매월 매일 매시
			ex)매일 오전 1시에 실행시키고 싶다?
			0 0 1 * * * *
		-->
		
	</task:scheduled-tasks>
</beans>

 

 

// FileDeleteScheduler.java
/*
    Board테이블과 BoardImg테이블 안에 있는 이미지 목록들을 모두 조회한 후
    resources/images 디렉토리 안에 있는 이미지, 파일들과 대조하여
    하나도 일치하지 않는 이미지 파일들을 삭제하기
    -> DB에 존재하지 않는 파일이 images안에 존재하는 경우

    매달 1일 정시에 딱 한 번만 실행되도록 크론표현식으로 작성하시오.
    (테스트를 위해 5초간격으로 설정한 후 변경해줄 것)
 */
 
@Slf4j
@Component
public class FileDeleteScheduler {

	@Autowired
	private ServletContext application; //정적파일들의 경로를 얻어오기 위해 추가
	
	@Autowired
	private BoardService boardService;	
	
	@Scheduled(cron="0 0 1 * * *")
	public void deleteFile() {
		
		//1) board_img안에 있는 모든 파일 목록 조회
		List<String> list = boardService.selectFileList();
		log.info("list ? {}", list);
			
		List<BoardType> boardTypeList = boardService.selectBoardTypeList();
			
		for(BoardType bt : boardTypeList) {
			
			// 2) resources/images/board/T/ 에 있는 모든 이미지 파일목록 조회
			File path = new File(application.getRealPath("/resources/images/board/"+bt.getBoardCd()+"/"));
			File[] files = path.listFiles();
			// 현재 디렉토리 안에 존재하는 모든 파일을 배열형태로 가져오기
			
			List<File> fileList = Arrays.asList(files); //배열을 컬렉션 형태로 반환
			
			int count = 0;
			if(!list.isEmpty()) {
				
                for(File serverFile  : fileList) {
                    String fileName = serverFile.getName(); // 파일명 반환
                    fileName = "/resources/images/board/"+bt.getBoardCd()+"/"+fileName;

                    // List.indexOf(value) : List안에 value와 같은 값이 있으면 해당 값의 인덱스 위치를 반환해주는 함수
                    if(list.indexOf(fileName) ==  -1) {
                        // select한 DB목록에 존재하지 않지만 웹서버상에 저장된 파일인 경우.
                        // -> 사용하고 있지 않는 파일로 간주
                        log.info(fileName+"을 삭제합니다");
                        count++;
                        serverFile.delete();
                    }
                }
            }
			log.info("총 {}개의 파일이 삭제됨", count);
			log.info("파일삭제 스케쥴러 종료");
		}
	}
}

 

// board-mapper.xml

<!-- 사용중인 이미지 리스트 -->
<select id="selectFileList" resultType="string">
    SELECT 
        '/resources/images/board/T/' || CHANGE_NAME
      FROM BOARD_IMG

     UNION ALL

    SELECT 
        '/resources/images/board/' || BOARD_CD || '/' || CHANGE_NAME
      FROM BOARD
      WHERE CHANGE_NAME IS NOT NULL
</select>

<!-- selectBoardTypeList -->
<select id="selectBoardTypeList" resultType="boardType">
    SELECT *
      FROM BOARD_TYPE
     ORDER BY BOARD_CD
</select>