Spring MVC ๊ธฐ๋ณธ ๊ธฐ๋ฅ - ์์ฒญ ๋งคํ @RequestMapping, @RequestParam
by rlaehddnd0422์์ฒญ ๋งคํ
MappingController.java
@RequestMapping ์ถ์ฝ - @GetMapping, @PostMapping ๋ฑ๋ฑ ..
@RestController
public class MappingController {
private Logger log = LoggerFactory.getLogger(getClass());
/**
ํธ๋ฆฌํ @RequestMapping ์ถ์ฝ ์ด๋
ธํ
์ด์
@GetMapping
@PostMapping
@DeleteMapping
@PatchMapping
@PutMapping
*/
@GetMapping(value = "/hello-basic")
public String helloBasic() {
log.info("helloBasic");
return "ok";
}
@RestController
: @Controller๋ ๋ฐํ ๊ฐ์ด String ์ด๋ฉด ๋ทฐ ์ด๋ฆ์ผ๋ก ์ธ์ํด์ ๋ทฐ๋ฅผ ์ฐพ๊ณ ๋ทฐ๋ฅผ ๋ ๋๋ง ํ๋ ๋ฐ๋ฉด @RestController๋ ๋ฐํ ๊ฐ์ผ๋ก ๋ทฐ๋ฅผ ์ฐพ๋ ๊ฒ ์๋๋ผ, String์ HTTP ๋ฐ๋์ ๋ฐ๋ก ์ ๋ ฅํฉ๋๋ค.
@RequestMapping("/hello-basic")
: /hello-basic URL์ด ํธ์ถ๋๋ฉด ์ด ๋ฉ์๋๊ฐ ์คํ๋๋๋ก ๋งคํํ์ต๋๋ค.
๋๋ถ๋ถ์ ์์ฑ์ ๋ฐฐ์ด[]๋ก ์ ๊ณตํ๊ธฐ ๋๋ฌธ์ ๋ค์ค ์ค์ ๋ํ ๊ฐ๋ฅํฉ๋๋ค.
๋ฉ์๋ ๋ํ ์ถ์ฝ ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํด์ ์ง์ ํ ์ ์์ต๋๋ค.
@GetMapping : GET ์์ฒญ์ผ ๊ฒฝ์ฐ๋ง ํธ์ถ (= @RequestMapping(value="", method = RequestMethod.GET)
@PostMapping : Post ์์ฒญ์ผ ๊ฒฝ์ฐ๋ง ํธ์ถ
@DeleteMapping : Delete ์์ฒญ์ผ ๊ฒฝ์ฐ๋ง ํธ์ถ
@PatchMapping : Patch ์์ฒญ์ผ ๊ฒฝ์ฐ๋ง ํธ์ถ
@PutMapping : Put ์์ฒญ์ผ ๊ฒฝ์ฐ๋ง ํธ์ถ
Logic : /hello-basic URL ํธ์ถ โถ๏ธ helloBasic() ๋ฉ์๋ ์คํ โถ๏ธ helloBasic log โถ๏ธ HTTP ๋ฐ๋์ "ok" ๋ฆฌํด
@PathVariable ๊ฒฝ๋ก ๋ณ์
/**
@PathVariable
*/
@GetMapping("/mapping/{userId}/{orderId}")
public String mappingPath(@PathVariable("userId") String userId, @PathVariable("orderId") String orderId) {
log.info("mappingPath userId ={}, orderId={}", userId, orderId);
return "Ok";
}
@PathVariable
: ๋ฉ์๋ ๋ด๋ถ์ @PathVariable๋ฅผ ์ฌ์ฉํด ๊ฒฝ๋ก๋ณ์๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
โ๏ธ@PathVariable ๋ณ์ ์ด๋ฆ๊ณผ ๋งคํ๋ URL ๋ณ์ ์ด๋ฆ์ด ๊ฐ๋ค๋ฉด @PathVariable์ ์๋ตํ ์ ์์ต๋๋ค.
* @PathVariable("userId") String userId, @PathVariable("orderId") String orderId โถ๏ธ @PathVariable String userId, @PathVariable String orderId
@RequestMapping - ํน์ ํ๋ผ๋ฏธํฐ ์กฐ๊ฑด ๋งคํ (params)
/**
* ํ๋ผ๋ฏธํฐ๋ก ์ถ๊ฐ ๋งคํ
* params="mode",
* params="!mode"
* params="mode=debug"
* params="mode!=debug" (! = )
* params = {"mode=debug","data=good"}
*/
@GetMapping(value = "/mapping-param", params = "mode=debug")
public String mappingParam() {
log.info("mappingParam");
return "ok";
}
ํน์ ํ๋ผ๋ฏธํฐ๊ฐ ์๊ฑฐ๋ ์๋ ์กฐ๊ฑด์ ์ถ๊ฐํ ์ ์์ต๋๋ค. ์ ์ฌ์ฉํ์ง ์์ต๋๋ค.
์คํ : localhost:8080/mapping-param?mode=debug
@RequestMapping - ํน์ ํค๋ ์กฐ๊ฑด ๋งคํ (header)
/**
*ํน์ ํค๋๋ก ์ถ๊ฐ ๋งคํ
* headers="mode",
* headers="!mode"
* headers="mode=debug"
* headers="mode!=debug" (! = )
*/
@GetMapping(value = "/mapping-header", headers = "mode=debug")
public String mappingHeader() {
log.info("mappingHeader");
return "ok";
}
ํ๋ผ๋ฏธํฐ์ ์ ์ฌํ์ง๋ง HTTP ํค๋๋ฅผ ์ฌ์ฉํฉ๋๋ค.
ํ ์คํธ ํ๊ธฐ ์ํด์๋ Postman์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
@RequestMapping - ํค๋ ๊ธฐ๋ฐ ์ถ๊ฐ ๋งคํ Media Type (consumes)
/**
* Content-Type ํค๋ ๊ธฐ๋ฐ ์ถ๊ฐ ๋งคํ Media Type
* consumes="application/json"
* consumes="!application/json"
* consumes="application/*"
* consumes="*\/*"
* MediaType.APPLICATION_JSON_VALUE
*/
@PostMapping(value = "/mapping-consume", consumes = "application/json")
public String mappingConsumes() {
log.info("mappingConsumes");
return "ok";
}
HTTP ์์ฒญ์ Content-Type ํค๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ฏธ๋์ด ํ์ ์ผ๋ก ๋งคํํฉ๋๋ค.
๋ง์ฝ ๋ง์ง ์์ผ๋ฉด HTTP 415 ์ํ์ฝ๋(Unsupported Media Type)๋ฅผ ๋ฆฌํดํฉ๋๋ค.
Accept ํค๋ ๊ธฐ๋ฐ Media Type ์ฝํ ์ธ ๋ค๊ณ ์์์ด์ ( produces )
Accpet ํค๋๋ฅผ ํตํด ํด๋ผ์ด์ธํธ๋ ์๋ฒ๋ก๋ถํฐ ๋ฐ๊ณ ์ ํ๋ ๋ฐ์ดํฐ ํ์์ ์ง์ ํ ์ ์์์ต๋๋ค.
https://rlaehddnd0422.tistory.com/45
/**
* Accept ํค๋ ๊ธฐ๋ฐ Media Type ( ์ฝํ
์ธ ๋ค๊ณ ์์์ด์
)
* produces = "text/html"
* produces = "!text/html"
* produces = "text/*"
* produces = "* \/*"
*/
@PostMapping(value = "/mapping-produce", produces = "text/html")
public String mappingProduces() {
log.info("mappingProduces");
return "ok";
}
HTTP ์์ฒญ์ Accept ํค๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ฏธ๋์ด ํ์ ์ผ๋ก ๋งคํํฉ๋๋ค.
๋ง์ฝ ๋ง์ง ์์ผ๋ฉด HTTP 406 ์ํ์ฝ๋(Not Acceptable)๋ฅผ ๋ฐํํฉ๋๋ค.
produces ํ๋ผ๋ฏธํฐ ์์produces = "text/plain" produces = {"text/plain", "application/*"} produces = MediaType.TEXT_PLAIN_VALUE produces = "text/plain;charset=UTF-8"
์์ฒญ ๋งคํ - API ์์
@RestController // @Controller + @ResponseBody
@RequestMapping("/mapping/users")
public class MappingClassController {
/**
* ํ์ ๊ด๋ฆฌ API
*
* ํ์ ๋ชฉ๋ก ์กฐํ: GET /users
* ํ์ ๋ฑ๋ก: POST /users
* ํ์ ์กฐํ: GET /users/{userId}
* ํ์์์ : PATCH /users/{userId}
* ํ์ ์ญ์ : DELETE /users/{userId}
*/
@GetMapping
public String user()
{
return "get users";
}
@PostMapping
public String addUser()
{
return "post user";
}
@GetMapping("/{userId}")
public String findUser(@PathVariable String userId)
{
return "get userId=" + userId;
}
@PatchMapping("/{userId}")
public String updateUser(@PathVariable String userId)
{
return "update userId=" + userId;
}
@DeleteMapping("/{userId}")
public String deleteUser(@PathVariable String userId)
{
return "delete userId=" + userId;
}
}
- @RequestMapping("/mapping/users") : ํด๋์ค ๋ ๋ฒจ์ ๋งคํ ์ ๋ณด๋ฅผ ๋๋ฉด ๋ฉ์๋ ๋ ๋ฒจ์์ ํด๋น ์ ๋ณด๋ฅผ Prefix๋ก ์ฌ์ฉํฉ๋๋ค.
- ์ด์ ๋งคํ ๋ฐฉ๋ฒ์ ์ดํดํ์ผ๋, ์ด์ ๋ถํฐ HTTP ์์ฒญ์ด ๋ณด๋ด๋ ๋ฐ์ดํฐ๋ค์ ์คํ๋ง MVC๋ก ์ด๋ป๊ฒ ์กฐํํ๋์ง ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
HTTP ์์ฒญ - ๊ธฐ๋ณธ, ํค๋ ์กฐํ
์ด๋ ธํ ์ด์ ๊ธฐ๋ฐ์ ์คํ๋ง ์ปจํธ๋กค๋ฌ๋ ๋ค์ํ ํ๋ผ๋ฏธํฐ๋ฅผ ์ง์ํฉ๋๋ค.
Request, Response์ ๋ํ HTTP ํค๋ ๋ํ ์กฐํ๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
์ฝ๋๋ฅผ ํตํด ์์๋ณด๊ฒ ์ต๋๋ค.
@Slf4j
@RestController
public class RequestHeaderController {
@RequestMapping("/headers")
public String headers(HttpServletRequest request,
HttpServletResponse response,
HttpMethod httpMethod,
Locale locale,
@RequestHeader MultiValueMap<String, String> headerMap,
@RequestHeader("host") String host,
@CookieValue(value = "myCookie", required = false) String cookie)
{
log.info("request={}", request);
log.info("response={}", response);
log.info("httpMethod={}", httpMethod);
log.info("locale={}", locale);
log.info("headerMap={}", headerMap);
log.info("header host={}", host);
log.info("myCookie={}", cookie);
return "ok";
}
}
HTTP ํค๋๋ฅผ ์กฐํํ๊ณ ์ถ์ ๋๋ ๋ฉ์๋ ํ๋ผ๋ฏธํฐ์ ์กฐํํ๊ณ ์ถ์ ์ ๋ณด๋ฅผ ์ ๋ ฅํ๋ฉด ๋ฉ๋๋ค.
์คํ๋ง ์ปจํธ๋กค๋ฌ์์๋ ArgumentResolver๋ผ๋ ํด์ ์ด์ฉํด ํ๋ผ๋ฏธํฐ๋ฅผ ์ด๋ ๊ฒ ์ ์ฐํ๊ฒ ์ฒ๋ฆฌํด์ค๋๋ค.
ArgumentResolver์ ๋ํด์๋ ๋ค์์ ๋ค๋ฃจ๋๋ก ํ๊ฒ ์ต๋๋ค.
- HttpServletRequest, HttpServletResponse
- HttpMethod : HTTP ๋ฉ์๋๋ฅผ ์กฐํํฉ๋๋ค (org.springframework.http.HttpMethod)
- Locale : Locale ์ ๋ณด๋ฅผ ์กฐํํฉ๋๋ค.
- @RequestHeader MultiValueMap<String, String > headerMap : ๋ชจ๋ HTTP ํค๋๋ฅผ MultiValueMap ํ์์ผ๋ก ์กฐํํฉ๋๋ค.
- MultiValueMap์ ํค์ ์ค๋ณต์ด ํ์ฉ๋๋ค. ์ฆ, ํ๋์ ํค๋ ์ฌ๋ฌ๊ฐ์ง value๋ฅผ ๊ฐ์ง ์ ์์.
- https://taehoung0102.tistory.com/182
- @RequestHeader("host") String host : ํน์ HTTP ํค๋๋ฅผ ์กฐํํฉ๋๋ค.
- ํ์ ๊ฐ ์ฌ๋ถ : required ๋ก ์ง์
- ๊ธฐ๋ณธ ๊ฐ : defaultValue
- @CookieValue(value="myCookie", required = false ) String Cookie : ํน์ ์ฟ ํค๋ฅผ ์กฐํํฉ๋๋ค.
- ํ์ ๊ฐ ์ฌ๋ถ : required
- ๊ธฐ๋ณธ ๊ฐ : defaultValue
1 , 2. HTTP ์์ฒญ ํ๋ผ๋ฏธํฐ - ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ(GET) , HTML Form(POST)
HTTP ์์ฒญ ๋ฉ์์ง๋ฅผ ํตํด ํด๋ผ์ด์ธํธ์์ ์๋ฒ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์๋ 3๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์์ต๋๋ค.
1. ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ฅผ ํตํ ์ ์ก(GET)
- /url?username=hello&age=20
- ๋ฉ์์ง ๋ฐ๋ ์์ด ์์ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ์ ๋ฐ์ดํฐ๋ฅผ ํฌํจํด์ ์ ๋ฌํ๋ ๋ฐฉ์
- ์ฃผ๋ก ๊ฒ์, ํํฐ, ํ์ด์ง๋ฑ์์ ์ฐ๋ ๋ฐฉ์
2. HTML Form ์ ํตํ ์ ์ก(POST)
- content-type : application/x-www-form-urlencoded
- ๋ฉ์์ง ๋ฐ๋์ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ ํ์์ผ๋ก ์ ๋ฌ username=hello&age=20
- ํ์๊ฐ์ ์ด๋ ์ํ ์ฃผ๋ฌธ ๋ฑ์์ HTML Form์ ํตํด ์ฌ์ฉํ๋ ๋ฐฉ์
3. HTTP message body์ ์ง์ ๋ฐ์ดํฐ๋ฅผ ๋ด์์ ์ ์ก
- HTTP API์์ ์ฃผ๋ก ์ฌ์ฉ. JSON, XML, TEXT
- ๋ฐ์ดํฐ ํ์์ ์ฃผ๋ก JSON์ ์ฌ์ฉํฉ๋๋ค.
- PUT, PATCH, POST
@RequestMapping("/request-param-v1")
public void requestParamV1(HttpServletRequest request, HttpServletResponse response) throws IOException
{
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
log.info("username = {}, age={}", username, age);
PrintWriter writer = response.getWriter();
writer.write("ok");
}
HttpServletRequest์ request.getParameter()์ ์ฌ์ฉํ๋ฉด POST, GET ๋ฐฉ์ ๋ชจ๋ ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ ์กฐํํ ์ ์์ต๋๋ค.
์ด๊ฒ์ ๊ฐ๋จํ ์์ฒญ ํ๋ผ๋ฏธํฐ (request parameter) ์กฐํ๋ผ๊ณ ํฉ๋๋ค.
์ง๊ธ๋ถํฐ๋ ์คํ๋ง์ผ๋ก ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ ์กฐํํ๋ ๋ฐฉ๋ฒ์ ๋จ๊ณ์ ์ผ๋ก ์์๋ณด๊ฒ ์ต๋๋ค.
HTTP ์์ฒญ ํ๋ผ๋ฏธํฐ -@RequestParam
@RequestParam V2 - ๊ธฐ๋ณธ
// @RequestParam ์ฌ์ฉ - String, int, Integer ๊ฐ์ ๋จ์ ํ์
@ResponseBody
@RequestMapping("/request-param-v2")
public String requestParamV2(@RequestParam("username") String username,
@RequestParam("age") int age) throws IOException
{
log.info("username = {}, age={}", username, age);
return "OK";
}
์ด ์ ์์๋ HttpServletRequest๊ฐ ์ ๊ณตํ๋ ๋ฐฉ์์ผ๋ก ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ ์กฐํํ์ง๋ง,
@RequestParam ์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ์ธ๋ฉํด์ ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ ์กฐํํ ์ ์์ต๋๋ค.
@RequestParam์ name(value) ์์ฑ์ด ํ๋ผ๋ฏธํฐ ์ด๋ฆ์ผ๋ก ์ฌ์ฉ
@RequestParam("username") String memberName โฃ request.getParameter("username")
@RequestParam : ํ๋ผ๋ฏธํฐ ์ด๋ฆ์ผ๋ก ๋ฐ์ธ๋ฉ
@Responsebody : View ์กฐํ ๋ฌด์, HTTP message body์ ์ง์ ํด๋น ๋ด์ฉ ์ ๋ ฅ
@RequestParam V3 - value ์๋ต
/**
* @PathVaraiable ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก
* @RequestParam ๋ํ value ์ ๋ณ์ ์ด๋ฆ์ด๋ ๊ฐ์ผ๋ฉด value ์๋ต ๊ฐ๋ฅ
*/
@ResponseBody
@RequestMapping("/request-param-v3")
public String requestParamV3(@RequestParam String username,
@RequestParam int age) throws IOException
{
log.info("username = {}, age={}", username, age);
return "OK";
}
@PathVariable๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก @RequestParam์์๋ ๋ณ์์ด๋ฆ๊ณผ value๊ฐ ๊ฐ์ผ๋ฉด value๋ฅผ ์๋ตํ ์ ์์ต๋๋ค.
@RequestParam V4 - @RequestParam ์๋ต
/**
*
* @param username
* @param age
* @return
* @throws IOException
*
* @RequestParam๋ ์๋ต ๊ฐ๋ฅ. ๊ทผ๋ฐ ๊ถ์ฅํ์ง ์์.
*/
@ResponseBody
@RequestMapping("/request-param-v4")
public String requestParamV4(String username, int age) throws IOException
{
log.info("username = {}, age={}", username, age);
return "OK";
}
์ฌ์ง์ด String, int, Integer์ ๊ฐ์ ๋จ์ ํ์ ์ผ ๊ฒฝ์ฐ์๋ @RequestParam๋ ์๋ตํ ์ ์์ต๋๋ค. ๊ทผ๋ฐ ๋ช ์์ ์ด์ง ์์ ์ฝ๋ ์ฌ๋์ด ์ฝ๊ธฐ ์ด๋ ค์ธ ์ ์์ด์. ๊ถ์ฅํ์ง ์์ต๋๋ค.
@RequestParam - required ์ต์ , defaultValue ์ต์
// required ์ต์
@ResponseBody
@RequestMapping("/request-param-required")
public String requestParamRequired(
@RequestParam(required = true) String username,
@RequestParam(required = false) Integer age) { // Integer ๋ null ์ง์
log.info("username={}, age={}", username, age);
return "OK";
}
// defaultValue ์ต์
// ๋น ๋ฌธ์("")๊น์ง defaultValue๋ก ์ฒ๋ฆฌ
@ResponseBody
@RequestMapping("/request-param-default")
public String requestParamDefault(
@RequestParam(required = true, defaultValue = "guest") String username,
@RequestParam(required = false, defaultValue = "1") Integer age) {
log.info("username={}, age={}", username, age);
return "OK";
}
- required ์ต์ ์ true๋ก ์ค์ ํ ํ๋ผ๋ฏธํฐ๋ ์์ฒญ ์ ํ์์ ์ผ๋ก ์์ด์ผ ํฉ๋๋ค.
- ์ฃผ์ : ๋น ๋ฌธ์("")๋ ํต๊ณผํจ (?username=""&age=20)
- defaultValue ์ต์ ์ ์ค์ ํ ํ๋ผ๋ฏธํฐ๋ ์์ฒญ ์ ์ ๋ ฅํ์ง ์์ผ๋ฉด defaultValue๋ก ์ค์ ๋ฉ๋๋ค.
- defaultValue๋ฅผ true๋ก ์ค์ ํ ๊ฒฝ์ฐ required ์ต์ ์ ์๋ฏธ๊ฐ ์ฌ๋ผ์ง๋๋ค ( ๋ํดํธ๋ก ๊ฐ์ด ์ค์ ๋๋ฏ๋ก )
- defaultValue๋ ๋น ๋ฌธ์์ ๊ฒฝ์ฐ์๋ ์ค์ ํ ๊ธฐ๋ณธ ๊ฐ์ด ์ ์ฉ๋ฉ๋๋ค.
@RequestParam - Map, MultiMap์ ํตํ ํ๋ผ๋ฏธํฐ ์กฐํ
/**
*
* @param paramMap
* @return
*/
@ResponseBody
@RequestMapping("/request-param-map")
public String requestParamMap(@RequestParam Map<String,Object> paramMap)
{
log.info("username={}, age={}", paramMap.get("username"), paramMap.get("age"));
return "OK";
}
/**
*
* @param paramMultiMap
* @return
*/
@ResponseBody
@RequestMapping("/request-param-Multimap")
public String requestParamMap(@RequestParam MultiValueMap<String, Object> paramMultiMap)
{
log.info("username={}, age={}", paramMultiMap.get("username"), paramMultiMap.get("age"));
return "OK";
}
- ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ Map, MultiMap์ ํตํด ์กฐํํ ์ ์์ต๋๋ค.
- ์์ฒญ ํ๋ผ๋ฏธํฐ์ ๊ฐ์ด 1๊ฐ๊ฐ ํ์คํ๋ค๋ฉด Map ์ ์ฌ์ฉํด๋ ๋์ง๋ง, ๊ทธ๋ ์ง ์๋ค๋ฉด MultiValueMap ์ ์ฌ์ฉํ๋๋ก ํฉ์๋ค.
HTTP ์์ฒญ ํ๋ผ๋ฏธํฐ -@ModelAttribute
๋จผ์ ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ์ธ๋ฉํ ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ฒ ์ต๋๋ค.
@Data
public class HelloData {
private String username;
private int age;
}
@Data - Lombok ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ด๋ ธํ ์ด์ ์ผ๋ก @Setter, @Getter, @Tostring, @EqualsAndHashCode, @RequiredArgsConstructor๋ฅผ ํฌํจํ๊ณ ์์ต๋๋ค.
์ค์ ๊ฐ๋ฐ์ ํ ๋์๋ ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ์, ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ , ๊ทธ ๊ฐ์ฒด์ ๊ฐ์ ๋ฃ์ด์ฃผ์ด์ผ ํฉ๋๋ค. ๋ณดํต ๋ค์๊ณผ ๊ฐ์ด ์์ฑํฉ๋๋ค.
@ResponseBody
@RequestMapping("/model-attribute-v0")
public String modelAttributeV0(@RequestParam String username, @RequestParam int age)
{
HelloData data = new HelloData();
data.setAge(age);
data.setUsername(username);
log.info("username = {} , age = {} ", username, age);
return "ok";
}
ํ์ง๋ง ์คํ๋ง์ ์ด ๊ณผ์ ์ ์์ ํ ์๋ํ ํด์ฃผ๋ @ModelAttribute ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
@ModelAttribute V1
@ResponseBody
@RequestMapping("/model-attribute-v1")
public String modelAttributeV1(@ModelAttribute HelloData helloData)
{
log.info("username = {} , age = {} ", helloData.getUsername(), helloData.getAge());
log.info("data = {}",helloData);
return "ok";
}
์คํ๋ง MVC์์๋ @ModelAttribute๊ฐ ์์ผ๋ฉด ๋ค์์ ์คํํฉ๋๋ค.
1. HelloData ๊ฐ์ฒด ์์ฑ
2. ์์ฒญ ํ๋ผ๋ฏธํฐ์ ์ด๋ฆ์ผ๋ก HelloData ๊ฐ์ฒด์ property( username, age )๋ฅผ ์ฐพ์ต๋๋ค.
3. ๊ทธ๋ฆฌ๊ณ ํด๋น ํ๋กํผํฐ์ setter๋ฅผ ํธ์ถํด์ ํ๋ผ๋ฏธํฐ์ ๊ฐ์ ์ ๋ ฅ(๋ฐ์ธ๋ฉ)ํด์ ๊ฐ์ฒด์ ๊ฐ์ ์ฃผ์ ํฉ๋๋ค.
ex) username -> setUsername() ๋ฉ์๋ ์ฐพ์์ ๊ฐ ์ฃผ์
โ๏ธ๋ฐ์ธ๋ฉ ์ค๋ฅ : age=abc ์ฒ๋ผ ์ซ์๊ฐ ๋ค์ด๊ฐ์ผ ํ ๊ณณ์ ๋ฌธ์๊ฐ ๋ค์ด๊ฐ๋ฉด BindException ์์ธ ๋ฐ์. ์ด๋ฐ ๋ฐ์ธ๋ฉ ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๊ฒ์ฆ ๋ถ๋ถ์์ ๋ค๋ฃจ๊ฒ ์ต๋๋ค. ์ฐ์ ํจ์ค
@ModelAttribute ์๋ต
// @ModelAttribute ๋ํ ์๋ต ๊ฐ๋ฅ.
// ํ์ง๋ง @RequestParam ๋ ์๋ต ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ํผ๋์ด ๋ฐ์ํ ์ ์๋ค.
// ๊ถ์ฅํ์ง ์์.
@ResponseBody
@RequestMapping("/model-attribute-v2")
public String modelAttributeV2(HelloData helloData)
{
log.info("username = {} , age = {} ", helloData.getUsername(), helloData.getAge());
log.info("data = {}",helloData);
return "ok";
}
3. HTTP ์์ฒญ ๋ฉ์์ง - ๋จ์ ํ ์คํธ
์์ฒญ ํ๋ผ๋ฏธํฐ์ ๋ค๋ฅด๊ฒ HTTP ๋ฉ์์ง ๋ฐ๋๋ฅผ ํตํด ๋ฐ์ดํฐ๊ฐ ์ง์ ๋์ด์ค๋ ๊ฒฝ์ฐ์๋ @RequestParam๊ณผ @ModelAttribute๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ฌผ๋ก HTML Form ํ์์ผ๋ก ์ ๋ฌ๋๋ ๊ฒฝ์ฐ๋ ์์ฒญ ํ๋ผ๋ฏธํฐ๋ก ์ธ์ ๋๊ธด ํ์ง๋ง.
๋จผ์ ๊ฐ์ฅ ๋จ์ํ ํ ์คํธ ๋ฉ์์ง๋ฅผ HTTP ๋ฉ์์ง ๋ฐ๋์ ๋ด์ ์ ์กํ๊ณ ์ฝ์ด๋ด ์๋ค.
HTTP ๋ฉ์์ง ๋ฐ๋์ ๋ฐ์ดํฐ๋ InputStream์ ์ฌ์ฉํด ์ง์ ์ฝ์ ์ ์์ต๋๋ค.
@PostMapping("/request-body-string-v1")
public void requestBodyString(HttpServletRequest request, HttpServletResponse response) throws IOException {
ServletInputStream inputStream = request.getInputStream();
String messagebody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("message body = {}", messagebody);
PrintWriter writer = response.getWriter();
writer.write("ok");
}
์ด์ ์คํ๋ง MVC๊ฐ ์ง์ํ๋ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํด ๋ฉ์์ง ๋ฐ๋๋ฅผ ์ฝ์ด๋ณด๊ฒ ์ต๋๋ค.
InputStream, OuputStream(Writer) ์ฌ์ฉํ ๋ฉ์์ง ๋ฐ๋ ์ถ๋ ฅ
/**
* @param inputStream : HTTP ์์ฒญ ๋ฉ์์ง ๋ฐ๋์ ๋ด์ฉ์ ์ง์ ์กฐํ
* @param responseWriter : HTTP ์๋ต ๋ฉ์์ง์ ๋ฐ๋์ ์ง์ ๊ฒฐ๊ณผ ์ถ๋ ฅ
* @return
* @throws IOException
*/
@PostMapping("/request-body-string-v2")
public void requestBodyStringV2(InputStream inputStream, Writer responseWriter) throws IOException {
String messagebody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("messageBody = {}", messagebody);
responseWriter.write("ok");
}
์คํ๋ง MVC๋ ๋ค์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ง์ํฉ๋๋ค.
- InputStream(Reader): HTTP ์์ฒญ ๋ฉ์์ง ๋ฐ๋์ ๋ด์ฉ์ ์ง์ ์กฐํ
- OutputStream(Writer): HTTP ์๋ต ๋ฉ์์ง์ ๋ฐ๋์ ์ง์ ๊ฒฐ๊ณผ ์ถ๋ ฅ
HttpEntity๋ฅผ ํตํ ๋ฉ์์ง ๋ฐ๋ ์กฐํ
/**
* HttpEntity ํจํค์ง ์ฌ์ฉ
* @param httpEntity
* @return
* @throws IOException
*/
@PostMapping("/request-body-string-v3")
public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) throws IOException {
String messagebody = httpEntity.getBody();
log.info("messageBody = {}", messagebody);
return new HttpEntity<String>("ok");
// return new ResponseEntity<>("ok", HttpStatus.CREATED);
}
HttpEntity ๋ HTTP ํค๋, body ์ ๋ณด๋ฅผ ํธ๋ฆฌํ๊ฒ ์กฐํํ ์ ์๋๋ก ๋์์ฃผ๋ ๊ฐ์ฒด์ ๋๋ค.
์์ฒญ๋ฟ๋ง ์๋๋ผ ์๋ต์์๋ HttpEntity๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์คํ๋ง MVC๋ ๋ค์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ง์ํฉ๋๋ค.
- HttpEntity: HTTP header, body ์ ๋ณด๋ฅผ ํธ๋ฆฌํ๊ฒ ์กฐํ
- ๋ฉ์์ง ๋ฐ๋ ์ ๋ณด๋ฅผ ์ง์ ์กฐํ
- ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ ์กฐํํ๋ ๊ธฐ๋ฅ๊ณผ ๊ด๊ณ ์์ @RequestParam X, @ModelAttribute X
- HttpEntity๋ ์๋ต์๋ ์ฌ์ฉ ๊ฐ๋ฅ
- ๋ฉ์์ง ๋ฐ๋ ์ ๋ณด ์ง์ ๋ฐํ
- ํค๋ ์ ๋ณด ํฌํจ ๊ฐ๋ฅ
- view ์กฐํX
RequestEntity, ResponseEntity๋ HttpEntity๋ฅผ ์์๋ฐ์ ๊ฐ์ฒด๋ก
RequestEntity๋ HttpMethod, url ์ ๋ณด๊ฐ ์ถ๊ฐ๋์ด , request์์ ์ฌ์ฉํฉ๋๋ค.
ResponseEntity๋ HTTP ์ํ์ฝ๋๋ฅผ ์ค์ ํ ์ ์๊ณ , response์์ ์ฌ์ฉํฉ๋๋ค.
@RequestBody๋ฅผ ์ฌ์ฉํ ๋ฉ์์ง ๋ฐ๋ ์กฐํ
/**
* @RequestBody ์ฌ์ฉ - ์ค๋ฌด์์ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ๋ฐฉ์
* @param messageBody
* @return
*/
@ResponseBody
@PostMapping("/request-body-string-v4")
public String requestBodyStringV4(@RequestBody String messageBody)
{
log.info("message body = {}",messageBody);
return "OK";
}
@RequestBody๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ ๊ฒ ์ฝ๊ฒ ๋ฉ์์ง ๋ฐ๋ ์ ๋ณด๋ฅผ ์กฐํํ ์ ์์ต๋๋ค. ์ฐธ๊ณ ๋ก ํค๋ ์ ๋ณด๊ฐ ํ์ํ๋ค๋ฉด HttpEntity๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ @RequestHeader๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
์ด๋ ๊ฒ ๋ฉ์์ง ๋ฐ๋๋ฅผ ์ง์ ์กฐํํ๋ ๊ธฐ๋ฅ์ ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ ์กฐํํ๋ @RequestParam, @ModelAttribute์๋ ์ ํ ๊ด๊ณ๊ฐ ์๋ค๋ ์ ์ ์์๋ก์๋ค.
์์ฒญ ํ๋ผ๋ฏธํฐ ์กฐํ : @RequestParam, @ModelAttribute
๋ฉ์์ง ๋ฐ๋ ์กฐํ : @RequestBody
3. HTTP ์์ฒญ ๋ฉ์์ง - JSON
๋จ์ ํ ์คํธํ์์ ๋ฉ์์ง๋ฐ๋์ Jsonํ์์ ๋ฉ์์ง ๋ฐ๋ ์กฐํ๋ ํฌ๊ฒ ๋ค๋ฅด์ง ์์ต๋๋ค.
์ฐ์ MVC ์ ์ฉ ์ด์ ์ Json ํ์์ ๋ฉ์์ง ๋ฐ๋ ์กฐํ ๋ฐฉ๋ฒ์
@PostMapping("/request-body-json-v1")
public void requestBodyJsonV1(HttpServletRequest request, HttpServletResponse response) throws IOException
{
ServletInputStream inputStream = request.getInputStream();
String messagebody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("messageBody={}",messagebody);
HelloData data = objectMapper.readValue(messagebody,HelloData.class);
log.info("username = {} , age = {}", data.getUsername(), data.getAge());
PrintWriter writer = response.getWriter();
writer.write("Ok");
}
์ด๋ ๊ฒ inputStream์ผ๋ก messagebody๋ฅผ ์ฝ์ด ๋ฌธ์๋ก ๋ณํํ ๋ค ๋ฌธ์๋ก ๋ json ๋ฐ์ดํฐ๋ฅผ jackson ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ objectMapper๋ฅผ ์ฌ์ฉํด ์๋ฐ ๊ฐ์ฒด๋ก ๋ณํํด ์ฃผ์์์ต๋๋ค.
๋จ์ ํ ์คํธ์ ๋ง์ฐฌ๊ฐ์ง๋ก JSON์์๋ @RequestBody๋ฅผ ์ฌ์ฉํฉ๋๋ค.
HttpServletRequest โถ๏ธ @RequestBody
// V2
// @RequestBody (์๋ต ๋ถ๊ฐ๋ฅ, ์๋ต ์ @ModelAttribute๊ฐ ์ ์ฉ๋์ด ๋ฒ๋ฆผ)
@ResponseBody
@PostMapping("/request-body-json-v2")
public String requestBodyJsonV2(@RequestBody String messagebody) throws IOException
{
HelloData data = objectMapper.readValue(messagebody, HelloData.class);
log.info("username = {} , age = {}", data.getUsername(), data.getAge());
return "Ok";
}
๋จ์ ํ ์คํธ์ฒ๋ผ @RequestBody๋ฅผ ์ฌ์ฉํด HTTP ๋ฉ์์ง์์ ๋ฐ์ดํฐ๋ฅผ ๊บผ๋ด๊ณ messagebody์ ์ ์ฅ.
๋ฌธ์๋ก ๋ json ๋ฐ์ดํฐ์ธ messagebody๋ฅผ objectMapper๋ฅผ ํตํด ์๋ฐ ๊ฐ์ฒด๋ก ๋ณํ.
messgae body -> ๋ฌธ์ ๋ณํ -> json ๋ณํ -> ๊ฐ์ฒด๋ก ๋ณํ
๋ฌธ์๋ก ๋ณํํ๊ณ ๋ค์ json์ผ๋ก ๋ณํํ๋ ๊ณผ์ ์ด ์ข ๊ท์ฐฎ์๋ฐ ์ค์ผ ์ ์์๊น?
์ค์ผ ์ ์์ต๋๋ค.
โ๏ธ@RequestBody๋ ์๋ต์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค.
์คํ๋ง์ @ModelAttribute, @RequestParam๊ณผ ๊ฐ์ ์ด๋ ธํ ์ด์ ์ ์๋ตํ ๋ ์๋ ๊ท์น์ ์ ์ฉํฉ๋๋ค.
- String , Integer, int ์ ๊ฐ์ ๋จ์ ํ์ = @RequestParam
- ๊ทธ ์ธ์ ํ์ = @ModelAttribute ( argument resolver๋ก ์ง์ ํด๋ ํ์ ์ ์ ์ธํ ๋ชจ๋ ํ์ )
๋ฐ๋ผ์ ์ด ๊ฒฝ์ฐ HelloData์ @RequestBody๋ฅผ ์๋ตํ๋ฉด @ModelAttribute๊ฐ ์ ์ฉ๋์ด ๋ฒ๋ฆฌ๊ธฐ ๋๋ฌธ์ ๋ฉ์์ง ๋ฐ๋๊ฐ ์๋ ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฒ๋ฆฌํ๊ฒ ๋ฉ๋๋ค!
@RequestBody์ String์ด ์๋ ๊ฐ์ฒด ํ๋ผ๋ฏธํฐ ์ฌ์ฉ
// V3
// @RequestBody์ ๊ฐ์ฒด๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ์ง์ ํ ์ ์๋ค.
@ResponseBody
@PostMapping("/request-body-json-v3")
public String requestBodyJsonV3(@RequestBody HelloData data)
{
log.info("username = {}, age = {}",data.getUsername(),data.getAge());
return "OK";
}
@RequestBody์ ์ง์ ๋ง๋ ๊ฐ์ฒด๋ฅผ ์ง์ ํ ์ ์๋ค.
HttpEntity๋ @RequestBody๋ฅผ ์ฌ์ฉํ๋ฉด HTTP ๋ฉ์์ง ์ปจ๋ฒํฐ๊ฐ HTTP ๋ฉ์์ง ๋ฐ๋์ ๋ด์ฉ์ ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๋ฌธ์๋ ๊ฐ์ฒด ๋ฑ์ผ๋ก ๋ณํํด ์ค๋๋ค.
HttpEntity๋ฅผ ์ฌ์ฉํ ver.
@ResponseBody
@PostMapping("/request-body-json-v4")
public String requestBodyJsonV4(HttpEntity<HelloData> dataHttpEntity)
{
HelloData data = dataHttpEntity.getBody();
log.info("username = {}, age = {}",data.getUsername(),data.getAge());
return "OK";
}
@ResponseBody์ String์ด ์๋ ๊ฐ์ฒด ๋ฆฌํดํ ๊ฒฝ์ฐ
@ResponseBody
@PostMapping("/request-body-json-v5")
public HelloData requestBodyJsonV5(@RequestBody HelloData data)
{
log.info("username = {}, age = {}", data.getUsername(),data.getAge());
return data;
}
๊ฐ์ฒด ์ ๋ณด๊ฐ JSON ํํ๋ก ๋ฉ์์ง ๋ฐ๋์ ๋ฆฌํด๋ฉ๋๋ค. ๋ฌผ๋ก ๋ง์ฐฌ๊ฐ์ง๋ก HttpEntity๋ฅผ ์ฌ์ฉํด๋ ๋ฉ๋๋ค.
@RequestBody ์์ฒญ : JSON ์์ฒญ -> HTTP ๋ฉ์์ง ์ปจ๋ฒํฐ -> ๊ฐ์ฒด
@ResponseBody ์๋ต : ๊ฐ์ฒด -> HTTP ๋ฉ์์ง ์ปจ๋ฒํฐ -> JSON ์๋ต
์ด๋ฒ ํฌ์คํ ์์๋ Request ๋งคํ์ ๋ํด ์์๋ณด์์ต๋๋ค.
๋ค์ ํฌ์คํ ์์๋ Response ๋งคํ๊ณผ HTTP ๋ฉ์์ง ์ปจ๋ฒํฐ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค. ๊ฐ์ฌํฉ๋๋ค.
<์ฐธ๊ณ ์๋ฃ>
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
https://rlaehddnd0422.tistory.com/45
'๐ Backend > MVC Pattern' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ฉ์์ง, ๊ตญ์ ํ ๊ธฐ๋ฅ (0) | 2023.03.20 |
---|---|
Spring MVC ๊ธฐ๋ณธ ๊ธฐ๋ฅ - ์๋ต ๋งคํ @ResponseBody, MessageConverter, ์์ฒญ ๋งคํ ํธ๋ค๋ฌ ์ด๋ํฐ ๊ตฌ์กฐ (0) | 2023.03.13 |
Spring MVC ๊ธฐ๋ณธ ๊ธฐ๋ฅ - Logging (0) | 2023.03.10 |
Spring MVC - @RequestMapping, @RequestParam, ModelAndView (0) | 2023.03.09 |
๋ค์ํ ๋ฐฉ์์ HandlerMapping, HandlerAdapter, ViewResolver (0) | 2023.03.03 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
Study Repository
rlaehddnd0422