Spring TIL - 커뮤니티 게시판(5) @Scheduled

Jieun·2023년 5월 11일
0

📝 Log 개념정리, @Scheduled 활용해서 DB와 서버 이미지 맞춰주기
#230511

📌 @Scheduled

Spring에서 제공하는 스케줄러 - 스케줄러 : 시간에 따른 특정 작업(Job)의 순서를 지정하는 방법.

설정 방법

1) servlet-context.xml ➡️ Namespaces 탭 ➡️ task 체크 후 저장

2) servlet-context.xml ➡️ Source 탭 ➡️ <task:annotation-driven/> 추가

<!-- @Scheduled 어노테이션 인식을 위한 태그 -->
<task:annotation-driven/>

@Scheduled 속성

리눅스 문법을 그대로 사용함 / 년도는 안써도됨 [ ] 표시 되서

  • fixedDelay : 이전 작업이 끝난 시점으로 부터 고정된 시간(ms)을 설정 (많이 안씀)

  • fixedRate : 이전 작업이 수행되기 시작한 시점으로 부터 고정된 시간(ms)을 설정.

  • cron 속성 : UNIX계열 잡 스케쥴러 표현식으로 작성 (제일많이씀)

    cron="초 분 시 일 월 요일 [년도]" - 요일 : 1(SUN) ~ 7(SAT)
    ex) 2019년 9월 16일 월요일 10시 30분 20초 cron="20 30 10 16 9 2" // 연도 생략 가능

특수문자
* : 모든 수.
- : 두 수 사이의 값. ex) 10-15 -> 10이상 15이하
, : 특정 값 지정. ex) 3,4,7 -> 3,4,7 지정
/ : 값의 증가. ex) 0/5 -> 0부터 시작하여 5마다
? : 특별한 값이 없음. (월, 요일만 해당)
L : 마지막. (월, 요일만 해당)


주의사항
@Scheduled 어노테이션은 매개변수가 없는 메소드에만 적용 가능.


package edu.kh.comm.common.scheduling;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
  
@Component 
public class SchedulingTest {
  
  	// slf4j import
	private Logger logger =  LoggerFactory.getLogger(SchedulingTest.class);
  
    @Scheduled(fixedRate = 5000)	
	// cron="초 분 시 일 월 요일 [년도]" - 요일 : 1(SUN) ~ 7(SAT) 
			
	// @Scheduled(cron = "0 * * * * *") // 매 분 0초마다 실행
	// @Scheduled(cron = "0 0 * * * *") // 정시 마다 (12:00:00 / 13:00:00)
	// @Scheduled(cron = "0 0 12 * * *") // 매일 12시 정각
	// @Scheduled(cron = "0 0 12 1, 11, 21 * *") // 매달 1, 11, 21일 12시 정각마다
	// @Scheduled(cron = "0 0 14 * * 2") // 월요일 14시 마다
	
	public void test() {
		logger.info("5초마다 출력");
	}
}

작업파일


package edu.kh.comm.common.scheduling;


import java.io.File;
import java.util.Arrays;
import java.util.List;

import javax.servlet.ServletContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import edu.kh.comm.board.model.service.BoardService;

@Component // bean등록
public class ImageDeleteScheduling {

	private Logger logger = LoggerFactory.getLogger(ImageDeleteScheduling.class);
	
	// BOARD_IMG 테이블에서 삭제되었으나
	// 서버/resource/images/board 폴더에는 존재하는
	// 이미지 파일을 정시마다 삭제
	
	@Autowired
	private BoardService service;
	
	@Autowired
	private ServletContext application; // application scope 객체 -> 서버 폴더 경로 얻어오기에 사용
	
	// 스케줄링에 사용되는 메서드는 무조건 public void 메서드명() 
	
	
	@Scheduled(cron ="0 * * * * *") // 매 분마다 (테스트용)  //나중에 할 때는 정시마다 매일마다 해두는게 좋음
	public void serverImageDelete() {
		
		// 1) BOARD_IMG에 존재하는 모든 이미지 목록 조회
		List<String> dbList = service.selectDBList();
		
		// 2) /resources/images/board 폴더에 존재하는 모든 이미지 파일 목록 조회
		String folderPath = application.getRealPath("/resources/images/board");
		
		File path = new File(folderPath); // resources/images/board 폴더를 참조하는 객체
		
		File[] arr = path.listFiles(); // path가 참조하는 폴더에 있는 모든 파일을 얻어와 File 배열로 반환
		
		List<File> serverList = Arrays.asList(arr); // arr을 List로 변환
		
		

		// 3) 두 목록을 비교해서 일치하지 않는 이미지 파일을 삭제
		// (DB에는 없는데 서버 폴더에 있으면 삭제)
		if( !serverList.isEmpty() ) { // 서버에 이미지 파일이 있을 때 비교/삭제 진행
			
			// server : \resources\images\board\sample2.jpg
			// DB     : /resources/images/board/sample2.jpg
			
			for (File serverImage : serverList) {
				
				String name = "/resources/images/board/" + serverImage.getName(); // 파일명만 얻어오기
				
				if(dbList.indexOf(name) == -1) { // List에 value와 같은 값이 있으면 인덱스 반환 / 없으면 -1 반환
				
					// dbList에는 없는데 serverList에만 파일이 존재하는 경우
					logger.info(serverImage.getName() + " 삭제");
					serverImage.delete(); // 파일 삭제
				}
				
			}
			
			logger.info("---------------- 서버 이미지 삭제 완료 ------------------");
		}
		
	}
	
}

public interface BoardService {

/** BOARD_IMG 이미지 목록 조회
 	 * @return dbList
	 */
	List<String> selectDBList();
    
}

-----------------------------------------------------------------------

@Service
public class BoardServiceImpl implements BoardService{
	
	@Autowired
	private BoardDAO dao;

// BOARD_IMG 이미지 목록 조회 서비스 구현
	@Override
	public List<String> selectDBList() {
	
		return dao.selectDBList();
	}

---------------------------------------------------------------------------

@Repository
public class BoardDAO {
	
	@Autowired
	private SqlSessionTemplate sqlSession;


	/** BOARD_IMG 이미지 목록조회 DAO
	 * @return
	 */
	public List<String> selectDBList() {
		
		return sqlSession.selectList("boardMapper.selectDBList");
	}

-------------------------------------------------------------------------------

<!-- BOARD_IMG 목록 조회 -->
<select id="selectDBList" resultType="string">
	SELECT IMG_RENAME FROM BOARD_IMG
</select>

-------------------------------------------------------------------------------
profile
👩‍💼👩‍💼➡️➡️➡️👩‍💻👩‍💻 생산자의 삶을 살기 위해 개발공부중

0개의 댓글