[개발] - Spring/[개발예제] - SpringBoot - 블로그 만들기
블로그 글 수정 API
완벽한 장면
2023. 10. 13. 23:58
글 수정 API
1. 서비스 코드 구현
- update() => 특정 아이디의 글 수정
1) Articles.java
- 엔티티에도 update() 메서드 구현
public void update(String title, String content) {
this.title = title;
this.content = content;
}
2) DTO 생성 - request.UpdateArticleRequest
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class UpdateArticleRequest {
private String title;
private String content;
}
3) 서비스 코드 구현 - BlogService
@RequiredArgsConstructor // final이 붙거나 @NotNull이 붙은 필드의 생성자 추가
@Service
public class BlogService {
private final BlogRepository blogRepository;
// 게시글을 작성한 유저인지 확인
private static void authorizeArticleAuthor(Article article) {
// 현재 사용자 이름을 가져와 게시물의 작성자와 비교하고, 다른 경우에 예외 던짐
String userName = SecurityContextHolder.getContext().getAuthentication().getName();
if (!article.getAuthor().equals(userName)) {
throw new IllegalArgumentException("not authorized");
}
}
// AddArticleRequest를 사용하여 새 게시물을 생성하고,
// 지정된 사용자 이름으로 게시물을 저장
public Article save(AddArticleRequest request, String username) {
return blogRepository.save(request.toEntity(username));
}
// 블로그 리포지토리를 통해 모든 게시물을 조회하여 반환
public List<Article> findAll() {
return blogRepository.findAll();
}
// 주어진 'id'로 게시물을 조회하고, 게시물이 없으면 예외 던짐
public Article findById(Long id) {
return blogRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("not fonund: " + id));
}
//추가
@Transactional
public Article update(Long id, UpdateArticleRequest request) {
// 주어진 'id'로 게시물을 조회하고, 게시물이 없으면 예외 던짐
Article article = blogRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("not found: " + id));
// 게시물의 작성자를 확인하고, 작성자와 현재 사용자가 다르면 예외 던짐
authorizeArticleAuthor(article);
// 게시물의 내용을 업데이트하고 업데이트된 게시물을 반환
article.update(request.getTitle(), request.getContent());
return article;
}
}
2. 컨트롤러 코드 구현
BlogApiController
@RequiredArgsConstructor
@RestController // HTTP Response Body에 객체 데이터를 JSON 형식으로 반환하는 컨트롤러
public class BlogApiController {
private final BlogService blogService;
@PostMapping("/api/articles")
//요청 본문 값 매핑
// HTTP POST 요청을 처리하여 블로그 글을 추가.
public ResponseEntity<Article> addArticle(@RequestBody AddArticleRequest request, Principal principal) {
Article savedArticle = blogService.save(request, principal.getName());
// 요청한 자원이 성공적으로 생성되었으며 저장된 블로그 글 정보를 응답 객체에 담아 전송
return ResponseEntity.status(HttpStatus.CREATED)
.body(savedArticle);
}
@GetMapping("/api/articles")
public ResponseEntity<List<ArticleResponse>> findAllArticles() {
// 블로그 서비스를 통해 모든 게시물을 조회하고, 각 게시물을 ArticleResponse로 매핑
List<ArticleResponse> articles = blogService.findAll()
.stream()
.map(ArticleResponse::new)
.toList();
// 조회된 게시물 목록을 ResponseEntity로 래핑하여 반환
return ResponseEntity.ok()
.body(articles);
}
@GetMapping("/api/articles/{id}")
// URL 경로에서 'id' 값을 추출하여 메서드의 매개변수로 사용
public ResponseEntity<ArticleResponse> findArticle(@PathVariable Long id) {
// 주어진 'id'로 블로그 서비스를 통해 게시물을 조회
Article article = blogService.findById(id);
// 조회된 게시물을 ArticleResponse로 매핑하고 ResponseEntity로 래핑하여 반환
return ResponseEntity.ok()
.body(new ArticleResponse(article));
}
// 추가
@PutMapping("/api/articles/{id}")
public ResponseEntity<Article> updateArticle(@PathVariable Long id,
@RequestBody UpdateArticleRequest request) {
// 주어진 'id'로 블로그 서비스를 통해 게시물을 업데이트하고 업데이트된 게시물을 받음
Article updatedArticle = blogService.update(id, request);
// 업데이트된 게시물을 ResponseEntity로 래핑하여 반환
return ResponseEntity.ok()
.body(updatedArticle);
}
}
실행 테스트
GET 으로 전체 조회 초기에 했을 때의 데이터(지난 글 참고)
2번 글을 수정해보기
이렇게 보내서 수정하고
조회해보면
완료된 수정사항 확인 가능
테스트 코드 작성하기
updateArticle() 개요
@SpringBootTest
@AutoConfigureMockMvc
class BlogApiControllerTest {
@Autowired
protected MockMvc mockMvc;
@Autowired
protected ObjectMapper objectMapper;
@Autowired
private WebApplicationContext context;
@Autowired
BlogRepository blogRepository;
@BeforeEach
public void mockMvcSetUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
.build();
blogRepository.deleteAll();
}
@DisplayName("updateArticle: 블로그 글 수정.")
@Test
public void updateArticle() throws Exception {
// given
final String url = "/api/articles/{id}";
final String title = "title";
final String content = "content";
Article savedArticle = blogRepository.save(Article.builder()
.title(title)
.content(content)
.build());
final String newTitle = "new title";
final String newContent = "new content";
UpdateArticleRequest request = new UpdateArticleRequest(newTitle, newContent);
// when
ResultActions result = mockMvc.perform(put(url, savedArticle.getId())
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsString(request)));
// then
result.andExpect(status().isOk());
Article article = blogRepository.findById(savedArticle.getId()).get();
assertThat(article.getTitle()).isEqualTo(newTitle);
assertThat(article.getContent()).isEqualTo(newContent);
}
}
728x90
반응형