[Practice] 공지사항 게시판 목록에 대한 요청 API 만들기 (19)

2021. 4. 12. 17:40Spring/Practice

1. 문제

  • 입력값은 입력 DTO를 통해서 입력받음
  • 제목과 내용은 필수 입력 조건으로 입력되지 않은 경우 400 리턴
  • 예외발생 시 각각의 에러를 취합하여 컬렉션 형태로 리턴

 

 

 

2. 풀이

- ApiNoticeController.java

package com.example.jpa.sample.notice.controller;

import com.example.jpa.sample.notice.entity.Notice;
import com.example.jpa.sample.notice.exception.AlreadyDeletedException;
import com.example.jpa.sample.notice.exception.NoticeNotFoundException;
import com.example.jpa.sample.notice.model.NoticeDeleteInput;
import com.example.jpa.sample.notice.model.NoticeInput;
import com.example.jpa.sample.notice.repository.NoticeRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.swing.text.html.Option;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@RequiredArgsConstructor
@RestController
public class ApiNoticeController {

    private final NoticeRepository noticeRepository;

    /*
    // 문제 6
    @GetMapping("/api/notice")
    public String noticeString() {
        return "공지사항입니다.";
    }
     */

    /*
    // 문제 7
    @GetMapping("/api/notice")
    public NoticeModel notice() {

        LocalDateTime regDate = LocalDateTime.of(2021, 1, 1, 0, 0);

        NoticeModel notice = new NoticeModel();
        notice.setId(1);;
        notice.setTitle("공지사항입니다.");
        notice.setContents("공지사항 내용입니다.");
        notice.setRegDate(regDate);

        return notice;
    }
     */

    /*
    // 문제 8
    @GetMapping("/api/notice")
    public List<NoticeModel> notice() {

        List<NoticeModel> noticeList = new ArrayList<>();

        noticeList.add(NoticeModel.builder()
                .id(1)
                .title("공지사항입니다.")
                .contents("공지사항 내용입니다.")
                .regDate(LocalDateTime.of(2021, 1, 1, 0, 0))
                .build()
        );
        noticeList.add(NoticeModel.builder()
                .id(2)
                .title("두번째 공지사항입니다.")
                .contents("두번째 공지사항 내용입니다.")
                .regDate(LocalDateTime.of(2021, 1, 2, 0, 0))
                .build()
        );

        return noticeList;
    }
     */

    // 문제 9
    @GetMapping("/api/notice")
    public List<NoticeInput> notice() {

        List<NoticeInput> noticeList = new ArrayList<>();

//        return null;
        return noticeList;
    }

    // 문제 10
    @GetMapping("/api/notice/count")
    public int noticeCount() {
//        return "10";
        return 10;
    }

    /*
    // 문제 11
    @PostMapping("/api/notice")
    public NoticeModel addNotice(@RequestParam String title, @RequestParam String contents) {

        NoticeModel notice = NoticeModel.builder()
                .id(1)
                .title(title)
                .contents(contents)
                .regDate(LocalDateTime.now())
                .build();

        return notice;
    }
     */

    /*
    // 문제 12
    @PostMapping("/api/notice")
    public NoticeModel addNotice(NoticeModel noticeModel) {

        noticeModel.setId(2);
        noticeModel.setRegDate(LocalDateTime.now());

        return noticeModel;
    }
     */

    /*
    // 문제 13
    @PostMapping("/api/notice")
    public NoticeModel addNotice(@RequestBody NoticeModel noticeModel) {

        noticeModel.setId(3);
        noticeModel.setRegDate(LocalDateTime.now());

        return noticeModel;
    }
     */

    /*
    // 문제 14
    @PostMapping("/api/notice")
    public Notice addNotice(@RequestBody NoticeInput noticeInput) {

        Notice notice = Notice.builder()
                .title(noticeInput.getTitle())
                .contents(noticeInput.getContents())
                .regDate(LocalDateTime.now())
                .build();

        return noticeRepository.save(notice);
    }
     */

    /*
    // 문제 15
    @PostMapping("/api/notice")
    public Notice addNotice(@RequestBody NoticeInput noticeInput) {

        Notice notice = Notice.builder()
                .title(noticeInput.getTitle())
                .contents(noticeInput.getContents())
                .regDate(LocalDateTime.now())
                .hits(0)
                .likes(0)
                .build();

        return noticeRepository.save(notice);
    }
     */

    // 문제 16
    @GetMapping("/api/notice/{id}")
    public Notice getNotice(@PathVariable long id) {
        return noticeRepository.findById(id).orElseThrow(null);
    }

    /*
    // 문제 17
    @PutMapping("/api/notice/{id}")
    public void updateNotice(@PathVariable long id, @RequestBody NoticeInput noticeInput) {
        Optional<Notice> notice = noticeRepository.findById(id);
        if(notice.isPresent()) {
            notice.get().setTitle(noticeInput.getTitle());
            notice.get().setContents(noticeInput.getContents());
            notice.get().setUpdateDate(LocalDateTime.now());
            noticeRepository.save(notice.get());
        }
    }
     */

    @ExceptionHandler(NoticeNotFoundException.class)
    public ResponseEntity<String> handlerNoticeNotFoundException(NoticeNotFoundException exception) {
        return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST);
    }

    // 문제 18
    @PutMapping("/api/notice/{id}")
    public void updateNotice(@PathVariable long id, @RequestBody NoticeInput noticeInput) {
//        Optional<Notice> notice = noticeRepository.findById(id);
//        if(!notice.isPresent()) {
//            throw new NoticeNotFoundException("공지사항의 글이 존재하지 않습니다.");
//        }

        Notice notice = noticeRepository.findById(id).orElseThrow(() -> new NoticeNotFoundException("공지사항의 글이 존재하지 않습니다."));

        notice.setTitle(noticeInput.getTitle());
        notice.setContents(noticeInput.getContents());
        notice.setUpdateDate(LocalDateTime.now());
        noticeRepository.save(notice);
    }

    // 문제 19
    @PatchMapping("/api/notice/{id}/hits")
    public void noticeHits(@PathVariable Long id) {
        Notice notice = noticeRepository.findById(id).orElseThrow(() -> new NoticeNotFoundException("공지사항의 글이 존재하지 않습니다."));

        notice.setHits(notice.getHits() + 1);
        noticeRepository.save(notice);
    }

    /*
    // 문제 20
    @DeleteMapping("/api/notice/{id}")
    public void deleteNotice(@PathVariable Long id) {
        Notice notice = noticeRepository.findById(id).orElseThrow(() -> new NoticeNotFoundException("공지사항의 글이 존재하지 않습니다."));

        noticeRepository.delete(notice);
    }
     */

    @ExceptionHandler(AlreadyDeletedException.class)
    public ResponseEntity<String> handlerAlreadyDeletedException(AlreadyDeletedException exception) {
        return new ResponseEntity<>(exception.getMessage(), HttpStatus.OK);
    }

    // 문제 21
    @DeleteMapping("/api/notice/{id}")
    public void deleteNotice(@PathVariable Long id) {
        Notice notice = noticeRepository.findById(id).orElseThrow(() -> new NoticeNotFoundException("공지사항의 글이 존재하지 않습니다."));

        if(notice.isDeleted()) {
            throw new AlreadyDeletedException("이미 삭제된 글입니다.");
        }

        notice.setDeleted(true);
        notice.setDeletedDate(LocalDateTime.now());
        noticeRepository.save(notice);
    }

    // 문제 22
    @DeleteMapping("/api/notice")
    public void deleteNoticeList(@RequestBody NoticeDeleteInput noticeDeleteInput) {

        List<Notice> noticeList = noticeRepository.findByIdIn(noticeDeleteInput.getIdList())
                .orElseThrow(() -> new NoticeNotFoundException("공지사항의 글이 존재하지 않습니다."));

        noticeList.stream().forEach(e -> {
            e.setDeleted(true);
            e.setDeletedDate(LocalDateTime.now());
        });

        noticeRepository.saveAll(noticeList);
    }

    // 문제 23
    @DeleteMapping("/api/notice")
    public void deleteAllNotice() {

        noticeRepository.deleteAll();
    }

    // 문제 24
    @PostMapping("/api/notice")
    public ResponseEntity<Object> addNotice(@RequestBody NoticeInput noticeInput) {

        if(noticeInput.getTitle() == null || noticeInput.getTitle().length() < 1 ||
            noticeInput.getContents() == null || noticeInput.getContents().length() < 1) {
            return new ResponseEntity<>("입력값이 정확하지 않습니다.", HttpStatus.BAD_REQUEST);
        }
        
        noticeRepository.save(Notice.builder()
                .title(noticeInput.getTitle())
                .contents(noticeInput.getContents())
                .regDate(LocalDateTime.now())
                .hits(0)
                .likes(0)
                .build()
        );
        
        return ResponseEntity.ok().build();
    }

}

- build.gradle

implementation 'org.springframework.boot:spring-boot-starter-validation'

- NoticeInput.java

package com.example.jpa.sample.notice.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotBlank;

@AllArgsConstructor // 모든 필드의 생성자
@NoArgsConstructor // 기본 생성자
@Builder // 빌더 패턴
@Data // Getter, Setter
public class NoticeInput {

    @NotBlank(message = "제목은 필수 항목입니다.")
    private String title;

    @NotBlank(message = "내용은 필수 항목입니다.")
    private String contents;
}

- ResponseError.java

package com.example.jpa.sample.notice.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;

@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class ResponseError {

    private String field;
    private String message;

    public static ResponseError of(ObjectError e) {
        return ResponseError.builder()
                .field(((FieldError)e).getField())
                .message(e.getDefaultMessage())
                .build();
    }
}

- ApiNoticeController.java

@RequiredArgsConstructor
@RestController
public class ApiNoticeController {

    private final NoticeRepository noticeRepository;
    
    ...
    
    // 문제 24
    @PostMapping("/api/notice")
    public ResponseEntity<Object> addNotice(@RequestBody @Valid NoticeInput noticeInput,
                                            Errors errors) {

        if(errors.hasErrors()) {
            List<ResponseError> responseErrors = new ArrayList<>();

            errors.getAllErrors().stream().forEach(e -> { 
                responseErrors.add(ResponseError.of((FieldError)e));
            });

            return new ResponseEntity<>(responseErrors, HttpStatus.BAD_REQUEST);
        }

        noticeRepository.save(Notice.builder()
                .title(noticeInput.getTitle())
                .contents(noticeInput.getContents())
                .regDate(LocalDateTime.now())
                .hits(0)
                .likes(0)
                .build()
        );

        return ResponseEntity.ok().build();
    }

}

728x90