본문 바로가기

Study/REST API

[REST API] 프로젝트 생성

개발환경 준비 

 

 

이용한 maven 라이브러리

  • jackson-databind : 버전 - 2.8.5
  • lombok : 버전 - 1.16.10
<!-- jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.5</version>
</dependency>

<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>

 

 

 

Controller생성

 

 

-RestApiController.java

@RestController // @Controller + @ResponseBody
@RequestMapping("/api")
public class RestAPIController {
	
	@Autowired
	UserService userService;
	
	// --- Retrieve All Users 모든 사용자 조회
	@RequestMapping(value="/users", method=RequestMethod.GET)
	public ResponseEntity<List<User>> listAllUsers(){ // header, body(json), HTTP.status
		List<User> users = userService.findAllUsers();
		if(users.isEmpty()) {
			return new ResponseEntity<>(HttpStatus.NO_CONTENT);
		}
		return new ResponseEntity<List<User>>(users, HttpStatus.OK); // body에 users.
		
	}

	
	
	// --- Retrieve Single User 한 사용자 조회 // template valuable
	@RequestMapping(value="/users/{id}", method=RequestMethod.GET)
	public ResponseEntity<User> getUser(@PathVariable("id") long id){ 
		User user = userService.FindById(id);
		if(user == null) {
			//do to list : exception (예외처리)
			throw new UserNotFoundException(id);
			
		}
		return new ResponseEntity<User>(user, HttpStatus.OK); // body에 users.	
	}
	
	// --- Create a User 
		@RequestMapping(value="/users", method=RequestMethod.POST) // request body(json)
		public ResponseEntity<Void> createUser(@RequestBody User user, // body부분은 없음을 Void로 표시
									UriComponentsBuilder ucBuilder){ // 새롭게 생성된 사용자의 uri를 header정보에 담아서 넘겨주기 위함
			
			if(userService.isUserExist(user)) {
				throw new UserDuplicatedException(user.getName());
			}
			userService.saveUser(user);
			
			HttpHeaders headers = new HttpHeaders();
			headers.setLocation(ucBuilder.path("/api/users/{id}")
									.buildAndExpand(user.getId()).toUri());
			
			return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
		}
	
	// --- Update a User	
		@RequestMapping(value="/users/{id}", method = RequestMethod.PUT)
		public ResponseEntity<User> updateUser(@PathVariable("id")long id,
												@RequestBody User user ){
			
			User currentUser = userService.FindById(id);
			
			if(currentUser == null) {
				throw new UserNotFoundException(id);
			}
			
			currentUser.setName(user.getName());
			currentUser.setAge(user.getAge());
			currentUser.setSalary(user.getSalary());
			
			userService.updateUser(currentUser);
			return new ResponseEntity<User>(currentUser, HttpStatus.OK);
		}
	
	// --- Delete a User
		@RequestMapping(value="/users/{id}", method = RequestMethod.DELETE)
		public ResponseEntity<User> deleteUser(@PathVariable("id")long id){
			User user = userService.FindById(id);
			if(user == null) {
				throw new UserNotFoundException(id);
			}
			userService.deleteUserById(id);
			return new ResponseEntity<User>( HttpStatus.NO_CONTENT);
		}

	// --- Delete a User
		@RequestMapping(value="/users", method = RequestMethod.DELETE)
		public ResponseEntity<User> deleteAllUsers(){

			userService.deleteAllUsers();
			return new ResponseEntity<User>( HttpStatus.NO_CONTENT);
		}
	
}

@RestController

  • -@Controller + @ResponseBody 를 합친 어노테이션
  • RestController의 주용도는 Json 형태로 객체 데이터를 반환하는 것이다..
    데이터를 응답으로 제공하는 REST API를 개발할 때 주로 사용하며 객체를 ResponseEntity로 감싸서 반환한다.

ResponseEntity

  • ResponseEntity를 사용하면 header, body, HTTP.status의 정보를 가져올 수 있다.
  • body는 json타입으로 넘겨준다.

@PathVariable

  • restful 서비스의 url 형태이다. 
  • 클라이언트에서 URL에 파라미터를 전달하는 url에서 각 구분자에 들어오는 값을 처리해야 할 때 사용한다.
  • http://0.0.0.1/index/1 (restful 서비스의 url 형태 ) 와 같이 Rest api에서 값을 호출할 때 사용한다.

@PathVariable 사용법 

@RequsetMapping의 URL 정의 & Method내의 파라미터 부분에 정의

  • @RequestMapping 어노테이션 값으로 {템플릿 변수} 설정
  • @PathVariable 어노테이션으로 {템플릿변수}와 동일한 이름을 가지는 파라미터를 추가.
    -> RequestMapping에 있는 변수는 PathVariable 의 동일한 이름의 파라미터에 매핑된다.

 

 

exception 처리

 

 

@ExceptionHandler 를 사용해 custom exception 를 구현하여 예외를 처리한다.

 

@ExceptionHandler 

  • Controller계층에서 발생하는 에러를 잡아서 메서드로 처리해주는 기능이다.
    Service, Repository에서 발생하는 에러는 제외한다.

 

@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ErrorResponse> 
	handleUserNotFoundException(HttpServletRequest req, UserNotFoundException ex){
			
		String requestURL = req.getRequestURI().toString();
			
		ErrorResponse errorResponse = new ErrorResponse();
		errorResponse.setRequestURL(requestURL);
		errorResponse.setErrorCode("user.notfound.exception");
		errorResponse.setErrorMsg("User with id " + ex.getUserId()+" not found");
		
		return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.NOT_FOUND); // errorResponse가 body에 json형태로
}

@ExceptionHandler(UserDuplicatedException.class)
public ResponseEntity<ErrorResponse>
	handleUserDuplicatedException(HttpServletRequest req, UserDuplicatedException ex){
			
	String requestURL = req.getRequestURI().toString();
			
	ErrorResponse errorResponse = new ErrorResponse();
	errorResponse.setRequestURL(requestURL);
	errorResponse.setErrorCode("user.duplicated.exception");
	errorResponse.setErrorMsg("Unable to create. A user with name " + ex.getUsername() + " already exist ");
		
	return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.CONFLICT); // CONFLICT : 이미 존재
}

 

 

 

REST Api 테스트 

 

 

  • Client Program인 Postman사용 하여 테스트 진행

 

REST API의 HTTP Method

HTTP Method URI Operation
GET /api/users users 리스트를 반환한다
GET /api/users/1 ID가 1인 user를 반환한다
POST /api/users 새로운 user를 생성한다
PUT /api/users/3 ID가 3인 user를 업데이트한다
DELETE /api/users/4 ID가 4인 user를 삭제한다
DELETE /api/users 모든 users를 삭제한다

 

 

GET

 

 

  • user객체를 json포멧으로 컨버팅하여 response message 의 body에 담아 보낸다.
  • user의 내용이 json포맷으로 컨버팅 되어 보여지는 모습이다.

 

 

존재하지 않는 ID일 경우

  • usernotfoundexception 발생
  • 이에대한 handler인 usernotfoundhandler에의해 errorResponse에 내용이 담겨져 응답이 온다.

 

POST

 

requestmessage의 body부분에 raw에서 만들 사용자의 정보를 넣어준다.

이미 존재하는 user를 만들 경우

  • userduplicatedexception 발생. body에 json형태로 errorrequest가 날아온다.

 

 

정상적으로 create가 이루어졌을 경우 id가 5인user가 생성됨을 알 수 있다. 

HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/api/users/{id}").buildAndExpand(user.getId()).toUri());

header의 location에서 설정해준 내용이 나타난다.

 

DELETE

 

없는 사용자를 제거할 경우 404 Not Found

 

성공적 제거  204 No Content

return new ResponseEntity<User>( HttpStatus.NO_CONTENT);

 

request를 보냈을때 response를 확인 할 수 있다.

 

 

 

+ 추가

ControllerAdvice를 사용한 예외처리 통합

 

exception handler가 특정 controller 안의 method에 의해서만 실행되지 않고, 모든 controller에 적용되도록 설정한다.

 

 

@ControllerAdvice
public class GlobalExceptionController {

	@ExceptionHandler(UserNotFoundException.class)
	public ResponseEntity<ErrorResponse>
		handleUserNotFoundException(HttpServletRequest req, UserNotFoundException ex){
		
		String requestURL = req.getRequestURI().toString();
		
		ErrorResponse errorResponse = new ErrorResponse();
		errorResponse.setRequestURL(requestURL);
		errorResponse.setErrorCode("user.notfound.exception");
		errorResponse.setErrorMsg("User with id " + ex.getUserId()+" not found");
	
		return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.NOT_FOUND); // errorResponse가 body에 json형태로
	}
	
	@ExceptionHandler(UserDuplicatedException.class)
	public ResponseEntity<ErrorResponse>
		handleUserDuplicatedException(HttpServletRequest req, UserDuplicatedException ex){
		
		String requestURL = req.getRequestURI().toString();
		
		ErrorResponse errorResponse = new ErrorResponse();
		errorResponse.setRequestURL(requestURL);
		errorResponse.setErrorCode("user.duplicated.exception");
		errorResponse.setErrorMsg("Unable to create. A user with name " + 
										ex.getUsername() + " already exist ");
	
		return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.CONFLICT); // 이미 존재
	}
	
	
}

@ControllerAdvice

  • exception을 다른 controller에서 hander를 사용할 수 있도록 한다.
  • 모든 @Controller 즉, 전역에서 발생할 수 있는 예외를 잡아 처리해주는 annotation이다.

 

 


[Spring] @Controller와 @RestController 차이 - MangKyu's Diary (tistory.com)

 

[Spring] @Controller와 @RestController 차이

Spring에서 컨트롤러를 지정해주기 위한 어노테이션은 @Controller와 @RestController가 있습니다. 전통적인 Spring MVC의 컨트롤러인 @Controller와 Restuful 웹서비스의 컨트롤러인 @RestController의 주요한 차..

mangkyu.tistory.com

@ControllerAdvice, @ExceptionHandler를 이용한 예외처리 분리, 통합하기(Spring에서 예외 관리하는 방법, 실무에서는 어떻게?) (tistory.com)

 

@ControllerAdvice, @ExceptionHandler를 이용한 예외처리 분리, 통합하기(Spring에서 예외 관리하는 방법, 실

예외 처리 과정 프로그래밍에서 예외 처리는 아주 중요하면서도 아주 어렵다. 과하다할 만큼 상세하고 다양하게 예외를 잡아 처리해준다면, 클라이언트도 그렇고 서버도 그렇고 더 안정적인 프

jeong-pro.tistory.com

 

'Study > REST API' 카테고리의 다른 글

[REST API] REST API 이해하기  (0) 2022.08.07