📝 Log 개념정리, @Scheduled 활용해서 DB와 서버 이미지 맞춰주기
#230511
Spring에서 제공하는 스케줄러 - 스케줄러 : 시간에 따른 특정 작업(Job)의 순서를 지정하는 방법.
1) servlet-context.xml ➡️ Namespaces 탭 ➡️ task 체크 후 저장
2) servlet-context.xml ➡️ Source 탭 ➡️ <task:annotation-driven/> 추가
<!-- @Scheduled 어노테이션 인식을 위한 태그 -->
<task:annotation-driven/>
리눅스 문법을 그대로 사용함 / 년도는 안써도됨 [ ] 표시 되서
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>
-------------------------------------------------------------------------------