본문 바로가기

Spring

[Spring] MVC2 패턴 동작과정2 - Spring framework 클래스 적용

반응형

이번 포스팅에서는 스프링에서 제공하는 클래스로 교체하면서 Spring MVC를 적용! 

 

★이전 포스팅 참고

 


동작순서대로 스프링에서 제공하는 클래스로 교체하는 작업을 해보려고 한다. 

 

1) *.do 요청을 하면 web.xml을 읽어들이는 서블릿 컨테이너가 동작하면서 서블릿 객체를 생성 

    기존에 "내가 직접 만든 DS"를 "Spring에서 제공하는 DS"로 교체 

 

< 변경 전 >   

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://Java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <servlet>
    <description></description>
    <display-name>DispatcherServlet</display-name>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>com.kim.biz.controller.DispatcherServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
</web-app>

< 변경 후 >   

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://Java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

Spring에서 제공하는 DS로 교체하기 위해서 servlet-class를 하기 코드로 변경! 

 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

web.xml 변경 후 서버를 돌려보면 하기와 같이 ClassNotFoundException이 발생

ClassNotFoundException 해결 방법 : 프로젝트 우클릭 -> properties -> Deployment Assembly -> 우측 Add -> Java Build Path Entries -> Maven Dependencirs 클릭 후 Finish  

상기와 같이 설정 후 다시 서버를 실행하면 이번엔 또다른 오류 발생...

FileNotFoundException 이 발생하는데 오류 문구를 살펴보면 

Could not open ServletContext resource [/WEB-INF/DispatcherServlet-servlet.xml] 

즉, WEB-INF 하위에 DispatcherServlet-servlet.xml 없다는 내용이다. 

 

결론적으로, 서블릿 컨테이너는 동작할 때( Spring에서 제공하는 DS객체를 생성해줄 때) init() 메서드가 자동 실행되는데 

init() 메서드가 자동 실행되는 이유는!! 스프링 컨테이너가 [/WEB-INF/DispatcherServlet-servlet.xml] 파일을 참고해서 

POJO(서블릿 객체가 아닌)인 HM, C, VR 객체를 생성하기 때문이다.


2) 등록할 서블릿 이름 -Servlet.xml 파일 생성 

 

DispatcherServlet-servlet.xml 이름으로 스프링 컨테이너가 참고할 xml 파일을 생성해보려고 한다. 

 

파일 위치 : WEB-INF 하단 

Spring Bean Configuration File -> Next -> Finish


3) 필터 클래스 만들기 

 

기존에는 Filter 클래스에 어노테이션을 적용하였지만,  Spring framework에서는  web.xml 설정파일에서 필터 설정 

기존 작성해두었던 web.xml에 filter 를 추가 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://Java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
  
  <filter>
     <filter-name>characterEncodingFilter</filter-name>
     <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
       <param-name>encoding</param-name>
       <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
     <filter-name>characterEncodingFilter</filter-name>
     <url-pattern>*.do</url-pattern>
  </filter-mapping>
  </web-app>

 


4) Spring에서 제공하는 Controller로 변경 

 

이전에는 interface클래스인 Controller 클래스는 직접 만들어서 각 Controller 클래스마다 inplements 해주었다. 

하지만 굳이 직접 만들 필요 없이 Spring framework에서 제공하는 Controller interface를 사용하면 된다. 

 

import에는 springframeswork가 제공하는 Controller와 ModelAndView 클래스가 되어 있다.

ModelAndView 객체는 데이터와 뷰를 동시에 설정이 가능하다. 

mav.setViewName("뷰의 경로);

mav.addObject("변수 이름", "데이터 값"); 

 

<LoginController> 

package com.kim.biz.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.kim.biz.member.MemberVO;
import com.kim.biz.member.impl.MemberDAO;

public class LoginController implements Controller {

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String mid=request.getParameter("mid");
		String mpw=request.getParameter("mpw");
		MemberVO mVO=new MemberVO();
		mVO.setMid(mid);
		mVO.setMpw(mpw);
		
		MemberDAO mDAO=new MemberDAO();
		mVO=mDAO.selectOneMember(mVO);
		
		ModelAndView mav= new ModelAndView();
		if(mVO==null) {
			mav.setViewName("redirect:login.jsp"); // redirect:를 붙이면 sendredirect 방식
		}
		else {
			HttpSession session=request.getSession();
			session.setAttribute("member", mVO);
			mav.setViewName("redirect:main.do");
		}
		return mav;
	}
}

5) HandlerMapping을 등록

 

기존에는 '내가 만든 DS'의 init() 메서드에서 생성

-> 스프링 컨테이너가 [/WEB-INF/DispatcherServlet-servlet.xml] 참고해서 HM을 생성 

-> "내가 만든 HM"을 사용하지않고, "Spring에서 제공하는 HM"으로 등록했기때문에 기존의 클래스파일을 제거해도 무방 

 

HM을 제대로 사용하려면? 

-> 멤버변수가 존재하기 때문에, == 의존관계가 존재하기때문에, DI(의존성 주입)을 반드시 해줘야함 

 

SimpleUrlHandlerMappingURL 패턴에 매핑되는 지정된 Controller를 사용하는 방법으로 

prop안에 key = string , value= controller 가 된다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	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.xsd">

	<!-- HM 등록 -->
	<bean
		class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<!-- 의존관계 주입 -->
		<property name="mappings">
			<props>
				<prop key="/login.do">login</prop>
				<prop key="/main.do">main</prop>
				<prop key="/board.do">board</prop>
				<prop key="/logout.do">logout</prop>
				<prop key="/signin.do">signin</prop>

			</props>
		</property>
	</bean>

	<!-- Controller 객체 등록 -->
	<bean id="login" class="com.kim.biz.controller.LoginController" />
	<bean id="main" class="com.kim.biz.controller.MainController" />
	<bean id="board" class="com.kim.biz.controller.BoardController" />
	<bean id="logout" class="com.kim.biz.controller.LogoutController" />
	<bean id="signin" class="com.kim.biz.controller.InsertMemberController" />
</beans>

6)  ViewResolver를 등록하여 VR를 통해서 화면을 제공

 

ViewResolver

  • 실행할 뷰를 찾는 일을 한다. 
  • 페이지 컨트롤러가 리턴한 뷰 이름에 해당하는 뷰 콤포넌트를 찾는 역할 

InternalResouceViewResolver

  • 미리 지정된 접두사, 접미사를 사용하여 뷰이름으로 콤포넌트 URL을 완성해 URL을 지정하기 편리 

※ 한가지 특징으로 main.jsp, board.jsp 외부에서 가져올 데이터가 있는 페이지들은  /WEB-INF 하위에 배치하여 

브라우저에서 절대 접근할 수 없도록 한다. (ex url로 검색으로 인한 접근) 

	<!-- ViewResolver 등록 , 뒤에 Resolver로 끝나는 애들은 이름이 고정적! spring에서 제공하는 방식-->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/view/" />
		<property name="suffix" value=".jsp" />
	</bean>

 

일부 Controller 에는 데이터를 전송시킬 수 있는 리턴 타입인 ModelAndView에 

key와 value를 담아 보낼 수 있는 메서드인 addObject를 사용한다. 

이 때 데이터를 담아 jsp에 forward 방식으로 전달한다. (ex MainController, BoardController) 

 

<BoardController.java>

mav.setViewName("main"); -> main.jsp에 forward 방식으로 이동 

package com.kim.biz.controller;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.kim.biz.board.BoardVO;
import com.kim.biz.board.impl.BoardDAO;

public class MainController implements Controller{

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
		BoardVO bVO=new BoardVO();
		BoardDAO bDAO=new BoardDAO();
		List<BoardVO> datas=bDAO.selectAllBoard(bVO);
		
		ModelAndView mav=new ModelAndView();
		mav.addObject("datas", datas);
		mav.setViewName("main"); //forward라서 
		return mav;
	}
}

forward 방식 외에 sendRedirect 방식을 으로 이동하고 싶다면

"redirect: 가고싶은 경로.jsp" or "redirect: 가고싶은 경로.do" 사용하여 다른 controller 거쳐서 view로 이동 할 수 있다.  

 

 

★ 다시 한번 흐름도 총정리 

웹브라우저 DispatcherServlet Controller 모델 앤 뷰 Controller DispatcherServlet 웹브라우저

 

① 웹브라우저에게 정보요청을 받은 DS는 어느 컨트롤러에 해당 요청을 전송할지 결정 

② DS는 HM에 어느 컨트롤러를 사용할건지 물어봄. (URL로 링크)

③ 결정된 컨트롤러는 해당요청을 수행하게 됨

④ 해당요청을 처리한 컨트롤러는 DS에 결과를 보냄. 이 과정에서 Model이 생성되어 View(JSP)에서 같이 사용됨 

⑤ ModelAndView는 실제 JSP정보를 갖고 있지 않기 때문에 VR가 실제 JSP이름으로 변환하여 해당 view를 검색함.

⑥ 검색한 결과를 View에 전송

⑦ View는 모든 과정에서 처리된 결과를 화면으로 표현함

⑧ 마지막으로 DS가 웹브라우저에 최종결과를 출력

반응형