728x90
반응형
User 도메인 클래스 생성
도메인
- 인간 활동이나 영역, 자율적인 컴퓨터 활동과 같은 특정한 전문 분야에서 사용되는 업무 지식
- 해당 분야의 업무 지식
// bean/User
package com.example.myrestfulservice.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Date;
@Data
@AllArgsConstructor
public class User {
private Integer id;
private String name;
private Date joinDate;
}
// dao/UserDaoService
package com.example.myrestfulservice.dao;
import com.example.myrestfulservice.bean.User;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Component
public class UserDaoService {
private static List<User> users = new ArrayList<>();
private static int usersCount = 3;
static {
users.add(new User(1, "Kenneth", new Date()));
users.add(new User(1, "Alice", new Date()));
users.add(new User(1, "Elena", new Date()));
}
public List<User> findAll() {
return users;
}
public User save(User user) {
if (user.getId() == null) {
user.setId(++usersCount);
}
if (user.getJoinDate() == null) {
user.setJoinDate(new Date());
}
users.add(user);
return user;
}
public User findOne(int id) {
for (User user : users) {
if (user.getId() == id) {
return user;
}
}
return null;
}
}
사용자 목록 조회를 위한 API 구현 - HTTP GET method
// controller/UserController
package com.example.myrestfulservice.controller;
import com.example.myrestfulservice.bean.User;
import com.example.myrestfulservice.dao.UserDaoService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
public class UserController {
// 인스턴스 이미 생성되어 있으니 주입 받아와서 사용
private UserDaoService service;
// Spring context가 호출
// 생성자 자동 생성: 마우스R -> Generate -> Constructor
public UserController(UserDaoService service) {
this.service = service;
}
// 사용자 목록
@GetMapping("/users")
public List<User> retrieveAllUsers() {
return service.findAll();
}
// 개별적인 1명
@GetMapping("/users/{id}")
public User retrieveUser(@PathVariable int id) {
return service.findOne(id);
}
}
사용자 등록을 위한 API 구현 - HTTP POSTS method
// UserController
// CREATED
// input - details of users
// output - CREATED & Return the created URI
@PostMapping("/users")
public void createUser(@RequestBody User user) {
User savedUser = service.save(user);
}
Post request 실행
- request client 필요
- Postman 명령어
HTTP Status Code 제어
ServeltUriComponentsBuild -> URI 생성
- 상태 코드 변경
- 적절한 상세 보기 하기 위해 필요한 URI 값 전달
// UserController
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
User savedUser = service.save(user);
// 현재 request 정보 -> URI 생성
URI location = ServletUriComponentsBuilder.fromCurrentRequest()
.path("/{id}") // 경로 지정
.buildAndExpand(savedUser.getId()) // 저장되어 있는 유저 값
.toUri(); // 전체 정보 -> URI
return ResponseEntity.created(location).build(); // 반환값 201
}
HTTP Status Code 제어를 위한 Exception Handling
user id 존재하지 않았을 때 -> 200 OK
=> 데이터 결과 찾지 못했을 경우가 아닌 적절한 상태 코드 반환(예외 처리)
=> throw new UserNotFoundException
// UserController
@GetMapping("/users/{id}")
public User retrieveUser(@PathVariable int id) {
User user = service.findOne(id);
if (user == null) {
throw new UserNotFoundException(String.format("ID[%s] not found", id));
}
return user;
}
// UserNotFoundException
package com.example.myrestfulservice.exception;
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}
-> 보안상 문제 생길 수 있음
=> 500이 아닌 적절한 상태 코드로 변경
user id: 4 요청 -> 존재 X => 클라이언트 잘못: 4xx 오류
// UserNotFoundException
package com.example.myrestfulservice.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.NOT_FOUND) // 추가
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}
Spring AOP를 이용한 Exception Handling
일반화된 예외 클래스 -> ExceptionResponse class
AOP(; Aspect Oriented Programming): 핵심적인 관점(비즈니스 로직) 기준해서 모듈화
=> 필요했던 예외만 전달해 줄 수 있는 상태로 제어
- Exception
- UserNotFoundException
// ExceptionResponse
package com.example.myrestfulservice.exception;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor // default 생성자
public class ExceptionResponse {
private Date timestamp;
private String message;
private String details;
}
// CustomizedResponseEntityExceptionHandler
package com.example.myrestfulservice.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 org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import java.util.Date;
@ControllerAdvice // 모든 컨트롤러가 실행될 때 반드시 실행
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(Exception.class)
public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
// 클라이언트에게 상세 정보 보여주지 X -> false
ExceptionResponse exceptionResponse =
new ExceptionResponse(new Date(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(UserNotFoundException.class)
public final ResponseEntity<Object> handleUserNotFoundException(Exception ex, WebRequest request) {
ExceptionResponse exceptionResponse =
new ExceptionResponse(new Date(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity(exceptionResponse, HttpStatus.NOT_FOUND);
}
}
사용자 삭제를 위한 API 구현 - HTTP DELETE method
// UserDaoService
public User deleteById(int id) {
Iterator<User> iterator = users.iterator(); // 리스트보다 속도 빠름
while (iterator.hasNext()) {
User user = iterator.next();
if (user.getId() == id) {
iterator.remove();
return user;
}
}
return null;
}
// UserController
@DeleteMapping("/users/{id}")
public ResponseEntity deleteUser(@PathVariable int id) {
User user = service.deleteById(id);
if (user == null) {
throw new UserNotFoundException(String.format("ID[%s] not found", id));
}
return ResponseEntity.noContent().build();
}
출처
728x90
반응형