명세
- Social media application
- User -> Posts
Description Rest API Http Method Retrieve all Users /users GET Create an Users /users POST Retrieve one User /user/{id} GET Update an User /user/{id} Patch Delete an User /user/{id} DELETE
User 서비스
- GetMapping
- /users
@GetMapping("/users") public List<User> retrieveAllUsers() { return userService.findAll(); }
- /users/${id}
@GetMapping("/users/{id}") public User retrieveUser(@PathVariable Integer id) { Optional<User> byId = userService.findOne(id); return byId.orElseThrow(()-> { throw new UserNotFoundException(String.format("ID[%s] not found", id)); }); }
- @PathVariable을 활용하여 URI에 선언된 변수(id)를 가져온다.
- 예외 처리
- id에 해당하는 User가 없는 경우 에외 발생
- Customizing Exception 구현
@ResponseStatus(HttpStatus.NOT_FOUND) public class UserNotFoundException extends RuntimeException{ public UserNotFoundException() { super(); } public UserNotFoundException(String message) { super(message); } }
- RuntimeException을 상속받아 구현한다.
- ResponseStatus를 활용하여 HttpStatus 상태 코드를 지정할 수 있다.
- 2XX번 대는 정상, 4XX번 대는 Client의 잘못된 요청, 5XX번 대는 서버 측의 문제
- 예외 Controller 구현
@RestController @ControllerAdvice public class CustomizeResponseEntityExceptionHandler extends ResponseEntityExceptionHandler{ @ExceptionHandler(Exception.class) public final ResponseEntity<Object> handleAllException(Exception ex, WebRequest request) { ExceptionResponse exceptionResponse = new ExceptionResponse(LocalDateTime.now(), ex.getMessage(), request.getDescription(false)); return new ResponseEntity<Object>(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR); } @ExceptionHandler(UserNotFoundException.class) public final ResponseEntity<Object> handleUserNotFoundException(Exception ex, WebRequest request) { ExceptionResponse exceptionResponse = new ExceptionResponse(LocalDateTime.now(), ex.getMessage(), request.getDescription(false)); return new ResponseEntity<Object>(exceptionResponse, HttpStatus.NOT_FOUND); } }
- @ControllerAdvice: 예외 Controller임을 알린다.
- @ExceptionHandler
- 예외 발생 시 해당 핸들러가 실행되도록 한다.
- 발생되는 예외마다 실행되는 핸들러를 지정해줄 수 있다.
- /users
- PostMapping
-
/users
@PostMapping("/users") public ResponseEntity<User> createUser(@Valid @RequestBody User user) { User savedUser = userService.save(user); URI location = ServletUriComponentsBuilder.fromCurrentRequest() .path("/{id}") .buildAndExpand(savedUser.getId()) .toUri(); return ResponseEntity.created(location).build(); }
- ServletUriComponentsBuilder.fromCurrentRequest().path(“/{id}”).buildAndExpand(saveUser.getId()).toUri();
- 현재 요청 URI(http://localhost:8180/users)을 리턴하며. path로 뒤에 path를 붙여 주며, buildAndExpand로 pathVariable 값을 세팅한다.
- ReseponseEntity.created(URI).build()
- HttpStatus.CREATED(201 code) 상태로 return 하며, location header에 지정한 URI로 설정한다.
- vadliation check
- 파라미터를 받을 객체에 @Valid를 붙여준다.
- DAO 객체에 사용하고자 하는 제약 사항을 걸어줄 수 있다.
- Annotation으로 불가능 한것은 Validator 구현체를 만들어 사용할 수 있다.
- @InitBinder를 사용하여 요청올 때마다 객체에 대한 검사를 진행할 수 있다.
@Data @NoArgsConstructor @AllArgsConstructor @Getter @Setter public class User { private Integer id; @Size(min = 2, message= "이름은 2글자 이상 입력해주세요.") private String name; @Past private LocalDateTime joinDate; }
-
Errors 객체로 에러를 받거나 Exception Handler를 받을 수 있다.
@Override protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { ExceptionResponse exceptionResponse = new ExceptionResponse(LocalDateTime.now(), "validation failed", ex.getBindingResult().toString()); return new ResponseEntity<Object>(exceptionResponse, HttpStatus.BAD_REQUEST); } // CustomizeResponseEntityExceptionHandler // ResponseEntityExceptionHandler의 handlermethodArgumentNotValid 오버라이딩
- ServletUriComponentsBuilder.fromCurrentRequest().path(“/{id}”).buildAndExpand(saveUser.getId()).toUri();
-
- PutMapping
- /users/id
@PutMapping("/users/{id}") public User updateUser(@PathVariable Integer id, @RequestBody User user) { Optional<User> byId = userService.updateUser(id, user); return byId.orElseThrow(() -> { throw new UserNotFoundException(String.format("ID[%s] not found", id)); }); }
- /users/id
- DeleteMapping
- /users/id
@DeleteMapping("/users/{id}") public void deleteUser(@PathVariable Integer id) { userService.deleteById(id).orElseThrow(()-> { throw new UserNotFoundException(String.format("ID[%s} not found", id)); }); }
- /users/id