62일째 메시지 본문 읽기, 응답 개체(2023.03.16)

  • by

1) HttpEntity의 getBody() 메소드를 통해 메시지 본문 내용을 읽습니다.

package com.example.mvc.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.databind.ObjectMapper;

@RestController
public class RequestBodyController {

	private final Logger log = LoggerFactory.getLogger(RequestMappingController.class);
	
	ObjectMapper objectMapper = new ObjectMapper();
	
	@PostMapping("requestBody-json-v1")
	public String requestBodyJsonV1(HttpEntity<String> httpEntity) {
		log.info("httpEntity: {}", httpEntity);
		return "requestBody-json-v1";
	}
}

촬영된 로그 값:

httpEntity: <(user-agent:"PostmanRuntime/7.31.1", accept:"*/*", cache-control:"no-cache", postman-token:"62f7e5a9-fa9a-4d69-9e28-bc6ac6e2b17f", host:"localhost:9000", accept-encoding:"gzip, deflate, br", connection:"keep-alive", content-length:"0")>

ㄴ headers 정보


postman headers 정보


본문에 메시지를 추가한 후

httpEntity:HelloWorld,(user-agent:”PostmanRuntime/7.31.1″, accept:”*/*”, cache-control:”no-cache”, postman-token:”a2741672-735f-463d-8836-d7aaecd47b64″, host: “localhost:9000″, accept-encoding:”gzip, deflate, br”, connection:”keep-alive”, content-length:”10″, Content-Type:”text/plain;charset=UTF-8″) >

빨간 부분이 몸에서 나온 메시지


log에 .getBody 메서드를 사용하면 본문 메시지 만 가져옵니다.

HttpEntity에는 헤더 값도 있고 바디 값도 있다.

따라서 .getBody 메소드를 사용하여 바디 값의 메시지를 얻을 수 있습니다.

2. @RequestBody 어노테이션을 사용하여 본문 메시지 가져오기

package com.example.mvc.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.databind.ObjectMapper;

@RestController
public class RequestBodyController {

	private final Logger log = LoggerFactory.getLogger(RequestMappingController.class);
	
	ObjectMapper objectMapper = new ObjectMapper();
	
	@PostMapping("requestBody-json-v2")
	public String requestBodyJsonV2(@RequestBody String messageBody) {
		log.info("messageBody: {}", messageBody);
		return "requestBody-json-v2";
	}
}


로그

JSON(JavaScript Object Notation)

– 데이터 전송 형식

1) JSON

{“data1″:”데이터 1”,

“data2″:”데이터 2”}

2) xml

<タグ名>

데이터

String type 메시지 대신 JSON 유형의 메시지 입력


json 입력

package com.example.mvc.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@RestController
public class RequestBodyController {

	private final Logger log = LoggerFactory.getLogger(RequestMappingController.class);
	
	ObjectMapper objectMapper = new ObjectMapper();

	@PostMapping("requestBody-json-v2")
	public String requestBodyJsonV2(@RequestBody String messageBody) throws JsonMappingException, JsonProcessingException {
		log.info("messageBody: {}", messageBody);
		MemberData data = objectMapper.readValue(messageBody, MemberData.class);
		log.info("messageBody: {}", data);
		return "requestBody-json-v2";
	}
}

log= messageBody: MemberData (id=null, name=홍길동, age=20)

3) @RequestBody 어노테이션에서 객체 타입의 파라미터를 받는다.


package com.example.mvc.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@RestController
public class RequestBodyController {

	private final Logger log = LoggerFactory.getLogger(RequestMappingController.class);
	
	ObjectMapper objectMapper = new ObjectMapper();

	@PostMapping("requestBody-json-v3")
	public String requestBodyJsonV3(@RequestBody MemberData memberData) {
		log.info("memberData: {}", memberData);
		return "requestBody-json-v3";
	}
}

매개 변수로 MemberData 형식의 memberData

log = memberData: MemberData (id=null, name=홍길동, age=20)

4) return 타입을 MemberData 타입으로 수신


package com.example.mvc.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@RestController
public class RequestBodyController {

	private final Logger log = LoggerFactory.getLogger(RequestMappingController.class);
	
	ObjectMapper objectMapper = new ObjectMapper();

	@PostMapping("requestBody-json-v4")
	public MemberData requestBodyJsonV4(@RequestBody MemberData memberData) {
		log.info("memberData: {}", memberData);
		return memberData;
	}
}

return 형을 MemberData 에 직접 지정하면


즉시 확인 가능

@RequestBody를 생략하면 @ModelAttribute가 자동으로 붙어 요청 매개 변수를 처리합니다.

생략하면 값을받을 수 없습니다.

두 가지 차이

@ModelAttribute는 매개 변수로 모든 정보를 포함하는 전송

@RequestBody가 메시지를 가져옵니다.

+ JSON에 저장할 수 있는 데이터 유형은 JavaScript가 처리할 수 있는 모든 데이터 유형입니다.

기본 데이터형에서 배열, 객체까지

지금까지 한 일

1. 요청 매핑

– @RequestMapping

– @GetMapping

– @PostMapping

2. 요청 파라미터(

– @RequestParam

– @ModelAttribute

ㄴ 이것은 2개는 get이든 post이든, 매개변수로 정보를 받는 것입니다.

3. HTTP Message Body에 데이터를 직접 저장하고 전달

– @RequestBody

지금 할

4. 응답 객체

– @HttpServletResponse : HTTP 응답 메시지를 구문 분석하는 객체

설정: HTTP 응답 코드(200 ok, 404 not fount…), 헤더, 바디,

응답 방식

1) 간단한 텍스트(return “ok”; …)

2) HTML

3) JSON, XML 등의 API, 데이터 전송 형식으로 응답 가능

1) ModelAndView를 사용하여 뷰 템플릿 찾기

@RestController 대신 @Controller

package com.example.mvc.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class ResponseViewContoller {
	
	private final Logger log = LoggerFactory.getLogger(RequestParamContoroller.class);

	@GetMapping("response-view-v1")
	public ModelAndView responseViewV1() {
		ModelAndView view = new ModelAndView("response/hello").addObject("data", "Hello World");
		return view;
	}
}

response 폴더 만들기 -> hello.html 생성 후

<!
DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <p th:text="${data}"></p> </body> </html>


http://localhost:9000/response-view-v1

페이지 소스를 보면

<!
DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <p>Hello World</p> </body> </html>

이렇게 뜸

2) 뷰 리졸버에서 뷰 템플릿 찾기

package com.example.mvc.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class ResponseViewContoller {

	private final Logger log = LoggerFactory.getLogger(ResponseViewContoller.class);

	@GetMapping("response-view-v2")
	public String responseViewV2(Model model) {
		model.addAttribute("data", "Hello Spring");
		return "response/hello";
	}
}


모델에 포함된 데이터의 이름과 내용을 지정합니다.

hello.html에 data와 model에 저장된 data라는 이름이 같으면 연결합니다.

return 값은 경로를 포함하는 html 파일 이름만 씁니다.

※build.gradle에 thymeleaf라는 뷰 템플릿이 링크되어 있어야 합니다.


but. jsp 더 자세히

3) 리턴 타입을 void 로 주면 url 리퀘스트 값과 같은 html 를 찾는다

package com.example.mvc.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class ResponseViewContoller {

	private final Logger log = LoggerFactory.getLogger(ResponseViewContoller.class);

	@GetMapping("response/hello")
	public void responseViewV3(Model model) {
		model.addAttribute("data", "Hello World");
	}
}


1) 상태 코드를 함께 보낼 때

package com.example.mvc.controller;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

// 응답값이 html이 아닌 api 호출 방식
@RestController
public class ResponseBodyController {

	@GetMapping("responseBody-v1")
	public ResponseEntity<String> responseBodyV1() {
		return new ResponseEntity<>("ok", HttpStatus.OK);
	}
}

응답 코드, 헤더 및 본문을 모두 수용할 수 있는 데이터 유형 ResponseEntity<>(generic이므로, 좋아하는 데이터형을 넣으면 좋다)


api는 화면이 아닌 데이터를 제공하는 것이므로 잘 작동하는지 여부는 상태 코드를 확인할 수 있습니다.

상태 코드를 함께 보내는 것이 ResponseEntity <>

403: Forbidden (권한 없음)

404: Not Found(데이터를 찾을 수 없을 때)

2) 상태 코드는 불필요하며 메시지 본문만 보고 싶은 경우

package com.example.mvc.controller;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

// 응답값이 html이 아닌 api 호출 방식
@RestController
public class ResponseBodyController {

	@GetMapping("responseBody-v2")
	public String responseBodyV2() {
		return "ok";
	}
}


3) 상태값과 바디에 들어간 데이터값을 함께 보낼 때

package com.example.mvc.controller;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

// 응답값이 html이 아닌 api 호출 방식
@RestController
public class ResponseBodyController {

	@GetMapping("responseBody-v3")
	public ResponseEntity<MemberData> responseBodyV3() {
		MemberData data = new MemberData();
		data.setId("hong");
		data.setName("홍길동");
		data.setAge(25);
		return new ResponseEntity<MemberData>(data, HttpStatus.CREATED);
	}
}


바디에 들어간 데이터 값은 JSON 형식으로 출력

4) 3번에 스테이터스 코드가 불필요할 때

package com.example.mvc.controller;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

// 응답값이 html이 아닌 api 호출 방식
@RestController
public class ResponseBodyController {
	
	@GetMapping("responseBody-v4")
	public MemberData responseBodyV4() {
		MemberData data = new MemberData();
		data.setId("hong");
		data.setName("홍길동");
		data.setAge(25);
		return data;
	}
}


+ 4에서 @ResponseStatus 어노테이션으로 상태 코드를 별도로 제공 할 수 있지만,

그런 경우에는 세 번 사용하는 것이 좋습니다.

package com.example.mvc.controller;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

// 응답값이 html이 아닌 api 호출 방식
@RestController
public class ResponseBodyController {

	@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
	@GetMapping("responseBody-v4")
	public MemberData responseBodyV4() {
		MemberData data = new MemberData();
		data.setId("hong");
		data.setName("홍길동");
		data.setAge(25);
		return data;
	}
}

+ 다음 주 프로젝트를 위해 미리 작성