[Spring MVC] 왜 jsp가 자동으로 매핑될까?

서현서현·2022년 7월 7일
0

Spring

목록 보기
2/31
@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로 매핑해줬다. 더 자세히 알아보자.

View Resolver?

클라이언트로부터 요청을 받으면 DispatcherServlet에서 HandlerMapping을 통해 Controller로 위임처리를 한다. 위임처리를 받은 Controller는 ViewResolver를 통해 View로 데이터를 전달한다.
컨트롤러가 뷰 오브젝트를 직접 리턴할수도 있지만 보통은 뷰의 논리적 이름을 리턴해주면 ViewResolver가 이를 이용해 뷰 오브젝트를 생성해준다.

Controller 메소드에서는 파라미터 뿐만 아니라 리턴타입도 다양하게 결정할 수 있다. Controller가 DispatcherServlet에 돌려줘야하는 정보는 모델, 뷰이다. HandlerAdapter를 거쳐 최종적으로 DispatcherServlet으로 들어갈때는 ModelAndView 타입으로 리턴값이 전달된다.

리턴방법을 살펴보자

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");

String

  • 메소드의 리턴타입이 스트링이면 이 리턴값은 뷰 이름으로 사용된다. 모델정보는 모델맵을 파라미터로 가져와 추가하는 방법을 사용한다
@RequestMapping("/hello")
public String hello(@RequestParam String name, Model model) throws Exception {
	model.addAttribute("name",name);
    return "hello";

void

  • 메소드의 리턴타입을 아예 void로 생성할수있다.
    이때 RequestToViewNameResolver 전략을 통해 자동 생성되는 뷰 이름이 사용된다.
    URL과 뷰 이름을 일관되게 통일한다면 더 단순해진다
@RequestMapping("/hello")
public void hello(@RequestParam String name, Model model) throws Exception {
	model.addAttribute("name",name);
   

리턴타입이 void이므로 ViewResolver를 통해 URL을 따라 뷰 이름을 hello로 만들어줄것이다.

View

  • String 리턴타입은 뷰 이름으로 인식한다고 설명했는데 뷰 이름대신 뷰 객체를 사용하고싶다면 리턴타입을 View로 선언하고 넘겨주면 된다
@RequestMapping("/user/xml")
public View userXml(@RequestParam int id) {
	...
	return new InternalResourceView("/WEB-INF/view/hello.jsp");
}

ResponseBody

@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 <<<< 또보자

0개의 댓글