상세 컨텐츠

본문 제목

[Spring] Spring MVC : Multiple view pages, Multiple Controllers

PROGRAMMING/Backend

by koharin 2022. 1. 18. 16:10

본문

728x90
반응형

Spring MVC(Model-View-Controller)

Spring Web Model-View-Controller

  • Spring MVC는 웹 애플리케이션을 빌드하는데 사용되는 Java framework이다.
  • DispatcherServlet
    • 들어오는 request를 받아서 요청에 대응하는 자원(controller, model, view)에 매핑하는 클래스이다.
    • Tomcat 내 Servlet container에 위치한다. 
    • Front Controller: DispatcherServlet 클래스는 front controller로서 동작한다. Spring MVC 애플리케이션의 흐름을 관리한다.
  • Model 애플리케이션의 데이터를 가지고 있다. 데이터는 하나의 객체 또는 객체의 집합이 될 수 있다.
  • Controller 애플리케이션의 로직을 가지고 있다. @Controller annotation은 controller 클래스를 명시하는데 사용된다.
  • View 주어진 정보를 특정 포맷으로 보여준다. 일반적으로 view 페이지를 구성하는데 JSP+JSTL가 사용된다.

 

 

Spring Web MVC 요청 처리 흐름

1. 모든 요청은 front controller로 동작하는 DispatcherServlet에 전달된다. Client가 요청을 Web Server로 보내면, Web Server는 Servlet container로 전달하고 Servlet container 쓰레드가 생성된다. 생성된 쓰레드에서 DispatcherServlet service()가 호출된다.

2. DispatcherServlet는 XML 파일에서 요청에 대한 HandlerMapping 엔트리를 찾는다. HandlerMapping에서는 요청에 대한 매핑된 Controller를 확인한다.

3. HandlerAdapter에 의해 매핑된 Controller에 요청이 전달된다.

4. Controller는 요청에 대한 view component를 반환한다.

5. DispatcherServlet은 XML 파일에서 view component에 대한 ViewResolver 찾고, ViewResolver는 view component의 구체적인 경로를 반환한다.

6. DispatcherServlet은 view component를 호출한다.

 

 

Spring MVC dependency

  • Spring Core jar files
  • Spring Web jar files
  • JSP + JSTL jar files

위 세 가지 dependency를 필요로 하지만, Maven을 사용하는 경우 Maven dependencies로 해당 파일들이 다운로드되기 때문에 별도로 다운로드하지 않아도 된다.

 

 

Controller 클래스 생성

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>
  • Controller class에는 @Controller와 @RequestMapping의 두 가지 annotation을 사용한다.
  • @Controller 해당 class를 Controller라고 명시한다.
  • @RequestMapping 특정 URL 이름으로 class를 매핑하는데 사용한다.
  • web.xml 파일에 Controller에 대한 entry를 적는다. 
  • Controller entry에 대한 XML 파일은 WEB-INF 하위에 위치해야 한다.
  • Controller 명은 아무거나 상관없다.

 

 

XML 파일에 bean 명시

  • view component에 대한 정보를 가져오는 configuration 파일이다. 해당 파일 이름은 원하는 파일명으로 해도 되고, web.xml에 해당 이름으로 명시해주면 된다.
  • <context:component-scan> 태그의 base-package에는 DispatcherServlet이 어떤 controller를 봐야 하는지 명시한다.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- 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>
	
	<context:component-scan base-package="org.smu.blood" />
	
	
	
</beans:beans>

 

 

Multiple View Pages

다음으로 서로 다른 view 페이지에서 redirect 하는 방법을 설명한다.

프로젝트 파일 구조

 

HomeController.java

package org.smu.blood;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
	
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
	
	@RequestMapping(value="/", method=RequestMethod.GET)
	public String home() {
		return "home";
	}
	@RequestMapping("/mid")
	public String redirect() {
		return "page";
	}
	@RequestMapping("/final")
	public String redirect2() {
		return "final";
	}
	
}

 

home.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
<h1>
	Hello world!  
</h1>

<a href="mid">Click here</a>
</body>
</html>

 

page.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>page</title>
</head>
<body>
	<a href="final">Finally</a>
</body>
</html>

 

final.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>final</title>
</head>
<body>
	<p>Spring MVC redirect between view component test</p>
</body>
</html>

 

  • Click here를 누르면 mid가 요청으로 DispatcherServlet에 전달된다. mid가 요청으로 들어오면 page 이름의 view component를 반환한다.
  • HomeController에서 반환한 page은 servlet-context.xml로 전달된다.
  • ViewResolver 에서는 전달받은 page 앞에 /WEB-INF/views/를 붙이고 뒤에 .jsp를 붙여서 View component를 찾는다.
  • DispatcherServlet에서는 해당 view component를 실행한다.

 

  • Finally를 누르면 final이 요청으로 DispatcherServlet에 전달된다.
  • DispatcherServlet은 요청에 대한 Controller entry를 web.xml에서 찾고, servlet-context.xml에서는 Controller 위치에서 HomeController를 호출한다. 
  • HomeController controller에서 final 요청에 대해 final 이름의 view component를 반환한다.
  • DispatcherServlet은 final이라는 view componet를 servlet-context.xml에서 ViewResolver에 전달하고, ViewResolver는 final 앞에 /WEB-INF/views/를 붙이고 뒤에 .jsp를 붙여서 /WEB-INF/views/final.jsp라는 view component를 반환한다.
  • final.jsp가 로드된다.

 

 

Multiple Controller

프로젝트 파일 구조

HomeController.java

package org.smu.blood;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
	
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

	@RequestMapping(value="/", method=RequestMethod.GET)
	public String home() {
		return "home";
	}
	@RequestMapping("/mid1")
	public String redirect() {
		return "page";
	}
	
}

HomeController2.java

package org.smu.blood;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
	
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

	@RequestMapping(value="/", method=RequestMethod.GET)
	public String home() {
		return "home";
	}
	@RequestMapping("/mid1")
	public String redirect() {
		return "page";
	}
	
}

home.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
<h1>
	Hello world!  
</h1>

<a href="mid1">Click here 1</a>
<a href="mid2">Click here 2</a>
</body>
</html>

page.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>page</title>
</head>
<body>
	<p>Multiple Controller Test #1</p>
</body>
</html>

final.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>page</title>
</head>
<body>
	<p>Multiple Controller Test #1</p>
</body>
</html>

 

프로젝트 실행 결과

  • Click here 1을 클릭하는 경우 mid1이 요청되어 HomeController에서 page 라는 view component를 반환하고, servlet-context.xml의 ViewResolver에 의해 /WEB-INF/views/page.jsp가 로드된다.

  • home.jsp에서 Click here 2를 클릭하면 mid2가 요청이 가고, 해당 요청에 대한 controller인 HomeController2에서 final이라는 view component를 반환한다. servlet-context.xml에서 ViewResolver에서는 /WEB-INF/views/final.jsp를 로드한다.

 

 

 

728x90
반응형

관련글 더보기