@Controller
@RequestMapping("/board/*")
public class BoardController {
private static final Logger logger = LoggerFactory.getLogger(BoardController.class);
@Inject
private BoardService service;
@RequestMapping(value="/register", method= RequestMethod.GET )
public void registerGET(BoardVO board, Model model) throws Exception {
logger.info("register get ....");
}
}
공부하던 책에서 예제의 일부 발췌했다.
서버를 실행한 후 localhost/board/register로 요청을 보내면 위의 @RequestMapping(value="/register", method= RequestMethod.GET )에 해당하는 메소드가 실행된다. 그리고 화면엔 다음 위치의 jsp파일이 뜬다.
이전에 서블릿을 통해 실습했던 예제들은 전부 어떤 jsp로 갈지 정해줬었다.
req.getRequestDispatcher("/cart/cartDetail.jsp").forward(req, resp);
이런식으로 말이다.
그런데 예제코드엔 저런 jsp를 결정하는 코드가 없었다. 그런데 어떻게 알맞은 jsp 파일이 떴을까?
해답은 viewResolver에 있다.
servlet-context.xml 파일을 열면 다음 코드가 존재한다
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
위 코드는 ViewResolver가 WEB-INF/views/뷰이름.jsp 을 뷰JSP로 이동한다는 뜻이다.
이게 우리의 코드를 jsp로 매핑해줬다. 더 자세히 알아보자.
클라이언트로부터 요청을 받으면 DispatcherServlet에서 HandlerMapping을 통해 Controller로 위임처리를 한다. 위임처리를 받은 Controller는 ViewResolver를 통해 View로 데이터를 전달한다.
컨트롤러가 뷰 오브젝트를 직접 리턴할수도 있지만 보통은 뷰의 논리적 이름을 리턴해주면 ViewResolver가 이를 이용해 뷰 오브젝트를 생성해준다.
Controller 메소드에서는 파라미터 뿐만 아니라 리턴타입도 다양하게 결정할 수 있다. Controller가 DispatcherServlet에 돌려줘야하는 정보는 모델, 뷰이다. HandlerAdapter를 거쳐 최종적으로 DispatcherServlet으로 들어갈때는 ModelAndView 타입으로 리턴값이 전달된다.
리턴방법을 살펴보자
@RequestMapping("/hello")
public ModelAndView hello(HttpServletRequest request) throws Exception {
String mname = request.getParameter("name");
//return new ModelAndView("hello.jsp"),addObject("name",name);
Map<String, Object> map = new HashMap<String, Object>();
map.put("name",name);
return new ModelAndView("hello.jsp",map);
모델은 맵을 먼저 만들어서 ModelAndView 생성자에 넣어도 되지만 주석처럼 해도된다.
그런데 Model타입 파라미터를 사용한다면 미리 생성된 모델 맵 오브젝트를 전달받아 사용하는것이므로 뷰에 전달되는 모델에 자동으로 추가된다. return 타입에 Model객체를 사용하지 않아도 뷰에 데이터가 전달된다.
@RequestMapping("/hello")
public ModelAndView hello(@RequestParam String name, Model model) throws Exception {
model.addAttribute("name",name);
return new ModelAndView("hello");
@RequestMapping("/hello")
public String hello(@RequestParam String name, Model model) throws Exception {
model.addAttribute("name",name);
return "hello";
@RequestMapping("/hello")
public void hello(@RequestParam String name, Model model) throws Exception {
model.addAttribute("name",name);
리턴타입이 void이므로 ViewResolver를 통해 URL을 따라 뷰 이름을 hello로 만들어줄것이다.
@RequestMapping("/user/xml")
public View userXml(@RequestParam int id) {
...
return new InternalResourceView("/WEB-INF/view/hello.jsp");
}
@ResponseBody는 @RequestBody와 비슷한 방식으로 동작한다. @ResponseBody가 메소드 레벨에 부여되면 메소드가 리턴하는 객체는 뷰를 통해 결과를 만들어내는 모델로 사용되는 대신 바로 HTTP응답 메세지 본문으로 전환된다.
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "<html><body>Hello Spring</body></html>";
}
메소드에 @ResponseBody가 없다면 스트링타입의 리턴값은 뷰 이름으로 인식될것이다.
하지만 @ResponseBody가 붙었으므로 HttpServletResponse의 출력스트림에 넣는다.
Controller에서 위의 여러 방식으로 리턴을 해주면 HandlerMapping이 URL로부터 컨트롤러를 찾아주는것처럼 뷰 리졸버가 뷰 이름으로부터 사용할 뷰 오브젝트를 찾아준다.
참고:) https://m.blog.naver.com/todoskr/220856216311
https://focus-on-my.tistory.com/130 <<<< 또보자