-
Notifications
You must be signed in to change notification settings - Fork 0
[feat] 다솜소식 API 구현 #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
9a6709d
7382b30
38def04
f936cc3
6db6309
c173492
4bd898a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| package dmu.dasom.api.domain.news.controller; | ||
|
|
||
| import dmu.dasom.api.domain.news.dto.NewsRequestDto; | ||
| import dmu.dasom.api.domain.news.dto.NewsResponseDto; | ||
| import dmu.dasom.api.domain.news.service.NewsService; | ||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||
| import io.swagger.v3.oas.annotations.Operation; | ||
| import io.swagger.v3.oas.annotations.responses.ApiResponse; | ||
| import io.swagger.v3.oas.annotations.responses.ApiResponses; | ||
| import io.swagger.v3.oas.annotations.media.Content; | ||
| import io.swagger.v3.oas.annotations.media.ExampleObject; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| import jakarta.validation.Valid; | ||
| import java.util.List; | ||
|
|
||
| @Tag(name = "NEWS API", description = "다솜소식 API") | ||
| @RestController | ||
| @RequestMapping("/api/news") | ||
| public class NewsController { | ||
|
|
||
| private final NewsService newsService; | ||
|
|
||
| public NewsController(NewsService newsService) { | ||
| this.newsService = newsService; | ||
| } | ||
|
|
||
| @Operation(summary = "소식 조회", description = "리스트로 조회") | ||
| @ApiResponse(responseCode = "200", description = "정상 응답", | ||
| content = @Content(mediaType = "application/json")) | ||
| @GetMapping | ||
| public ResponseEntity<List<NewsResponseDto>> getAllNews() { | ||
| List<NewsResponseDto> newsList = newsService.getAllNews(); | ||
| return ResponseEntity.ok(newsList); | ||
| } | ||
|
|
||
| @Operation(summary = "소식 등록", description = "새로운 소식을 등록") | ||
| @ApiResponses(value = { | ||
| @ApiResponse(responseCode = "201", description = "생성 완료"), | ||
| @ApiResponse(responseCode = "400", description = "유효하지 않은 요청 데이터", | ||
| content = @Content(mediaType = "application/json", | ||
| examples = @ExampleObject(value = "{ \"errorCode\": \"E003\", \"errorMessage\": \"유효하지 않은 입력입니다.\" }"))) | ||
| }) | ||
|
|
||
| @PostMapping | ||
| public ResponseEntity<NewsResponseDto> createNews(@Valid @RequestBody NewsRequestDto requestDto) { | ||
| NewsResponseDto responseDto = newsService.createNews(requestDto); | ||
| return ResponseEntity.status(201).body(responseDto); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package dmu.dasom.api.domain.news.dto; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import jakarta.validation.constraints.NotBlank; | ||
| import jakarta.validation.constraints.Size; | ||
| import lombok.Getter; | ||
|
|
||
| @Getter | ||
| @Schema(name = "NewsRequestDto", description = "뉴스 생성 요청 DTO") | ||
| public class NewsRequestDto { | ||
|
|
||
| @NotBlank | ||
| @Size(max = 100) | ||
| @Schema(description = "뉴스 제목", example = "새로운 뉴스 제목") | ||
| private String title; | ||
|
|
||
| @NotBlank | ||
| @Schema(description = "뉴스 내용", example = "새로운 뉴스 내용") | ||
| private String content; | ||
|
|
||
| @Size(max = 255) | ||
| @Schema(description = "뉴스 이미지 URL", example = "http://example.com/image.jpg", nullable = true) | ||
| private String imageUrl; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package dmu.dasom.api.domain.news.dto; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import lombok.Getter; | ||
|
|
||
| import java.time.LocalDateTime; | ||
|
|
||
| @Getter | ||
| @Schema(name = "NewsResponseDto", description = "뉴스 응답 DTO") | ||
| public class NewsResponseDto { | ||
|
|
||
| @Schema(description = "소식 ID", example = "1") | ||
| private final Long id; | ||
|
||
|
|
||
| @Schema(description = "뉴스 제목", example = "제목") | ||
| private final String title; | ||
|
|
||
| @Schema(description = "뉴스 내용", example = "내용") | ||
| private final String content; | ||
|
|
||
| @Schema(description = "작성일", example = "2025-02-14T12:00:00") | ||
| private final LocalDateTime createdAt; | ||
|
|
||
| @Schema(description = "뉴스 이미지 URL", example = "http://example.com/image.jpg", nullable = true) | ||
| private final String imageUrl; | ||
|
|
||
| public NewsResponseDto(Long id, String title, String content, LocalDateTime createdAt, String imageUrl) { | ||
| this.id = id; | ||
| this.title = title; | ||
| this.content = content; | ||
| this.createdAt = createdAt; | ||
| this.imageUrl = imageUrl; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| package dmu.dasom.api.domain.news.entity; | ||
|
|
||
| import dmu.dasom.api.domain.common.BaseEntity; | ||
| import dmu.dasom.api.domain.common.Status; | ||
| import dmu.dasom.api.domain.news.dto.NewsResponseDto; | ||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import jakarta.persistence.*; | ||
| import jakarta.validation.constraints.NotNull; | ||
| import lombok.*; | ||
|
|
||
| @Getter | ||
| @Setter | ||
|
||
| @Entity | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| @Builder | ||
| @Schema(description = "뉴스 엔티티") | ||
| public class NewsEntity extends BaseEntity { | ||
|
|
||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| @Schema(description = "뉴스 ID", example = "1") | ||
| private Long id; | ||
|
|
||
| @NotNull | ||
| @Schema(description = "뉴스 제목", example = "뉴스 예제 제목") | ||
| @Column(nullable = false, length = 100) | ||
| private String title; | ||
|
|
||
| @NotNull | ||
| @Schema(description = "뉴스 내용", example = "뉴스 예제 내용") | ||
| @Column(columnDefinition = "TEXT", nullable = false) | ||
| private String content; | ||
|
|
||
| @Schema(description = "뉴스 이미지 URL", example = "http://example.com/image.jpg") | ||
| @Column(length = 255) | ||
| private String imageUrl; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이미지는 외부 DB에 저장하는 건가요? |
||
|
|
||
| // 🔹 뉴스 상태 업데이트 | ||
| public void updateStatus(Status status) { | ||
| super.updateStatus(status); | ||
| } | ||
|
|
||
| // 🔹 NewsEntity → NewsResponseDto 변환 | ||
| public NewsResponseDto toResponseDto() { | ||
| return new NewsResponseDto(id, title, content, getCreatedAt(), imageUrl); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package dmu.dasom.api.domain.news.repository; | ||
|
|
||
| import dmu.dasom.api.domain.news.entity.NewsEntity; | ||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
| import org.springframework.stereotype.Repository; | ||
|
|
||
| @Repository | ||
| public interface NewsRepository extends JpaRepository<NewsEntity, Long> { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| package dmu.dasom.api.domain.news.service; | ||
|
|
||
| import dmu.dasom.api.domain.news.dto.NewsRequestDto; | ||
| import dmu.dasom.api.domain.news.dto.NewsResponseDto; | ||
| import dmu.dasom.api.domain.news.entity.NewsEntity; | ||
| import dmu.dasom.api.domain.news.repository.NewsRepository; | ||
| import org.springframework.stereotype.Service; | ||
| import java.util.List; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| @Service | ||
| public class NewsService { | ||
|
|
||
| private final NewsRepository newsRepository; | ||
|
|
||
| public NewsService(NewsRepository newsRepository) { | ||
| this.newsRepository = newsRepository; | ||
| } | ||
|
|
||
| // 🔹 전체 조회 | ||
| public List<NewsResponseDto> getAllNews() { | ||
| return newsRepository.findAll().stream() | ||
| .map(NewsEntity::toResponseDto) | ||
| .collect(Collectors.toList()); | ||
| } | ||
|
|
||
| // 🔹 생성 | ||
| public NewsResponseDto createNews(NewsRequestDto requestDto) { | ||
| NewsEntity news = NewsEntity.builder() | ||
| .title(requestDto.getTitle()) | ||
| .content(requestDto.getContent()) | ||
| .imageUrl(requestDto.getImageUrl()) | ||
| .build(); | ||
|
|
||
| NewsEntity savedNews = newsRepository.save(news); | ||
| return savedNews.toResponseDto(); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Request Body->NewsRequestDto역직렬화 과정에서 필드 값 Validation을 하기 위해서는NewsRequestDto선언부 앞에@Valid어노테이션을 추가하고NewsRequestDto의 각 필드에 제약 조건을 설정하면 됩니다.ApplicantCreateRequestDto를 참고해보세요