Restful web service를 스프링에서 어떻게 구현할 수 있을까?
기존의 Spring 방식은 밑의 방식과 같다.
request를 받으면 Dispatcher Servlet이 받고, Handler Mapping을 통해 어떤 컨트롤러로 보낼지 결정해서 Service, DAO를 거쳐 View를 만들어 다시 Response로 Client로 보내주는 방식이였다.
Controller는 단순히 object(객체)를 return한다.
이 object data(객체데이터)가 json/xml 형태로 HTTP response 메시지에 담겨서 전달이 된다.
@RestController, @RequestBody, ResponseEntity class, @PathVariable을 통해 REST API를 구현하게 된다.
1) @ResonseBody 어노테이션
@Controller
@RequestMapping("/rest/cart")
public class CartResources {
@RequestMapping("/{cartId}")
public @ResponseBody Cart getCartById (@PathVariable(value = "cartId") int cartId) {
return cartService.getCartById(cartId);
}
}
- return되는 Cart가 ResponseBody에 담아서 넣어주게 된다.
- spring 3 부터 지원이됨.
- return 하는 객체는 json 형태로 serialize해준다.
2) @RestController 어노테이션
@RestController
@RequestMapping("/rest/cart")
public class CartResources {
@RequestMapping("/{cartId}")
public Cart getCartById (@PathVariable(value = "cartId") int cartId) {
return cartService.getCartById(cartId);
}
}
- spring 4.0 에서 추가됨.
- @Controller + @ResponseBody 라고 보면된다. -> @ResponseBody안써두되고, @RestController만 달아주면 된다.
3) @PathVariable 어노테이션
@RestController
@RequestMapping("/rest/cart")
public class CartResources {
@RequestMapping("/{cartId}")
public Cart getCartById (@PathVariable(value = "cartId") int cartId) {
return cartService.getCartById(cartId);
}
}
- @RequestMapping("/{cartId}") 에 cartId에 넣어줌
4) ResponseEntity <T> class
- status code, headers, body 이렇게 3가지의 내용을 Response에 담아야하는데 그걸 담아주는 객체가 ResponseEntity 이다.
- 밑의 표처럼 몇가지 생성자가 있다.
Constructor | Description |
ResponseEntity (HttpStatus status) |
Create a new ResponseEntity with the given status code, and no body nor headers. |
ResponseEntity (MultiValueMap<String,String> headers, HttpStatus status) |
Create a new ResponseEntity with the given headers and status code, and no body. |
ResponseEntity (T body, HttpStatus status) |
Create a new ResponseEntity with the given body and status code, and no headers. |
ResponseEntity (T body, MultiValueMap<String,String> headers, HttpStatus status) |
Create a new ResponseEntity with the given body, headers, and status code. |
@RestController
@RequestMapping("/api")
public class RestApiController {
@Autowired
private UserService userService;
@RequestMapping(value = "/users", method = RequestMethod.GET)
public ResponseEntity<List<User>> listAllUsers() {
List<User> users = userService.findAllUsers();
if (users.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<List<User>>(users, HttpStatus.OK);
}
}
5) @RequestBody 어노테이션
- client가 정보를 보낼때 json형태로 보내는데 이것을 받아서 Deserialization해서 필드에 넣어주기를 원함.
=> 그렇게 스프링에게 하도록 해주는 것이 @RequestBody 어노테이션이라고 보면된다.
@RequestMapping(value = "/users", method = RequestMethod.POST)
public ResponseEntity<Void> createUser(@RequestBody User user, UriComponentsBuilder ucBuilder) {
if (userService.isUserExist(user)) {
throw new UserDuplicateException(user);
}
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);
}
1) REST API 정의
HTTP Method | URI | Operation |
GET | /api/users | returns a list of users |
GET | /api/users/1 | returns the user with ID 1 |
POST | /api/users | creates a new user |
PUT | /api/users/3 | updates the user with ID 3 |
DELETE | /api/users/4 | deletes the user with ID 4 |
DELETE | /api/users | deletes all the users |
2) Dependencies 추가
<!-- jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
3) Rest Client (Postman)
4) CRUD 과정
@RestController // @Controller + @ResponseBody
@RequestMapping("/api")
public class RestApiController {
@Autowired
UserService userService;
//Retrieve All Users
@GetMapping(value ="/users")
public ResponseEntity<List <User>> listAllUsers(){//status, header, body
List<User> users = userService.findAllUsers();
if(users.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<List<User>>(users, HttpStatus.OK);
//body(json), status
}
@GetMapping(value ="/users/{id}")
public ResponseEntity<User> getUser(@PathVariable("id") long id){
User user = userService.findById(id);
if(user == null) {
//to do list: custom exception
throw new UserNotFoundException(id);
}
return new ResponseEntity<User>(user, HttpStatus.OK);
}
//Create a User
@PostMapping(value="/users")
public ResponseEntity<Void> createUser(@RequestBody User user, UriComponentsBuilder ucBuilder){
//중복확인
if(userService.doesUserExist(user)) {
//to do list: exception
throw new UserDuplicatedException(user.getName());
}
userService.saveUser(user);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/api/users/{id}").buildAndExpand(user.getId()).toUri());
//헤더에 location을 준다.
return new ResponseEntity<>(headers, HttpStatus.CREATED);
}
//Update a User
@PutMapping(value="/users/{id}")
public ResponseEntity<User> updateUser(@PathVariable("id") long id, @RequestBody User user){
User currentUser = userService.findById(id);
if(currentUser == null) {
//to do list: custom exception
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);
}
@DeleteMapping(value="/users/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable("id") long id){
User user = userService.findById(id);
if(user == null) {
//to do list: custom exception
throw new UserNotFoundException(id);
}
userService.deleteUserById(id);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@DeleteMapping(value="/users")
public ResponseEntity<Void> deleteAllUser(){
userService.deleteAllUsers();
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
}
'Backend > Spring & SpringBoot' 카테고리의 다른 글
[JPA] JPA / Hibernate Cascade Types 요약 (0) | 2022.03.09 |
---|---|
[Spring Boot] Spring Boot 의 특징 (0) | 2022.03.08 |
Restful Web Service (0) | 2022.03.07 |
[Spring Boot] Spring Data JPA의 사용법과 사용이유, 예시 (0) | 2022.03.07 |
[Spring Boot] Spring에서의 Hibernate 사용법 (0) | 2022.03.07 |