팀프로젝트 당시 '투데이 수 집계' 기능 구현을 담당했었다.
일별로 사이트 접속자 수를 파악하여 DB에 넣는 기능을 만들어야 했다.
이를 구현하기 위해 Logback 라이브러리를 사용하여 접속자 수를 파악하고
DB에 INSERT 하는 코드를 만들어서
요일별 방문자 수 집계를 자동화했었다.
자바의 컬렉션을 적절하게 사용했던 예제라고 생각되어 정리해본다.
코드를 설명하자면
@Scheduled(cron = "0 0 0 * * *")
public void readLogFile () throws IOException {
일별 접속자 정보가 들어있는 로그파일을 읽어 DB에 INSERT 하는 기능을 가진
readLogFile() 은 매일 자정에 실행된다
String basePath = "C:\\logs\\accesslog\\accesslog-";
Date d = new Date();
d = new Date(d.getTime()+(1000*60*60*24*-1));
SimpleDateFormat yesterday = new SimpleDateFormat("yyyy-MM-dd");
파일이 저장된 경로를 구하고
Date 객체 생성 후 Format 된 어제 날짜를 구한다
String filePath = basePath+ yesterday.format(d)+".0.log";
List<String> list = Files.readAllLines(Paths.get(filePath), StandardCharsets.UTF_8);
System.out.println(list);
경로 + 날짜 + 0.log (파일 형식) 으로 구성된 파일 경로를 filePath 변수에 저장한다
어제 날짜의 로그파일 읽어들여 List 에 저장한다.
컬렉션 중 하나인 ArrayList 는 데이터의 중복을 허용하는 특징이 있다.
사이트 접속자 수 집계를 위해서는 중복접속한 유저는 제외되어야 하는데, List 의 특성때문에
현재 list 객체에는 중복접속로그까지 포함있는 것이다.
중복접속 로그들은 지워버리기 위해 HashSet 을 이용한다.
HashSet 은 중복저장되지 않는다는 특징을 갖고있다.
HashSet<String>set = new HashSet<>();
for(int i = 0; i<list.size(); i++) {
String[] temp = list.get(i).split("[=]");
System.out.println(temp[0]+","+temp[1]);
set.add(temp[1]);
}
System.out.println("최종 = "+set);
이렇게 list 객체 안의 값을 set 으로 넣어 중복을 제거해준다.
위 단계에서 set으로 바로 데이터를 받으면 list에서 set 으로 옮기는 과정은 생략할 수 있지 않느냐 ? 물을수도있는데
바로 set 으로 받는건 안되더라
int cnt =0;
Iterator<String> iter = set.iterator();
while(iter.hasNext()) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("usersNo",iter.next());
map.put("date", date);
cnt = userService.insertToday(map);
}
iterator() 메서드로 iterator 인터페이스를 가져올 수 있는데,
hashset 의 데이터를 iterator 에 담았다고 생각하면 된다.
Iterator 는 컬렉션에 저장된 요소를 접근하는데 사용되는 인터페이스이다. Set에는 순서가 없으니 for 문을 이용해서는 데이터를 출력할 수 없다.
HashMap 은 키는 중복을 허용하지 않으며, 값은 중복을 허용한다는 특징을 가지고 있다.
map 에 사용자번호(userNo)와 date(날짜) 를 담아 insert 쿼리를 실행시킨다.
iter 객체의 데이터 수만큼 쿼리가 날라가는 것이다.
▽ 전체코드
public class LogScheduler {
private final UserService userService;
@Scheduled(cron = "0 0 0 * * *") //매일자정
public void readLogFile () throws IOException {
String basePath = "C:\\logs\\accesslog\\accesslog-"; // 파일 저장경로
Date d = new Date();
d = new Date(d.getTime()+(1000*60*60*24*-1)); //어제날짜
SimpleDateFormat yesterday = new SimpleDateFormat("yyyy-MM-dd");
//accesslog 파일 찾아서 => 파일 정보 읽어서 => list에 저장
String filePath = basePath+ yesterday.format(d)+".0.log";
List<String> list = Files.readAllLines(Paths.get(filePath), StandardCharsets.UTF_8); //어제 날짜의 로그파일 읽어들임
System.out.println(list);
//중복데이터 제거를 위해 LIST에 담긴 정보를 HashSet에 담는다
HashSet<String>set = new HashSet<>();
for(int i = 0; i<list.size(); i++) {
String[] temp = list.get(i).split("[=]");
System.out.println(temp[0]+","+temp[1]);
set.add(temp[1]);
}
System.out.println("최종 = "+set);
//today format
Date today = new Date();
String date = yesterday.format(today);
System.out.println("date = "+date);
//HashSet size 만큼 insert 쿼리 실행
int cnt =0;
Iterator<String> iter = set.iterator();
while(iter.hasNext()) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("usersNo",iter.next());
map.put("date", date);
cnt = userService.insertToday(map);
}
}
}
'프로젝트' 카테고리의 다른 글
| [과제] 셀프 코드리뷰 (0) | 2022.11.05 |
|---|---|
| [ERROR] 프로젝트 빌드 에러 : Execution failed for task ':compileJava'.> invalid source release: 11 (1) | 2022.11.04 |
| [SpringBoot & JPA 프로젝트] 카카오 전체 오류로 인해 서비스 이용불가 => 네이버 로그인 API 적용 (0) | 2022.10.17 |
| [SpringBoot & JPA 프로젝트] 토스페이먼츠 카드사심사 후 라이브 API 적용 & 결제 TEST (성공/실패) (0) | 2022.10.11 |
| [SpringBoot & JPA 프로젝트] 아쉬운점 & 보완할점 (2) | 2022.10.05 |