Spring - Spring의 Controller들. 1.AbastractCommandController

Published on: 2009. 9. 13. 16:31 by louis.dev
소개
AbstractCommandController는 페이지의 넘어오는 파라미터들을 bean 객체에 자동맵핑이 되어 Controller 에서 사용 할 수 있게 만드는 역할을 한다.

jsp 페이지의 회원가입페이지 에서 파라미터로 name,age... 등등이 넘어오면 선언한 bean의 property인 String name, String age에 대응되어 자동 저장이 된다.

사용방법
DI를 선언한 xml 파일에서 직접 bean의 클래스경로인 "commandClass" 와 commandClass의 이름인 "commandName" 을 파라미터로 넘겨주어야 한다.

예)
<bean id="listAbstractCommandController"
       class="kr.co.springboard.controllers.ListAbstractCommandController">
     <property name="commandClass" value="kr.co.springboard.beans.BoardBean"/>
     <property name="commandName" value="boardBean"/>

     <property name="boardService" ref="boardService"/>
     <property name="viewName" value="boardList"/>
</bean>

이렇게 property 로 설정하는 방법이 있는가 하면 직접 AbstractCommandController를 확장한 클래스에서 다음과 같이 Contructor를 구현해도 된다.
public ListAbstractCommandController(){
  setCommandClass(BoardBean.class);
  setCommandName("boardBean");
 }


위의 2가지 방법으로 선언하면 AbstractCommandController의 handle() method를 통해서 전달 인자인 command를 통해 전송된 데이터를 받을 수 있다.

protected ModelAndView handle(HttpServletRequest request,
                         HttpServletResponse response,
                         Object command,
                         BindException errors) throws Exception {
  ModelAndView mnv = new ModelAndView();
  BoardBean boardBean = (BoardBean)command;
  BoardDTO dto = new BoardDTO();
  dto.setNowPage(boardBean.getNowPage());
  
  if(dto.getNowPage() == 0){
   dto.setNowPage(1);
  }
  dto.setTotalCount(boardService.boardTotalCount(dto));
  dto = (BoardDTO)PagingUtil.setPagingInfo(dto);
  List<BoardDTO> boardList = this.boardService.boardList(dto);
  
  mnv.setViewName(viewName);
  mnv.addObject("boardList", boardList);
  mnv.addObject("dto",dto);
  
  return mnv;
 }

위와 같이 생성자,혹은 xml문서의 property 로 세팅해준 commandClass와 commandName 은 handle() 메소드의 command object를 통해 데이터를 전달 받기 때문에 command instance를 생성해 주는 역할을 한다.
이렇게 전달된 command 객체를 원하는 형으로 형변환을 해서 사용하면 된다.






Spring - SpringMVC + iBatis 사용하기(스프링에서 지원하는 template 사용하기)

Published on: 2009. 9. 13. 16:13 by louis.dev

전체적으로 iBatis의 기본설정은 크게 바뀌지 않는다. 다만 SpringFramework는 DI를 지원하기 때문에 이 설정만 들어가게 되면 다른게 없다.

1.web.xml 의 context-param 부분에 ibatis의 설정이 들어가 있는 xml 파일의 위치를 정해준다.
<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
   /WEB-INF/config/applicationContext.xml,
   /WEB-INF/config/applicationContext-iBatis.xml
  </param-value>
 </context-param>

2. applicationContext-iBatis.xml 파일에 DataSource를 설정하고 DataSource를 사용하는 sqlMapClient,sqlMapClient를 사용하는 template를 만든다.
template를 사용하기 위해서는 spring-orm.jar 파일을 라이브러리에 추가해야 한다.

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
  <property name="url" value="jdbc:oracle:thin:@localhost:1521:XE"/>
  <property name="username" value="user01"/>
  <property name="password" value="user01"/>
  <property name="initialSize" value="10"/>
  <property name="maxActive" value="100"/>
  <property name="maxIdle" value="16"/>
  <property name="maxWait" value="2000"/>
 </bean>
 
 <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
  <property name="configLocation" value="WEB-INF/config/sqlMapConfig.xml" />
  <property name="dataSource" ref="dataSource" />
 </bean>
 
 <bean id="template" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
     <property name="sqlMapClient" ref="sqlMapClient"/>
 </bean>

위의 Datasource를 구현방법은 DBCP를 사용하는 방법이기 때문에 www.apache.org 에 들어가서 commonms --> dbcp 에서 다운 받은 라이브러리를 추가하여야 사용할 수 있다.


3. sqlMapClient를 사용하기 위해서 로딩한 configLocation인 sqlMapConfig.xml 파일을 설정한다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0 //EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
    <settings
  cacheModelsEnabled="true"
  enhancementEnabled="true"
  lazyLoadingEnabled="true"
  maxRequests="32"
  maxSessions="10"
  maxTransactions="5"
  useStatementNamespaces="true"
 />
 
  <sqlMap resource="kr/co/springboard/dao/sqlmap/sqlMapBoard.xml"/>
</sqlMapConfig>

4. 위의 빨간색의 sqlMapBoard.xml 파일을 생성한다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
      "http://ibatis.apache.org/dtd/sql-map-2.dtd">
      
<sqlMap>
 <typeAlias alias="Board" type="kr.co.springboard.dto.BoardDTO"/>
 <resultMap class="Board" id="boardResult">
  <result property="seq" column="SEQ"/>
  <result property="category" column="CATEGORY"/>
  <result property="title" column="TITLE"/>
  <result property="readCount" column="READ_COUNT"/>
  <result property="writer" column="WRITER"/>
  <result property="regDate" column="REG_DATE"/>
 </resultMap>
 
 <resultMap class="Board" id="boardFullResult">
  <result property="seq" column="SEQ"/>
  <result property="category" column="CATEGORY"/>
  <result property="title" column="TITLE"/>
  <result property="readCount" column="READ_COUNT"/>
  <result property="writer" column="WRITER"/>
  <result property="regDate" column="REG_DATE"/>
  <result property="contents" column="CONTENTS"/>
 </resultMap>
 
 <select id="selectBoardTotalCount" resultClass="int">
  SELECT COUNT(0)
  FROM MY_BOARD
 </select>
 
 <select id="selectBoardList" parameterClass="Board" resultMap="boardResult">
  <![CDATA[
  select
   *
  from
   (
   select *
   from
    ( select * from MY_BOARD order by SEQ ASC )
   where rownum <= #startNum#
   order by SEQ desc
   )
  where rownum <= #countPerPage#
  ]]>
 </select>
 
 <insert id="insertBoard" parameterClass="Board">
  INSERT INTO
   MY_BOARD
   (SEQ,CATEGORY,TITLE,WRITER,REG_DATE,READ_COUNT,CONTENTS)
  VALUES
   (MY_BOARD_SEQ.NEXTVAL,#category#,#title#,#writer#,sysdate,0,#contents#)
 </insert>
 
 <select id="selectBoardItem" parameterClass="int" resultMap="boardFullResult">
  SELECT
   *
  FROM MY_BOARD
  WHERE SEQ=#seq#
 </select>
 
 <update id="updateBoardReadCount" parameterClass="int">
  UPDATE
   MY_BOARD
  SET
   READ_COUNT = READ_COUNT + 1
  WHERE SEQ = #seq#
 </update>
 
 <update id="updateBoardItem" parameterClass="Board">
  UPDATE
   MY_BOARD
  SET
   CATEGORY = #category#,
   WRITER = #writer#,
   TITLE = #title#,
   CONTENTS = #contents#
  WHERE SEQ = #seq#
 </update>
 
 <delete id="deleteBoardItem" parameterClass="int">
  DELETE
  FROM MY_BOARD
  WHERE SEQ = #seq#
 </delete>
</sqlMap>

Spring - Spring FrameWork 과 Log4J 사용해서 Log출력하기

Published on: 2009. 9. 13. 14:29 by louis.dev


위 그림과 같이 Log4J를 사용하면 무슨 Sql문을 사용하는지 무슨 데이터가 parameter로 넘어오는지 DB를 갔다 왔을때 어떤 데이터를 불러오는지를 이클립스의 Consol창을 통해 한번에 알 수 있다.
스프링에서는 Log4J를 설정하는 방법이 있어서 소개해 본다.

1. http://logging.apache.org/log4j/1.2/download.html 
다음 사이트에서 apache-log4j-1.2.15.zip를 다운 받고 압축을 푼다.
그 안에 있는 log4j-1.2.14.jar 파일을 압축 풀고 이클립스의 lib폴더에 넣는다.

2. log4j.properties 파일을 생성한다.
log4j.properties 파일은 콘솔에 로그가 어떻게 형태로 찍힐 것인지를 세팅하는 레이아웃을 잡아준다. 이런 설정은 구글 검색을 통해서 쉽게 얻을 수 있다. 물론 아래의 내용처럼 해도 된다.
properties파일은 #으로 시작하면 주석으로 처리한다.

# For JBoss: Avoid to setup Log4J outside $JBOSS_HOME/server/default/deploy/log4j.xml!
# For all other servers: Comment out the Log4J listener in web.xml to activate Log4J.
log4j.rootCategory=DEBUG, stdout

log4j.debug=false

#Console log
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.ImmediateFlush=true
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout.ConversionPattern=[%p] (%F) - %m%n


3. web.xml 파일에 log4j를 로딩할 Listener와 log4j.perperties 파일위치를 정해주는 설정을 해준다.

<listener> 
   <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<context-param>
  <param-name>log4jConfigLocation</param-name>
  <param-value>/WEB-INF/config/log4j.properties</param-value>
</context-param>

Spring - Spring 초기 설정

Published on: 2009. 9. 13. 14:08 by louis.dev
                                                                   <그림출처 : 웹개발자를 위한 Spring 2.5 프로그래밍: 저자 최범균>

SpringFrameWork는 웹을 개발하는데 있어 Full Spec을 지원하는 프레임 웍이다.
SpringMVC로 웹개발을 할때 작동 순서는 위의 그림과 같다.

1. 클라이언트로 부터 URL이 요청되어 들어오면 제일먼저 web.xml 파일을 로딩하여 스프링에서 지원하는 DispatcherServlet이 실행된다.
(이름에서 알수 있듯이 SpringFramework는 Servlet 기반임으로 스프링에서 지원해주는 Controller에서는 HttpServletRequest,HttpServletResponse 인터페이스를 이용해서 request, response 인스턴스를 사용 할 수가 있다.)

2. DispatcherServlet은 클라이언트로부터 들어온 URL을 HandlerMapping 이라는 곳으로 전송후에 URL을 분석해서 알맞은 컨트롤러 이름을 DispatcherServlet 으로 보낸다.

3. HandlerMapping이라는 것을 통해서 실행될 Controller의 이름을 입력받은 DispatcherServlet은 전달받은 Controller를 실행 시킨다. 이렇게 실행된 Controller는 스프링에서 제공하는 ModelAndView 객체에 뷰페이지에 전달할 객체와 뷰페이지 이름 정보를 담고 DispatcherServlet으로 보낸다.

4. ViewResolver를 통해 보여질 View페이지를 탐색한후 View페이지를 보여준다.

SpringMVC 의 웹개발은 위와같은 루틴으로 움직이기 때문에 스프링 초기 설정을 할때는 다음과 같이 순서를 생각하면서 셋팅을 하면 잊어 버리지 않는다.

<스프링 설정>
1. web.xml 세팅
① DispatcherServlet을 세팅해 준다.
<servlet>
   <servlet-name>dispatcher</servlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
   <!-- 기본 위치는 [servlet name]-servlet.xml 은 WEB-INF에서 불러 오지만 기타 다른위치에 있을때는 위치를 지정한다 -->
   <init-param>
    <param-name>contextConfigLocation</param-name>
     <!-- 클래스 패스에 위치한 파일로부터 설정정보를 읽으려면 "classpath:" 를 붙이고 경로를 써준다 -->
     <!-- ex) classpath:kr/co/springboard/config.xml -->

    <param-value>/WEB-INF/config/dispatcher-servlet.xml</param-value>
   </init-param>
  </servlet>


<servlet-mapping>
   <servlet-name>dispatcher</servlet-name>
   <url-pattern>*.do</url-pattern>
</servlet-mapping>

Url pattern이 ~~.do 로 들어오게 되면 위에 설정에 servlet name이 dispatcher인 servlet을 실행해서 Spring의 핵심인 DispatcherServlet을 실행한다.

② DI 를 선언할 applicationContext 파일을 로딩하기 위해서 알맞은 리스너와 Context Param을 설정해 준다.

<listener>
   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
   /WEB-INF/config/applicationContext.xml
  </param-value>
 </context-param>

ContextLoaderListner는 기본적으로 /WEB-INF/applicationContext.xml 을 설정 파일로 로딩한다.
다른위치에 있을때 위와같이 context-param설정을 통해 위치를 정해 준다. 그리고 context파일이 많을때는 ,(콤마)를 찍고 다른 경로를 또 입력하면 된다.
context파일 이름이 applicationContext.xml 과 applicationContext-ibatis.xml 이라면 applicationContext*.xml 이라고 설정하면 한번에 두가지 파일을 불러 들인다.

③ encoding 설정을 해준다.
jsp에서 response.setCharactorEncoding() 메소드를 사용해서 페이지에 맞는 케릭터셋을 지정할 수 있으나 스프링에서는 위와 같은 설정 없이 케릭터 셋을 지정해 줄 수 있다.

<filter>
   <filter-name>encodingFilter</filter-name>
   <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
   <init-param>
    <param-name>encoding</param-name>
    <param-value>EUC-KR</param-value>
   </init-param>
  </filter>
 
  <filter-mapping>
   <filter-name>encodingFilter</filter-name>
   <url-pattern>/*</url-pattern>
  </filter-mapping>

2. 위에서 선언한 dispatcher-servlet.xml 파일을 생성한다.
① urlHandlerMapping을 설정한다.
<bean id="springBoardUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
     <property name="mappings">  <!-- mappings는 바뀌면 안된다. -->
      <props>
       <prop key="/boardList.do">listAbstractCommandController</prop>
       <prop key="/boardWrite.do">writeSimpleFormController</prop>
       <prop key="/boardReadDelete.do">readDeleteMultiActionController</prop>
      </props>
     </property>
    </bean>

boardList.do 라는 url로 들어오면 listAbstractCommandController 클래스를 실행 시킨다. 물론 이 이름은 나중에 설정할 applicationContext.xml 에 선언되어있는 bean의 id와 같아야 한다.

② ModelAndView객체를 받아 View페이지로 이동시켜줄 View Resolver를 구현한다.

<bean id="viewResolver"
       class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <property name="prefix" value="/WEB-INF/view/"/>
       <property name="suffix" value=".jsp"/>
</bean>

위와 같은 설정으로 만약에 ModelAndView 에 ViewName 이 boardList 라는 String 값이 들어 있으면 /WEB-INF/view/boardList.jsp 라는 파일을 부르게 된다. prefix는 경로의 앞에 붙는 것, 즉 viewName의 앞쪽에 붙는 것, subffix는 viewName뒤에 붙는것, 즉 확장자라고 생각하면 되겠다.


3.스프링에서 사용할 DI를 applicationContext.xml에 설정한다.

4. 기능에 맞게 각종 Controller를 사용해서 구현한다.

게시판 Paging Source Code

Published on: 2009. 9. 6. 19:19 by louis.dev

적용 방법
paging을 하고 싶은 페이지에 업로드 된 paging.jsp를 include 한다.

작업 순서
1. Paging 정보를 가지고 있을 Bean 객체를 만든다. 이 Paging Class는 다음과 같은 property를 가진다. 이와 같은 Paging class는 다른 Bean class에서 상속 받아 사용할 수도 있다


[[ PagingBean.java ]]

① private int nowPage;                // 현재 페이지가 몇페이지 인가를 적용
② private int startNum;                // 게시판이 시작되는 ROW의 Number
③ private int totalCount;               // 게시판 총 페이지 수
④ private int countPerPage;         // 페이지당 보여줄 게시판 리스트 갯수
⑤ private int blockCount;             // paging 갯수를 표현함 예를 들어 blockCount = 5 라면 
                        << [1][2][3][4][5] 다음 >>  -> 다음을 클릭하면
                        << [6][7][8][9][10] 다음 >> -> 이런 식으로 페이징 수가 5개가 된다.
⑥ private String searchColumn;     // 검색할 때 사용, 카테고리 선택
⑦ private String searchWord;         // 검색어


2. 기본적으로 늘 초기화 세팅이 되어 있어야할 countPerPage 라든가 blockCount, startNum을 초기화 세팅해줄 PaingUtil Class를 생성한다.
초기화 세팅하지 않을 util 클래스를 작성하지 않으면 페이징 시에 항상 세팅을 해주어야 한다.
만약 페이징 할 모듈이 많고 각각 다른 세팅값을 가져야 한다면 사용자의 요구에 맞게 static method를 정의해 주고 그 안에 있는 값을 세팅을 각각 맞춰서 해주면 된다.


3. Paging을 할 페이지에 paging.jsp 파일을 다음과 같이 include 시킨다.


<jsp:include page="paging.jsp">
     <jsp:param name="actionPath" value="boardList.jsp"/>
     <jsp:param name="totalCount" value="<%=String.valueOf(paging.getTotalCount()) %>"/>
     <jsp:param name="countPerPage" value="<%=String.valueOf(paging.getCountPerPage()) %>"/>
     <jsp:param name="blockCount" value="<%=String.valueOf(paging.getBlockCount()) %>"/>
     <jsp:param name="nowPage" value="<%=String.valueOf(paging.getNowPage()) %>"/>
 </jsp:include>

물론 이 페이지를 인클루드 시키기 전에 위에 파라미터로 넘겨주는 모든 값은 세팅이 되어 있어야 한다.

페이지의 맨상단에서 다음과 같은 코드로 파라미터로 넘어오는 nowPage를 받아야 한다.
if(request.getParameter("nowPage") == null){
  paging.setNowPage(1);
 }else{
  paging.setNowPage(Integer.valueOf(request.getParameter("nowPage")));
 }

totalCount는
   SELECT COUNT(0) FROM 테이블 명
이런 Query문을 날려서 값을 받아 오는 값을 저장하면 된다.