Domain : Domain Knowledge, 즉 인간 활동 영역, 혹은 자율적인 컴퓨터 활동*과 같은 어떤 특정한 전문 분야에서 사용되어지는 업무 지식을 뜻함
User
restful-api-service -> user 패키지 생성
@Data
@AllArgsConstructor
public class User {
private Integer id;
private String name;
private Date joinDate;
}
UserDaoService
restful-api-service -> user
@Service
public class UserDaoService {
private static List<User> users = new ArrayList<>();
private static int userCount = 3;
// 데이터베이스에 3개의 데이터가 들어 있다고 가정
static {
users.add(new User(1, "roxy", new Date()));
users.add(new User(2, "yujin", new Date()));
users.add(new User(3, "kyj", new Date()));
}
// 모든 사용자 조회
public List<User> findAll() {
return users;
}
// 신규 사용자 추가
public User save(User user) {
if (user.getId() == null) {
user.setId(++userCount);
}
users.add(user);
return user;
}
// id값으로 사용자 조회
public User findOne(int id) {
for (User user : users) {
if (user.getId() == id) {
return user;
}
}
return null;
}
}
UserController
restful-api-service -> user
@RestController
@RequiredArgsConstructor
public class UserController {
private final UserDaoService service;
// 전체 사용자 목록 조회
@GetMapping("/users")
public List<User> retrieveAllUsers() {
return service.findAll();
}
// 사용자 상세 조회
@GetMapping("/user/{id}")
public User retrieveUser(@PathVariable("id") int id) {
return service.findOne(id);
}
}


Post, Put등 클라이언트로부터 Form data 타입이 아닌 json, xml등 오브젝트 형태의 데이터를 받기 위해서 매개변수 타입에 @RequestBody 선언해줘야 한다.
UserController
restful-api-service -> user
@PostMapping("/users")
public void createUser(@RequestBody User user) {
User savedUser = service.save(user);
}
cannot deserialize from object value (no delegate- or property-based creator)
User 도메인에 빈 생성자를 추가해준다.
User
@NoArgsConstructor


응답코드 값을 제어하기 위해서 Servlet URI Component build 클래스 사용
UserController
createUser() 메서드 수정
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
User savedUser = service.save(user);
URI location = ServletUriComponentsBuilder.fromCurrentRequest() // 현재 가지고 있는 Request 사용
.path("/{id}") // 반환 시 URI 뒤에 /{id} 추가
.buildAndExpand(savedUser.getId()) // {id}에 savedUser.getId() 값을 넣어줌
.toUri();
return ResponseEntity.created(location).build();

status coder가 201로 변경되었다.

존재하지 않는 id 100의 사용자를 요청했는데 status code 200 ok가 발생했다.
UserController
retrieveUser() 메서드 수정
@GetMapping("/user/{id}")
public User retrieveUser(@PathVariable("id") int id) {
User user = service.findOne(id);
if (user == null) {
throw new UserNotFoundException(String.format("ID[%s] not found", id));
}
return user;
}
UserNotFoundException
restful-api-service -> user
@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException{
public UserNotFoundException(String message) { //실행시 발생하는 오류로 처리
super(message); //생성자는 부모 클래스로부터 전달받은 메시지로 처리
}
}

404번 오류 발생
ExceptionResponse
restful-api-service -> exception 생성
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ExceptionResponse {
private Date timestamp;
private String message;
private String details;
}
ResponseEntityExceptionHandler 클래스를 상속받은 Handler 클래스 선언ResponseEntityExceptionHandler 클래스 : 시스템에서 에러 발생시 에러를 핸들링하기 위해 스프링에서 제공하는 클래스 ControllerBean에서 예외 발생시 이 클래스가 발생하도록 설정AOP : 스프링 프레임워크에서 로깅 정보, 로그인 정보, 메시지 추가 정보 등 모든 비즈니스 로직을 수행하는 Controller에서 항상 실행시켜줘야 하는 공통적인 로직@RestController 어노테이션 추가하여 웹 서비스에서 사용할 수 있도록 함@ContollerAdvice 어노테이션 추가하여 모든 Controller가 실행될 때 반드시 이 어노테이션이 붙은 Bean이 실행되도록 함CustomizedResponseEntityExceptionHandler
restful-api-service -> exception
@RestControllerAdvice
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
/**
ResponseEntity는 사용자 객체 한명 추가했을 때 반환하는 형태의 값
Exception ex는 메소드에서 발생했던 에러 객체
WebRequest request는 어디서 발생했는지 알아보기 위한 request 정보
@ExceptionHandler 어노테이션은 이 메소드가 ExceptionHandler로 사용될 수 있음을 지칭.
*/
@ExceptionHandler(Exception.class)
public final ResponseEntity<Object> handlerAllException(Exception ex, WebRequest request) {
// 발생 날짜, 에러 메시지, request의 부가적인 내용
ExceptionResponse exceptionResponse = new ExceptionResponse(
new Date(), ex.getMessage(), request.getDescription(false)
);
return new ResponseEntity(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
서버에서 발생하는 일반화 된 에러이기 때문에 500번 에러 발생

CustomizedResponseEntityExceptionHandler
restful-api-service -> exception
@ExceptionHandler(UserNotFoundException.class)
public final ResponseEntity<Object> handleUserNotFound(Exception ex, WebRequest request) {
// 발생 날짜, 에러 메시지, request의 부가적인 내용
ExceptionResponse exceptionResponse = new ExceptionResponse(
new Date(), ex.getMessage(), request.getDescription(false)
);
return new ResponseEntity(exceptionResponse, HttpStatus.NOT_FOUND);
}

404 Not Found 발생
UserDaoService
public User deleteUser(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 void deleteUser(@PathVariable("id") int id) {
User user = service.deleteUser(id);
if (user == null) {
throw new UserNotFoundException(String.format("ID[%s] not found", id));
}
}


UserDaoService
public User modifyUser(int id, String name) {
Iterator<User> iterator = users.iterator();
while (iterator.hasNext()) {
User user = iterator.next();
if (user.getId() == id) {
user.setName(name);
return user;
}
}
return null;
}
UserController
@PutMapping("/users/modify")
public User modifyUser(@RequestBody Map<String, String> param) {
int id = Integer.parseInt(param.get("id"));
String name = param.get("name");
User user = service.modifyUser(id, name);
return user;
}

