[Spring Boot #11] 스프링 웹 MVC - HttpMessageConverters
- 📚 Spring/Spring Boot
- 2020. 5. 3. 19:36
참고 URL : https://docs.spring.io/spring/docs/5.0.7.RELEASE/spring-framework-reference/web.html#spring-web
| 웹 MVC 컨트롤러 구현
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping
// @ResponseBody가 생략되어 있는 것이다.
public String hello(){
// @RestController가 아닌 @Controller 어노테이션을 사용할 때는
// 아래 return되는 문자열은 ViewResolver를 통해 jsp파일을 찾는다.
// 하지만 @RestController 어노테이션을 사용하면 자동적으로 StringMessageConverter가
// 사용되어 HTTP응답 본문에 들어가게 된다.
return "hello";
}
}
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.run(args);
//SpringApplication.run(Application.class, args);
}
}
테스트코드
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
public class UserControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void hello() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("hello"));
}
}
- @RestController : 스프링4부터 기존 특정한 JSP를 만들어 내는 뷰를 반환하는 방식이 아닌 데이터 자체를 서비스하는 것을 지원하는 어노테이션이다. @RestController을 사용할 때는 @ResponseBody를 생략해도 HttpMessageConverter인터페이스를 통해 자동적으로 반환 객체를 HTTP 응답 본문으로 변환한다. 위의 코드는 StringMessageConverter가 사용되어 String 객체를 HTTP응답 본문으로 변환해주는 것이다.
- @GetMapping : @RequestMapping(method = RequestMethod.GET)의 축약형 이다.
| HttpMessageConverters - @RequestBody 를 통한 HTTP 메세지와 객체 매핑
HTTP 요청 본문을 객체로 변환하거나, 객체를 HTTP 응답 본문으로 변경할 때 사용한다.
- @RequestBody
- @ResponseBody
테스트 코드
import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
public class UserControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void hello() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("hello"));
}
//JSON 활용한 테스트
@Test
public void createUser_JSON() throws Exception {
String userJson = "{\"username\":\"kyh\", \"password\":\"123\"}";
mockMvc.perform(MockMvcRequestBuilders.post("/users/create")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.accept(MediaType.APPLICATION_JSON_UTF8)
.content(userJson))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.username",
Matchers.is(Matchers.equalTo("kyh"))))
.andExpect(MockMvcResultMatchers.jsonPath("$.password",
Matchers.is(Matchers.equalTo("123"))));
}
//XML활용한 테스트
@Test
public void createUser_XML() throws Exception {
String userJson = "{\"username\":\"kyh\", \"password\":\"123\"}";
mockMvc.perform(MockMvcRequestBuilders.post("/users/create")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.accept(MediaType.APPLICATION_XML)
.content(userJson))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.xpath("/User/username").
string("kyh"))
.andExpect(MockMvcResultMatchers.xpath("/User/password").string("123"));
}
}
-
MediaType.[데이터형식] : 스프링3부터 지원한다. HTTP에 정의된 데이터 전달 형식을 나타내는 HTTP Response의 Content-type 리스트
-
jsonPath : https://github.com/json-path/JsonPath의 경로 규칙을 따라서 response-body의 json포맷에 접근할 수 있게 지원하는 메서드 이다.
소스코드
package com.kyhslam.spring.user;
public class User {
private Long id;
private String username;
private String password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.kyhslam.spring.user;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping
public String hello(){
// @ResponseBody가 생략되어 있는 것이다.
// @RestController가 아닌 @Controller 어노테이션을 사용할 때는
// 아래 return되는 문자열은 ViewResolver를 통해 jsp파일을 찾는다.
// 하지만 @RestController 어노테이션을 사용하면 자동적으로 StringMessageConverter가
// 사용되어 HTTP응답 본문에 들어가게 된다.
return "hello";
}
@PostMapping("/users/create")
public User create(@RequestBody User user){
// HttpMessageConverter는 스프링 프레임워크에서 제공하는 인터페이스이다.
return user;
}
}
-
@PostMapping : @GetMapping과 유사하게 @RequestMapping(method = RequestMethod.POST) 의 축약형이다.
-
Controller 단에서 따로 json타입에 대한 정보를 명시하지 않아도 아래에서 설명할 ContentNegotiatingViewResolver를 통해 자동적으로 json형식으로 데이터를 반환하도록 스프링부트에서 제공을 한다. 이 ViewResolver는 Converter와 연관되어있어 Content-type을 기준으로 어떤 Converter를 쓸지 결정한다.
| ViewResolver : ContentNegotiatingViewResolver
-
ViewResolver : 스프링에서 Controller에서 반환한 값(ModelAndView 혹은 Model)을 통해 뷰를 만드느 역할을 한다.
-
ContentNegotiatingViewResolver : 동일한 URI에서 HTTP Request에 있는 Content-type 및 Accept 헤더를 기준으로 다양한 Content-type으로 응답할 수 있게하는 ViewResolver 이다.
아래를 보면 JSON 및 XML 형식의 다른 요청일 때도 잘 동작하는 걸 볼 수 있다.
import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
public class UserControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void hello() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("hello"));
}
//JSON 활용한 테스트
@Test
public void createUser_JSON() throws Exception {
String userJson = "{\"username\":\"kyh\", \"password\":\"123\"}";
mockMvc.perform(MockMvcRequestBuilders.post("/users/create")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.accept(MediaType.APPLICATION_JSON_UTF8)
.content(userJson))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.username",
Matchers.is(Matchers.equalTo("kyh"))))
.andExpect(MockMvcResultMatchers.jsonPath("$.password",
Matchers.is(Matchers.equalTo("123"))));
}
//XML활용한 테스트
@Test
public void createUser_XML() throws Exception {
String userJson = "{\"username\":\"kyh\", \"password\":\"123\"}";
mockMvc.perform(MockMvcRequestBuilders.post("/users/create")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.accept(MediaType.APPLICATION_XML)
.content(userJson))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.xpath("/User/username").
string("kyh"))
.andExpect(MockMvcResultMatchers.xpath("/User/password").string("123"));
}
}
'📚 Spring > Spring Boot' 카테고리의 다른 글
[Spring Boot #13] 스프링 웹 MVC - index페이지와 파비콘 (0) | 2020.05.04 |
---|---|
[Spring Boot #12] 스프링 웹 MVC - 정적 리소스 (0) | 2020.05.03 |
[Spring Boot #10] 스프링 부트 테스트 (Spring Boot Test) (0) | 2020.04.29 |
[Spring Boot #9] 스프링 부트 로깅(Logging) (0) | 2020.04.28 |
[Spring Boot #8] 스프링 부트 프로파일(Profile) (0) | 2020.04.28 |