본문 바로가기
Lecture/Spring

[본격 게시판짜기 Part3.4 Spring MVC] Spring MVC 개요 및 설정하기2

by cusmaker 2012. 9. 22.
반응형

- html 기초부터 spring까지! 게시판? 나도 만들수있다! 

(좋아요, View on, 댓글 환영합니다!!!)

2012/06/13 - [Lecture/HTML] - [본격 게시판짜기 Part1.1 - 게시판도 HTML부터] 게시글 리스트

2012/06/13 - [Lecture/HTML] - [본격 게시판짜기 Part1.2 - 게시판도 HTML부터] 글입력폼

2012/06/13 - [Lecture/Javascript-기초] - [본격 게시판짜기 Part1.3 - Dom 맛보기 ] 글입력폼 검사

2012/06/13 - [Lecture/Jsp] - [본격 게시판짜기 Part1.4 - HTML-> JSP] form 파라미터 받기

2012/06/26 - [Lecture/SQL / Oracle] - [본격 게시판짜기 Part1.5 JSP > Oracle] 게시판 DB 테이블 생성

2012/06/26 - [Lecture/Jsp] - [본격 게시판짜기 Part1.6 Oracle > JSP] Database 접속 및 Select

2012/07/05 - [Lecture/Jsp] - [본격 게시판짜기 Part1.7 JSP, SQLDeveloper] 게시글 입력 및 리스트조회기능

2012/07/08 - [Lecture/Jsp] - [본격 게시판짜기 Part1.8 JSP 게시글 조회] 게시글 조회기능 및 게시글 삭제

2012/07/10 - [Lecture/Jsp] - [본격 게시판짜기 Part2.1 Model2 MVC패턴] 뷰(View) 코드 분리

2012/07/10 - [Lecture/Jsp] - [본격 게시판짜기 Part2.2 Model2 MVC패턴] Entity Beans의 사용

2012/07/12 - [Lecture/Jsp] - [본격 게시판짜기 Part2.3 Model2 MVC패턴] Controller구성

2012/07/13 - [Lecture/Jsp] - [본격 게시판짜기 Part2.4 Model2 MVC패턴] Model 구성

2012/07/16 - [Lecture/Mybatis] - [본격 게시판짜기 Part2.5 Model2 MVC패턴] Model 구성2 - i-batis의 사용

2012/07/17 - [Lecture/Mybatis] - [본격 게시판짜기 Part2.6 Model2 MVC패턴] Model 구성2 - i-batis의 사용2

2012/07/21 - [Lecture/Mybatis] - [본격 게시판짜기 Part2.7 Model2 MVC패턴] i-batis의 queryForList 활용 Paging기능구현

2012/07/22 - [Lecture/Jsp] - [본격 게시판짜기 Part2.8 Model2 MVC패턴] count기능추가

2012/07/28 - [Lecture/Jsp] - [본격 게시판짜기 Part2.9 Model2 MVC패턴] 파일업로드 기능추가

2012/07/28 - [Lecture/Jsp] - [본격 게시판짜기 Part2.10 Model2 MVC패턴] 파일다운로드/삭제 기능추가

2012/07/31 - [Lecture/Jsp] - [본격 게시판짜기 Part3.1 Spring MVC] Ajax란?

2012/08/28 - [Lecture/Jsp] - [본격 게시판짜기 Part3.2 Spring MVC] lightbox 적용하기

2012/09/22 - [Lecture/Spring] - [본격 게시판짜기 Part3.3 Spring MVC] Spring MVC 개요 및 설정하기


안녕하세요 cocy입니다.

이번 포스팅에서는 지난시간에 이어 못다한 설정과 

컨트롤러 셋팅을 진행하도록 하겠습니다.


먼저 보실부분은 index.jsp 페이지를 제외한 모든 페이지들입니다.

WebContent > WEB-INF 밑에 board 폴더를 생성하고, 이사갑시다!


그럼 그다음은 스프링에서 사용할 뷰들을 구성해 주어야겟죠?

좌표는 여기!

spring.board.view > template-board.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN" "http://tiles.apache.org/dtds/tiles-config_2_1.dtd">


<tiles-definitions>


<definition name="ajaxList" template="/WEB-INF/board/ajaxList.jsp" />

<definition name="content" template="/WEB-INF/board/content.jsp" />

<definition name="delete" template="/WEB-INF/board/delete.jsp" />

<definition name="insert" template="/WEB-INF/board/insert.jsp" />

<definition name="list" template="/WEB-INF/board/list.jsp" />

<definition name="redirect" template="/WEB-INF/board/redirect.jsp" />

<definition name="redirect2" template="/WEB-INF/board/redirect2.jsp" />

<definition name="write" template="/WEB-INF/board/write.jsp" />

</tiles-definitions>




name은 나중에 컨트롤러에서 뷰를 찾을때 식별자로 사용됩니다. 오타에 주의하세요!


다음으로는 컨트롤러 구성입니다.

스프링에서는 따로 컨트롤러를 구성할 필요가 없습니다.

@controller 이라는 요상한 구문을 넣어주면

해당클래스가 자동으로 컨트롤러로 인식되며

@RequestMapping("/list") 와 같이 쓰이게되면

자동으로 list요청에 사용되는 해당액션을 맵핑해줍니다.


그래서 컨트롤러의 소스는 더욱 간결해지고,

액션하나당 하나의 클래스를 구성하는 것 보다는 하나의 컨트롤러에서 처리하는것이 효율적입니다.

다만 그 규모를 잘 판단하고 나누어 사용해야겟죠?


게다가 url 요청을 따로 모아둘 필요가 없어집니다.

이것이 장점만 가지고 있진 않은데요, 바로 url을 한눈에 보기가 힘들다는 것입니다.

그래서 저는 Abstract 클래스를 활용하여 url과 해당 액션의 정형을 선언하여,

컨트롤러를 구성할 것입니다.


자 코드로 설명하겠습니다.

우선 기존의 소스는 그대로 놔두고 새로운 패키지를 작성하겠습니다.


spring.board.controller 패키지를 생성해주시고 그안에 추상클래스인 BoardController.java를 생성합니다.

소스는 다음과 같습니다.

package spring.board.controller;


import javax.servlet.http.HttpServletRequest;


import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.ModelAttribute;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.servlet.ModelAndView;

import com.board.beans.Board;


@Controller // 컨트롤러 등록

public abstract class BoardController {

@RequestMapping("/list/{page}") // url 맵핑

public abstract ModelAndView listAction(@PathVariable Integer page) throws Exception;

                                                               // Restful : url에서 파라미터 가져오기

@RequestMapping("/insert")

public abstract ModelAndView insertAction( HttpServletRequest request, @ModelAttribute Board article) throws Exception;                                          // 파일 업로드를 위한 request객체 // 폼에서 넘어온 값 자동으로 빈에 셋팅

}

일단 기본적으로 두개의 액션의 정형을 선언하였습니다.

listAction과 insertAction입니다.


@Controller : 컨트롤러 어노테이션은 위에서 설명드린대로 해당 클래스를 컨트롤러로 등록하는 역할을 합니다.

그렇기때문에 항상 위치는 클래스 위에 위치해야합니다.


@RequestMapping("url") : 요청 맵핑 어노테이션은 해당 요청에 대한 메서드를 맵핑해줍니다.

그렇기때문에 항상 위치는 메소드 위에 위치해야합니다.

listAction에 맵핑된 어노테이션을 보시면 /list/{page} 와 같이 요상하게 적힌 내용이 나옵니다.

여기서  RESTful  서비스에대해 이해를 하셔야하는데요,


RESTful 웹서비스란 리로스 중심의 표현, 전달, 접근 방식의 특성으로 인해 

리소스 기반아키텍쳐(ROA)라고 합니다.

리소스의 URI를 알면 웹서버와 웹클라이언트의 종류에 상관없이 HTTP 프로토콜만으로 접근 가능한 서비스로,

단순 명료한 접근방식을 사용하며 구글, 야후, 트위터 등 대부분의 웹 2.0 PAI가 RESTful웹서비스로

제공되고있으며, 위젯을 이용한 서비스 매시업(mashup)을 활성화시킨 원동력입니다.....

- 네이버 어딘가에서 발췌-


뭔가 설명이 어려운데요, 쉽게 말하자면 get방식의 요청이 단순하게 표현되는 형태입니다.

기존의 get방식의 경우 

request.do?name=value&name2=value2

이런식이었다면 RESTful 웹서비스형식의 요청은

request/value/value2

이런 형태가 됩니다.

그래서 컨트롤러에서는 이 URL로부터 값을 가져올 필요가있는데,

중괄호 '{}'로 감싼 부분은 파라미터로 인식이 되어,

메소드의 @PathVariable 어노테이션을 달아 해당 값을 사용 할 수 있게 되는 것입니다.


이해가 덜 되셨더라도 사용하다보면 익숙해지실 겁니다.


다음은 마찬가지로 @ModelAttribute 어노테이션에대한 설명인데요

@PathVariable 의 경우 URL에서 가져온 값을 변수에 대입해주는 반면

@ModelAttribute는 폼에서 넘어온 값 또는 get방식으로 넘어온값들을 

자동으로 entity bean에 name을 기준으로 맵핑해줍니다.

쉽게말해서 기존에 사용하시던 board.setName(request.getParameter("name")); 

이 구문을 대신해 준다는 것입니다. 편리하죠?


그럼 설명은 이정도 까지하고, 지금부터는 해당 Action들을 구현하기위한 클래스를 작성합시다.

마찬가지로 spring.board.service 패키지를 생성해주시고 그안에 추상클래스인 BoardService.java를 생성합니다.

package spring.board.service;

import java.util.ArrayList;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Service;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.servlet.ModelAndView;

import com.board.beans.Board;

import com.board.dao.BoardDao;

import com.oreilly.servlet.MultipartRequest;

import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;


import spring.board.controller.*;

@Service

public class BoardService extends BoardController {


@Override

public ModelAndView listAction(@PathVariable Integer page) throws Exception {

if(page == null){ // 넘어온 파라미터가 있다면

page =0;

}  // 해당 파라미터를 int형으로 캐스팅후 변수에 대입합니다.

ArrayList<Board> articleList = BoardDao.getInstance().getArticleList(page);

// 그리고 변경된 dao 메서드에 넣어줍니다.

ModelAndView mav = new ModelAndView("list");

mav.addObject("articleList", articleList); // 셋팅된 리스트를 뷰에 포워드합니다.

mav.addObject("page", page);// 페이지번호를 뷰에서 보기위해 표시합니다.

return mav;

}


@Override

public ModelAndView insertAction(HttpServletRequest request, Board article)

throws Exception {

request.setCharacterEncoding("euc-kr");

MultipartRequest multi = null;

int sizeLimit = 10 * 1024 * 1024 ; 

String savePath = request.getRealPath("/upload");    

try{

multi=new MultipartRequest(request, savePath, sizeLimit, "euc-kr", new DefaultFileRenamePolicy());

}catch (Exception e) {

e.printStackTrace();

}

 

int count = 0;

article.setRegip(request.getRemoteAddr());

article.setCount(count);

BoardDao.getInstance().insertArticle(article);

return new ModelAndView("insert");

}

}

기존의 ListAction.java의 소스와

InsertAction.java의 소스를 조금 수정하여

BoardService에 반영하였습니다.


차이점이 보이시나요?

여기서 주목하실 부분은 바로 ModelAndView 객체입니다.

Model에 해당하는 부분은 addObjcet("name",value);의 형태로

request.setAttribute("name", value); 구문을 대체 한다고 이해하시면 되겠습니다.

객체를 생성할때 주는 list나 insert가 바로 

template-board.xml 에서 지정했던 name과 일치되는 부분으로

mav.setViewName("viewname"); 의 형태로 대체될 수 있습니다.


여기까지 수정하셨다면 이제 페이지를 실행 시켜 볼 차례입니다.

허나 에러때문에 작동하지 않을텐데요,

스프링 프레임워크는 해당 사이트에서 제공하는 모듈만으로는 모든 기능을 활용 할 수 없습니다.

이는 오픈소스 라이센스 정책 때문인지 모든 모듈을 제공하지 않는데요... 해서

RESTful 웹서비스라던가, json 뷰라던가, tiles의 라이브러리들이 각기 추가되어야합니다.


정말 죄송하게도 하나하나의 모듈과 사용법을 알려드리고 싶지만,

제가 미숙한 탓에 하나하나의 쓰임새를 정확히 알려드릴수가 없어서,

jar파일을 한대 묶어 압축하여 파일로 첨부합니다. (10mb제한으로 두개의 파일을 각각압축하였습니다)



모두 압축을 풀어 lib폴더로 직행해주시면 되겠습니다.




작업을 마치셨다면

다음과같은 결과화면을 보실 수 있습니다.




한꺼번에 많은 내용을 다루다보니 설명이 무척 부족합니다.

시간을 들여 차츰차츰 포스팅한내용을 수정하며 설명을 추가하도록 하겠습니다.

현재 BoardService의 소스상으로는 기존의 ibatis 설정을 가지고 DAO도 기존의 DAO를 활용하여 작성하였는데요,

다음 포스팅에서는 이를 스프링에서 지원하는 기능을 가지고 

@Repository 어노테이션을 적용하여 DAO를 구현해 보도록 하겠습니다.


수고하셨습니다.


다음장 (spring 모델 구성) >> http://cusmaker.tistory.com/134