게시판 백 수정

This commit is contained in:
dyhj625 2025-01-16 11:06:38 +09:00
parent 7fbb3a2a87
commit 5d91c2d46a
4 changed files with 303 additions and 66 deletions

View File

@ -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; package io.company.localhost.controller.api;
import java.math.BigInteger; import java.math.BigInteger;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.sql.Blob; import java.sql.Blob;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; 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.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; 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.annotation.ReqMap;
import io.company.localhost.common.dto.ApiResponse; import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto; import io.company.localhost.common.dto.MapDto;
@ -34,41 +53,77 @@ import lombok.extern.slf4j.Slf4j;
public class BoardController { public class BoardController {
private final LocalBordService boardService; private final LocalBordService boardService;
//공지사항 /**
* 공지사항 목록 조회
* @ReqMap map 요청 파라미터 (searchKeyword)
* @return 페이징된 공지사항 목록
*/
@GetMapping("/notices") @GetMapping("/notices")
public ApiResponse<List<MapDto>> getNotices() { public ApiResponse<List<MapDto>> getNotices(@ReqMap MapDto map) {
List<MapDto> posts = boardService.getNotices(); List<MapDto> posts = boardService.getNotices(map);
for (Map<String, Object> post : posts) {
// Blob 데이터를 처리 (문자열로 변환)
for (MapDto post : posts) {
Object content = post.get("content"); Object content = post.get("content");
if (content instanceof Blob) { if (content instanceof Blob) {
Blob blob = (Blob) content; Blob blob = (Blob) content;
try { post.put("content", safeBlobToString(blob));
post.put("content", new String(blob.getBytes(1, (int) blob.length()), StandardCharsets.UTF_8));
} catch (Exception e) {
post.put("content", ""); // 변환 실패 기본 설정
}
} }
} }
return ApiResponse.ok(posts); return ApiResponse.ok(posts);
} }
//비밀,자유게시판
/**
* 자유/익명 게시판 목록 조회
* @ReqMap map 요청 파라미터 (page, size, searchKeyword 포함)
* @return 페이징된 자유/익명 게시판 목록
*/
@GetMapping("/general") @GetMapping("/general")
public ApiResponse<List<MapDto>> getGeneralPosts() { public ApiResponse<PageInfo<MapDto>> getGeneralPosts(@ReqMap MapDto map) {
List<MapDto> posts = boardService.getGeneralPosts(); PageInfo<MapDto> posts = boardService.getGeneralPosts(map);
for (Map<String, Object> post : posts) {
// Blob 데이터를 처리 (문자열로 변환)
for (MapDto post : posts.getList()) {
Object content = post.get("content"); Object content = post.get("content");
if (content instanceof Blob) { if (content instanceof Blob) {
Blob blob = (Blob) content; Blob blob = (Blob) content;
try { post.put("content", safeBlobToString(blob));
post.put("content", new String(blob.getBytes(1, (int) blob.length()), StandardCharsets.UTF_8));
} catch (Exception e) {
post.put("content", ""); // 변환 실패 기본 설정
}
} }
} }
return ApiResponse.ok(posts); 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 @PostMapping
public ApiResponse<?> createBoard(@ReqMap MapDto map) { public ApiResponse<?> createBoard(@ReqMap MapDto map) {
BigInteger createdIdx = boardService.createBoard(map); // 작성된 게시물의 idx를 반환 BigInteger createdIdx = boardService.createBoard(map); // 작성된 게시물의 idx를 반환
@ -77,7 +132,19 @@ public class BoardController {
responseData.put("message", "게시물이 작성되었습니다."); responseData.put("message", "게시물이 작성되었습니다.");
return ApiResponse.ok(responseData); 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") @PostMapping("/{boardId}/attachments")
public ApiResponse<String> uploadAttachment( public ApiResponse<String> uploadAttachment(
@PathVariable("boardId") Long boardId, @PathVariable("boardId") Long boardId,
@ -107,7 +174,12 @@ public class BoardController {
return ApiResponse.ok("첨부파일이 저장되었습니다."); return ApiResponse.ok("첨부파일이 저장되었습니다.");
} }
// 게시물 상세보기
/**
* 게시물 상세보기
* @param boardId 게시물 ID
* @return 게시물 상세정보, 첨부파일 목록, 댓글 목록
*/
@GetMapping("/{boardId}") @GetMapping("/{boardId}")
public ApiResponse<MapDto> getBoardDetail(@PathVariable("boardId") Long boardId) { public ApiResponse<MapDto> getBoardDetail(@PathVariable("boardId") Long boardId) {
log.info("Fetching details for board ID: {}", boardId); log.info("Fetching details for board ID: {}", boardId);
@ -141,7 +213,12 @@ public class BoardController {
return ApiResponse.ok(result); return ApiResponse.ok(result);
} }
// 게시물 삭제
/**
* 게시물 삭제
* @param boardId 게시물 ID
* @return 삭제 결과 메시지
*/
@DeleteMapping("/{boardId}") @DeleteMapping("/{boardId}")
public ApiResponse<String> deleteBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) { public ApiResponse<String> deleteBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) {
map.put("LOCBRDSEQ", boardId); map.put("LOCBRDSEQ", boardId);
@ -149,62 +226,176 @@ public class BoardController {
boardService.deleteBoard(map); boardService.deleteBoard(map);
return ApiResponse.ok("게시물이 삭제되었습니다."); return ApiResponse.ok("게시물이 삭제되었습니다.");
} }
//게시물 수정
/**
* 게시물 수정
* @param boardId 게시물 ID
* @ReqMap map 수정 데이터 (제목, 내용 )
* @return 수정 결과 메시지
*/
@PutMapping("/{boardId}") @PutMapping("/{boardId}")
public ApiResponse<String> updateBoard(@PathVariable("boardId") Long boardId,@ReqMap MapDto map) { public ApiResponse<String> updateBoard(@PathVariable("boardId") Long boardId,@ReqMap MapDto map) {
map.put("LOCBRDSEQ", boardId); map.put("LOCBRDSEQ", boardId);
boardService.updateBoard(map); boardService.updateBoard(map);
return ApiResponse.ok("게시물이 수정되었습니다."); return ApiResponse.ok("게시물이 수정되었습니다.");
} }
//게시물과 댓글에 좋아요/싫어요 추가
/**
* 게시물 좋아요/싫어요 추가
* @param boardId 게시물 ID
* @ReqMap map 좋아요/싫어요 데이터
* @return 반응 추가 결과 메시지
*/
@PostMapping("/{boardId}/reaction") @PostMapping("/{boardId}/reaction")
public ApiResponse<String> reactToBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) { public ApiResponse<String> reactToBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) {
map.put("LOCBRDSEQ", boardId); map.put("LOCBRDSEQ", boardId);
boardService.reactToBoard(map); boardService.reactToBoard(map);
return ApiResponse.ok("반응이 추가되었습니다."); return ApiResponse.ok("반응이 추가되었습니다.");
} }
//댓글/대댓글 조회
/**
* 댓글/대댓글 조회
* @param boardId 게시물 ID
* @return 댓글과 대댓글의 계층 구조 데이터
*/
@GetMapping("/{boardId}/comments") @GetMapping("/{boardId}/comments")
public ApiResponse<List<MapDto>> getComments(@PathVariable("boardId") int boardId) { public ApiResponse<List<Map<String, Object>>> getComments(@PathVariable("boardId") int boardId) {
return ApiResponse.ok(boardService.getComments(boardId)); // 모든 댓글과 대댓글 조회
List<MapDto> comments = boardService.getComments(boardId);
// 댓글과 대댓글을 계층 구조로 정렬
Map<Integer, Map<String, Object>> commentMap = new HashMap<>();
for (MapDto comment : comments) {
int commentId = (int) comment.get("LOCCMTSEQ");
Integer parentId = (Integer) comment.get("LOCCMTRPY");
Map<String, Object> commentData = new HashMap<>(comment);
commentData.put("replies", new ArrayList<>()); // 대댓글 리스트 초기화
if (parentId == null) {
// 댓글인 경우
commentMap.put(commentId, commentData);
} else {
// 대댓글인 경우, 부모 댓글의 "replies" 추가
Map<String, Object> parentComment = commentMap.get(parentId);
if (parentComment != null) {
List<Map<String, Object>> replies = (List<Map<String, Object>>) parentComment.get("replies");
replies.add(commentData);
} }
//댓글/대댓글 작성 }
}
// 최상위 댓글 리스트 반환
List<Map<String, Object>> result = new ArrayList<>(commentMap.values());
return ApiResponse.ok(result);
}
/**
* 댓글/대댓글 작성
* @param boardId 게시물 ID
* @ReqMap map 댓글 데이터 (내용, 부모 ID )
* @return 작성 결과 메시지
*/
@PostMapping("/{boardId}/comment") @PostMapping("/{boardId}/comment")
public ApiResponse<String> addCommentOrReply(@PathVariable("boardId") int boardId, @ReqMap MapDto map) { public ApiResponse<String> 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); boardService.addCommentOrReply(map);
return ApiResponse.ok("댓글 또는 대댓글이 작성되었습니다."); return ApiResponse.ok("댓글 또는 대댓글이 작성되었습니다.");
} }
//댓글/대댓글 수정
/**
* 댓글/대댓글 수정
* @param commentId 댓글 ID
* @ReqMap map 수정 데이터 (내용, 비밀번호 )
* @return 수정 결과 메시지
*/
@PutMapping("/comment/{commentId}") @PutMapping("/comment/{commentId}")
public ApiResponse<String> updateComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { public ApiResponse<String> updateComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) {
// 기존 댓글 조회
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); map.put("LOCCMTSEQ", commentId);
boardService.updateComment(map); boardService.updateComment(map);
return ApiResponse.ok("댓글이 수정되었습니다."); return ApiResponse.ok("댓글이 수정되었습니다.");
} }
//댓글/대댓글 삭제
/**
* 댓글/대댓글 삭제
* @param commentId 댓글 ID
* @ReqMap map 요청 데이터 (비밀번호 )
* @return 삭제 결과 메시지
*/
@DeleteMapping("/comment/{commentId}") @DeleteMapping("/comment/{commentId}")
public ApiResponse<String> deleteComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { public ApiResponse<String> deleteComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) {
map.put("LOCCMTSEQ", commentId); map.put("LOCCMTSEQ", commentId);
boardService.deleteComment(map); boardService.deleteComment(map);
return ApiResponse.ok("댓글이 삭제되었습니다."); return ApiResponse.ok("댓글이 삭제되었습니다.");
} }
//비밀번호 확인 (게시물)
/**
* 댓글 비밀번호 확인
* @param commentId 댓글 ID
* @ReqMap map 비밀번호 데이터
* @return 비밀번호 확인 결과
*/
@PostMapping("/comment/{commentId}/password") @PostMapping("/comment/{commentId}/password")
public ApiResponse<Boolean> checkCommentPassword(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { public ApiResponse<Boolean> checkCommentPassword(@PathVariable("commentId") int commentId, @ReqMap MapDto map) {
map.put("LOCCMTSEQ", commentId); map.put("LOCCMTSEQ", commentId);
return ApiResponse.ok(boardService.checkCommentPassword(map)); return ApiResponse.ok(boardService.checkCommentPassword(map));
} }
//비밀번호 확인 (댓글)
/**
* 게시물 비밀번호 확인
* @param boardId 게시물 ID
* @ReqMap map 비밀번호 데이터
* @return 비밀번호 확인 결과
*/
@PostMapping("/{boardId}/password") @PostMapping("/{boardId}/password")
public ApiResponse<Boolean> checkBoardPassword(@PathVariable("boardId") int boardId, @ReqMap MapDto map) { public ApiResponse<Boolean> checkBoardPassword(@PathVariable("boardId") int boardId, @ReqMap MapDto map) {
map.put("LOCBRDSEQ", boardId); map.put("LOCBRDSEQ", boardId);
return ApiResponse.ok(boardService.checkBoardPassword(map)); return ApiResponse.ok(boardService.checkBoardPassword(map));
} }
// 비밀게시판 여부 확인
/**
* 비밀게시판 여부 확인
* @param boardId 게시물 ID
* @return 비밀게시판 여부
*/
@GetMapping("/{boardId}/isSecret") @GetMapping("/{boardId}/isSecret")
public ApiResponse<Boolean> isSecretBoard(@PathVariable("boardId") Long boardId) { public ApiResponse<Boolean> isSecretBoard(@PathVariable("boardId") Long boardId) {
log.info("Checking if board ID {} is secret", boardId); log.info("Checking if board ID {} is secret", boardId);
return ApiResponse.ok(boardService.isSecretBoard(boardId)); return ApiResponse.ok(boardService.isSecretBoard(boardId));
} }
/**
* 댓글 좋아요/싫어요 추가
* @param commentId 댓글 ID
* @ReqMap map 좋아요/싫어요 데이터
* @return 반응 추가 결과 메시지
*/
@PostMapping("/comment/{commentId}/reaction")
public ApiResponse<String> reactToComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) {
map.put("LOCCMTSEQ", commentId);
boardService.reactToComment(map);
return ApiResponse.ok("Comment reaction added.");
}
} }

View File

@ -11,10 +11,10 @@ import io.company.localhost.common.dto.MapDto;
@Mapper @Mapper
public interface LocalBordMapper { public interface LocalBordMapper {
// 공지사항 조회 // 공지사항 조회
List<MapDto> getNotices(); List<MapDto> getNotices(MapDto map);
// 자유/비밀 게시판 조회 // 자유/비밀 게시판 조회
List<MapDto> getGeneralPosts(); List<MapDto> getGeneralPosts(MapDto map);
// 게시물 작성 // 게시물 작성
void createBoard(MapDto map); void createBoard(MapDto map);
@ -57,5 +57,11 @@ public interface LocalBordMapper {
// 첨부파일 가져오기 // 첨부파일 가져오기
List<MapDto> selectAttachments(Long boardId); List<MapDto> selectAttachments(Long boardId);
//댓글 좋아요/싫어요추가
void reactToComment(MapDto map);
//댓글id 확인
MapDto getCommentById(int commentId);
} }

View File

@ -6,8 +6,12 @@ import java.util.Map;
import org.springframework.stereotype.Service; 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.common.dto.MapDto;
import io.company.localhost.mapper.LocalBordMapper; import io.company.localhost.mapper.LocalBordMapper;
import io.company.localhost.utils.PageUtil;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@Service @Service
@ -15,12 +19,15 @@ import lombok.RequiredArgsConstructor;
public class LocalBordService { public class LocalBordService {
private final LocalBordMapper boardMapper; private final LocalBordMapper boardMapper;
public List<MapDto> getNotices() { public List<MapDto> getNotices(MapDto map) {
return boardMapper.getNotices(); return boardMapper.getNotices(map);
} }
public List<MapDto> getGeneralPosts() { public PageInfo<MapDto> getGeneralPosts(MapDto map) {
return boardMapper.getGeneralPosts(); 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) { public BigInteger createBoard(MapDto map) {
@ -61,6 +68,7 @@ public class LocalBordService {
boardMapper.addCommentOrReply(map); boardMapper.addCommentOrReply(map);
} }
public void updateComment(MapDto map) { public void updateComment(MapDto map) {
boardMapper.updateComment(map); boardMapper.updateComment(map);
} }
@ -82,6 +90,15 @@ public class LocalBordService {
return boardMapper.isSecretBoard(boardId); return boardMapper.isSecretBoard(boardId);
} }
public void reactToComment(MapDto map) {
boardMapper.reactToComment(map);
}
public MapDto getCommentById(int commentId) {
return boardMapper.getCommentById(commentId);
}
} }

View File

@ -3,18 +3,21 @@
<mapper namespace="io.company.localhost.mapper.LocalBordMapper"> <mapper namespace="io.company.localhost.mapper.LocalBordMapper">
<!-- 공지사항 조회 --> <!-- 공지사항 조회 -->
<select id="getNotices" resultType="hashmap"> <select id="getNotices" resultType="io.company.localhost.common.dto.MapDto">
SELECT SELECT
LOCBRDSEQ AS id, LOCBRDSEQ AS id,
LOCBRDTTL AS title, LOCBRDTTL AS title,
LOCBRDCON AS content, LOCBRDCON AS content,
LOCBRDRDT AS date LOCBRDRDT AS date
FROM localbord FROM localbord
WHERE b.LOCBRDTYP = 'N' WHERE LOCBRDTYP = 'N'
ORDER BY b.LOCBRDRDT DESC <if test="searchKeyword != null and searchKeyword != ''">
AND LOCBRDTTL LIKE CONCAT('%', #{searchKeyword}, '%')
</if>
ORDER BY LOCBRDRDT DESC
</select> </select>
<!-- 자유/비밀 게시판 조회 --> <!-- 자유/익명 게시판 조회 -->
<select id="getGeneralPosts" resultType="io.company.localhost.common.dto.MapDto"> <select id="getGeneralPosts" resultType="io.company.localhost.common.dto.MapDto">
SELECT SELECT
LOCBRDSEQ AS id, LOCBRDSEQ AS id,
@ -23,9 +26,13 @@
LOCBRDRDT AS date LOCBRDRDT AS date
FROM localbord FROM localbord
WHERE LOCBRDTYP IN ('F', 'S') WHERE LOCBRDTYP IN ('F', 'S')
<if test="searchKeyword != null and searchKeyword != ''">
AND LOCBRDTTL LIKE CONCAT('%', #{searchKeyword}, '%')
</if>
ORDER BY LOCBRDRDT DESC ORDER BY LOCBRDRDT DESC
</select> </select>
<!-- 게시물 작성 --> <!-- 게시물 작성 -->
<insert id="createBoard" parameterType="map" useGeneratedKeys="true" keyProperty="LOCBRDSEQ"> <insert id="createBoard" parameterType="map" useGeneratedKeys="true" keyProperty="LOCBRDSEQ">
INSERT INTO localbord (LOCBRDTTL, LOCBRDCON, LOCBRDCAT, MEMBERSEQ, LOCBRDCNT, LOCBRDRDT, LOCBRDUDT, LOCBRDPWD, LOCBRDTYP) INSERT INTO localbord (LOCBRDTTL, LOCBRDCON, LOCBRDCAT, MEMBERSEQ, LOCBRDCNT, LOCBRDRDT, LOCBRDUDT, LOCBRDPWD, LOCBRDTYP)
@ -83,10 +90,12 @@
</insert> </insert>
<!-- 댓글/대댓글 조회 --> <!-- 댓글/대댓글 조회 -->
<select id="getComments" resultType="java.util.Map"> <select id="getComments" resultType="io.company.localhost.common.dto.MapDto">
SELECT LOCCMTSEQ, LOCBRDSEQ, LOCCMTRPY, LOCCMTPWD, LOCCMTRDT, LOCCMTPNT SELECT
LOCCMTSEQ,LOCBRDSEQ,LOCCMTPNT,LOCCMTRPY,
LOCCMTUDT,LOCCMTPWD,LOCCMTRDT,LOCCMTPNT
FROM localcomt FROM localcomt
WHERE LOCBRDSEQ = #{LOCBRDSEQ} WHERE LOCBRDSEQ = #{boardId}
ORDER BY LOCCMTPNT ASC, LOCCMTRDT ASC ORDER BY LOCCMTPNT ASC, LOCCMTRDT ASC
</select> </select>
@ -126,5 +135,19 @@
WHERE LOCBRDSEQ = #{LOCBRDSEQ} WHERE LOCBRDSEQ = #{LOCBRDSEQ}
</select> </select>
<!-- 댓글 좋아요/싫어요 추가 -->
<insert id="reactToComment">
INSERT INTO localcomt (LOCCMTSEQ, MEMBERSEQ, LOCGORGOD, LOCGORBAD)
VALUES (#{LOCCMTSEQ}, #{MEMBERSEQ}, #{LOCGORGOD}, #{LOCGORBAD})
ON DUPLICATE KEY UPDATE LOCGORGOD = #{LOCGORGOD}, LOCGORBAD = #{LOCGORBAD}
</insert>
<!-- 댓글 id확인 -->
<select id="getCommentById" resultType="io.company.localhost.common.dto.MapDto">
SELECT LOCCMTSEQ AS id, LOCCMTPNT AS point
FROM localcomt
WHERE LOCCMTSEQ = #{commentId}
</select>
</mapper> </mapper>