새소식

TIL

[TIL] 230514 <Spring> Spring MVC

  • -

 

  • MVC :  Model-View-Controller의 약자로, 소프트웨어 디자인 패턴 중 하나
  • MVC 패턴 :  소프트웨어를 구성하는 요소들을 Model, View, Controller로 구분하여 각각의 역할을 분리
    ㄴ 코드의 재사용성과 유지보수성을 높이고, 개발자들 간의 협업을 용이하게 함
    ㄴ 따라서 소프트웨어를 개발할 때, MVC 패턴을 적용하여 구조를 잘 설계하는 것이 중요

Model

  • 데이터와 비즈니스 로직을 담당
  • 데이터베이스와 연동하여 데이터를 저장하고 불러오는 등의 작업을 수행

View

  • 사용자 인터페이스를 담당
  • 사용자가 보는 화면과 버튼, 폼 등을 디자인하고 구현

Controller

  • Model과 View 사이의 상호작용을 조정하고 제어
  • 사용자의 입력을 받아 Model에 전달하고, Model의 결과를 바탕으로 View를 업데이트

 

 


Spring MVC 

중앙에 있는 DispatcherServlet이 HTTP 요청을 처리하기 위한 공유 알고리즘을 제공하는 Front Controller 패턴을 중심으로 설계됨
ㄴ ‘Spring에서 MVC 디자인 패턴을 적용하여 HTTP 요청을 효율적으로 처리하고 있다’ 

 

Servlet(서블릿) : 자바를 사용하여 웹 페이지를 동적으로 생성하는 서버 측 프로그램 혹은 그 사양

▼ 사용자가 (HTTP) API 요청했을 때 서버의 서블릿의 동작

  1. 사용자가 Client(브라우저)를 통해 서버에 HTTP Request 즉, API 요청을 함
  2. 요청을 받은 Servlet 컨테이너는 HttpServletRequest, HttpServletResponse 객체를 생성
                                                      ㄴ 약속된 HTTP의 규격을 맞추면서 쉽게 HTTP에 담긴 데이터를 사용하기 위한 객체
  3. 설정된 정보를 통해 어떠한 Servlet에 대한 요청인지 찾음
  4. 해당 Servlet에서 service 메서드를 호출한 뒤 브라우저의 요청 Method에 따라 doGet 혹은 doPost 등의 메서드를 호출
  5. 호출한 메서드들의 결과를 그대로 반환하거나 동적 페이지를 생성한 뒤 HttpServletResponse 객체에 응답을 담아 Client(브라우저)에 반환
  6. 응답이 완료되면 생성한 HttpServletRequest, HttpServletResponse 객체를 소멸

 

 

  • 모든 API 요청을 앞서 살펴본 서블릿의 동작 방식에 맞춰 코드를 구현한다면 무수히 많은 Servlet 클래스를 구현해야함
  • 따라서 Spring은 DispatcherServlet을 사용하여 Front Controller 패턴 방식으로 API 요청을 효율적으로 처리함

▼ Front Controller 패턴의 동작과정

1. Client(브라우저)에서 HTTP 요청이 들어오면 DispatcherServlet 객체가 요청을 분석

2. DispatcherServlet 객체는 분석한 데이터를 토대로 Handler mapping을 통해 Controller를 찾아 요청을 전달
  - GET /api/hello HelloControllerhello() 함수
  - GET /user/login UserControllerlogin() 함수
  - GET /user/signup UserControllersignup() 함수
  - POST /user/signup UserControllerregisterUser() 함수

           ◆ Handler mapping 에는 API path 와 Controller 메서드가 매칭되어 있음

@RestController
public class HelloController {
    @GetMapping("/api/hello")
    public String hello() {
        return "Hello World!";
    }
}

              - API path 즉, URL을 Controller에 작성하는 방법은 @Controller 애너테이션이 달려있는 클래스를 생성한 뒤
                @GetMapping 처럼 요청한 HTTP Method 와 일치하는 애너테이션을 추가한 메서드를 구현

              - URL은 @GetMapping("/api/hello") 이처럼 해당 애너테이션의 속성값으로 전달해주면됨

              - 해당 메서드명은 URL을 매핑하는데 영향을 미치지 않음으로 자유롭게 정해도 상관 없음

       → 직접 Servlet을 구현하지 않아도 DispatcherServlet에 의해 간편하게 HTTP 요청을 처리 가능

 

3. ControllerDispatcherServlet
     ㄴ 해당 Controller는 요청에 대한 처리를 완료 후 처리에 대한 결과 즉, 데이터('Model')와 'View' 정보를 전달함

4. DispatcherServletClient   
     ㄴ ViewResolver 통해 View에 Model을 적용하여 View를 Client에게 응답으로 전달

 

 


  • API 마다 파일을 만들 필요 없이 유사한 성격의 API 를 하나의 Controller 로 관리
  • 클래스 내의 중복메서드명 불가

Thymeleaf 포함시킬 것

 

  • @GetMapping, @PostMapping, @PutMapping, @DeleteMapping (각각의 HTTP Method에 매핑되는 애너테이션)
  • @RequestMapping : 중복되는 URL 단축
package com.sparta.springmvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller  //@Controller는 해당 클래스가 Controller의 역할을 수행할 수 있도록 등록해줌
@RequestMapping("/api")  //로 시작되는 요청은 아래 클래스로 넘어옴 (중복되는 경로 넣을 것)
public class HelloController {
	// api 경로는 중복될 수 있지만, 메서드명은 달라야함!!!

	@GetMapping("/hello")
	@ResponseBody  //지금은 순수하게 문자열을 반환하려 하므로
	public String hello() {
		return "Hello World!!";  //원래는 뷰 이름 정보 전달하는 부분
	}

	@GetMapping("/get")
	@ResponseBody
	public String get() {
		return "GET Method 요청";
	}

	@PostMapping("/post")
	@ResponseBody
	public String post() {
		return "POST Method 요청";
	}

	@PutMapping("/put")
	@ResponseBody
	public String put() {
		return "PUT Method 요청";
	}

	@DeleteMapping("/delete")
	@ResponseBody
	public String delete() {
		return "DELETE Method 요청";
	}

}

 

 


 

1. static 폴더

/resources/static/hello.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello Spring</title>
</head>
<body>
Hello, Spring 정적 웹 페이지!! (static)
</body>
</html>

 

HtmlController

package com.sparta.springmvc.html;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HtmlController {

	@GetMapping("/static-hello")
	public String hello() {
		return "hello.html";
	}
}

 

이 상태에서 실행하여 http://localhost:8080/static-hello.html 실행 시 오류 발생

ㄴ Controller를 통해서 반환하는 것을 테스트 하려면
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf’
    해당 dependency를 주석 처리해야 테스트가 가능

thymeleaf 는 동적 페이지 처리를 위한 템플릿 엔진!
    추가하면 자동으로 Controller에서 html 파일 찾는 경로를/resources/templates 로 설정함

→ 주석 처리하지 않고 http://localhost:8080/hello.html 과 같이 SpringBoot 서버에 html 파일 바로 요청 시 해당 html 파일을 static 폴더에서 찾아서 반환해줌

 

 

2. Redirect

implementation 'org.springframework.boot:spring-boot-starter-thymeleaf’를 주석 처리하지 않고 하려면
"redirect:/hello.html" redirect 요청을 문자열로 반환하면 http://localhost:8080/html/redirect실행 시 http://localhost:8080/hello.html 요청이 재 수행되면서 static 폴더의 파일을 반환

@GetMapping("/html/redirect")
public String htmlStatic() {
    return "redirect:/hello.html";
}

그냥 바로 hello.html 요청했을 때
http://localhost:8080/html/redirect를 통해 hello.html 파일 접근했을 때!!!

 

 

3. Template engine 에 View 전달

/templates/hello.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello Spring</title>
</head>
<body>
Hello, Spring 정적 웹 페이지!! (templates)
</body>
</html>

http://localhost:8080/html/templates

static 폴더에 있는 html 파일을 바로 호출하는 방법이 가장 간단하지만
외부 즉, 브라우저에서 바로 접근하지 못하게 하고 싶거나 특정 상황에 Controller를 통해서 제어하고 싶다면
이렇게 templates 폴더에 해당 정적 html 파일을 추가하고 해당 html 파일명인 "hello" 문자열을 반환하여 처리가능
(.html은 생략가능!)

 

 

 

 

/templates/hello-visit.html

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Hello Spring</title></head>
<body>
  <div>
    Hello, Spring 동적 웹 페이지!!
  </div>
  <div>
    (방문자 수: <span th:text="${visits}"></span>)
  </div>
</body>
</html>

 

HtmlController

private static long visitCount = 0;

...

@GetMapping("/html/dynamic")
public String htmlDynamic(Model model) {
    visitCount++;
    model.addAttribute("visits", visitCount);
    return "hello-visit";
}

 

http://localhost:8080/html/dynamic

  • 동적 페이지 처리 과정
    1. Client 의 요청을 Controller에서 Model 로 처리
      ㄴ DB 조회가 필요하다면 DB 작업 후 처리한 데이터를 Model에 저장

    2. Template engine(Thymeleaf) 에게 View, Model 전달
      ㄴ View: 동적 HTML 파일
      ㄴ Model: View 에 적용할 정보들

    3. Template engine
      ㄴ ViewModel을 적용 → 동적 웹페이지 생성
           - 예) 로그인 성공 시, "로그인된 사용자의 Nickname"을 페이지에 추가
           - Template engine 종류: 타임리프(Thymeleaf), Groovy, FreeMarker, Jade, JSP 등

    4. Client(브라우저)에게 View(동적 웹 페이지, HTML)를 전달해줌

 

  • Thymeleaf
    <View 정보>
    ㄴ "hello-visit" → resources**/templates/hello-visit.html
<div>
  (방문자 수: <span th:text="${visits}"></span>)
</div>

        <Model 정보>
        ㄴ visits: 방문 횟수 (visitCount) -예) 방문 횟수: 1,000,000

<div>
  (방문자 수: <span>1000000</span>)
</div>

 


 

최근의 경향으로는 서버는 요청을 받아 html/css/js 파일을 반환해주는게 주 업무라고 할 수는 없음!
웹 생태계가 고도화 되는 과정중에 상대적으로 프론트엔드와 백엔드가 각각 따로 발전하게 되면서, 느슨하게 결합하는 방식을 더 많이 채택하게 되었고, 최근에는 서버가 직접 뷰(html/css/js)를 반환하기 보다는 요청에 맞는 특정한 정보만 반환하는 것을 조금 더 선호하기도 함!
그래서 요즘에는 주로 서버에서는 데이터 교환 포맷 중 JSON 형태로 데이터를 반환하기도 함

 

 

 

1. 반환값 : String

Java는 JSON 타입을 지원하지 않기 때문에 JSON 형태의 String 타입으로 변환해서 사용해야 함

http://localhost:8080/response/json/string

 

ResponseController.java

@Controller
@RequestMapping("/response")
public class ResponseController {
    // [Response header]
    //   Content-Type: text/html
    // [Response body]
    //   {"name":"Robbie","age":95}
    
    @GetMapping("/json/string")
    @ResponseBody
    public String helloStringJson() {
        return "{\"name\":\"Robbie\",\"age\":95}";
    }
}

 

 

2. 반환값 : String 외 자바 클래스

  • "자바 객체 → JSON 으로 변환"
    ㄴ Spring에서 자동으로 Java의 객체를 JSON으로 변환해줌

 

Star.java

package com.sparta.springmvc.response;

import lombok.Getter;

@Getter
public class Star {
    String name;
    int age;

    public Star(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Star() {}
}

 

ResponseController.java

@Controller
@RequestMapping("/response")
public class ResponseController {
    // [Response header]
    //   Content-Type: application/json
    // [Response body]
    //   {"name":"Robbie","age":95}
    
    @GetMapping("/json/class")
    @ResponseBody
    public Star helloClassJson() {
        return new Star("Robbie", 95);  //자바 객체
    }
}

 

 

 

= @Controller + @ResponseBody
    ㄴ @RestController를 사용하면 해당 클래스의 모든 메서드에 @ResponseBody 애너테이션이 추가되는 효과를 부여할 수 있음

 

ResponseRestController.java

package com.sparta.springmvc.response;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/response/rest")
public class ResponseRestController {
	// [Response header]
	//   Content-Type: text/html
	// [Response body]
	//   {"name":"Robbie","age":95}
	@GetMapping("/json/string")
	public String helloStringJson() {
		return "{\"name\":\"Robbie\",\"age\":95}";
	}

	// [Response header]
	//   Content-Type: application/json
	// [Response body]
	//   {"name":"Robbie","age":95}
	@GetMapping("/json/class")
	public Star helloClassJson() {
		return new Star("Robbie", 95);
	}
}

 

 

 


JSON 데이터 구조를 처리해주는 라이브러리
 ㄴ Object를 JSON 타입의 String으로 변환 가능
 ㄴ JSON 타입의 StringObject로 변환 가능

Spring은 3.0버전 이후로 Jacskon과 관련된 API를 제공함으로써, 직접 소스 코드를 작성하여 JSON 데이터를 처리하지 않아도 자동으로 처리해줌
→ SpringBoot의 starter-web에서는 default로 Jackson 관련 라이브러리들을 제공
 직접 JSON 데이터를 처리해야할 때는 Jackson 라이브러리의 ObjectMapper를 사용 가능

 

@Test
@DisplayName("Object To JSON : get Method 필요")
void test1() throws JsonProcessingException {
    Star star = new Star("Robbie", 95);

    ObjectMapper objectMapper = new ObjectMapper(); // Jackson 라이브러리의 ObjectMapper
    String json = objectMapper.writeValueAsString(star);

    System.out.println("json = " + json);
}
  • objectMapper의 writeValueAsString 메서드를 사용하여 변환 가능
    ㄴ 파라미터에 JSON으로 변환시킬 Object의 객체
  • Object를 JSON 타입의 String으로 변환하기 위해서는 해당 Object에 get Method가 필요!!!

 

@Test
@DisplayName("JSON To Object : 기본 생성자 & (get OR set) Method 필요")
void test2() throws JsonProcessingException {
    String json = "{\"name\":\"Robbie\",\"age\":95}"; // JSON 타입의 String

    ObjectMapper objectMapper = new ObjectMapper(); // Jackson 라이브러리의 ObjectMapper

    Star star = objectMapper.readValue(json, Star.class);
    System.out.println("star.getName() = " + star.getName());
    System.out.println("star.getAge() = " + star.getAge());
}
  • objectMapper의 readValue 메서드를 사용하여 변환 가능
    ㄴ 첫 번째 파라미터는 JSON 타입의 String, 두 번째 파라미터에는 변환할 Object의 class 타입
  • JSON 타입의 StringObject로 변환하기 위해서는 해당 Object에 기본 생성자와 get 혹은 set 메서드가 필요!!!

 


 

hello-request-form.html

<!DOCTYPE html>
<html>
<head>
  <title>Hello Request</title>
</head>
<body>
<h2>GET /star/{name}/age/{age}</h2>
<form id="helloPathForm">
  <div>
    이름: <input name="name" type="text">
  </div>
  <div>
    나이: <input name="age" type="text">
  </div>
</form>
<div>
  <button id="helloPathFormSend">전송</button>
</div>
<br>

<h2>GET /hello/request/form/param</h2>
<form method="GET" action="/hello/request/form/param">
  <div>
    이름: <input name="name" type="text">
  </div>
  <div>
    나이: <input name="age" type="text">
  </div>
  <button>전송</button>
</form>

<br>

<h2>POST /hello/request/form/param</h2>
<form method="POST" action="/hello/request/form/param">
  <div>
    이름: <input name="name" type="text">
  </div>
  <div>
    나이: <input name="age" type="text">
  </div>
  <button>전송</button>
</form>
<br>

<h2>POST /hello/request/form/model</h2>
<form method="POST" action="/hello/request/form/model">
  <div>
    이름: <input name="name" type="text">
  </div>
  <div>
    나이: <input name="age" type="text">
  </div>
  <button>전송</button>
</form>
<br>

<h2>GET /hello/request/form/param/model </h2>
<form method="GET" action="/hello/request/form/param/model">
  <div>
    이름: <input name="name" type="text">
  </div>
  <div>
    나이: <input name="age" type="text">
  </div>
  <button>전송</button>
</form>
<br>

<h2>POST /hello/request/form/json</h2>
<form id="helloJsonForm">
  <div>
    이름: <input name="name" type="text">
  </div>
  <div>
    나이: <input name="age" type="text">
  </div>
</form>
<div>
  <button id="helloJsonSend">전송</button>
</div>
<div>
  <div id="helloJsonResult"></div>
</div>
</body>
<script>
  // GET /star/{name}/age/{age}
  const helloPathForm = document.querySelector("#helloPathFormSend")
  helloPathForm.onclick = (e) => {
    const form = document.querySelector("#helloPathForm");
    const name = form.querySelector('input[name="name"]').value;
    const age = form.querySelector('input[name="age"]').value;
    const relativeUrl = `/hello/request/star/${name}/age/${age}`;
    window.location.href = relativeUrl;
  }

  // POST /hello/request/form/json
  const helloJson = document.querySelector("#helloJsonSend")
  helloJson.onclick = async (e) => {
    const form = document.querySelector("#helloJsonForm");

    const data = {
      name: form.querySelector('input[name="name"]').value,
      age: form.querySelector('input[name="age"]').value
    }

    const response = await fetch('/hello/request/form/json', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(data),
    })

    const text = await response.text(); // read response body as text
    document.querySelector("#helloJsonResult").innerHTML = text;
  };
</script>
</html>

 

requestController.java

@Controller
@RequestMapping("/hello/request")
public class RequestController {
    @GetMapping("/form/html")
    public String helloForm() {
        return "hello-request-form";
    }
}

 

 

서버에 보내려는 데이터를 URL 경로에 추가

  • @PathVariable(required = false)
     ㄴ Client에서 전달받은 값들에서 해당 값이 포함되어있지 않아도 오류가 발생하지 않음 (해당 값이 없어도 오류 안남)

이름에 Robbie, 나이에 95 입력하여 전송
‘Robbie’와 ‘95’ 데이터를 서버에 보내기 위해 URL 경로에 추가한 것을 볼 수 있음

GET http://localhost:8080/hello/request/star/Robbie/age/95

requestController.java

// [Request sample]
// GET http://localhost:8080/hello/request/star/Robbie/age/95
@GetMapping("/star/{name}/age/{age}")
@ResponseBody
public String helloRequestPath(@PathVariable String name, @PathVariable int age)
{
    return String.format("Hello, @PathVariable.<br> name = %s, age = %d", name, age);
}
  • 데이터를 받기 위해서는 /star/{name}/age/{age}처럼 URL 경로에서 데이터를 받고자 하는 위치의 경로에 {data} 중괄호를 사용
  • (@PathVariable String name, @PathVariable int age)
    ㄴ 해당 요청 메서드 파라미터에 @PathVariable 애너테이션과 함께 {name} 중괄호에 선언한 변수명과 변수타입을 선언하면 해당 경로의 데이터를 받아올 수 있음

 

 

 

서버에 보내려는 데이터를 URL 경로 마지막에 ?& 를 사용하여 추가

  • @RequestParam은 생략이 가능함!
  • @RequestParam(required = false)
     ㄴ Client에서 전달받은 값들에서 해당 값이 포함되어있지 않아도 오류가 발생하지 않음 (해당 값이 없어도 오류 안남)

이름에 Robbie, 나이에 95 입력하여 전송
‘Robbie’와 ‘95’ 데이터를 서버에 보내기 위해 URL 경로 마지막에 추가한 것을 볼 수 있음

GET http://localhost:8080/hello/request/form/param?name=Robbie&age=95

requestController.java

// [Request sample]
// GET http://localhost:8080/hello/request/form/param?name=Robbie&age=95
@GetMapping("/form/param")
@ResponseBody
public String helloGetRequestParam(@RequestParam String name, @RequestParam int age) {
    return String.format("Hello, @RequestParam.<br> name = %s, age = %d", name, age);
}
  • 데이터를 받기 위해서는 ?name=Robbie&age=95 에서
    key 부분에 선언한 name과 age를 사용하여 value에 선언된 Robbie, 95 데이터를 받아올 수 있음
  • (@RequestParam String name, @RequestParam int age)
    ㄴ 해당 요청 메서드 파라미터에 @RequestParam 애너테이션과 함께 key 부분에 선언한 변수명과 변수타입을 선언하면 데이터를 받아올 수 있음

 

 

▶ form 태그 POST
POST http://localhost:8080/hello/request/form/param

이름에 Robbie, 나이에 95 입력하여 전송
HTTP Body에 name=Robbie&age=95 형태로 담겨져서 서버로 전달

  • HTML의 form 태그를 사용하여 POST 방식으로 HTTP 요청을 보낼 수 있음
    ㄴ 해당 데이터는 HTTP Body에 name=Robbie&age=95 형태로 담겨져서 서버로 전달됨

requestController.java

// [Request sample]
// POST http://localhost:8080/hello/request/form/param
// Header
//  Content type: application/x-www-form-urlencoded
// Body
//  name=Robbie&age=95
@PostMapping("/form/param")
@ResponseBody
public String helloPostRequestParam(@RequestParam String name, @RequestParam int age) {
    return String.format("Hello, @RequestParam.<br> name = %s, age = %d", name, age);
}

 

hello-request-form.html 중 일부 (form 태그)

<form method="POST" action="/hello/request/form/param">
  <div>
    이름: <input name="name" type="text">
  </div>
  <div>
    나이: <input age="age" type="text">
  </div>
  <button>전송</button>
</form>

 

 


⚠️ 데이터를 Java의 객체로 받아올 때 주의할 점⚠️ 
해당 객체의 필드에 데이터를 넣어주기 위해 set or get 메서드 또는 오버로딩된 생성자가 필요!!!

 

 

  • @ModelAttribute은 생략이 가능함!
    ㄴ Q. Spring에서는 @ModelAttribute뿐만 아니라 @RequestParam도 생략이 가능한데
             그렇다면 Spring은 이를 어떻게 구분???
         A. 해당 파라미터(매개변수)가 SimpleValueType (원시타입(int), Wrapper타입(Integer), Date등) 이라면
              @RequestParam으로 간주하고, 아니라면 @ModelAttribute가 생략되어있다 판단!

▶ form 태그 POST
POST http://localhost:8080/hello/request/form/model

이름에 Robbie, 나이에 95 입력하여 전송
HTTP Body에 name=Robbie&age=95 형태로 담겨져서 서버로 전달됨

requestController.java

// [Request sample]
// POST http://localhost:8080/hello/request/form/model
// Header
//  Content type: application/x-www-form-urlencoded
// Body
//  name=Robbie&age=95
@PostMapping("/form/model")
@ResponseBody
public String helloRequestBodyForm(@ModelAttribute Star star) {
    return String.format("Hello, @ModelAttribute.<br> (name = %s, age = %d) ", star.name, star.age);
}
  • HTML의 form 태그를 사용하여 POST 방식으로 HTTP 요청을 보낼 수 있음
    ㄴ 해당 데이터는 HTTP Body에 name=Robbie&age=95 형태로 담겨져서 서버로 전달됨
  • (해당 데이터를 Java의 객체 형태로 받는 방법): @ModelAttribute 애너테이션을 사용한 후 Body 데이터를 Star star 받아올 객체를 선언

 

 

▶ Query String 방식
GET http://localhost:8080/hello/request/form/param/model?name=Robbie&age=95

이름에 Robbie, 나이에 95 입력하여 전송

requestController.java

// [Request sample]
// GET http://localhost:8080/hello/request/form/param/model?name=Robbie&age=95
@GetMapping("/form/param/model")
@ResponseBody
public String helloRequestParam(@ModelAttribute Star star) {
    return String.format("Hello, @ModelAttribute.<br> (name = %s, age = %d) ", star.name, star.age);
}
  • ?name=Robbie&age=95 처럼 데이터가 두 개만 있다면 괜찮지만 여러 개 있다면 @RequestParam 애너테이션으로 하나씩 받아오기 힘들 수 있음
  • 이때 @ModelAttribute 애너테이션을 사용하면 Java의 객체로 데이터를 받아올 수 있음!
    ㄴ 파라미터에 선언한 Star 객체가 생성되고, 오버로딩된 생성자 혹은 Setter 메서드를 통해 요청된 name & age 의 값이 담김

 

 

 

 

HTTP Body에 JSON 데이터를 담아 서버에 전달할 때 해당 Body 데이터를 Java의 객체로 전달 받을 수 있음

▶ Body JSON 데이터
POST http://localhost:8080/hello/request/form/json

requestController.java

// [Request sample]
// POST http://localhost:8080/hello/request/form/json
// Header
//  Content type: application/json
// Body
//  {"name":"Robbie","age":"95"}
@PostMapping("/form/json")
@ResponseBody
public String helloPostRequestJson(@RequestBody Star star) {
    return String.format("Hello, @RequestBody.<br> (name = %s, age = %d) ", star.name, star.age);
}
  • HTTP Body에 {"name":"Robbie","age":"95"} JSON 형태로 데이터가 서버에 전달되었을 때 @RequestBody 애너테이션을 사용해 데이터를 객체 형태로 받을 수 있음
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.