티스토리 뷰
[Spring]Spring MVC - Controller 클래스에 ResponseEntity 적용
Vagabund.Gni 2022. 8. 22. 20:29Spring MVC - Controller + Service
[Spring]Spring MVC - Controller 클래스 구조 생성 및 설계
[Spring]Spring MVC - Controller 클래스에 핸들러 메서드(Handler Method) 구현
[Spring]Spring MVC - Controller 클래스에 ResponseEntity 적용
[Spring]Spring MVC - Controller 클래스에 DTO 적용
[Spring]Spring MVC - DTO 유효성 검증(Validation)
[Spring]Spring MVC - DI를 통한 API 계층 ↔ 서비스 계층 연동
[Spring]Spring MVC - 매퍼(Mapper)를 이용한 DTO 클래스 ↔ 엔티티(Entity) 클래스 매핑
[Spring]Spring MVC - @ExceptionHandler를 이용한 예외처리
[Spring]Spring MVC - @RestControllerAdvice를 이용한 예외처리
Spring Data JDBC
[Spring]JDBC(Java DataBase Connectivity)
[Spring]Spring Data JDBC, Spring Data JDBC 사용법
[Spring]Spring Data JDBC - 도메인 엔티티&테이블 설계
Spring Data JPA
[Spring]JPA(Java Persistence API)
[Spring]JPA - Entity ↔ DB Table Mapping
[Spring]JPA - Entity ↔ Entity Mapping
[Spring]Spring Data JPA - 데이터 액세스 계층 구현
지난 글에서 컨트롤러 클래스를 작성하며 두 가지 개선할 부분을 지적했다.
- 수작업으로 JSON 문자열을 만들어 주는 부분 - 오타가 나기 쉽고 코드와 그 작성 시간이 길어진다.
- @RequestParam 애너테이션을 사용한 요청 파라미터 수신 - 파라미터가 많아질수록 코드와 그 작성 시간이 길어진다.
2022.08.22 - [개발/Spring] - [Spring]Spring MVC - Controller 클래스에 핸들러 메서드(Handler Method) 구현
이번 글에선 마지막으로 작성했던 MemberController를 가져와 리스트의 첫 번째 항목을 개선해 보자.
// 개선 이전 코드
package com.gnidinger.member;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping(value = "/v1/members", produces = {MediaType.APPLICATION_JSON_VALUE})
public class MemberController {
@PostMapping
public String postMember(@RequestParam("email") String email,
@RequestParam("name") String name,
@RequestParam("phone") String phone) {
System.out.println("# email: " + email);
System.out.println("# name: " + name);
System.out.println("# phone: " + phone);
String response =
"{\"" +
"email\":\""+email+"\"," +
"\"name\":\""+name+"\",\"" +
"phone\":\"" + phone+
"\"}";
return response;
}
@GetMapping("/{member-id}")
public String getMember(@PathVariable("member-id")long memberId) {
System.out.println("# memberId: " + memberId);
// not implementation
return null;
}
@GetMapping
public String getMembers() {
System.out.println("# get Members");
// not implementation
return null;
}
}
수작업으로 JSON 문자열을 만들어 주는 부분을 개선하기 위해 ResponseEntity를 사용하는데,
먼저 ResponseEntity 클래스에 대해 짧게 알아보고 가자.
- ResponseEntity
- HttpEntity - HTTP 요청(Request)과 응답(Response)에 해당하는 HttpHeader와 HttpBody를 포함하는 클래스
- ResponseEntity - HttpEntity 클래스를 상속받아 HttpHeaders, HttpBody, HttpStatus를 포함
- 주로 Controller 클래스의 핸들러 메서드(Handler Method)에서 요청 처리에 대한 응답을 구성하는 데 사용
public class HttpEntity<T> {
private final HttpHeaders headers;
@Nullable
private final T body;
}
public class ResponseEntity<T> extends HttpEntity<T> {
private final Object status;
public ResponseEntity(HttpStatus status) {
this(null, null, status);
}
public ResponseEntity(@Nullable T body, HttpStatus status) {
this(body, null, status);
}
// ...
}
계속해서 ResponseEntity와 Map을 이용해 개선된 코드를 보자.
package com.gnidinger.member;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/v1/members") // (1) produces 설정 제거
public class MemberController {
@PostMapping
public ResponseEntity postMember(@RequestParam("email") String email,
@RequestParam("name") String name,
@RequestParam("phone") String phone) {
// (2) JSON 문자열 수작업을 Map 객체로 대체
Map<String, String> map = new HashMap<>();
map.put("email", email);
map.put("name", name);
map.put("phone", phone);
// (3) 리턴 값을 ResponseEntity 객체로 변경
return new ResponseEntity<>(map, HttpStatus.CREATED);
}
@GetMapping("/{member-id}")
public ResponseEntity getMember(@PathVariable("member-id") long memberId) {
System.out.println("# memberId: " + memberId);
// not implementation
// (4) 리턴 값을 ResponseEntity 객체로 변경
return new ResponseEntity<>(HttpStatus.OK);
}
@GetMapping
public ResponseEntity getMembers() {
System.out.println("# get Members");
// not implementation
// (5) 리턴 값을 ResponseEntity 객체로 변경
return new ResponseEntity<>(HttpStatus.OK);
}
}
- (1), (2) - produces 속성 생략 및 JSON 문자열 수작업이 Map 객체로 대체
- Map 객체를 리턴하게 되면 스프링 MVC 내부에서 JSON 형식으로 자동 변환
- 따라서 @RequestMapping 부분의 produces 속성 생략 가능
- (3) 리턴 값으로 JSON 문자열(String)을 리턴하던 부분이 ResponseEntity 객체 리턴으로 변경
- new ResponseEntity<>(map, HttpStatus.CREATED); 와 같이 응답 데이터뿐 아니라 응답 상태까지 전달
- HTTP 응답 상태를 명시적으로 전달함으로써 클라이언트의 요청을 서버가 어떻게 처리했는지 확인 가능
- (4), (5) 나머지 핸들러 메서드 역시 ResponseEntity 객체를 리턴하는 것으로 변경 및 응답 상태도 전달하도록 수정
개선 후 동일한 요청을 보냈을 때 응답 상태가 ‘200 OK’에서 ‘201 Created’로 바뀐 것을 확인할 수 있다.
이어서 CoffeeController 클래스와 OrderController 클래스를 개선하면 아래와 같이 된다.
package com.gnidinger.coffee;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/v1/coffees")
public class CoffeeController {
@PostMapping
public ResponseEntity postCoffee(@RequestParam("engName") String engName,
@RequestParam("korName") String korName,
@RequestParam("price") String price) {
Map<String, String> map = new HashMap<>();
map.put("engName", engName);
map.put("korName", korName);
map.put("price", price);
return new ResponseEntity<>(map, HttpStatus.CREATED);
}
@GetMapping("/{coffee-id}")
public ResponseEntity getCoffee(@PathVariable("coffee-id") long coffeeId) {
System.out.println("# coffeeId: " + coffeeId);
// not implementation
return new ResponseEntity<>(HttpStatus.OK);
}
@GetMapping
public ResponseEntity getCoffees() {
System.out.println("# get Coffees");
// not implementation
return new ResponseEntity<>(HttpStatus.OK);
}
}
package com.gnidinger.order;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/v1/orders")
public class OrderController {
@PostMapping
public ResponseEntity postOrder(@RequestParam("memberId") long memberId,
@RequestParam("coffeeId") long coffeeId) {
Map<Object, Object> map = new HashMap<>();
map.put("memberId", memberId);
map.put("coffeeId", coffeeId);
return new ResponseEntity<>(map, HttpStatus.CREATED);
}
@GetMapping("/{order-id}")
public ResponseEntity getOrder(@PathVariable("order-id") long orderId) {
System.out.println("# orderId: " + orderId);
// not implementation
return new ResponseEntity<>(HttpStatus.OK);
}
@GetMapping
public ResponseEntity getOrders() {
System.out.println("# get Orders");
// not implementation
return new ResponseEntity<>(HttpStatus.OK);
}
}
'Java+Spring > Spring' 카테고리의 다른 글
[Spring]Spring MVC - DI를 통한 API 계층 ↔ 서비스 계층 연동 (2) | 2022.08.23 |
---|---|
[Spring]Spring MVC - DTO 유효성 검증(Validation) (2) | 2022.08.23 |
[Spring]Spring MVC - Controller 클래스에 DTO 적용 (0) | 2022.08.22 |
[Spring]Spring MVC - Controller 클래스에 핸들러 메서드(Handler Method) 구현 (0) | 2022.08.22 |
[Spring]Spring MVC - Controller 클래스 구조 생성 및 설계 (0) | 2022.08.22 |
[Spring]Spring MVC (4) | 2022.08.20 |
- Total
- Today
- Yesterday
- 파이썬
- 맛집
- 알고리즘
- 중남미
- 자바
- 여행
- 면접 준비
- 야경
- 기술면접
- RX100M5
- BOJ
- Python
- 유럽
- 지지
- Algorithm
- 세모
- spring
- a6000
- 백준
- java
- 동적계획법
- Backjoon
- 리스트
- 세계여행
- 유럽여행
- 칼이사
- 스프링
- 남미
- 세계일주
- 스트림
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |