'Spring MVC 초간단 예제'에 해당되는 글 1건

  1. 2009.12.21 Spring MVC 초간단 예제 1
반응형

출처 : http://www.javajigi.net/display/OSS/Spring+MVC

Table of Contents

Spring Introduction

Spring에 대한 전반적인 내용은 아래를 참조하기 바란다.
http://wiki.javajigi.net/pages/viewpage.action?pageId=280
http://martinfowler.com/articles/injection.html

Spring MVC


Spring's web MVC framework is designed around a DispatcherServlet that dispatches requests to handlers, with configurable handler mappings, view resolution, locale and theme resolution as well as support for upload files.
The default handler is a very simple Controller interface, just offering a ModelAndView handleRequest(request,response) method.
This can already be used for application controllers, but you will prefer the included implementation hierarchy, consisting of, for example AbstractController, AbstractCommandController and SimpleFormController.
Application controllers will typically be subclasses of those. Note that you can choose an appropriate base class: If you don't have a form, you don't need a FormController. This is a major difference to Struts.

A flexible MVC web application framework, built on core Spring functionality.
This framework is highly configurable via strategy interfaces, and accommodates multiple view technologies like JSP, Velocity, Tiles, iText, and POI. Note that a Spring middle tier can easily be combined with a web tier based on any other web MVC framework, like Struts, WebWork, or Tapestry.

Spring의 웹 MVC framework는 설정가능한 핸들러 맵핑들, view분석, 로케일과 파일 업로드를 위한 지원같은 테마분석과 함께 핸들러에 요청을 할당하는 DispatcherServlet을 기반으로 디자인되었다.
디폴트 핸들러는 ModelAndView handleRequest(request,response)메소드를 제공하는 매우 간단한 컨트롤러 인터페이스이다.
이것은 이미 애플리케이션 컨트롤러를 위해 사용될수 있지만 AbstractController, AbstractCommandController그리고 SimpleFormController같은 것들을 포함한 구현 구조를 포함한것을 더 선호할것이다.
애플리케이션 컨트롤러들은 전형적으로 이것들의 하위 클래스가 된다. 당신이 선호하는 빈 클래스를 선택하도록 하라.
만약에 당신이 form을 가지지 않는다면 당신은 FormController가 필요없다. 이것이 Struts와 가장 큰 차이점이다.

유연한 MVC 웹 어플리케이션 프레임웍은 Core Spring과 상호작용하여 만들어진다.
이 프레임웍은 전략적인 인터페이스를 거쳐 높은수준으로 만들어진다. 그리고, JSP, Velocity, Tiles, iText, POI처럼 다양한 view 기술을 수용한다.
Spring middle tier는 Struts, WebWork, Tapestry와 같은 다른 웹 MVC 프레임워크를 기반으로 한 웹티어와 결합할수 있다.
Spring프레임웍에서 Model-View-Controller를 지원하는 기능이다.

강좌가 올라와있네요...
Spring MVC에서 클라이언트 요청의 처리 과정을 먼저 살펴보시면 이해가 되실거 같습니다.
http://wiki.javajigi.net/pages/viewpage.action?pageId=1133

참 고 : http://www.springframework.org/docs/reference/
번역본 : http://openframework.or.kr/framework_reference/spring/ver1.2.2/html/

설정 방법

Spring MVC를 사용하기 위해서는

  • web-app/WEB-INF/lib 아래로 spring.jar 또는 spring-webmvc.jar파일을 복사한다.
  • web-app/WEB-INF/web.xml에 DispatcherServlet를 설정한다.
  • <web.xml>
     
    
    <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>
    <servlet-mapping>
    	<servlet-name>action</servlet-name>
    	<url-pattern>*.html</url-pattern>
    </servlet-mapping>
    

    .do, .html 로 끝나는 모든 요청은 DispatcherServlet에서 담당한다.

  • DispattcherServlet이 초기화 할 때 디폴트로 사용하는 빈 설정파일의 이름은 "서블릿 이름-servlet.xml"이 된다.
  • web-app/WEB-INF/web.xml에서 설정한 <servlet-name>인 action-servlet.xml 파일을 생성한다.

즉 spring.jar 와 web.xml에 DispatcherServlet 을 사용한다는 선언 그리고 서블릿 이름-servlet.xml 을 작성하면 사용할 수 있다.

다양한 예제들

Spring MVC를 사용한 초간단 예제

링크된 강좌를 살펴보고 대략적인 것을 파악한다면 Spring MVC 사용하기 위해서 개발자들이 만들어야 하는 것은 Controller 라는 것을 알게 될 것이다. 물론 화면에 보여주는 jsp(여기선 jsp 를 연결) 파일, 빈 설정 파일을 만드는 것은 당연한 것이다.

Controller를 생성하고 빈 설정파일에 맵핑 하는 방법 등의 관계를 보여주기 위한 데이터를 가져와서 List 형태로 보여주는 예제이다

  • Controller
     
    package com.tmax.spring.web;
    
    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.tmax.spring.service.iface.BbsServiceIface;
    
    public class BbsController implements Controller {
    	
    	private BbsServiceIface bbsService;
    	
    	public void setBbsService(BbsServiceIface newBbsService){
    		this.bbsService = newBbsService;
    	}
    	
    	public ModelAndView handleRequest(HttpServletRequest arg0,
    			HttpServletResponse arg1) throws Exception {
    	    
            List list = bbsService.findBbsList();
            
            return new ModelAndView("bbs/list","bbsList", list);
       }
    
    }
    

위에서 보면 직접적으로 Controller 인터페이스를 구현해서 ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; 를 구현한다. Spring MVC에서 제공하는 다양한 Controller 들은 모두 Controller 인터페이스를 구현하기 때문에 가장 기본적인 구조라고 생각할 수 있다.

Service 객체는 setter Injection을 통해 생성된 것이다. 이것은 이미 앞에서 다 이해했을 것이다.
handleRequest(... ) 안에서 실제 메소드를 호출한 뒤 ModelAndView 객체를 통해 리턴을 하였다.

링크된 Spring MVC의 요청에 대한 생명주기를 보게 되면 비지니스 계층에서 전달된 모델 데이타와 클라이언트에게 보여줄 뷰화면에 대한 정보를 ModelAndView 클래스에 담아서 반환을 하게 되어 있다. 즉 전달 데이타 모델, 화면이름, 화면에서 사용될 객체 이름 등을 담아서 ModelAndView객체를 생성, 리턴한다.

ModelAndView 객체의 View정보가 논리적인 view이름(String) 인 경우 빈 설정 파일에 정의되어 있는 ViewResolver클래스를 이용하여 클라이언트에세 출력할 화면이름을 만들어 낼 수 있다. ModelAndView의 첫번째 인자인 "bbs/list"가 view 이름이기 때문에 설정파일의 ViewResolver를 만나서 리턴되는 화면의 전체이름이 완성되는 것이다.

  • action-servlet.xml
      
        <bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
    	
        <bean name="/bbs/listBbs.do" class="com.tmax.spring.web.BbsController">
    	<property name="bbsService">
    		<ref bean="bbsService" />
    	</property> 
        </bean>
    
        <!-- View Resolver for JSPs -->
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
          		<property name="prefix" value="/jsp/"/>
                      <property name="suffix" value=".jsp"/>
        </bean>
    

설정파일을 보면 ViewResolver로 InternalResourceViewResolver클래스를 사용한다.
그리고 JSTLView를 사용해서 jsp 로 화면을 출력할 것이라는 것을 알 수 있다. 위에 설정된 것과 ModelAndView객체에 넘긴 view이름을 조합해 보면 /jsp/bbs/list.jsp 가 되는 것이다. (prefix+view 이름+suffix )

설정파일을 보면 BeanNameUrlHandlerMapping 클래스를 사용해서 Controller와 URL을 맵핑해주는 것을 알 수 있다.
만일 빈 설정파일에 HandlerMapping이 설정되어 있지 않으면 default 로 BeanNameURLHandlerMapping을 설정한다.
맵핑 방법에는 BeanNameURLHandlerMapping, SimpleUrlHandlerMapping,CommonsPathMapHandlerMapping 등이 있다.

  • BeanNameURLHandlerMapping
    빈 이름과 URL을 mapping 하는 방법이다.
        <bean name="/bbs/listBbs.do" class="com.tmax.spring.web.BbsController">
    	<property name="bbsService">
    		<ref bean="bbsService" />
    	</property> 
        </bean>
     

즉 요청이 ..../bbs/listBbs.do가 오면 BbsController 클래스를 호출하겠다는 의미이다. name에는 <bean name="/bbs/listBbs.do /bbs/listBbs2.do".. /> 로 여러 개를 기술할 수 있다.

  • SimpleUrlHandlerMapping
    매핑에 대한 정보를 각각의 Controller에서 설정하는 것이 아니라 하나의 저장소에서 관리하는 것이다.
    Controller를 개발하는 개발자들은 빈을 정의하기만 하고 이 Controller가 어떻게 맵핑되어서 사용하는지에 대해서는 몰라도 된다.
    위의 설정파일을 SimpleUrlHandlerMapping으로 바꾸어 보면
       
        <bean id="bbsController" class="com.tmax.spring.web.BbsController">
    	<property name="bbsService">
    		<ref bean="bbsService" />
    	</property> 
        </bean>
        
       <bean id="urlMapping" 
            class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
            <property name="mappings">
                <props>
                    <prop key ="/bbs/listBbs.do">bbsController</prop>
    	   </props>
            </property>
        </bean>
    
     

실제 Controller에 대한 정의는 일반 빈을 정의 할 때와 다르지 않게 된다. 맵핑에 대한 정보는 별도의 빈(urlMapping)에서 관리되고 있다. 만일 더욱 많은 Controller가 생성되고 맵핑을 해 줘야 할 때 모든 매핑 정보는 한곳에서 관리를 할 수 있게 되는 것이다. Controller 마다 맵핑정보까지 나열할 필요가 없게 된다.

urlMapping 빈에서 Controller와 URL을 맵핑할 때 <props/>를 사용해서 기술할 수 있다. 또 다른 방법은 <props/>를 사용하지 않고 별도의 Properties 파일에서 관리 할 수도 있다.

  • CommonsPathMapHandlerMapping

Spring MVC를 사용하여 다중요청 처리하기

개발자들이 Controller 만 만들면 되지만 개발하면서 페이지, 기능이 추가 될 때마다 새로운 Contoller를 만드는 것은 굉장히 짜증이 나는 작업이다. 게다가 점점 관리해야 하는 파일의 수가 많아져서 빈 설정파일도 점점 복잡해질 것이다.이 같은 상황을 해결하기 위하여 Spring MVC는 MultiActionController를 제공한다. MultiActionController은 하나의 Controller를 구현함으로써 다수의 요청을 처리하는 것이 가능하다.

아래 예는 회원가입,수정을 통해 MultiActionController 구현을 보여준다.

Controller 객체인 MemberController.java

MemberController.java
package net.javajigi.member.web;

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

import net.javajigi.member.model.Member;
import net.javajigi.member.service.MemberService;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

public class MemberController extends MultiActionController{
	
	private MemberService memberService = null;
	public void setMemberService(MemberService memberService){
		this.memberService = memberService;
	}
	
	public ModelAndView add(HttpServletRequest request, HttpServletResponse reponse) throws Exception{
		
		Member command = new Member();
		bind(request,command);
		
                  memberService.addMember(command);
		
		return new ModelAndView("main");		
		
	}
	
	public ModelAndView update(HttpServletRequest request, HttpServletResponse reponse) throws Exception{
		
		Member command = new Member();
                  bind(request,command);
		memberService.updateMember(command);
		
		return new ModelAndView("list");
		
		
	}

}

위의 예제는 add(가입), update(수정)을 구현하기 위해 MultiActionController를 상속받은 Controller 이다.
각각의 메소드에 로직이나 서비스 호출 부분들의 소스를 구현하다.
add 메소드를 보면 화면에서 입력받은 내용을 bind()를 사용해 domain 객체에 넘기고 있다.(이 내용은 나중에..)
그 뒤 서비스의 addMember()를 호출한다.
처리 후 리턴될 페이지를 설정한다.(add->main.jsp, update->list.jsp)

Controller를 작성 후 webapps/WEB-INF/action-servlet.xml 파일에 빈을 매핑한다.

action-servlet.xml
<bean id="memberService" class="net.javajigi.member.service.MemberService"/>

<bean name="/member/addMember.do /member/updateMember.do" class="net.javajigi.member.web.MemberController">
	<property name="methodNameResolver">
		<ref local="memberControllerMethodNameResolver"/>
	</property>	
	<property name="memberService">
		<ref local="memberService"/>
	</property>			
</bean>	

<bean id="memberControllerMethodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
	<property name="mappings"> 
		<props>
			<prop key="/member/addMember.do">add</prop>
			<prop key="/member/updateMember.do">update</prop>
		</props>
	</property>
</bean>

MemberController는 두 개의 URL(/member/addMember.do,/member/updateMember.do)에 맵핑이 되었다.각각의 URL이 호출될 때 MemberController 안의 어떤 메소드가 호출될 지는 "memberControllerMethodNameResolver"빈에서 PropertiesMethodNameResolver를 통해 매핑이 된다. 결국 /member/addMember.do 가 호출되면 MemberController의 add 메소드가 /member/updateMember.do가 호출되면 update 메소드가 호출된다.

결국 위의 예는 빈 설정파일에서 URL을 다르게 함으로써 메소드에 접근할 수 있도록 설정한 것이다. (PropertiesMethodNameResolver 클래스를 통해서)

<bean name="/member/member.do" class="net.javajigi.member.web.MemberController">
	<property name="methodNameResolver">
		<ref local="methodNameResolver"/>
	</property>
</bean>

<bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
	<property name="paramName"> 
		<value>method</value>
	</property>
	<property name="defaultMethodName"> 
		<value>add</value>
	</property>
</bean>

위의 예를 보면 MemberController는 하나의 URL에 맵핑이 되었다. 그럼 어떻게 MemberController의 다른 메소드를 호출할 수 있을까? 그것은 "methodNameResolver" 빈의 "ParameterMethodNameResolver" 를 이용해서 호출이 가능하다.
URL을 통해 전달되는 인자중에 "paramName"인 method라는 이름을 가지는 인자의 값에 해당하는 메소드를 호출해 주는 것이다.
즉 /member/member.do?method=add 를 하게 되면 MemberController의 add()를 호출하는 것이다. /member/member.do?method=update를 하면 update()를 호출하게 될 것이다. 만일 아무 값도 없다면 default 으로 add()를 호출하게 된다. 호출하는 URL은 같지만 뒤 인자의 인자값을 변경해 줌으로써 다른 메소드를 호출할 수 있다.

ParameterMethodNameResolver를 이용하면 MultiActionController를 상속받은 Controller 에 메소드가 추가되더라도 설정파일에 추가적인 설정이 필요 없을 것이다. 하지만 호출할 때 추가된 메소드 이름을 알아야 한다.

데이터 바인딩(Data Binding)
웹 애플리케이션 개발에서 입력, 수정과 관련된 기능을 구현하기 위해서 입력하는 값에 대한 유효성 체크와 입력 값을 도메인 모델로 바인딩 하는 기능이 필요하다.그 동안 개발자들은 유효성 체크를 위해서 화면단에는 많은 자바스크립트를 데이타 바인딩을 위해서는 HttpServletRequest에 담긴 인자를 꺼내서 다시 도메인 모델로 set하는 코드들이 난무했을 것이다.

Spring MVC 에서는 입력화면(또는 수정화면)에서 전달되는 입력 데이터를 비즈니스 계층에 전달하기 위하여 HttpServletRequest에 담긴 인자와 도메인 모델의 속성을 자동적으로 연결하는 데이터 바이팅을 지원하고 있다.

위에 나온 bind()가 그 역할을 하는 것이다.

bind(request,command);

Bind request parameters onto the given command bean
@param request request from which parameters will be bound
@param command command object, that must be a JavaBean
@throws Exception in case of invalid state or arguments

대신 클라이언트가 입력한 데이터를 도메인 모델과 데이터 바인딩 하기 위해서는 입력 화면에서 사용한 속성이름과 도메인 모델의 속성이름이 같아야 한다.

  • 회원가입 입력폼인 memberEntry.jsp
    <%--
    작성자 : 난다
    일자 : 2006.02.13
    설명: 회원가입
    --%> 
    <%@page contentType="text/html; charset=euc-kr"%>
    <%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"%>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>    
        <title>사용자 관리 - 회원 가입</title>     
        <link rel="stylesheet" type="text/css" href="../css/style.css" media="screen">
      </head>  
     <body>
     <div id="member">
     <form name="thisform" method="post" action="${pageContext.request.contextPath}/member/addMember.do">   
    	<table summary="회원가입">
    		<caption>회원 정보 </caption>
    		<tr>
    			<th id="id">* 아이디</th>
    			<td headers="id">
    				<input type="text" id="id" name="id" />
    			</td>
    		</tr>
    		<tr>
    			<th id="password">* 비밀번호</th>
    			<td headers="password">
    				<input type="text" id="password" name="password" />
    			</td>
    		</tr>
    		<tr>
    			<th id="passwordRepeat">* 비밀번호</th>
    			<td headers="passwordRepeat">
    				<input type="text" id="passwordRepeat" name="passwordRepeat" />
    			</td>
    		</tr>	
    		<tr>
    			<th id="password_hint">* 비밀번호 힌트 </th>
    			<td headers="passwordHint">
    				<input type="text" id="passwordHint" name="passwordHint" />
    			</td>
    		</tr>
    		<tr>
    			<th id="passwordAnswer">* 비밀번호 답 </th>
    			<td headers="passwordAnswer">
    				<input type="text" id="passwordAnswer" name="passwordAnswer" />
    			</td>
    		</tr>
    		<tr>
    			<th id="email">* e-mail</th>
    			<td headers="email">
    				<input type="text" id="email" name="email" />
    			</td>
    		</tr>						
    	</table>
    	<center>	
    		<input type="submit" value="확인" tabindex="4" />
    	</center>
    </form>
    </div>
    </body>
    </html>
    
    
  • 도메인 모델 Member.java
Member.java
package net.javajigi.member.model;

import org.apache.commons.lang.builder.ToStringBuilder;

public class Member {
	private String userId = null;
	private String password = null;
	private String passwordRepeat = null;
	private String passwordHint = null;
	private String passwordAnswer = null;
	private String email = null;
	
         변수들에 대한 getter,setter 메소드...
              .
              .
              .
        public String toString() {
          return ToStringBuilder.reflectionToString(this);
        }
	
}

memberEntry.jsp의 입력필드의 이름은 id,password,passwordRepeat,passwordHint,passwordAnswer,email로 정의 되어 있다.
그리고 바인딩되는 도메인 모델 Member도 id,password,passwordRepeat,passwordHint,passwordAnswer,email 가 정의되어 있다.
즉 같은 속성이름에 대해서는 가져올 수 있지만 만일 다르다면 가져오지 못하게 된다.

위의 예제에서 사용한 MultiActionController는 입력데이터에 대한 유효성 체크 기능을 지원하지 않는다. 만일 유효성 체크도 원한다면 MultiActionContorller를 상속받아서는 사용할 수 없다.
유효성 체크와 바인딩 기능까지 모든 기능을 사용하길 원한다면 AbstractCommandControllder 클래스를 상속받아야 한다.

AbstractCommandControllder를 상속받은 Controller

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractCommandController;

import com.tmax.spring.domain.Member;
import com.tmax.spring.service.app.MemberService;

public class MemberAbstractCommandController extends AbstractCommandController{
    private static transient Log log = LogFactory.getLog(MemberAbstractCommandController.class);
	
    private MemberService memberService = null;
	
    public void setMemberService(MemberService memberService){
	this.memberService = memberService;
    }
	
    public MemberAbstractCommandController(){
	setCommandClass(Member.class);
    }
	
    protected ModelAndView handle(HttpServletRequest request, 
		HttpServletResponse response, Object command, BindException errors) 
                 		throws Exception {
	Member member = (Member)command;
		
	//memberService.addBbs(command);
	log.error("가져오는지..."+member.toString());
		
	return new ModelAndView("../index");	
     }
 }

AbstractCommandController를 상속받아 구현 하려면 바인딩하는 클래스를 디폴트 생성자 안에 setCommandClass()를 통해서 설정해야 한다. 위의 예를 보면

public MemberAbstractCommandController()

Unknown macro: { setCommandClass(Member.class); }

그러면 들어오는 입력 값들과 설정한 클래스와의 바인딩이 이전에 보았던 bind() 라는 메소드 없이 Casting 만으로 이루어 진다.

하지만 AbstractCommandController는 요청에 대해 각각의 Controller를 만들어야 한다.결국 데이터 바인딩 및 데이터에 대한 유효성 체크 기능을 지원하고 있지만 AbstractCommandController를 상속받은 Controller로는 다수의 요청을 처리 할 수 없는 것이다.즉 Controller 를 이용하면 요청에 따라 추가되고 빈 설정 정보또한 수정해 주어야 한다.

결국 큰 주제로 했던 다수의 요청을 한 Controller에서 처리하는 방법은 아니지만 좀 더 손쉽게 유효성체크와 데이터 바인딩을 할 수 있다는 점에서는 유용하다. 간단한 CRUD 같은 작업은 MultiController를 구현해 한 Controller에서 사용할 수도 있고( 물론 유효성체크는 스크립트나 다른 방법을 통해) 복잡하고 많은 입력 필드를 가지고 있는 화면이라면 AbstractCommandController를 사용해 좀 더 손쉽게 처리 할 수 있을 것이다.

이것은 각각의 프로젝트, 요구사항등에 맞추어 결정하면 될 것이다.

action-servlet.xml 추가사항
	<bean name="/member/addMemberWithAbstract.do"   class="com.tmax.spring.web.MemberAbstractCommandController">
	  <property name="memberService">
		<ref bean="memberService" />
	 </property>	
        </bean>
  • 실제로직을 담당하는 비지니스 객체인 MemberService.java 파일을 생성한다.
MemberService.java
package net.javajigi.member.service;

import net.javajigi.member.model.Member;

public class MemberService {
	
	public void addMember(Member member){
		//로직처리
	}
	
	public void updateMember(Member member){
		//로직처리
	}
}

하나의 Controller만으로 입력,수정처리하기

<ation-servlet.xml>
 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
	<property name="mappings">
			<props>				
				<prop key="/login.do">loginFormController</prop>				
			</props>
		</property>
	</bean>	
	
	<bean id="loginFormController" class="spring.LoginFormController">
		<property name="formView"><value>/login</value></property>
		<property name="successView"><value>/main</value></property>
	</bean>
		
	<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="viewClass">
			<value>org.springframework.web.servlet.view.JstlView</value>
		</property>
		<property name="cache"> 
			<value>false</value>
		</property>
		<property name="prefix">
			<value>/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>		
	</bean>
</beans>

Controller를 URL과 매핑해주어야 한다.
login.do에 대한 요청을 loginFormController가 담당하며, 이 Controller는 로그인을 위한 로직처리를 포함하고, 사용자가 직접 작성해야한다.
입력화면은 /login 이며, 로직을 무사히 처리한후에는 /main으로 이동한다.
JSTL pages , jsp Page를 사용하기위해 JstlView를 선언하였다.

  • web-app/login.jsp 로그인 페이지를 생성한다.
    <login.jsp>
    <%@page contentType="text/html; charset=euc-kr"%>
    <%@ page language="java" import="java.util.*" %>
    <html>
      <head>
        <title>My JSP 'login.jsp' starting page</title>    
      </head>  
      <body>
      <form name="myForm" method="post" action="/spring/login.do">
       	<table>
       		<tr>
       			<td>
       				ID	: <input type="text" name="userId" value="1">   				
       			</td>
       		</tr>
       		<tr>
       			<td>
       				PASSWORD	: <input type="password" name="password" value="2">   				
       			</td>
       		</tr>
       		<tr>
       			<td>
       				<input type="submit" name="login" value="로그인"/>
       			</td>
       		</tr>
       	</table>
       </form>
      </body>
    </html>
    
  • web-app/main.jsp 로그인성공후 이동할 메인 페이지를 생성한다.
    <main.jsp>
    <%@page contentType="text/html; charset=euc-kr"%>
    <%@ page language="java" import="java.util.*" %>
    
    <html>
      <head>
        <title>My JSP 'main.jsp' starting page</title>   
      </head>  
      <body>
      	Login Success~!!
      </body>
    </html>
    
  • web-app/WEB-INF/net.javajigi.user.web.LoginFormController.java 파일을 생성한다.
LoginFormController.java
package net.javajigi.user.web;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import net.javajigi.user.model.Authenticate;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

public class LoginFormController extends SimpleFormController {	
	
	public LoginFormController() {
                  // bean 객체
		setCommandName("authenticate");
		setCommandClass(Authenticate.class);
	}
	
	public ModelAndView onSubmit(HttpServletRequest request,
			HttpServletResponse response, Object command, BindException errors)
			throws Exception {
		
		if (request.getParameter("login") != null) {
			Authenticate auth = (Authenticate) command;

			try {
				//로직처리 
                                          //boolean bResult = UserLoginProc.login(auth);

                                    //View 객체 리턴 
				return new ModelAndView(getSuccessView());
				
			} catch (Exception e) {
				request.setAttribute("errorMessage", e.getMessage());

				return new ModelAndView(getFormView());
			} 
			
		} else {
			HttpSession session = request.getSession();

			if (session.getAttribute("loginUser") != null) {
				return new ModelAndView("decorators/logout");
			} else {
				return new ModelAndView("decorators/login");
			}
		}
	}
}

SimpleFormController 을 상속받은 LoginFormController.java 파일을 생성한다.

  • web-app/WEB-INF/net.javajigi.user.model.Authenticate.java 파일을 생성한다.
Authenticate .java
package net.javajigi.user.model;


public class Authenticate {
    private String userId = null;

    private String password = null;
    
	public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }
}

LoginFormController.java에서 호출되는 bean객체를 생성한다.

참고문헌

Posted by 1010