21장. 스프링 MVC 기능

21.1 스프링 프레임워크 MVC의 특징

  • 모델2 아키텍쳐를 지원
  • 스프링과 다른 모듈과의 연계가 쉬움
  • 타일즈나 사이트메시 같은 View 기술과의 연계가 쉬움
  • 태그 라이브러리를 통해 message 출력, theme 적용 그리고 입력 폼을 보다 쉽게 구현 가능

< 스프링 프레임워크의 MVC 구조도와 실행과정 >

+) 9. view의 결과를 DispatcherServlet으로 보냄

+) 10. DispatcherServlet은 최종 결과를 브라우저로 전송

 

- 각 구성요소의 설명

구성 요소 설명
DispatcherServlet 클라이언트의 요청을 전달받아 해당 요청에 대한 컨트롤러를 선택하여 클라이언트의 요청을 전달, 또한 컨트롤러가 반환한 값을 View에 전달하여 알맞은 응답을 생성
HandlerMapping 클라이언트가 요청한 URL을 처리할 컨트롤러를 지정
Controller 클라이언트의 요청을 처리한 후 그 결과를 DispatcherServlet에 전달
ModelAndView 컨트롤러가 처리한 결과 및 뷰선택에 필요한 정보를 저장
ViewResolver 컨트롤러의 처리 결과를 전달할 뷰를 지정
View 컨트롤러의 처리 결과 화면을 생성

출처 : https://goblin9.tistory.com/34

 

 

21.2 SimpleUrlController 이용해 스프링 MVC 실습하기

  •  요청 URL에 대해 미리 매핑해 놓은 컨트롤러를 호출, 컨트롤러에서는 JSP를 브라우저로 전송하는 실습!
  • 이전과 다르게 xml에서 미리 브라우저의 요청과 컨트롤러를 매핑!

< 구현과정 >

  1. (스프링 설정 - 스프링 3.0 라이브러리 파일들을 /WebContent/WEB-INF/lib 폴더에 넣음) 
  2. web.xml에서 DispatcherServlet 서블릿 이름 설정 후 *.do 매핑
  3. '서블릿이름-servlet.xml'에서 요청명과 컨트롤러를 매핑
  4. 컨트롤러에서는 ModelAndView에 viewname(jsp파일이름)을 설정해서 반환하도록 함
  5. 브라우저로 전송될 jsp작성

< 실행 과정>

 1. 브라우저에서 ~pro21/test/index.do로 요청

 2. DispatcherServlet이 '~-servlet.xml'에서 SimpleUrlHandelrMapping 클래스에 설정된 요청명-컨트롤러 매핑을 보고 컨트롤러를 요청

 3. 컨트롤러에서 반환된 jsp를 찾아 DispatcherServlet이 브라우저로 전송함

 

 

- web.xml

>> 브라우저에서 *.do 요청 시 스프링의 DispatcherServlet 클래스가 요청을 받을 수 있게 서블릿 매핑

>> load-on-startup을 양수로 지정하여 톰캣 실행 시 미리 스프링의 DispatcherServlet을 메모리에 로드

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
 <servlet>
 	<servlet-name>action</servlet-name>
 	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 	<load-on-startup>1</load-on-startup>
 </servlet>
	
 <servlet-mapping>
 	<servlet-name>action</servlet-name>
 	<url-pattern>*.do</url-pattern>
 </servlet-mapping>
	
</web-app>html

 

- action-servlet.xml

>> 스프링 프레임워크에서 필요한 빈들을 설정(여기선 컨트롤러, SimpleUrlHandlerMapping 클래스)

>> 파일이름은 반드시 '(web.xml에서 매핑했던)서블릿의 이름(여기선 action)-servlet.xml' 형태가 되어야 함

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans   
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<bean id="simpleUrlController" class="com.spring.ex01.simpleUrlController"></bean>
	<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="mappings">
			<props>
				<prop key="/test/index.do">simpleUrlController</prop>
			</props>
		</property>
	</bean>
</beans>html

>> 상단 <beans> 태그 부분은 실습파일에서 복붙하기

 

- SimpleUrlController.java

>> 요청을 처리하기 위해 반드시 Controller 인터페이스를 구현해야 함

public class SimpleUrlController implements Controller {
	@Override
	public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
		return new ModelAndView("index.jsp");
	}
}java

 

- index.jsp

..
<title>spring 테스트입니다.</title>
</head>
<body>
   <h1>index.jsp파일입니다.</h1>
   <p>Hello Spring!!</p>
</body>
</html>html

 

>> 이 방법으로 하면 각 요청명에 대해 (스프링의 Controller 인터페이스를 구현한)각각의 컨트롤러 클래스들을 일일이 만들어야 함 >> MultiActionController로 해결

 

21.3 MultiActionController 이용해 스프링 MVC 실습하기

  • MultiActionController를 이용하면 여러 요청명에 대해 한 개의 컨트롤러에 구현된 각 메서드로 처리 가능
  • < 실습에 사용되는 스프링 클래스들 >
클래스 설명
MultiActionController URL 요청명으로 바로 컨트롤러를 지정해서 사용
PropertiesMethodNameResolver URL 요청명 - 메서드 매핑
InternalResourceViewResolver - 컨트롤러에 반환된 이름+조건에 해당하는 뷰를 선택
- prefix, suffix 프로퍼티로 디폴트 조건 지정

 

- action-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans   
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<bean id="userController" class="com.spring.ex02.UserController">
		<property name="methodNameResolver">
			<ref local="userMethodNameResolver"/>
		</property>
	</bean>
	
	<bean id="userMethodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
		<property name="mappings">
			<props>
				<prop key="/test/login.do">login</prop>
			</props>
		</property>
	</bean>



	<bean id="userUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="mappings">
			<props>
				<prop key="/test/*.do">userController</prop>
			</props>
		</property>
	</bean>



	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
		<property name="prefix" value="/test/" />
		<property name="suffix" value=".jsp"/>
	</bean>
</beans>html
  • PropertiesMethodNameResolver : 여기서 요청명과 메서드를 매핑

                                                   : Controller에 이 빈이 주입됨

  • 이전과 동일하게 SimpleUrlHandlerMapping를 이용해서 *.do와 컨트롤러를 매핑
  • InternalResourceViewResolver :  컨트롤러에서 ModelAndView 인자로 뷰이름이 반환되면 InternalResourceViewResolver의 프로퍼티 prefix/suffix 속성에 지정된 조건에 맞는 JSP를 선택해 DispatcherServlet으로 보냄

 

- UserController.java

>> MultiActionController를 상속받아 methodNameResolver 프로퍼티를 사용할수 있도록 한다.

>> ModelAndView객체에 JSP에 전달할 값을 바인딩한다! => MAV 객체의 addObject 메서드 이용

public class UserController extends MultiActionController{

	public ModelAndView login(HttpServletRequest request, HttpServletResponse response) throws Exception{
		ModelAndView mav=new ModelAndView("result");
		
		request.setCharacterEncoding("utf-8");
		String userID=request.getParameter("userID");
		String passwd=request.getParameter("passwd");
		
		mav.addObject("userID",userID);
		mav.addObject("passwd",passwd);
		
		return mav;
	}
}java

>> setViewName()으로 jsp이름을 설정할 수 있다.(but 여기서는 modelAndView의 생성자 매개변수로 설정했음)

>> action-servlet.xml에서 ViewResolver로 디폴트 설정을 했기 때문에 여기서는 이름만 넘겨주면된다.

 

 

- loginForm.jsp : action="${contextPath}/test/login.do"으로 설정하여 로그인 폼 화면 작성

- reuslt.jsp : 컨트롤러에서 바인딩 되어 넘어온 정보를 출력

 

 

21.4 MultiActionController 이용해 회원 정보 표시하기

  • action-servlet.xml에서는 methodNameResolver에서 회원정보 요청명과 메서드를 매핑
  • controller에서는 회원정보를 처리하는 메서드(memberInfo)를 하나 생성
  • memberForm.jsp에서 폼을, memberInfo.jsp에서 결과를 출력

(앞서 한 로그인 예제에서 추가한 것)

- action-servlet.xml

...
				<prop key="/test/login.do">login</prop>
				<prop key="/test/memberInfo.do">memberInfo</prop>
...html

- Controller.java

...
	public ModelAndView memberInfo(HttpServletRequest request, HttpServletResponse response) throws Exception{
		ModelAndView mav=new ModelAndView("memberInfo");
		
		request.setCharacterEncoding("utf-8");
		String id=request.getParameter("id");
		String pwd=request.getParameter("pwd");
		String name=request.getParameter("name");
		String email=request.getParameter("email");
		
		mav.addObject("id",id);
		mav.addObject("pwd",pwd);
		mav.addObject("name",name);
		mav.addObject("email",email);
		
		return mav;
	}
...java

 

 

21.5 요청명과 동일한 JSP 표시하기

- 결과를 보여주는 jsp의 이름을 직접 지정하지 않고 요청명과 같은 이름의 jsp를 선택하도록 해보자

   >> 전체 URL 요청명에서 찐 요청명을 추출하는 getViewName() 메서드를 직접 작성~

 

- Controller

public ModelAndView memberInfo(HttpServletRequest request, HttpServletResponse response) throws Exception{
		String viewName=getViewName(request);
		ModelAndView mav=new ModelAndView(viewName);
        ...
        }
        
private String getViewName(HttpServletRequest request) throws Exception{
    String contextPath=request.getContextPath();
    String uri=(String)request.getAttribute("javax.servlet.include.request_uri");
    if(uri==null || uri.trim().contentEquals("")) {
        uri=request.getRequestURI();
    }

    int begin=0;
    if(!((contextPath==null)||("".contentEquals(contextPath)))) {
        begin=contextPath.length();
    }

    int end;
    if(uri.indexOf(";")!=-1) {
        end=uri.indexOf(";");
    } else if(uri.indexOf("?")!=-1) {
        end=uri.indexOf("?");
    } else {
        end=uri.length();
    }

    String fileName=uri.substring(begin, end);
    if(fileName.indexOf(".")!=-1) {
        fileName=fileName.substring(0,fileName.lastIndexOf("."));
    }
    if(fileName.indexOf("/")!=-1) {
        fileName=fileName.substring(fileName.lastIndexOf("/"),fileName.length());
    }

    return fileName;
}java

 

 

>> URL 요청명 = 컨트롤러 메서드 이름 = JSP페이지 이름

     >> 가독성&유지관리에 좋음