-
Notifications
You must be signed in to change notification settings - Fork 134
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
[Spring MVC] 김나윤 미션 제출합니다. #298
base: bbggr1209
Are you sure you want to change the base?
Changes from all commits
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,13 @@ | ||
package roomescape.controller; | ||
|
||
import org.springframework.stereotype.Controller; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
|
||
@Controller | ||
public class HomeController { | ||
|
||
@GetMapping("/") | ||
public String home() { | ||
return "home"; | ||
} | ||
} | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package roomescape.controller; | ||
|
||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.stereotype.Controller; | ||
import org.springframework.web.bind.annotation.*; | ||
import roomescape.dto.ReservationReqDto; | ||
import roomescape.dto.ReservationResDto; | ||
import roomescape.exception.BadRequestException; | ||
import roomescape.model.Reservation; | ||
import roomescape.template.ApiResponseTemplate; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.concurrent.atomic.AtomicLong; | ||
import java.util.stream.Collectors; | ||
|
||
@Controller | ||
public class ReservationController { | ||
|
||
private final List<Reservation> reservations = new ArrayList<>(); | ||
private final AtomicLong index = new AtomicLong(1); | ||
|
||
@GetMapping("/reservation") | ||
public String reservation() { | ||
return "reservation"; | ||
} | ||
|
||
@GetMapping(value = "/reservations", produces = "text/html") | ||
public String reservationPage() { | ||
return "new-reservation"; | ||
} | ||
|
||
@GetMapping(value = "/reservations", produces = "application/json") | ||
@ResponseBody | ||
Comment on lines
+35
to
+36
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.
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.
|
||
public ApiResponseTemplate<List<ReservationResDto>> getReservations() { | ||
List<ReservationResDto> dtoList = reservations.stream() | ||
.map(reservation -> new ReservationResDto( | ||
reservation.getId(), | ||
reservation.getName(), | ||
reservation.getDate(), | ||
reservation.getTime())) | ||
.collect(Collectors.toList()); | ||
|
||
return new ApiResponseTemplate<>("success", dtoList); | ||
} | ||
|
||
@PostMapping("/reservations") | ||
@ResponseBody | ||
public ResponseEntity<ApiResponseTemplate<ReservationResDto>> addReservation(@RequestBody ReservationReqDto reservationReqDto) { | ||
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.
|
||
validateReservationRequest(reservationReqDto); | ||
|
||
Reservation newReservation = new Reservation( | ||
index.getAndIncrement(), | ||
reservationReqDto.getName(), | ||
reservationReqDto.getDate(), | ||
reservationReqDto.getTime() | ||
); | ||
reservations.add(newReservation); | ||
|
||
HttpHeaders headers = new HttpHeaders(); | ||
headers.add("Location", "/reservations/" + newReservation.getId()); | ||
|
||
ReservationResDto newReservationResDto = new ReservationResDto( | ||
newReservation.getId(), | ||
newReservation.getName(), | ||
newReservation.getDate(), | ||
newReservation.getTime() | ||
); | ||
|
||
return new ResponseEntity<>( | ||
new ApiResponseTemplate<>("success", newReservationResDto), | ||
headers, | ||
HttpStatus.CREATED | ||
); | ||
} | ||
|
||
@DeleteMapping("/reservations/{id}") | ||
@ResponseBody | ||
public ResponseEntity<ApiResponseTemplate<String>> deleteReservation(@PathVariable Long id) { | ||
ensureReservationExists(id); | ||
removeReservation(id); | ||
return createSuccessDeleteResponse(); | ||
} | ||
Comment on lines
+79
to
+85
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. 메소드 분리를 잘한 거 같아요🙂 |
||
|
||
private ResponseEntity<ApiResponseTemplate<String>> createSuccessDeleteResponse() { | ||
return new ResponseEntity<>(new ApiResponseTemplate<>("success", "예약 삭제 성공"), HttpStatus.NO_CONTENT); | ||
} | ||
|
||
private void ensureReservationExists(Long id) { | ||
if (!reservationExists(id)) { | ||
throw new BadRequestException("예약 삭제 실패"); | ||
} | ||
} | ||
|
||
private void validateReservationRequest(ReservationReqDto reservationReqDto) { | ||
if (reservationReqDto.getName() == null || reservationReqDto.getName().isEmpty()) { | ||
throw new BadRequestException("이름을 작성해주세요"); | ||
} | ||
if (reservationReqDto.getDate() == null) { | ||
throw new BadRequestException("날짜를 선택해주세요"); | ||
} | ||
if (reservationReqDto.getTime() == null || reservationReqDto.getTime().isEmpty()) { | ||
throw new BadRequestException("시간을 선택해주세요"); | ||
} | ||
} | ||
|
||
private boolean reservationExists(Long id) { | ||
return reservations.stream().anyMatch(reservation -> reservation.getId().equals(id)); | ||
} | ||
|
||
private void removeReservation(Long id) { | ||
reservations.removeIf(reservation -> reservation.getId().equals(id)); | ||
} | ||
|
||
@PostMapping("/reservations/reset") | ||
@ResponseBody | ||
public ResponseEntity<Void> resetReservations() { | ||
index.set(1); | ||
reservations.clear(); | ||
return new ResponseEntity<>(HttpStatus.NO_CONTENT); | ||
} | ||
Comment on lines
+117
to
+123
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. 모든 예약 삭제 API도 구현한 건가요? 열정적인 모습👍 |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package roomescape.dto; | ||
|
||
import java.time.LocalDate; | ||
|
||
public class ReservationReqDto { | ||
private String name; | ||
private LocalDate date; | ||
private String time; | ||
|
||
public ReservationReqDto() {} | ||
|
||
public ReservationReqDto(String name, LocalDate date, String time) { | ||
this.name = name; | ||
this.date = date; | ||
this.time = time; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public LocalDate getDate() { | ||
return date; | ||
} | ||
|
||
public String getTime() { | ||
return time; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package roomescape.dto; | ||
|
||
import java.time.LocalDate; | ||
|
||
public class ReservationResDto { | ||
private Long id; | ||
private String name; | ||
private LocalDate date; | ||
private String time; | ||
|
||
public ReservationResDto() {} | ||
|
||
public ReservationResDto(Long id, String name, LocalDate date, String time) { | ||
this.id = id; | ||
this.name = name; | ||
this.date = date; | ||
this.time = time; | ||
} | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public LocalDate getDate() { | ||
return date; | ||
} | ||
|
||
public String getTime() { | ||
return time; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package roomescape.exception; | ||
|
||
public class BadRequestException extends IllegalArgumentException { | ||
public BadRequestException(String message) { | ||
super(message); | ||
} | ||
Comment on lines
+3
to
+6
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. 커스텀 예외 👍 |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package roomescape.exception; | ||
|
||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.ControllerAdvice; | ||
import org.springframework.web.bind.annotation.ExceptionHandler; | ||
import roomescape.template.ApiResponseTemplate; | ||
|
||
@ControllerAdvice | ||
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.
|
||
public class GlobalExceptionHandler { | ||
@ExceptionHandler(BadRequestException.class) | ||
public ResponseEntity<ApiResponseTemplate<String>> handleBadRequestException(BadRequestException e) { | ||
ApiResponseTemplate<String> response = new ApiResponseTemplate<>("error", e.getMessage()); | ||
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package roomescape.model; | ||
|
||
import java.time.LocalDate; | ||
|
||
public class Reservation { | ||
|
||
private Long id; | ||
private String name; | ||
private LocalDate date; | ||
private String time; | ||
|
||
public Reservation() {} | ||
|
||
public Reservation(Long id, String name, LocalDate date, String time) { | ||
this.id = id; | ||
this.name = name; | ||
this.date = date; | ||
this.time = time; | ||
} | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public LocalDate getDate() { | ||
return date; | ||
} | ||
|
||
public String getTime() { | ||
return time; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package roomescape.template; | ||
|
||
public class ApiResponseTemplate<T> { | ||
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. 클래스 |
||
|
||
private final String status; | ||
private final T data; | ||
|
||
public ApiResponseTemplate(String status, T data) { | ||
this.status = status; | ||
this.data = data; | ||
} | ||
|
||
public String getStatus() { | ||
return status; | ||
} | ||
|
||
public T getData() { | ||
return data; | ||
} | ||
} | ||
Comment on lines
+3
to
+20
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. 이런 식으로 API 응답에서 상태 코드와 실질적인 데이터를 분리할 수 있군요 굿👍 |
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.
목적에 따라 컨트롤러 분리한 거 좋아보여요 굿👍