
안녕하세요, 오늘은 Request Mapping 에 대해 정리해 보았습니다.
HTTP Request Parameter
http://localhost:8080/model/attribute?name=wonuk&age=100public class Member {
private String name;
private int age;
}
@Controller
public class RequestParamController {
@ResponseBody
@GetMapping("/request/param")
public String requestParam (
@RequestParam String name,
@RequestParam int age
) {
Membmer member = new Member();
member.setName(name);
member.setAge(age);
// or
// Membmer member = new Member(name, age);
return "success";
}
}
http://localhost:8080/model/attribute?name=wonuk&age=100@Data // 실제로는 사용하지 않고, 테스트 용도로 많이 사용 @Getter @Setter @Equals...등등
public class Member {
private String name
private int age;
}
@Controller
public class RequestParamController {
@ResponseBody
@GetMapping("/model/attribute")
public String modelAttribute (
@ModelAttribute Member member
) {
String memberName = member.getName();
int memberAge = member.getAge();
return "success";
}
}
name 이면 setName(value) 메서드를 호출한다age 에 int가 아닌 String 이 전달된다면?http://localhost:8080/model/attribute?name=wonuk&age=100@Data
public class Member {
private String name
private int age;
}
@Controller // + @Responsebody = @RestController
public class RequestParamController {
@ResponseBody
@GetMapping("/model/attribute")
public String modelAttribute (Member member) {
String memberName = member.getName();
int memberAge = member.getAge();
return "success";
}
}
String, int, Integer 와 같은 기본 타입은 @RequestParam과 Mapping한다.💡 지난시간 배운 @RequestParam과 오늘배울 @ModelAttribute는 GET 쿼리 파라미터와, POST HTML Form Data를 바인딩하는 방법입니다.HTTP Request Body
@Controller
public class RequestBodyStringController {
@PostMapping("/request-body/text")
public void requestBodyText(
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
ServletInputStream inputStream = request.getInputStream();
String bodyText = StreamUtils.copyToString(inputStream, StandardCharsets.UTF-8);
}
}

Request Header Content-Type : text/plain
코드예시2
@Controller
public class RequestBodyStringController {
@PostMapping("/request-body/text")
public void requestBodyText(
InputStream inputStream,
Writer responseWriter
) throws IOException {
String body = StreamUtils.copyToString(inputStream, StandardCharsets.UTF-8);
}
}
@Controller
public class RequestBodyStringController {
@PostMapping("/request-body/text")
public HttpEntity<String> requestBodyText(HttpEntity<String> httpEntity) {
// HttpMessageConverter가 동작해서 아래 코드가 동작하게됨
String body = httpEntity.getBody();
return new HttpEntity<>("success"); // 매개변수 = Body Message
}
}
@Controller
public class RequestBodyStringController {
@PostMapping("/request-body/text")
public HttpEntity<String> requestBodyText(RequestEntity<String> httpEntity) {
// HttpMessageConverter가 동작해서 아래 코드가 동작하게됨
String body = httpEntity.getBody();
// url, method 사용 가능
return new ResponseEntity<>("success", HttpStatus.CREATED); // Body Data, 상태코드
}
}
Spring은 Http RequestBody Message를 읽어서 String이나 Object로 자동으로 변환해준다.
이때HttpMessageConverter가 사용된다.
@Controller
public class RequestBodyStringController {
@ResponseBody
@PostMapping("/request-body/text")
public HttpEntity<String> requestBodyText(@RequestBody String body) {
// HttpMessageConverter가 동작해서 아래 코드가 동작하게됨
String bodyMessage = body;
return "success";
}
}
💡 Json은 @RestController 에서 가장 많이 사용되는 데이터 형식이다. 현재 대부분의 API는 Request, Response 모두 JSON 형태로 통신한다.Json
주의! Json 형태로 Data를 전송할 때는 Request Header의 content-type이
꼭 application/json 이여야한다
코드예시1(기존방식)
@Data
public class Member {
private String name;
private int age;
}
@Controller
public class JsonController {
private ObjectMapper objectMapper = new ObjectMapper();
@PostMapping("/request-body/json")
public void requestJson(
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
// request body message를 Read
ServletInputStream inputStream = request.getInputStream();
// UTF-8 형식의 String으로 변환한다.
String requestBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
// String requestBody를 ObjectMapper를 사용하여 변환 "{\"name\":\"wonuk\", \"age\":10}"
Member member =
objectMapper.readValue(requestBody, Member.class);
}
}



코드예시2(@RequestBody)
@Data
public class Member {
private String name;
private int age;
}
@Controller
public class JsonController {
private ObjectMapper objectMapper = new ObjectMapper();
@PostMapping("/request-body/json")
public String requestJson(@RequestBody String body) throws IOException {
Member member = objectMapper.readValue(requestBody, Member.class);
return "success";
}
}
@RequestBody를 사용하여 HTTP Request Body의 Data에 접근한다
@ModelAttribute 처럼 객체로 바로 반환은 안되는건가?
코드예시3(ObjectMapper 제거)
@Data
public class Member {
private String name;
private int age;
}
@Controller
public class JsonController {
@PostMapping("/request-body/json")
public String requestJson(@RequestBody Member member) {
Member requestBodymember = member;
return "success";
}
}
@RequestBody 어노테이션을 사용하면 Object를 Mapping할 수 있다.
HttpEntity<Member>, @RequestBody를 사용하면 HTTPMessageConverter가
Request Body의 Data를 개발자가 원하는 String, Object로 변환해준다.
JSON to Object의 Mapping까지 해준다.MappingJackson2HttpMessageConverter

@Data
public class Member {
private String name;
private int age;
}
@Slf4j
@Controller
public class JsonController {
@PostMapping("/request-body/json")
public String requestJson(@RequestBody Member member) {
Member requestBodymember = member;
log.info("name={}, age={}", member.getName(), member.getAge());
return "success";
}
}
member.getName() = null
member.getAge() = 0
값이 비어있는 형태(아무것도 하지않음)가 되버린다.
생략하면 @ModelAttribute가 되버리기 때문! 위에 기억해 달라고 했습니다!
꼭 Request Header의 contentType은 꼭 application/json 이여야한다
코드예시4(HttpEntity)
@Data
public class Member {
private String name;
private int age;
}
@Controller
public class JsonController {
@PostMapping("/request-body/json")
public String requestJson(
HttpEntity<Member> httpEntity
) {
// 값을 꺼내서 사용해야한다!
Member member = httpEntity; // .getBody();
return "success";
}
}
HttpEntity<Member> Generic Type으로 Member가 지정되어 있기때문에
해당 Class 로 반환된다.
코드예시5(@ResponseBody)
@Data
public class Member {
private String name;
private int age;
}
@Controller
public class JsonController {
@ResponseBody // 여기
@PostMapping("/request-body/json")
public String requestJson(@RequestBody Member member) {
return member; // 여기
}
}
@RequestBody 는 생략이 불가능하다. → @ModelAttribute가 적용되기 때문
HttpMessageConverter를 사용한다.
MappingJackson2HttpMessageConverter(application/json) 적용 Json → Object@ResponseBody
HttpMessageConverter가 동작한다.MaapingJackson2HttpMessageConverter 적용정적 리소스
/static/public/META-INF/resourcessrc/main/resources 위 4가지 경로는 Spring Boot에서 정적 resource를 보관하는 경로들이다.

src/main/resources/static/hello/world.html 디렉토리 구조라면http://localhost:8080/hello/world.html URL 로 리소스에 접근이 가능하다./static 대신 /public 혹은 /META-INF/resources 도 사용가능View Template(Server Side Rendering)
💡 Model은 View Template을 거쳐서 HTML 등이 동적으로 만들어지고 Client에 응답한다. Spring Boot는 기본적으로 View Template 경로를 제공한다. ex) `src/main/resources/templates`spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html // or jsp
@ResponseBody 가 없으면 View Resolver가 실행되며 View를 찾고 Rendering한다.@ResponseBody 가 있으면 HTTP Message Body에 return 문자열 값이 입력됨.@RequestMapping("/response/view")
public String responseView(Model model) {
// model.addAttribute("{viewTemplate에서 사용할 key값}", "{Value값}")
return "string";
}
// /response/view.html 과 Mapping됨
@RequestMapping("/response/view")
public void responseView(Model model) {
model.addAttribute("{viewTemplate에서 사용할 key값}", "{Value값}")
}
HTTP Message Body
💡 HTTP API(Rest API)를 만드는 경우에는 HTML이 아닌 Data를 전달한다. → HTTP Message Body에 Data를 JSON 형식으로 담아서 통신한다참고 : 정적 HTML, View Template 또한 HTTP Message Body에 담겨서 전달된다.
현재 설명하는 Response의 경우는 정적 HTML, View Template을 거치지 않고
직접 HTTP Response Message를 만들어 전달하는 경우를 말하는것.
예시코드1 (HttpServletResponse)
@Controller
public class ResponseBodyController {
@GetMapping("/response/body")
public void responseBody(
HttpServletResponse response
) throws IOException {
response.getWriter().write("data");
}
}
Response Body에 data 라는 문자열이 입력된채 응답한다.
기존 Servlet을 다룰 때 코드와 형태가 같다.
예시코드2(ResponseEntity<>)
@Controller
public class ResponseBodyController {
@GetMapping("/response/body")
public ResponseEntity<String> responseBody() {
return new ResponseEntity<>("data", HttpStatus.OK);
}
}
Response Body에 data라는 문자열과 HttpStatus.OK에 해당하는 상태코드를 반환한다.
ResponseEntity는 HttpEntity 를 상속받았다.
HttpEntity는 HTTP Message의 Header, Body 모두 가지고있다.예시코드3(@ResponseBody- TEXT, JSON)
// TEXT 데이터 통신
@Controller
public class ResponseBodyController {
@ResponseBody
@GetMapping("/response/body")
public String responseBody() {
return "data"; // HTTP Message Body에 "data"
}
}
// JSON 데이터 통신
@Controller
public class ResponseBodyController {
@ResponseBody
@GetMapping("/response/body")
public Data responseBody() {
Data data = new Data("field1", "field2");
return data; // HTTP Message Body에 JSON Member Object -> JSON
}
}
ResponseEntity와 같음@ResponseStatus 를 사용하여 상태코드를 지정할 수 있다.@Controller
public class ResponseBodyController {
@ResponseStatus(HttpStatus.OK)
@ResponseBody
@GetMapping("/response/body")
public Data responseBody() {
Data data = new Data("field1", "field2");
return data;
}
}
단, 응답 코드를 조건에 따라서 동적으로 변경할 수는 없다.
ex) 1번의 경우 OK, 2번의 경우 Created
예시코드4(ResponseEntity - JSON)
@ResponseBody
@Controller
public class ResponseBodyController {
@GetMapping("/response/body")
public ResponseEntity<Data> responseBody() {
Data data = new Data("field1", "field2");
return new ResponseEntity<>(Data, HttpStatus.OK);
}
}
@Controller 대신에 @RestController를 사용하면@ResponseBody가 적용된다@RestController이다.@ResponseBody 내부구조

@Target : @Target이 선언된 하위 어노테이션이 어떤 범위에 적용되는지 설정하는 어노테이션
ElementType Enum

@ResponseBody를 직접 적어주지 않는다Client에서 Server로 Data를 전달하는 세가지 방법
Spring(Server)에서 HTTP 응답을 Client에 전달하는 세가지 방법
오늘의 코드카타
class Solution {
public String solution(String rsp) {
String answer = "";
String[] arr = rsp.split("");
for (int i = 0; i < arr.length; i++) {
if (arr[i].equals("2")) {
answer += "0";
} else if (arr[i].equals("0")) {
answer += "5";
} else {
answer += "2";
}
}
return answer;
}
}
public class Main {
public static void main(String[] args) {
Solution solution = new Solution();
System.out.println(solution.solution("2"));
System.out.println(solution.solution("205"));
}
}
가위 바위 보