From 5d91c2d46a096d9949fe8988d598b328fc822b25 Mon Sep 17 00:00:00 2001 From: dyhj625 Date: Thu, 16 Jan 2025 11:06:38 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B2=8C=EC=8B=9C=ED=8C=90=20=EB=B0=B1=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/api/BoardController.java | 263 +++++++++++++++--- .../localhost/mapper/LocalBordMapper.java | 10 +- .../localhost/service/LocalBordService.java | 25 +- src/main/resources/mapper/LocalBordMapper.xml | 71 +++-- 4 files changed, 303 insertions(+), 66 deletions(-) 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 a09e794..32dfcfa 100644 --- a/src/main/java/io/company/localhost/controller/api/BoardController.java +++ b/src/main/java/io/company/localhost/controller/api/BoardController.java @@ -1,8 +1,24 @@ +/************************************************************ + * + * @packageName : io.company.localhost.controller.api + * @fileName : BoardController.java + * @author : 서지희 + * @date : 25.01.07 + * @description : 게시판 + * + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 24.01.02 서지희 최초 생성 + * + *************************************************************/ + package io.company.localhost.controller.api; import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.sql.Blob; +import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -20,6 +36,9 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; +import com.github.pagehelper.PageInfo; +import com.github.pagehelper.PageSerializable; + import io.company.localhost.common.annotation.ReqMap; import io.company.localhost.common.dto.ApiResponse; import io.company.localhost.common.dto.MapDto; @@ -34,41 +53,77 @@ import lombok.extern.slf4j.Slf4j; public class BoardController { private final LocalBordService boardService; - //공지사항 + /** + * 공지사항 목록 조회 + * @ReqMap map 요청 파라미터 (searchKeyword) + * @return 페이징된 공지사항 목록 + */ @GetMapping("/notices") - public ApiResponse> getNotices() { - List posts = boardService.getNotices(); - for (Map post : posts) { + public ApiResponse> getNotices(@ReqMap MapDto map) { + List posts = boardService.getNotices(map); + + // Blob 데이터를 처리 (문자열로 변환) + for (MapDto post : posts) { Object content = post.get("content"); if (content instanceof Blob) { Blob blob = (Blob) content; - try { - post.put("content", new String(blob.getBytes(1, (int) blob.length()), StandardCharsets.UTF_8)); - } catch (Exception e) { - post.put("content", ""); // 변환 실패 시 기본 값 설정 - } + post.put("content", safeBlobToString(blob)); } } + return ApiResponse.ok(posts); } - //비밀,자유게시판 + + /** + * 자유/익명 게시판 목록 조회 + * @ReqMap map 요청 파라미터 (page, size, searchKeyword 포함) + * @return 페이징된 자유/익명 게시판 목록 + */ @GetMapping("/general") - public ApiResponse> getGeneralPosts() { - List posts = boardService.getGeneralPosts(); - for (Map post : posts) { + public ApiResponse> getGeneralPosts(@ReqMap MapDto map) { + PageInfo posts = boardService.getGeneralPosts(map); + + // Blob 데이터를 처리 (문자열로 변환) + for (MapDto post : posts.getList()) { Object content = post.get("content"); if (content instanceof Blob) { Blob blob = (Blob) content; - try { - post.put("content", new String(blob.getBytes(1, (int) blob.length()), StandardCharsets.UTF_8)); - } catch (Exception e) { - post.put("content", ""); // 변환 실패 시 기본 값 설정 - } + post.put("content", safeBlobToString(blob)); } } + return ApiResponse.ok(posts); } - //게시물 작성 + + /** + * 안전하게 Blob 데이터를 문자열로 변환하는 메서드 + * @ReqMap + * @return 변환된 문자열 또는 null + */ + private String safeBlobToString(Blob blob) { + if (blob == null) { + return null; // Blob이 null이면 null 반환 + } + + try { + long blobLength = blob.length(); + if (blobLength > Integer.MAX_VALUE) { + throw new IllegalArgumentException("Blob is too large to process."); + } + + return new String(blob.getBytes(1, (int) blobLength), StandardCharsets.UTF_8); + } catch (Exception e) { + System.err.println("Failed to convert Blob to String: " + e.getMessage()); + e.printStackTrace(); + return null; // 변환 실패 시 null 반환 + } + } + + /** + * 게시물 작성 + * @ReqMap map 요청 파라미터 (page, size, searchKeyword 포함) + * @return 작성된 게시물의 ID + */ @PostMapping public ApiResponse createBoard(@ReqMap MapDto map) { BigInteger createdIdx = boardService.createBoard(map); // 작성된 게시물의 idx를 반환 @@ -77,7 +132,19 @@ public class BoardController { responseData.put("message", "게시물이 작성되었습니다."); return ApiResponse.ok(responseData); } - // 첨부파일 추가 + + /** + * 첨부파일 추가 + * @param boardId 게시물 ID + * @param file 업로드된 파일 + * @param filePath 파일 저장 경로 + * @param originalFileName 원본 파일명 + * @param fileExtension 파일 확장자 + * @param fileSize 파일 크기 + * @param registrantId 등록자 ID + * @param fileName 저장될 파일명 + * @return 첨부파일 저장 결과 메시지 + */ @PostMapping("/{boardId}/attachments") public ApiResponse uploadAttachment( @PathVariable("boardId") Long boardId, @@ -107,7 +174,12 @@ public class BoardController { return ApiResponse.ok("첨부파일이 저장되었습니다."); } - // 게시물 상세보기 + + /** + * 게시물 상세보기 + * @param boardId 게시물 ID + * @return 게시물 상세정보, 첨부파일 목록, 댓글 목록 + */ @GetMapping("/{boardId}") public ApiResponse getBoardDetail(@PathVariable("boardId") Long boardId) { log.info("Fetching details for board ID: {}", boardId); @@ -141,7 +213,12 @@ public class BoardController { return ApiResponse.ok(result); } - // 게시물 삭제 + + /** + * 게시물 삭제 + * @param boardId 게시물 ID + * @return 삭제 결과 메시지 + */ @DeleteMapping("/{boardId}") public ApiResponse deleteBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) { map.put("LOCBRDSEQ", boardId); @@ -149,62 +226,176 @@ public class BoardController { boardService.deleteBoard(map); return ApiResponse.ok("게시물이 삭제되었습니다."); } - //게시물 수정 + + /** + * 게시물 수정 + * @param boardId 게시물 ID + * @ReqMap map 수정 데이터 (제목, 내용 등) + * @return 수정 결과 메시지 + */ @PutMapping("/{boardId}") public ApiResponse updateBoard(@PathVariable("boardId") Long boardId,@ReqMap MapDto map) { map.put("LOCBRDSEQ", boardId); boardService.updateBoard(map); return ApiResponse.ok("게시물이 수정되었습니다."); } - //게시물과 댓글에 좋아요/싫어요 추가 + + /** + * 게시물 좋아요/싫어요 추가 + * @param boardId 게시물 ID + * @ReqMap map 좋아요/싫어요 데이터 + * @return 반응 추가 결과 메시지 + */ @PostMapping("/{boardId}/reaction") public ApiResponse reactToBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) { map.put("LOCBRDSEQ", boardId); boardService.reactToBoard(map); return ApiResponse.ok("반응이 추가되었습니다."); } - //댓글/대댓글 조회 + + /** + * 댓글/대댓글 조회 + * @param boardId 게시물 ID + * @return 댓글과 대댓글의 계층 구조 데이터 + */ @GetMapping("/{boardId}/comments") - public ApiResponse> getComments(@PathVariable("boardId") int boardId) { - return ApiResponse.ok(boardService.getComments(boardId)); + public ApiResponse>> getComments(@PathVariable("boardId") int boardId) { + // 모든 댓글과 대댓글 조회 + List comments = boardService.getComments(boardId); + + // 댓글과 대댓글을 계층 구조로 정렬 + Map> commentMap = new HashMap<>(); + for (MapDto comment : comments) { + int commentId = (int) comment.get("LOCCMTSEQ"); + Integer parentId = (Integer) comment.get("LOCCMTRPY"); + + Map commentData = new HashMap<>(comment); + commentData.put("replies", new ArrayList<>()); // 대댓글 리스트 초기화 + + if (parentId == null) { + // 댓글인 경우 + commentMap.put(commentId, commentData); + } else { + // 대댓글인 경우, 부모 댓글의 "replies"에 추가 + Map parentComment = commentMap.get(parentId); + if (parentComment != null) { + List> replies = (List>) parentComment.get("replies"); + replies.add(commentData); + } + } + } + + // 최상위 댓글 리스트 반환 + List> result = new ArrayList<>(commentMap.values()); + return ApiResponse.ok(result); } - //댓글/대댓글 작성 + + /** + * 댓글/대댓글 작성 + * @param boardId 게시물 ID + * @ReqMap map 댓글 데이터 (내용, 부모 ID 등) + * @return 작성 결과 메시지 + */ @PostMapping("/{boardId}/comment") public ApiResponse addCommentOrReply(@PathVariable("boardId") int boardId, @ReqMap MapDto map) { - map.put("LOCBRDSEQ", boardId); + map.put("LOCBRDSEQ", boardId); + + // 부모 댓글 확인 + Integer parentCommentId = (Integer) map.get("LOCCMTRPY"); + if (parentCommentId != null) { + MapDto parentComment = boardService.getCommentById(parentCommentId); + if (parentComment == null) { + throw new IllegalArgumentException("Invalid parent comment ID: " + parentCommentId); + } + } + boardService.addCommentOrReply(map); return ApiResponse.ok("댓글 또는 대댓글이 작성되었습니다."); } - //댓글/대댓글 수정 + + /** + * 댓글/대댓글 수정 + * @param commentId 댓글 ID + * @ReqMap map 수정 데이터 (내용, 비밀번호 등) + * @return 수정 결과 메시지 + */ @PutMapping("/comment/{commentId}") public ApiResponse updateComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { - map.put("LOCCMTSEQ", commentId); + // 기존 댓글 조회 + MapDto existingComment = boardService.getCommentById(commentId); + if (existingComment == null) { + throw new IllegalArgumentException("Comment not found for ID: " + commentId); + } + + // 부모 댓글 ID는 수정 불가 + map.remove("LOCCMTRPY"); + + map.put("LOCCMTSEQ", commentId); boardService.updateComment(map); + return ApiResponse.ok("댓글이 수정되었습니다."); } - //댓글/대댓글 삭제 + + /** + * 댓글/대댓글 삭제 + * @param commentId 댓글 ID + * @ReqMap map 요청 데이터 (비밀번호 등) + * @return 삭제 결과 메시지 + */ @DeleteMapping("/comment/{commentId}") public ApiResponse deleteComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { - map.put("LOCCMTSEQ", commentId); + map.put("LOCCMTSEQ", commentId); boardService.deleteComment(map); + return ApiResponse.ok("댓글이 삭제되었습니다."); } - //비밀번호 확인 (게시물) + + /** + * 댓글 비밀번호 확인 + * @param commentId 댓글 ID + * @ReqMap map 비밀번호 데이터 + * @return 비밀번호 확인 결과 + */ @PostMapping("/comment/{commentId}/password") public ApiResponse checkCommentPassword(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { map.put("LOCCMTSEQ", commentId); return ApiResponse.ok(boardService.checkCommentPassword(map)); } - //비밀번호 확인 (댓글) + + /** + * 게시물 비밀번호 확인 + * @param boardId 게시물 ID + * @ReqMap map 비밀번호 데이터 + * @return 비밀번호 확인 결과 + */ @PostMapping("/{boardId}/password") public ApiResponse checkBoardPassword(@PathVariable("boardId") int boardId, @ReqMap MapDto map) { map.put("LOCBRDSEQ", boardId); return ApiResponse.ok(boardService.checkBoardPassword(map)); } - // 비밀게시판 여부 확인 + + /** + * 비밀게시판 여부 확인 + * @param boardId 게시물 ID + * @return 비밀게시판 여부 + */ @GetMapping("/{boardId}/isSecret") public ApiResponse isSecretBoard(@PathVariable("boardId") Long boardId) { log.info("Checking if board ID {} is secret", boardId); return ApiResponse.ok(boardService.isSecretBoard(boardId)); } + + /** + * 댓글 좋아요/싫어요 추가 + * @param commentId 댓글 ID + * @ReqMap map 좋아요/싫어요 데이터 + * @return 반응 추가 결과 메시지 + */ + @PostMapping("/comment/{commentId}/reaction") + public ApiResponse reactToComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { + map.put("LOCCMTSEQ", commentId); + boardService.reactToComment(map); + return ApiResponse.ok("Comment reaction added."); + } + } diff --git a/src/main/java/io/company/localhost/mapper/LocalBordMapper.java b/src/main/java/io/company/localhost/mapper/LocalBordMapper.java index b0943f3..347ec07 100644 --- a/src/main/java/io/company/localhost/mapper/LocalBordMapper.java +++ b/src/main/java/io/company/localhost/mapper/LocalBordMapper.java @@ -11,10 +11,10 @@ import io.company.localhost.common.dto.MapDto; @Mapper public interface LocalBordMapper { // 공지사항 조회 - List getNotices(); + List getNotices(MapDto map); // 자유/비밀 게시판 조회 - List getGeneralPosts(); + List getGeneralPosts(MapDto map); // 게시물 작성 void createBoard(MapDto map); @@ -57,5 +57,11 @@ public interface LocalBordMapper { // 첨부파일 가져오기 List selectAttachments(Long boardId); + + //댓글 좋아요/싫어요추가 + void reactToComment(MapDto map); + + //댓글id 확인 + MapDto getCommentById(int commentId); } diff --git a/src/main/java/io/company/localhost/service/LocalBordService.java b/src/main/java/io/company/localhost/service/LocalBordService.java index 2aca545..330555e 100644 --- a/src/main/java/io/company/localhost/service/LocalBordService.java +++ b/src/main/java/io/company/localhost/service/LocalBordService.java @@ -6,8 +6,12 @@ import java.util.Map; import org.springframework.stereotype.Service; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; + import io.company.localhost.common.dto.MapDto; import io.company.localhost.mapper.LocalBordMapper; +import io.company.localhost.utils.PageUtil; import lombok.RequiredArgsConstructor; @Service @@ -15,12 +19,15 @@ import lombok.RequiredArgsConstructor; public class LocalBordService { private final LocalBordMapper boardMapper; - public List getNotices() { - return boardMapper.getNotices(); + public List getNotices(MapDto map) { + return boardMapper.getNotices(map); } - public List getGeneralPosts() { - return boardMapper.getGeneralPosts(); + public PageInfo getGeneralPosts(MapDto map) { + int page = map.getString("page") != null ? Integer.parseInt(map.getString("page")) : 1; + int size = map.getString("size") != null ? Integer.parseInt(map.getString("size")) : 10; + PageHelper.startPage(page, size); + return PageUtil.redefineNavigation(new PageInfo<>(boardMapper.getGeneralPosts(map), size)); } public BigInteger createBoard(MapDto map) { @@ -61,6 +68,7 @@ public class LocalBordService { boardMapper.addCommentOrReply(map); } + public void updateComment(MapDto map) { boardMapper.updateComment(map); } @@ -81,6 +89,15 @@ public class LocalBordService { public boolean isSecretBoard(Long boardId) { return boardMapper.isSecretBoard(boardId); } + + public void reactToComment(MapDto map) { + boardMapper.reactToComment(map); + } + + public MapDto getCommentById(int commentId) { + return boardMapper.getCommentById(commentId); + } + } diff --git a/src/main/resources/mapper/LocalBordMapper.xml b/src/main/resources/mapper/LocalBordMapper.xml index 4d4a0c4..c471d50 100644 --- a/src/main/resources/mapper/LocalBordMapper.xml +++ b/src/main/resources/mapper/LocalBordMapper.xml @@ -3,29 +3,36 @@ - - - - + SELECT LOCBRDSEQ AS id, LOCBRDTTL AS title, LOCBRDCON AS content, LOCBRDRDT AS date FROM localbord - WHERE LOCBRDTYP IN ('F', 'S') - ORDER BY LOCBRDRDT DESC + WHERE LOCBRDTYP = 'N' + + AND LOCBRDTTL LIKE CONCAT('%', #{searchKeyword}, '%') + + ORDER BY LOCBRDRDT DESC + + + + + INSERT INTO localbord (LOCBRDTTL, LOCBRDCON, LOCBRDCAT, MEMBERSEQ, LOCBRDCNT, LOCBRDRDT, LOCBRDUDT, LOCBRDPWD, LOCBRDTYP) @@ -83,12 +90,14 @@ - + @@ -125,6 +134,20 @@ FROM localbord WHERE LOCBRDSEQ = #{LOCBRDSEQ} - - + + + + INSERT INTO localcomt (LOCCMTSEQ, MEMBERSEQ, LOCGORGOD, LOCGORBAD) + VALUES (#{LOCCMTSEQ}, #{MEMBERSEQ}, #{LOCGORGOD}, #{LOCGORBAD}) + ON DUPLICATE KEY UPDATE LOCGORGOD = #{LOCGORGOD}, LOCGORBAD = #{LOCGORBAD} + + + + + +