컨트롤러 다루기
스프링에서 컨트롤러
컨트롤러 기본사용
HelloController.java
import org.springframework.stereotype.Controller;
@Controller
public class HelloController {
}
@Component를 상속한 @Controller는 @Controller가 붙은 클래스의 객체를 메모리에 생성하는 기능을 제공 단순히 객체를 생성하는 것에 그치지 않고, DispatcherServlet이 인식하는 Controller객체로 만들어준다
만일 @Controller를 사용하지 않는다면, 다음의 예처럼 모든 클래스는 반드시 스프링에서 제공하는 Controller 인터페이스를 구현해야 한다. 그리고 handleRequest() 메소드를 반드시 재정의하여 DispatcherServlet이 모든 Controller의 handleRequest() 메소드를 호출할 수 있도록 해야 한다.
HelloController.java
package com.study.spring;
import org.springframework.web.servlet.mvc.Controller;
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
System.out.println("hello");
return null;
}
}
하지만 이렇게 구현한 Controller는 스프링 프레임워크가 지향하는 POJO(Plain Old Java Object)스타일의 클래스가 아니다. Controller를 POJO 스타일의 클래스로 구현하려면 우선 클래스 선언부에 있는 "implements Controller"를 제거하고 클래스 위에 "@Controller"를 선언해야 한다. 스프링 컨테이너는 @Controller가 선언된 객체를 자동으로 Controller 객체로 인식한다.
@RequestMapping 사용하기
제일 처음의 코드처럼 @Controller를 클래스 위에 추가함으로써 HelloController을 컨트롤러 로써 인식하게 할 수는 있지만, 클라이언트의 특정 uri요청에 대해서 특정 메서드가 실행되 도록 할 수는 없다. 기존에는 HandlerMapping을 이용하여 클라이언트의 요청을 매핑했었다.
스프링에서는 @RequestMapping을 이용하여 HandlerMapping설정을 대체한다.
@RequestMapping을 메서드 위에 써줌으로써 각 메서드를 uri에 매핑시켜준다.
여기까지가 스프링 퀵 스타트에서 발췌한 인용문 이다.
간단하게 컨트롤러를 어떤식으로 써야하는지 왜 이렇게 써야 하는지 알아보았다.
이제 실제 사용법을 좀 알아보자
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class HelloController {
@RequestMapping(value = "/hello-people", method = { RequestMethod.GET })
@ResponseBody
public Map<String, Object> getHelloPeople() {
Map<String, Object> result = new HashMap<String, Object>();
return result;
}
}
Spring 4.3부터는 다음과 같은 어노테이션이 추가되었으므로, 위의 코드를 조금더 간편하게 쓸 수 있다.
- @PostMApping
- @GetMApping
- @PutMApping
- @PDeleteMApping
- @PatchMApping
다음과 같은 코드를
@RequestMapping(value="/hello-people", method = { RequestMethod.GET}
이렇게 쓸 수 있다.
// GET메서드로 받을때는 GetMapping을 import해준다
import org.springframework.web.bind.annotation.GetMapping;
@GetMapping("/hello-people")
잠깐....
@RequestMapping의 기본사용에 대해서 조금더 알아보자
@RequestMapping(value="/test", method=RequestMethod.GET, headers="Accept=application/*", params="id=002")
- value : uri를 지정한다.
- method : HTTP메소드를 지정한다
- headers : HTTP헤더를 지정한다. 헤더명이 지정되었을 경우 그 헤더가 존재하는지 매칭판정을 한다. 위의 경우는 Accept헤더에 application/*에 매치되는 값이 설정되었을 경우 매치판정이 된다.
- params : 헤더와 같은 방법으로 기재한다. 위의 경우는 id가 002일 경우에 매치된다.
단순하게 View를 통한(thymeleaf나 freemarker 등의) 페이지 uri를 리턴하려고 한다면 @ResponseBody 를 빼고 리소스 쪽의 templates의 파일구조대로 적어주면 된다.
@ResponseBody 로 어노테이션이 있으면 메소드의 리턴값을 View(thymeleaf등등)로 출력하지않고 HTTP Response Body에 직접 매핑한다
반대로 @ResponseBody를 쓰지않으면 View(thymeleaf등등)쪽을 엑세스하게하여 템플릿엔진이 렌더링한 결과를 HTTP Response로 매핑한다
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HelloController {
@GetMapping(value = "/hello")
public String hello() {
return "hello";
}
}
위의 경우는 thymeleaf나 freemarker 등의 템플릿 엔진의 리소스가 있는 templates/hello.html 을 로드한다.
만약 하위 폴더구조를 갖고 있는경우에는 다음과 같이 사용하면 된다.
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HelloController {
@GetMapping(value = "/hello")
public String helloworld() {
return "hello/hello";
}
}
templates/hello/hello.html을 로드한다.
@RequestHeader을 사용 할 경우
@RequestMapping("/test")
public ModelAndView test(@RequestHeader(value="User-Agent", required=false) String agent, ModelAndView mav) {
...
}
@CookieValue을 사용 할 경우
@RequestMapping("/test")
public ModelAndView test(@CookieValue(value="SESSIONID", required=false) String sid, ModelAndView mav) {
...
}
@RequestParam어노테이션을 사용 할 경우
@Controller
public class HelloController {
@GetMapping(value = "/hello")
public String helloworld(
@RequestParam(value = "world",required = false) String world {
return helloService.getWorldMsg(world);
}
}
required의 기본은 true이기 때문에 클라이언트쪽에서 값을 안넘겨주면 에러가 발생한다