본문 바로가기

nerv-team.co.kr

[Spring] nerv-team.co.kr "Default MVC" CH01.목록 띄우기


미루고 미뤄왔던 nerv-team.co.kr 의 spring 세미나 준비 chapter01.

일반적으로 M - V - C 는 Model (비지니스)- View - Controller 를 각각 분리해 자기 자신들의 일만 하겠다는 뜻이다.
spring Application  은 다른 프레임웍과 마친가지로 Front controller 패턴을 채용하고 있다.

개념 1. Front Controller 패턴이란?
핸들러 오브젝트를 매개로 하여 요청을 분배함으로써 요청을 통합하고,
요청에 대한 통일된 처리를 기술 할 수 있도록 하기위한 패턴이다.



**** 흐름  *****
Request 웹 브라우저 요청은 DispatcherServlet (이하 D.S)인스턴스로 송신되어 공통처리를 실행한 다음,
RequestURL 고유의 처리를 실행하는 Request 컨트롤러를 호출한다.
<이때 컨트롤러의 처리 단위는 개발자가 작성하기 때문에 어느 Request 컨트롤러에 매핑되어 있는가를 알아야 함!!>

흐름 1. HanddlerMapping(이하 핸들러맵핑) : ReuqestURL - Request controller 의 맵핑을 관리 (D.S 는 가지고 있지 않음)
흐름 2. 핸들러맵핑에서 받은 controller 인스턴스를 가지고 프로세스 전달 (빨간색)
비즈니스 로직을 호출하여 처리 결과와 이동할 View 정보를 D.S 에 반환한다. (검은색)
D.S 로 넘어온 정보 : modelAndView (모델과 뷰)
흐름 3. Controller 인스턴스로 부터 반환된 View 는 논리정보 이기 때문에 D.S는 View 의 실체를 ViewResolver 에 문의한다.
(여기서 뭐 벨로시티나, jsp 나 등등.. 뭐 JSP 에 관련된 프레임웍 중 하나 골라골라~)
흐름 4. View 에서 결과를 브라우저로 출력!

Summery

DispatcherServlet : 웹 브라우저로부터 송신된 Reuqst 를 일괄적으로 관리.

HandlerMapping : ReuqstURL 과 Controller 클래스의 맵핑을 관리.

Controller : 비즈니스 로직을 호출하여 처리결과 ModelAndView 인스턴스를 반환.

ViewResolver : Controller 클래스로부터 반환된 View 정보가 논리적인 view 이름일 경우에는 bean 설정 파일에
                       정의되어 있는 ViewResolver 클래스를 이용하여 클라이언트에게 출력할 View 객체를 얻음.

View : 프레젠테이션층으로의 출력 데이터를 설정한다.


자, 이제 한번 예제를 만들어 보도록 하자.

정말 Spring 에서 명시적으로 정의해 주지 않아도 묵시적으로 사용되고 있는
Hadler Mapping  과 Controller, ViewResolver, View 를 사용하여 간단히 select 해 오는것을 만들어 보도록 하자.

Spring Default


자, 이렇게 되면 다음과 같은 화면 처리 흐름이 나오겠군요. 
어디가 바뀐지 모르겠다구요? 그래서 체크 표시로 바뀐부분을 표시해 뒀습니다 ^^

앞서 spring library 는 다운받는 것은 써 놓았기 때문에 숙지 한다음에 다시 오도록 합니다.
http://joke00.tistory.com/22  에서 참조 하거나 http://www.springframework.org  에서 다운 받도록 합시다.

* DB생성 및 구현

다음과 같이 db 를 만들었습니다.


 DB Creation 파일과 예제 데이터를 첨부하도록 하겠습니다 히힛-

starUML tool을 이용하여 다음과 같은  클래스 다이어 그램을 그려보겠습니다.


SequenceDiagram도 만들어 보았습니다.
아... 뭔가 많이 부족합니다 -_-;;(그냥 일단 starUML 을 이용해 class Diagram 과 sequence 를 그려봤다는거에 의의를 둡시다)


믿기 힘들겠지만, 위의 모양(클래스와 시퀀스 다이어그램)을 본 따 프로젝트 구조는 다음과 같이 나오겠죠
(그럴꺼라 믿어 의심치 않습니다 !!! +_+)


자, 이제 본격적인 Source 작성에 들어가 봅시다.

1.web.xml  설정
스프링의 캐릭터인코딩필터 -_-;; (영문귀차나염;;) 를 이용하여 UTF-8 로 인코딩합니다.
EUC-KR 인분들은 EUC-KR 로 써 주셈...


다음은 servlet mapping  차례 입니다.
모든 *.do 로 들어오는 것은 스프링의 DispatcherServlet  을 통해서 간답니다.



2.shop-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="indexController" name="/index.do" class="controller.IndexController">
  <property name="itemCatalog"><ref bean="itemCatalog"/></property>
 </bean>

 <!-- DataSource -->
 <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
  <property name="driverClassName"><value>oracle.jdbc.driver.OracleDriver</value></property>
  <property name="url"><value>jdbc:oracle:thin:@nerv-team.co.kr:1521:XE</value></property>
  <property name="username"><value>아이디</value></property>
  <property name="password"><value>패스워드</value></property>
 </bean>

 <!-- ItemCatalog -->
 <bean id="itemCatalog" class="service.impl.ItemCatalogImpl">
  <property name="itemDao"><ref bean="itemDao" /></property>
 </bean>
 
 <!-- ItemDao -->
 <bean id="itemDao" class="dao.impl.ItemDaoImpl">
  <property name="dataSource"> <ref bean="dataSource" /></property>
 </bean>
</beans>

3. Item Class 생성
public class Item {
 private Integer itemId;
 private String itemName;
 private Integer price;
 private String description;
 private String pictureUrl;
.............
getter() / setter()
}

4.IndexController  생성
기본적인 Controller 인터페이스를 구현하여 작성해 보겠습니다.
public class IndexController implements Controller {
private ItemCatalog itemCatalog; 
 
 public void setItemCatalog(ItemCatalog itemCatalog) {
  this.itemCatalog = itemCatalog;
 }

public ModelAndView handleRequest(HttpServletRequest request,
   HttpServletResponse response) throws Exception {
  //상품리스트 정보 취득
  List itemList = this.itemCatalog.getItemList();
  //모델작성
  Map model = new HashMap();
  model.put("itemList", itemList);
  //반환값이 되는 ModelAndView 인스턴스작성
  ModelAndView mav = new ModelAndView();
  mav.setViewName("/jsp/index.jsp");
  mav.addAllObjects(model);
  return mav;
 }
}

5. ItemCatalogImpl
public class ItemCatalogImpl implements ItemCatalog {
private ItemDao itemDao;
 
 public void setItemDao(ItemDao itemDao) {
  this.itemDao = itemDao;
 }

 public List getItemList() {
  return this.itemDao.findAll(); // 쿼리 날리러 갑시다~ 이야이야오~
 }
}

6.ItemDaoImpl
RowMapper 인터페이스에는 추상 메소드인 mapRow() 를 멤버로 가지고 있기 때문에,
RowMappert 의 구현클래스에서는 mapRow() 메소드를 오버라이딩 해야 합니다.

*mapRow()
: 쿼리의 실행결과를 스프링으로 부터  ResultSet 인터페이스형 인수를 전달 받습니다.
아래의 예제에선 Item 인스턴스를 생성하여 ResultSet 클래스로부터 꺼낸 값을 item 객체에 저장하고 있습니다.
(Item item = new Item();) <-요기 부분

public class ItemDaoImpl extends JdbcDaoSupport implements ItemDao {
private static final String SELECT_ALL =" SELECT ITEM_ID, ITEM_NAME, PRICE , DESCRIPTION, PICTUREURL  FROM ITEM" ;
 
 private class ItemRowMapper implements RowMapper {
  public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
   Item item = new Item();
   item.setItemId(new Integer(rs.getInt(1)));
   item.setItemName(rs.getString(2));
   item.setPrice(new Integer(rs.getInt(3)));
   item.setDescription(rs.getString(4));
   item.setPictureUrl(rs.getString(5));
   return item;
  }
 }

 public List findAll() {
  return getJdbcTemplate().query(ItemDaoImpl.SELECT_ALL, new ItemRowMapper());
  }
}

스프링에서 제공하는 jdbcDaoSupport 를 상속받으므로써 db Access 를 간단하게 처리하고 있습니다.
그럼 jdbcDaoSupport 와 RowMapper , 콜백함수의 의미에 대해 알아보도록 하겠습니다.
(우후~ 아직도 갈 길이 멀군아~ -0-)

JdbcDaoSupport 
*JdbcDaoSupport  : DataSource 를 관리할 뿐만 아니라 jdbcTemplate 를 지원하는 DaoSupport 클래스 입니다.
                            getJdbcTemplate() 메소드는 JdbcTemplate 클래스를 구현할 수 있는 메소드 입니다.
*JdbcTemplate : 데이터 베이스를 간단하게 처리 할 수 있도록 qurey() 메소드가 오버로딩 되어 있다. 


콜백 (RowMapper)
  사용자가 메소드를 정의해 두면 스프링 프레임워크 내부에서 자동으로 호출하는 것 을 말합니다.
(이전에 우리가 자바에서 . (점) 연산자로 호출 했다고 하면 이건 그 반대라고 생각하면 되겠습니다)

 개발자가 정의해 놓은 메소드를 프레임워크가 호출하는 것을 "콜백처리" 라고 하며
 프레임워크가 콜백을 위해 제공하는 인터페이스를 "콜백 인터페이스" 라고 합니다.

자, 다음과 같은 흐름 수행이 되겠죠?~ (아마도? -_-;;;) ItemDaoImpl 파일 의 흐름을 읽어봅시다.

mapRow() 를 스프링 프레임웍이 호출한답니다. 이것이 콜! 백!!!
자, 뭔가 의문드는 점이 없나요? while () 문이 없죠? while(rs.next()) 가 있어야 할 것 같은데...
위의 mapRow 처럼 정의해두면 쿼리의 결과가 10개의 행이라면 mapRow() 메소드를 10번 호출 하게 된답니다.

이밖에도 RowMapper 뿐만아니라 여러 콜백 인터페이스를 통시에 JdbcTemplate  로 전달할 수도 있다고 합니다.
뭐 책보며 나중에 나오는 대로 summery  해 두도록 합시다.

**** 그리고 개발자들이 항상 깜빡하는것 하나중에 rs.close() 나 conn.close() 를 빼먹곤 하죠..
이거 큰일 납니다. 하지만 spring 프레임웍의 jdbcTemplate 를 쓰게 되면 spring 이 다 알아서 해주니 close() 에 신경 안써도 됩니다. 어떻게 보면 좋은것 같으면서도.. 왠지 내가 안닫으니 불안한 마음이 드는건 뭐., 어쩔수 없죠?! ^^
히히히

자, 실행 이제 소스코드도 다 썻으니, 실행도 해 봐야겠죵?~!




JDK : 1.6
TOMCAT : 6.0
DB : Oracle 10g
OS : windows XP

다음과 같은 사양에서 작성 되었으니 알아서 build Path 라던지 , library 못 찾는거 잡아주세욤~ ^^

실행 주소 (tomcat)  : http://localhost:8080/Shop/index.do