Spring Boot | Spring MVC의 간단한 사용법
응답과 요청 매핑(Mapping Requests and Responses)
- 기본적으로 요청과 응답은 모두 JSON 의한 매핑이 되어 있다.
- 매핑은 Jackson으로 하고 있고 있다 (그래서 매핑 조정은 Jackson 어노테이션으로 가능하다).
코드 작성
src/main/java/sample/springboot/web/Hoge.java
package sample.springboot.web;
public class Hoge {
public int id;
public String value;
@Override
public String toString() {
return "Hoge [id=" + id + ", value=" + value + "]";
}
}
src/main/java/sample/springboot/web/HelloController.java
package sample.springboot.web;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hello")
public class HelloController {
@RequestMapping(method=RequestMethod.POST)
public Hoge hello(@RequestBody Hoge param) {
System.out.println(param);
Hoge hoge = new Hoge();
hoge.id = 20;
hoge.value = "Response";
return hoge;
}
}
어플리케이션 실행
curl으로 테스트하기
$ curl -H "Content-type: application/json" -X POST -d '{"id": 10, "value": "Request"}' http://localhost:8080/hello
{"id":20,"value":"Response"}
Hoge [id=10, value=Request]
요청(Requests)
URL 매핑
@RequestMapping
메서드(클래스)와 경로를 매핑한다.value
속성에 경로를 지정한다.method
속성에 HTTP 메소드를 지정한다.
src/main/java/sample/springboot/web/HelloController.java
package sample.springboot.web;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hello")
public class HelloController {
@RequestMapping(method=RequestMethod.GET)
public String getMethod() {
return "get";
}
@RequestMapping(method=RequestMethod.POST)
public String postMethod1() {
return "post";
}
@RequestMapping(value="/hey", method=RequestMethod.POST)
public String postMethod2() {
return "hey post";
}
}
실행 결과 curl 명령으로 실행 결과를 확인해 본다.
$ curl http://localhost:8080/hello
get
$ curl http://localhost:8080/hello -X POST
post
$ curl http://localhost:8080/hello/hey -X POST
hey post
경로 변수(@PathVariable)값 얻기
- 경로의 정의에 중괄호(
{}
)로 묶은 매개 변수를 정의한다. - 메소드의 매개 변수로 같은 이름의 인수를 정의한다.
@PathVariable
어노테이션이 부여한다.
src/main/java/sample/springboot/web/HelloController.java
package sample.springboot.web;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hello")
public class HelloController {
@RequestMapping(value="/{id}/{name}", method=RequestMethod.GET)
public void getMethod(@PathVariable int id, @PathVariable String name) {
System.out.println("id=" + id + ", name=" + name);
}
}
실행 결과 curl 명령으로 실행 결과를 확인해 본다.
$ curl http://localhost:8080/hello/100/hoge
id=100, name=hoge
쿼리 파라미터(@RequestParam)값 얻기
- 메소드의 인수에
@RequestParam
어노테이션를 부여하면 쿼리 매개 변수를 얻을 수 있다. - 인수의 형태가 Map이라면 쿼리 파라미터 정보를 Map 형태로 얻을 수 있다.
- 하나의 매개 변수에 여러 값이 설정되어있는 경우, Spring에서 제공하는
MultiValueMap
로 받을 수 있다.
코드 작성
src/main/java/sample/springboot/web/HelloController.java
package sample.springboot.web;
import java.util.Map;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hello")
public class HelloController {
@RequestMapping(method=RequestMethod.GET)
public void getMethod(
@RequestParam String id,
@RequestParam Map<String, String> queryParameters,
@RequestParam MultiValueMap<String, String> multiMap) {
System.out.println("id=" + id);
System.out.println(queryParameters);
System.out.println(multiMap);
}
}
실행 결과
curl으로 테스트하기
$ curl "http://localhost:8080/hello?id=100&name=hoge&name=fuga"
id=100
{id=100, name=hoge}
{id=[100], name=[hoge, fuga]}
요청 헤더(@RequestHeader)값 얻기
@RequestHeader
로 헤더 정보를 얻을 수 있다.
src/main/java/sample/springboot/web/HelloController.java
package sample.springboot.web;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hello")
public class HelloController {
@RequestMapping(method=RequestMethod.GET)
public void getMethod(@RequestHeader("Test-Header") String value) {
System.out.println("Test-Header=" + value);
}
}
실행 결과
curl으로 테스트하기
$ curl -H "Test-Header: hoge" http://localhost:8080/hello
Test-Header=hoge
요청 바디(@RequestBody)값 얻기
@RequestBody
에서 요청 바디를 얻을 수 있다.
src/main/java/sample/springboot/web/HelloController.java
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hello")
public class HelloController {
@RequestMapping(method=RequestMethod.POST)
public void getMethod(@RequestBody String body) {
System.out.println("body=" + body);
}
}
실행 결과
curl으로 테스트하기
$ curl http://localhost:8080/hello -X POST -d "Request Body"
body=Request Body
응답 (Responses)
응답 상태 코드(@ResponseStatus)값 지정하기
- 메소드를
@ResponseStatus
에 어노테이션을 부여하고 value에 상태 코드를 지정하면, 그 응답의 상태 코드를 지정할 수 있다. - 아무것도 지정하지 않으면 200 OK가 반환된다.
src/main/java/sample/springboot/web/HelloController.java
package sample.springboot.web;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hello")
public class HelloController {
@RequestMapping(method=RequestMethod.GET)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public void getMethod() {
}
}
실행 결과
curl으로 테스트하기
$ curl http://localhost:8080/hello -v
( 생략 )
< HTTP/1.1 400 Bad Request
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< Content-Length: 0
< Date: Wed, 29 Apr 2015 11:50:08 GMT
< Connection: close
( 생략 )
여러가지 응답의 반환 방법
Spring MVC의 컨트롤러 메소드에서 사용할 수 있는 반환 값에 어떤 것이 있는지, 어떤 방법이 있는지 대해 설명한다.
@Controller와 @RestController의 차이
먼저 @Controller와 @RestController의 차이를 설명한다.
Spring MVC에서 컨트롤러 클래스에 어노테이션으로 @Controller 또는 @RestController을 붙인다.
@Controller
는 주로 Web 페이지의 컨트롤러에서 사용한다.
Web 페이지용 컨트롤러는 JSP나 템플릿 엔진 View로 전환 응답의 HTML을 생성하기 때문에 기본적으로 메소드의 반환 값은 View 전환 대상을 지정하는 데 사용한다.
@RestController
는 Json이나 XML 등을 반환 WebAPI 용 컨트롤러로 사용한다.
이것은 View로 전환하지 않기 때문에 메소드의 반환 값은 응답(response)의 내용(content)이 된다.
@Controller
반환 값을 String으로 한다.
View 이동 페이지를 지정하는 가장 간단한 방법이다.
@RequestMapping("/method1")
public String method1() {
return "/index.html";
}
반환 값을 ModelAndView으로 한다.
ModevAndView를 사용하면 View로 전달하려는 정보를 함께 반환할 수 있다.
@RequestMapping("/method2")
public ModelAndView method2() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject(new User("kimkc"));
modelAndView.setViewName("/index.html");
return modelAndView;
}
포워드
반환 값으로 지정하여 이동처로 “forward:“를 붙이면 다른 컨트롤러 메소드로 이동한다.
@RequestMapping("/forward1")
public String forward1() {
return "forward:method1";
}
리다이렉트
리다이렉트하려면 “redirect:“를 붙인다.
@RequestMapping("/redirect1")
public String redirect1() {
return "redirect:method1";
}
외부 URL을 지정하는 경우도 있다.
@RequestMapping("/redirect2")
public String redirect2() {
return "redirect:https://www.google.co.jp/";
}
컨트롤러에서 직접 텍스트 콘텐츠를 반환한다.
메소드에 @ResponseBody를 붙이면 반환 값으로 직접 응답 내용을 반환할 수 있다.
@RequestMapping("/text1")
@ResponseBody
public String text1() {
return "text content";
}
HttpServletResponse에서 텍스트 콘텐츠를 반환한다.
반환 값을 void로하고 HttpServletResponse를 인자로 받도록하면 직접 응답을 쓸 수도 있다.
@RequestMapping("/text2")
public void text2(HttpServletResponse res) throws IOException {
res.getWriter().write("text content");
}
@RestController
반환 값으로 텍스트 콘텐츠를 반환한다.
@RestController을 붙인 컨트롤러 메소드에서는 @ResponseBody를 사용하지 않고도 반환 값이 응답 내용이 된다.
@RequestMapping("/text1")
public String text1() {
return "text content";
}
HttpServletResponse에서 텍스트 콘텐츠를 반환한다.
@Controller의 경우와 마찬가지로 HttpServletResponse에서 직접 콘텐츠를 쓸 수 있다.
@RequestMapping("/text2")
public void text2(HttpServletResponse res) throws IOException {
res.getWriter().write("text content");
}
콘텐츠 형식을 지정한다.
콘텐츠 형식을 @RequestMapping
의 produces으로 지정한다.
@RequestMapping(value = "/xml1", produces = "application/xml")
public String xml1() {
return "<a><b>content</b></a>";
}
org.springframework.http.MediaType
클래스에 콘텐츠 형식의 상수가 정의되어 있으므로 이것을 사용하면 좋다.
@RequestMapping(value = "/xml2", produces = MediaType.APPLICATION_XML_VALUE)
public String xml2() {
return "<a><b>content</b></a>";
}
HTTP 상태 및 응답 헤더를 지정한다.
HTTP 상태 및 콘텐츠 형식 이외의 응답 헤더를 지정하고 싶을 때는 반환 값을 ResponseEntity한다.
@RequestMapping("/responseEntity")
public ResponseEntity<String> responseEntity() {
HttpHeaders headers = new HttpHeaders();
headers.add("header1", "heaer1-value");
HttpStatus status = HttpStatus.NOT_FOUND;
return new ResponseEntity<String>("text content", headers, status);
}
JSON을 반환한다.
메소드의 반환 값을 임의의 클래스로하면, SpringMVC가 Jackson을 사용하여 json로 변경하여 반환해준다.
@RequestMapping("/json")
public List<User> json() {
return Arrays.asList(new User("kim", "kc"), new User("kim", "sj"));
}
[
{
"lastName": "kim",
"firstName": "kc"
},
{
"lastName": "kim",
"firstName": "sj"
}
]
파일 다운로드
흔히 볼 샘플에서는 HttpServletResponse 직접 쓰는 경우가 많을 거다.
@RequestMapping("/file1")
public void file1(HttpServletResponse res) throws IOException {
File file = new File("pom.xml");
res.setContentLength((int) file.length());
res.setContentType(MediaType.APPLICATION_XML_VALUE);
FileCopyUtils.copy(new FileInputStream(file), res.getOutputStream());
}
반환 값을 org.springframework.core.io.Resource 인터페이스하면 더 쉽게 구현할 수 있다.
@RequestMapping(value = "/file2", produces = MediaType.APPLICATION_XML_VALUE public Resource file2() {
return new FileSystemResource("pom.xml");
}
반환 값이 Resource이면 Content-Length는 자동으로 설정 해준다.
org.springframework.core.io.Resource
의 구현 클래스에서 자주 사용할 것 같은 것을 아래와 같다.
- FileSystemResource
- ClassPathResource
- ServletContextResource
- ByteArrayResource
- InputStreamResource
그밖에
이외에도 그 밖에도 방법은 여러가지 있을 수 있다. 더 자세하게 알고 싶다면 Spring Framework 문서 등을 참조하기 바란다.