스프링 : Quartz , Task , 오라클 to_char , Cron 사용법 , 첨부 파일 목록 처리
Quartz 라이브러리
잘못 업로드된 파일 비정상적으로 브라우저를 종료할때 페이지 빠져나갈때의 문제를 해결 하기 위함
파일의 목록은 오늘이 아닌 파일을 해야함.
Why? 오늘 날짜를 대상으로 하면 지금 게시물 작성하거나,수정 중인 파일을 삭제할 가능성이 있기 때문!
주기적으로 스케줄링을 할 수 있는 Spring-Batch나 Quartz라이브러리 사용
서버를 운영할 때는 매일, 매주, 매월 등 주기적으로 특정한 프로그램을 사용함.
(Spring-Batch의 경우 많은 양의 데이터를 주기적으로 읽고 쓰는 작업에는 유용하지만 설정이 살짝 더 복잡하다)
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz-jobs -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.3.0</version>
</dependency>
task 항목을 체크
root-context.xml에 <task:annotation-driven>을 추가
Task 작업의 처리
이 작업은 별도로 다른 패키지를 만들어서 처리합니다.
@Component
- 스프링 빈 설정 XML파일에 <bean id="..."/> 또는 @Configuration 클래스에서 @Bean을 붙여 빈을 등록하는 것처럼
빈 클래스에 @Component 어노테이션을 붙여서 빈을 등록할 수 있음.
@Scheduled
- cron을 이용해서 속성을 부여해서 주기를 제어한다.
@Scheduled(cron="0 * * * * *")
public void checkFiles()throws Exception{
log.warn("File Check Task run.............");
log.warn("=================================");
}
cron 설정은 매분 0초마다 한번 씩 실행되도록 지정해 놓은 것
1분에 한번씩 로그가 기록되는 것을 확인할 수 있다.
오라클 to_char
오라클에서 쿼리문을 작성할 때 TO_CHAR() 함수는 날짜, 숫자 등의 값을 문자열로 변환하는 함수,
자주 사용하는 기본 함수이므로 아래 다양한 변환 방법을 알고 있으면 많은 도움이 됨.
날짜 포맷 변경
SELECT TO_CHAR(SYSDATE, 'YYYYMMDD') --20211116
, TO_CHAR(SYSDATE, 'YYYY/MM/DD') --2021/11/16
, TO_CHAR(SYSDATE, 'YYYY-MM-DD') --2021-11-16
, TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS')--2021-11-16 15:52:50
FROM dual
소수점 변경
SELECT TO_CHAR(123.456, 'FM990.999') -- 123.456
, TO_CHAR(1234.56, 'FM9990.99') -- 1234.56
, TO_CHAR(0.12345, 'FM9990.99') -- 0.12
FROM dual
FM: 문자열의 공백 제거
9 : 값이 없으면 표시안함, 0 : 값이 없으면 "0"으로 처리
숫자 단위 천 단위 콤마
SELECT TO_CHAR(123456, 'FM999,999') -- 123,456
, TO_CHAR(123456789, 'FM999,999,999') -- 123,456,789
, TO_CHAR(123456, 'FML999.999') -- \123,456
FROM dual
마지막 Char는 \123,456으로 나옴
지정한 길이 만큼 "0"으로 채우기
SELECT TO_CHAR(123456, 'FM999,999') -- 123,456
, TO_CHAR(123456789, 'FM999,999,999') -- 123,456,789
, TO_CHAR(123456, 'FML999.999') -- \123,456
FROM dual
날짜의 "0" 없애기
SELECT TO_CHAR(SYSDATE, 'MM/DD') -- 09/05
TO_CHAR(SYSDATE, 'FMMM/DD') -- 9/05
FROM dual
날짜에서 숫자0이 없어진다
임의의 구분자로 날짜 형식 만들기
SELECT TO_CHAR(SYSDATE, '""YYYY"년 "MM"월 "DD"일') -- 2021년 11월 16일
TO_CHAR(SYSDATE, '""HH24"시 "MI"분 "SS"초"') -- 16시 11분 30초
FROM dual
시간의 오전,오후 값 반환
SELECT TO_CHAR(SYSDATE, 'AM') -- 오후
, TO_CHAR(SYSDATE, 'AM HH:MI:SS') -- 오후 16:20:30
, TO_CHAR(SYSDATE, 'YYYY-MM-DD AMHH:MI:SS') -- 2021-11-16 오후 16:20:31
FROM dual
날짜의 요일 반환
SELECT TO_CHAR(SYSDATE, 'D') -- 3 1(일)~7(토)
, TO_CHAR(SYSDATE, 'DY') -- 수
, TO_CHAR(SYSDATE, 'DAY') -- 수요일
FROM dual
1년기준 몇일, 몇주, 분기 반환
SELECT TO_CHAR(SYSDATE, 'DDD') --365일 기준 320일
, TO_CHAR(SYSDATE, 'WW') --1년 기준 46주
, TO_CHAR(SYSDATE, 'Q') --4분기
FROM dual
간편한 날짜 변환
SELECT TO_CHAR(SYSDATE, 'MON') --11월
, TO_CHAR(SYSDATE, 'DL') --2021년 11월 16일 목요일
FROM dual
Cron 사용법
cron의 사용법은
@Scheduled(cron="0 * * * * *")
public void checkFiles()throws Exception{
1 2 3 4 5 6 7
0 * * * * * (*)의 부분을 하나씩 보자면
1 seconds(0~59) 초를 나타낸다.
2 minutes(0~59) 분을 나타낸다.
3 hours(0~23) 시간을 나타낸다.
4 day(1~31) 일을 나타낸다.
5 months (1~12) 월을 나타낸다.
6 day of week (1~7) 요일 나타낸다.
7 year(optional) 년도를 나타낸다. 생략 가능
매월 5일에 반복하고 싶으면 4인 부분에 5를 넣으면 된다.
각 기호가 뜻하는 것은
* | 모든 수 |
? | 제외 |
- | 기간 |
, | 특정 시간 |
/ | 시작 시간과 반복 시간 |
L | 마지막 |
W | 가까운 평일 |
@Scheduled(cron = "0 0 2 * * *")
public void checkFiles() throws Exception{
log.warn("File Check Task run .....");
log.warn(new Date());
// db의 파일들
List<BoardAttachVO> fileList = attachMapper.getOldFiles();
// 먼저 폴더에 db에 있는 파일 확인
List<Path> fileListPaths = fileList.stream()
.map(vo -> Paths.get("D:\\upload", vo.getUploadPath(), vo.getUuid()
+ "_" + vo.getFileName()))
.collect(Collectors.toList());
// 이미지 타입의 섬네일 파일
fileList.stream().filter(vo -> vo.isFileType() == true)
.map(vo -> Paths.get("D:\\upload", vo.getUploadPath(), "s_" + vo.getUuid() + "_"
+ vo.getFileName()))
.forEach(p -> fileListPaths.add(p));
log.warn("========================");
fileListPaths.forEach(p -> log.warn(p));
// 어제 폴더
File targetDir = Paths.get("D:\\upload",getFolderYesterDay()).toFile();
File[] removeFiles = targetDir.listFiles(file -> fileListPaths.contains(file.toPath()) == false);
log.warn("------------------------");
for(File file : removeFiles) {
log.warn(file.getAbsolutePath());
file.delete();
}
}
checkFiles()는 매일 새벽 2시에 동작.
어제 날짜의 첨부 파일 목록을 가져온다.
BoardAttachVO 타입의 객체를 비교를 위해 Paths의 목록으로 변환한다.
java.nio.Paths의 목록으로 변환, 이미지 파일도 썸네일 목록 필요 변환