: 매일 저녁, 하루를 마무리하며 작성 !
: ⭕ 지식 위주, 학습한 것을 노트 정리한다고 생각하고 작성하면서 머리 속 흩어져있는 지식들을 정리 !
class Solution {
public String solution(String s, int n) {
String answer = "";
for(int i=0; i<s.length(); i++) {
char ch = s.charAt(i);
if(Character.isLowerCase(ch)) {
ch = (char) ((ch - 'a' + n) % 26 + 'a');
} else if(Character.isUpperCase(ch)) {
ch = (char) ((ch - 'A' + n) % 26 + 'A');
}
answer += ch;
}
return answer;
}
}
뉴스 피드 프로젝트 Post CRUD 구현
// PostController
package com.sparta.wildcard_newsfeed.domain.post.controller;
import com.sparta.wildcard_newsfeed.domain.comment.dto.CommentResponseDto;
import com.sparta.wildcard_newsfeed.domain.comment.dto.PostWithCommentsResponseDto;
import com.sparta.wildcard_newsfeed.domain.comment.service.CommentService;
import com.sparta.wildcard_newsfeed.domain.common.CommonResponseDto;
import com.sparta.wildcard_newsfeed.domain.post.dto.PostRequestDto;
import com.sparta.wildcard_newsfeed.domain.post.dto.PostResponseDto;
import com.sparta.wildcard_newsfeed.domain.post.service.PostService;
import com.sparta.wildcard_newsfeed.security.AuthenticationUser;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/post")
@Tag(name = "Post 컨트롤러", description = "Post API")
public class PostController {
private final PostService postService;
private final CommentService commentService;
// 게시물 등록
@PostMapping
@Operation(summary = "게시물 등록")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "게시물 등록 성공",
content = @Content(mediaType = "application/json",
schema = @Schema(implementation = CommonResponseDto.class)))
})
public ResponseEntity<CommonResponseDto<PostResponseDto>> addPost(
@AuthenticationPrincipal AuthenticationUser user,
@Valid @RequestBody PostRequestDto postRequestDto
) {
PostResponseDto postResponseDto = postService.addPost(postRequestDto, user);
return ResponseEntity.ok()
.body(CommonResponseDto.<PostResponseDto>builder()
.statusCode(HttpStatus.OK.value())
.message("게시물 등록 성공")
.data(postResponseDto)
.build());
}
// 게시물 전체 조회
@GetMapping
@Operation(summary = "게시물 전체 조회")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "게시물 전체 조회 성공",
content = @Content(mediaType = "application/json",
schema = @Schema(implementation = CommonResponseDto.class)))
})
public ResponseEntity<CommonResponseDto<Object>> findAll() {
List<PostResponseDto> posts = postService.findAll();
return ResponseEntity.ok()
.body(CommonResponseDto.builder()
.statusCode(HttpStatus.OK.value())
.message("게시물 전체 조회 성공")
.data(posts)
.build());
}
// // 게시물 단일 조회 + 해당 게시물에 달린 댓글 전체 조회
@GetMapping("/{postId}")
@Operation(summary = "게시물 단일 조회")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "게시물 단일 조회 성공",
content = @Content(mediaType = "application/json",
schema = @Schema(implementation = CommonResponseDto.class)))
})
public ResponseEntity<CommonResponseDto<PostWithCommentsResponseDto>> findById(@PathVariable(name = "postId") long id) {
// 게시물 단일 조회
PostResponseDto post = postService.findById(id);
// 해당 게시물에 달린 댓글 전체 조회
List<CommentResponseDto> comments = commentService.findAllCommentsByPostId(id);
// Post와 Comments를 하나의 객체로 병합
PostWithCommentsResponseDto postWithCommentsResponse = new PostWithCommentsResponseDto(post, comments);
return ResponseEntity.ok()
.body(CommonResponseDto.<PostWithCommentsResponseDto>builder()
.statusCode(HttpStatus.OK.value())
.message("게시물 단일 조회, 댓글 조회 성공")
.data(postWithCommentsResponse)
.build());
}
//게시물 수정
@PutMapping("/{postId}")
@Operation(summary = "게시물 수정")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "게시물 수정 성공",
content = @Content(mediaType = "application/json",
schema = @Schema(implementation = CommonResponseDto.class)))
})
public ResponseEntity<CommonResponseDto<PostResponseDto>> updatePost(
@AuthenticationPrincipal AuthenticationUser user,
@Valid @RequestBody PostRequestDto postRequestDto,
@PathVariable Long postId
) {
PostResponseDto postResponseDto = postService.updatePost(postRequestDto, postId, user);
return ResponseEntity.ok()
.body(CommonResponseDto.<PostResponseDto>builder()
.statusCode(HttpStatus.OK.value())
.message("게시물 수정 성공")
.data(postResponseDto)
.build());
}
//게시물 삭제
@DeleteMapping("/{postId}")
@Operation(summary = "게시물 삭제")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "게시물 삭제 성공",
content = @Content(mediaType = "application/json",
schema = @Schema(implementation = CommonResponseDto.class)))
})
public ResponseEntity<CommonResponseDto<PostResponseDto>> deletePost(
@AuthenticationPrincipal AuthenticationUser user,
@Valid @PathVariable Long postId
) {
postService.deletePost(postId, user);
return ResponseEntity.ok()
.body(CommonResponseDto.<PostResponseDto>builder()
.statusCode(HttpStatus.OK.value())
.message("게시물 삭제 성공")
.build());
}
}
// PostRequestDto
package com.sparta.wildcard_newsfeed.domain.post.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class PostRequestDto {
@Schema(description = "게시물 제목", example = "제목")
@NotBlank(message = "제목은 필수 입력 값입니다.")
private String title;
@Schema(description = "게시물 내용", example = "내용")
@NotBlank(message = "내용은 필수 입력 값입니다.")
private String content;
}
// PostResponseDto
package com.sparta.wildcard_newsfeed.domain.post.dto;
import com.sparta.wildcard_newsfeed.domain.post.entity.Post;
import lombok.Getter;
import java.time.LocalDateTime;
@Getter
public class PostResponseDto {
private Long id;
private String title;
private String content;
private String username;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
public PostResponseDto(Post post) {
this.id = post.getId();
this.title = post.getTitle();
this.content = post.getContent();
this.username = post.getUser().getName();
this.createdAt = post.getCreatedAt();
this.updatedAt = post.getUpdatedAt();
}
}
// Post
package com.sparta.wildcard_newsfeed.domain.post.entity;
import com.sparta.wildcard_newsfeed.domain.common.TimeStampEntity;
import com.sparta.wildcard_newsfeed.domain.post.dto.PostRequestDto;
import com.sparta.wildcard_newsfeed.domain.user.entity.User;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@Entity
@NoArgsConstructor(access = AccessLevel.PUBLIC)
public class Post extends TimeStampEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "user_id", nullable = false)
private User user;
@Column(nullable = false)
private String title;
@Column(nullable = false)
private String content;
public Post(PostRequestDto postRequestDto, User user) {
this.user = user;
this.title = postRequestDto.getTitle();
this.content = postRequestDto.getContent();
}
public void update(PostRequestDto postRequestDto) {
this.title = postRequestDto.getTitle();
this.content = postRequestDto.getContent();
}
}
// PostRepository
package com.sparta.wildcard_newsfeed.domain.post.repository;
import com.sparta.wildcard_newsfeed.domain.post.entity.Post;
import com.sparta.wildcard_newsfeed.domain.user.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface PostRepository extends JpaRepository<Post, Long> {
Optional<Post> findPostById(Long postId);
}
// PostService
package com.sparta.wildcard_newsfeed.domain.post.service;
import com.sparta.wildcard_newsfeed.domain.post.dto.PostRequestDto;
import com.sparta.wildcard_newsfeed.domain.post.dto.PostResponseDto;
import com.sparta.wildcard_newsfeed.domain.post.entity.Post;
import com.sparta.wildcard_newsfeed.domain.post.repository.PostRepository;
import com.sparta.wildcard_newsfeed.domain.user.entity.User;
import com.sparta.wildcard_newsfeed.domain.user.repository.UserRepository;
import com.sparta.wildcard_newsfeed.security.AuthenticationUser;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Comparator;
import java.util.List;
@Slf4j
@Service
@RequiredArgsConstructor
public class PostService {
private final PostRepository postRepository;
private final UserRepository userRepository;
@Transactional
public PostResponseDto addPost(PostRequestDto postRequestDto, AuthenticationUser user) {
User byUsercode = userRepository.findByUsercode(user.getUsername())
.orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다."));
Post post = new Post(postRequestDto, byUsercode);
postRepository.save(post);
return new PostResponseDto(post);
}
public PostResponseDto findById(long id) {
Post post = findPostById(id);
return new PostResponseDto(post);
}
public List<PostResponseDto> findAll() {
List<Post> postlist = postRepository.findAll();
return postlist.stream()
.sorted(Comparator.comparing(Post::getCreatedAt).reversed())
.map(PostResponseDto::new)
.toList();
}
@Transactional
public PostResponseDto updatePost(PostRequestDto postRequestDto, Long postId, AuthenticationUser user) {
Post post = findPostById(postId);
validateUser(post, user);
post.update(postRequestDto);
postRepository.save(post);
return new PostResponseDto(post);
}
@Transactional
public void deletePost(Long postId, AuthenticationUser user) {
Post post = findPostById(postId);
validateUser(post, user);
postRepository.delete(post);
}
private Post findPostById(long id) {
return postRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("해당 게시물이 존재하지 않습니다."));
}
private void validateUser(Post post, AuthenticationUser user) {
if (!post.getUser().getUsercode().equals(user.getUsername())) {
throw new IllegalArgumentException("작성자만 할 수 있습니다.");
}
}
}