From 87a9240a9726abebf8522e1bed1b184b15ec22d0 Mon Sep 17 00:00:00 2001 From: dyhj625 Date: Fri, 7 Feb 2025 16:20:03 +0900 Subject: [PATCH] =?UTF-8?q?=ED=9C=B4=EA=B0=80=EA=B4=80=EB=A6=AC,=EB=B3=B4?= =?UTF-8?q?=EB=93=9C=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../localhost/common/config/AppConfig.java | 16 +++ .../security/config/SecurityConfig.java | 2 +- .../controller/api/BoardController.java | 36 +++-- .../controller/api/VacationController.java | 23 +-- .../localhost/mapper/localbordMapper.java | 2 +- .../localhost/mapper/localvacaMapper.java | 2 +- .../localhost/service/localbordService.java | 4 +- .../localhost/service/localvacaService.java | 132 +++++++++++++++++- src/main/resources/application.yml | 5 + src/main/resources/mapper/localbordMapper.xml | 6 +- src/main/resources/mapper/localvacaMapper.xml | 14 +- 11 files changed, 191 insertions(+), 51 deletions(-) create mode 100644 src/main/java/io/company/localhost/common/config/AppConfig.java diff --git a/src/main/java/io/company/localhost/common/config/AppConfig.java b/src/main/java/io/company/localhost/common/config/AppConfig.java new file mode 100644 index 0000000..57e6d3b --- /dev/null +++ b/src/main/java/io/company/localhost/common/config/AppConfig.java @@ -0,0 +1,16 @@ +package io.company.localhost.common.config; + +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class AppConfig { + @Bean + public RestTemplate restTemplate(RestTemplateBuilder builder) { + return builder + .defaultHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)") + .build(); + } +} diff --git a/src/main/java/io/company/localhost/common/security/config/SecurityConfig.java b/src/main/java/io/company/localhost/common/security/config/SecurityConfig.java index d6ab1c3..58f9f84 100644 --- a/src/main/java/io/company/localhost/common/security/config/SecurityConfig.java +++ b/src/main/java/io/company/localhost/common/security/config/SecurityConfig.java @@ -80,7 +80,7 @@ public class SecurityConfig { http .securityMatcher("/api/**") // '/api/**' 경로에 대해서만 보안 적용 .authorizeHttpRequests(auth -> auth - .requestMatchers("/api/board/**").hasRole("MEMBER") + //.requestMatchers("/api/board/**").hasRole("MEMBER") .requestMatchers("/api/**").permitAll() // 특정 엔드포인트 허용 .anyRequest().authenticated() // 나머지 요청은 인증 필요 //auth.anyRequest().access(authorizationManager) // 모든 요청에 대해 권한 관리 diff --git a/src/main/java/io/company/localhost/controller/api/BoardController.java b/src/main/java/io/company/localhost/controller/api/BoardController.java index b306e51..f5da9b3 100644 --- a/src/main/java/io/company/localhost/controller/api/BoardController.java +++ b/src/main/java/io/company/localhost/controller/api/BoardController.java @@ -95,29 +95,26 @@ public class BoardController { /** * 게시물 삭제 - * @param boardId 게시물 ID + * @ReqMap map 수정 데이터 (LOCBRDSEQ) * @return 삭제 결과 메시지 */ @Member @ParameterCheck @DeleteMapping("/{boardId}") - public ApiResponse deleteBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) { - map.put("LOCBRDSEQ", boardId); + public ApiResponse deleteBoard(@ReqMap MapDto map) { boardService.deleteBoard(map); return ApiResponse.ok("게시물이 삭제되었습니다."); } /** * 게시물 수정 - * @param boardId 게시물 ID - * @ReqMap map 수정 데이터 (LOCBRDTTL, LOCBRDCON) + * @ReqMap map 수정 데이터 (LOCBRDTTL, LOCBRDCON, LOCBRDSEQ) * @return 수정 결과 메시지 */ @Member @ParameterCheck @PutMapping("/{boardId}") - public ApiResponse updateBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) { - map.put("LOCBRDSEQ", boardId); + public ApiResponse updateBoard(@ReqMap MapDto map) { boardService.updateBoard(map); return ApiResponse.ok("게시물이 수정되었습니다."); } @@ -154,14 +151,14 @@ public class BoardController { /** * 댓글/대댓글 조회 - * @param boardId 게시물 ID + * @ReqMap map 수정 데이터 (LOCBRDSEQ) * @return 댓글과 대댓글의 계층 구조 데이터 */ @Member @ParameterCheck @GetMapping("/{boardId}/comments") - public ApiResponse> getComments(@PathVariable("boardId") int boardId) { - return ApiResponse.ok(boardService.getComments(boardId)); + public ApiResponse> getComments(@ReqMap MapDto map) { + return ApiResponse.ok(boardService.getComments(map)); } /** @@ -189,48 +186,47 @@ public class BoardController { @Member @ParameterCheck @PutMapping("/comment/{commentId}") - public ApiResponse updateComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { + public ApiResponse updateComment(@ReqMap MapDto map) { boardService.updateComment(map); return ApiResponse.ok("댓글이 수정되었습니다."); } /** * 댓글/대댓글 삭제 - * @param commentId 댓글 ID - * @ReqMap map 삭제 데이터 + * @ReqMap map 수정 데이터 (LOCCMTSEQ) * @return 삭제 결과 메시지 */ @Member @ParameterCheck @DeleteMapping("/comment/{commentId}") - public ApiResponse deleteComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { + public ApiResponse deleteComment(@ReqMap MapDto map) { boardService.deleteComment(map); return ApiResponse.ok("댓글이 삭제되었습니다."); } /** * 댓글 비밀번호 확인 - * @param commentId 댓글 ID - * @ReqMap map 비밀번호 데이터 + * @ReqMap map 수정 데이터 (LOCCMTSEQ, LOCCMTPWD) * @return 비밀번호 확인 결과 */ @Member @ParameterCheck @PostMapping("/comment/{commentId}/password") - public ApiResponse checkCommentPassword(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { + public ApiResponse checkCommentPassword(@ReqMap MapDto map) { + int commentId = (int) map.get("LOCCMTPWD"); return ApiResponse.ok(boardService.getCommentPassword(commentId).equals(map.getString("LOCCMTPWD"))); } /** * 게시물 비밀번호 확인 - * @param boardId 게시물 ID - * @ReqMap map 비밀번호 데이터 + * @ReqMap map 수정 데이터 (LOCBRDSEQ, LOCBRDPWD) * @return 비밀번호 확인 결과 */ @Member @ParameterCheck @PostMapping("/{boardId}/password") - public ApiResponse checkBoardPassword(@PathVariable("boardId") int boardId, @ReqMap MapDto map) { + public ApiResponse checkBoardPassword(@ReqMap MapDto map) { + int boardId = (int) map.get("LOCBRDSEQ"); return ApiResponse.ok(boardService.getBoardPassword(boardId).equals(map.getString("LOCBRDPWD"))); } diff --git a/src/main/java/io/company/localhost/controller/api/VacationController.java b/src/main/java/io/company/localhost/controller/api/VacationController.java index e8d110a..ef1b3ae 100644 --- a/src/main/java/io/company/localhost/controller/api/VacationController.java +++ b/src/main/java/io/company/localhost/controller/api/VacationController.java @@ -2,6 +2,7 @@ package io.company.localhost.controller.api; import java.util.List; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -43,15 +44,21 @@ public class VacationController { return ApiResponse.ok("모든 휴가가 성공적으로 저장되었습니다."); } + /** - * 휴가 정보를 조회하여 프론트엔드로 전달 + * ✅ 특정 연월에 대한 휴가 데이터 조회 */ - @GetMapping("/list") - public ApiResponse> getVacationList(@ReqMap MapDto map) { - - // 서비스 호출을 통해 데이터 조회 - List vacationList = localVacaService.getVacationList(map); - - return ApiResponse.ok(vacationList); + @GetMapping("/list/{year}/{month}") + public List getVacations(@PathVariable("year") int year, @PathVariable("month") int month) { + return localVacaService.getVacationList(year, month); } + + /** + * ✅ 특정 연월에 대한 공휴일 데이터 조회 + */ + @GetMapping("/{year}/{month}") + public List getHolidays(@PathVariable("year") int year, @PathVariable("month") int month) { + return localVacaService.getHolidays(year, month); + } + } diff --git a/src/main/java/io/company/localhost/mapper/localbordMapper.java b/src/main/java/io/company/localhost/mapper/localbordMapper.java index 7190ee7..f9de76a 100644 --- a/src/main/java/io/company/localhost/mapper/localbordMapper.java +++ b/src/main/java/io/company/localhost/mapper/localbordMapper.java @@ -44,7 +44,7 @@ public interface localbordMapper { void updateReaction(MapDto map); // 댓글 조회 - List getComments(int boardSeq); + List getComments(MapDto map); // 댓글/대댓글 작성 void addCommentOrReply(MapDto map); diff --git a/src/main/java/io/company/localhost/mapper/localvacaMapper.java b/src/main/java/io/company/localhost/mapper/localvacaMapper.java index 21bb469..7f034f1 100644 --- a/src/main/java/io/company/localhost/mapper/localvacaMapper.java +++ b/src/main/java/io/company/localhost/mapper/localvacaMapper.java @@ -12,7 +12,7 @@ import io.company.localhost.common.dto.MapDto; public interface localvacaMapper { void insertVacation(MapDto map); - List findVacations(MapDto map); + List findVacations(@Param("year") int year, @Param("month") int month); } diff --git a/src/main/java/io/company/localhost/service/localbordService.java b/src/main/java/io/company/localhost/service/localbordService.java index 7e6550a..cddff6d 100644 --- a/src/main/java/io/company/localhost/service/localbordService.java +++ b/src/main/java/io/company/localhost/service/localbordService.java @@ -111,8 +111,8 @@ public class localbordService { } } - public List getComments(int boardSeq) { - return boardMapper.getComments(boardSeq); + public List getComments(MapDto map) { + return boardMapper.getComments(map); } public void addCommentOrReply(MapDto map) { diff --git a/src/main/java/io/company/localhost/service/localvacaService.java b/src/main/java/io/company/localhost/service/localvacaService.java index b932f60..b046348 100644 --- a/src/main/java/io/company/localhost/service/localvacaService.java +++ b/src/main/java/io/company/localhost/service/localvacaService.java @@ -1,9 +1,17 @@ package io.company.localhost.service; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.List; - +import java.util.Map; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; - +import org.springframework.web.client.RestTemplate; import io.company.localhost.common.dto.MapDto; import io.company.localhost.mapper.localvacaMapper; import lombok.RequiredArgsConstructor; @@ -12,14 +20,124 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor public class localvacaService { private final localvacaMapper localvacaMapper; + private final RestTemplate restTemplate = new RestTemplate(); + @Value("${api.public-holiday.key}") + private String serviceKey; public void insertVacation(MapDto map) { - localvacaMapper.insertVacation(map); + localvacaMapper.insertVacation(map); } - - public List getVacationList(MapDto map) { - return localvacaMapper.findVacations(map); + + public List getVacationList(int year, int month) { + return localvacaMapper.findVacations(year, month); + } + + /** + * 🔹 특정 연월에 대한 공휴일 데이터 조회 + */ + public List getHolidays(int year, int month) { + // ✅ ServiceKey를 디코딩해서 사용 + String decodedServiceKey = URLDecoder.decode(serviceKey, StandardCharsets.UTF_8); + System.out.println("📌 디코딩된 ServiceKey: " + decodedServiceKey); + + // ✅ URI를 직접 문자열로 구성하여 ServiceKey가 다시 인코딩되지 않도록 함 + String url = "http://apis.data.go.kr/B090041/openapi/service/SpcdeInfoService/getRestDeInfo" + + "?solYear=" + year + + "&solMonth=" + String.format("%02d", month) + + "&ServiceKey=" + decodedServiceKey // ✅ 디코딩된 상태로 직접 추가 + + "&_type=json"; + + System.out.println("📌 API 요청 URL: " + url); + + // ✅ API 요청 헤더 추가 (User-Agent 포함) + HttpHeaders headers = new HttpHeaders(); + headers.set(HttpHeaders.USER_AGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"); + + HttpEntity entity = new HttpEntity<>(headers); + + // ✅ `exchange` 메서드를 사용하여 요청 + ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, Map.class); + + System.out.println("📌 API 응답 데이터: " + response.getBody()); + + return parseResponse(response.getBody()); + } + + /** + * 🔹 공휴일 데이터를 MapDto로 변환 + */ + private List parseResponse(Map response) { + List holidays = new ArrayList<>(); + + if (response == null || !response.containsKey("response")) { + System.out.println("📌 응답이 비어 있음."); + return holidays; + } + + Map responseBody = (Map) response.get("response"); + System.out.println("📌 responseBody: " + responseBody); + + if (responseBody == null || !responseBody.containsKey("body")) { + System.out.println("📌 API 응답 데이터에서 'body' 필드 없음."); + return holidays; + } + + Map body = (Map) responseBody.get("body"); + System.out.println("📌 body: " + body); + + if (body == null || !body.containsKey("items")) { + System.out.println("📌 API 응답 데이터에서 'items' 필드 없음."); + return holidays; + } + + Object items = body.get("items"); + System.out.println("📌 items: " + items); + + // ✅ 'items'가 Map 타입인지 확인 후 처리 + if (items instanceof Map) { + Map itemMap = (Map) items; + if (itemMap.containsKey("item")) { + Object itemData = itemMap.get("item"); + + System.out.println("📌 itemData: " + itemData); + + // ✅ 'item'이 리스트인지 단일 객체인지 확인 후 변환 + if (itemData instanceof List) { + for (Map item : (List>) itemData) { + holidays.add(convertToMapDto(item)); + } + } else if (itemData instanceof Map) { + holidays.add(convertToMapDto((Map) itemData)); + } + } + } + + System.out.println("📌 최종 holidays: " + holidays); + return holidays; + } + + /** + * 🔹 공휴일 데이터를 MapDto로 변환 + */ + private MapDto convertToMapDto(Map item) { + MapDto dto = new MapDto(); + + // ✅ locdate를 안전하게 변환 (int, long, double 등 다양한 형태 대응) + String locdateStr = String.valueOf(item.get("locdate")); + if (locdateStr.contains(".")) { + locdateStr = locdateStr.split("\\.")[0]; // 소수점 제거 + } + + // ✅ YYYY-MM-DD 형식으로 변환 + if (locdateStr.length() == 8) { + String formattedDate = locdateStr.substring(0, 4) + "-" + locdateStr.substring(4, 6) + "-" + locdateStr.substring(6, 8); + dto.put("date", formattedDate); + } else { + dto.put("date", locdateStr); // 변환 불가능한 경우 원본 저장 + } + + dto.put("name", item.get("dateName")); + return dto; } - } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 5099504..117559d 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -52,6 +52,11 @@ management: server: max-uri-tags: 200 +api: + public-holiday: + key: "MugzCRZ7VmR/LJ3BZ1Ehmmg5yiI0GPFt4evLjNkNuwKoiWbKbe/M9U5pLjAxfSP13OOwHi943aMFM9yiI8OADA==" + + server: shutdown: graceful port: 10325 diff --git a/src/main/resources/mapper/localbordMapper.xml b/src/main/resources/mapper/localbordMapper.xml index ed00e27..d99cd63 100644 --- a/src/main/resources/mapper/localbordMapper.xml +++ b/src/main/resources/mapper/localbordMapper.xml @@ -129,7 +129,7 @@ LOCCMTSEQ,LOCBRDSEQ,LOCCMTPNT,LOCCMTRPY, LOCCMTUDT,LOCCMTPWD,LOCCMTRDT,LOCCMTPNT FROM localcomt - WHERE LOCBRDSEQ = #{boardId} + WHERE LOCBRDSEQ = #{LOCBRDSEQ} ORDER BY LOCCMTPNT ASC, LOCCMTUDT ASC @@ -187,14 +187,14 @@ diff --git a/src/main/resources/mapper/localvacaMapper.xml b/src/main/resources/mapper/localvacaMapper.xml index e4b4694..a6728d8 100644 --- a/src/main/resources/mapper/localvacaMapper.xml +++ b/src/main/resources/mapper/localvacaMapper.xml @@ -9,12 +9,10 @@ - + + \ No newline at end of file