른록노트
[NetBeans로 Spring MVC 게시판 만들기] 3. 프로젝트 진행(#1) 본문
안녕하세요 른록입니다.
드디어 이제 본격적인 게시판 만들기에 돌입하네요
지금까지 내용이 어려우셨으면.. 제 설명 때문 일 겁니다. (차차 나아질거예요!)
[계획]
1. 소개(개념)
-2. Web.xml과 ApplicationContext,dispatcher_servlet.xml
-. Mybatis(Mysql)
-. Log4j
3. 프로젝트 진행
-1. 게시판 리스트 보기
-2. 게시판 글 작성
-. HandlerMethodArgumentResolver
-3. 게시판 글 상세 조회
-4. 게시판 글 수정
-5. 게시판 글 삭제
[NetBeans로 Spring MVC 게시판 만들기] 3. 프로젝트 진행(#1) - 게시판리스트
-1. 프로젝트 구조
지금까지 잘 따라와 주셨으면 아래와 같은 구조가 됐을겁니다~
( 아직 실행해도 아무것도 되지 않습니다~ )
그럼이제 실행해봐야겠죠?? Controller를 만들어 봅시다~
MVC는 Model(DB), View(출력화면), Controller(로직처리)로써 지금 저희 프로젝트에는 jsp폴더가 View, Model은 저희가 설정한 Mybatis가 설정되 있습니다 하지만Controller가 없는데요 이제 만들어 주겠습니다
com.eunbok.springproject에 controller 패키지를 생성해주세요
그리고 controller 패키지 안에 HomeController.java 파일을 생성해주세요
아래 코드를 복붙해주세요
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package com.eunbok.springproject.controller; import java.util.Locale; import org.apache.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class HomeController { Logger log = Logger.getLogger(this.getClass()); //우리가 만들었던 log4j를 이용해서 //이 클래스가 실행될때 알려줍니다 @RequestMapping(value = "/index", method = RequestMethod.GET) // '/' url 요청이 들어오면 GET 정보를 받아와 처리합니다 public String home(Locale locale, Model model) { log.debug("인터셉터 테스트"); return "index"; //jsp 폴더에 있는 index 파일을 view로 출력해줍니다 } } | cs |
우선 클래스 위에 @Controller라고 어노테이션으로
이 클래스는 컨트롤러라고 명시를 해줍니다.
그리고 home 메서드 위에 @RequestMapping 을 해줍니다.
RequestMapping은 해당 url이 요청되면 이 메서드를 실행하라는 뜻입니다.
RequestMapping 방법은 여러가지가 있는데 지금 보여드리는
RequestMapping 방식은 반환값(return)을 String 값으로 받는데 이러한 경우 return되는 문자열의 jsp파일이 출력됩니다. Model은 매개변수로 들어가 있습니다.
Controller에선 ModelAndView를 알아야 합니다.
Model은 데이터라고 생각하면 되고, View는 출력 페이지입니다. 그래서 컨트롤러에서 Model을 View로 주입시켜주고 어떤 View에서 출력할지 정해주는 건데요. 지금 소스에서 ModelAndView 클래스가 보이지 않지만 Model과 View가 다 선언된걸 볼 수 있습니다.
이제 드디어 실행해 보겠습니다!!!
Build단축키는 F11입니다. (빌드 후 해당폴더 target에 보시면 빌드된 war파일을 찾을 수 있습니다.) 그리고 Run단축키는 F6입니다.
(리빌드 하고 싶으시면 넷빈즈를 재부팅 해주시고 해야 에러가 안뜨고 작동합니다.)
F11을 누른후 F6을 눌러주세요~ (에러가 나시면 댓글로 적어주세요)
(참고 : url을 잘못치시면 (RequestMapping 오류=404에러가 뜰 수 있어요!)
제대로 실행이 되면
이 화면이 실행 될겁니다
그리고 Log를 보시면
요청된 url과 실행된 Controller가 로그에 찍히고, Controller에 입력한 로그가 뜨는걸 볼 수 있습니다.
이제 BoardController를 만들어 보겠습니다.
같은 패키지에 BoardController 자바 파일을 만들어주세요
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.eunbok.springproject.controller; import java.util.List; import java.util.Map; import javax.annotation.Resource; import org.apache.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller public class BoardController { Logger log = Logger.getLogger(this.getClass()); @Resource(name = "boardService") private BoardService boardService; @RequestMapping(value = "/BoardList.do") public ModelAndView BoardList(Map<String, Object> commandMap) throws Exception { ModelAndView mv = new ModelAndView("/boardList"); List<Map<String, Object>> list = boardService.selectBoardList(commandMap); mv.addObject("list", list); return mv; } } | cs |
이렇게 작성하시면 BoardService에 밑줄이 뜰겁니다.
왜냐하면 아직 생성되지 않았기 때문이죠. Service는 로직을 처리하는 애들이라고 말할 수 있습니다. 만들어 주기에 앞서 다른 소스도 설명해 드리겠습니다.
RequestMapping이 HomeController와 조금 다릅니다.
(value = "/BoardList.do") // 이 url이 요청되면 이 메소드를 실행해주세요
public ModelAndView BoardList(Map<String, Object> commandMap)
// 아깐 String으로 반환했었는데 이번엔 ModelAndView로 반환합니다.
이제 Service를 만들겠습니다.
com.eunbok.springproject.service라는 패키지를 만들어 주세요
그 안에 BoardService.java파일을 생성하여 인터페이스로 사용할겁니다.
1 2 3 4 5 6 7 8 9 10 | package com.eunbok.springproject.service; import java.util.List; import java.util.Map; public interface BoardService { public List<Map<String, Object>> selectBoardList(Map<String, Object> map) throws Exception; } | cs |
그리고 BoardServiceImpl.java 파일을 만들어 주세요, 위에 인터페이스를 implement 받을겁니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.eunbok.springproject.service; import com.eunbok.springproject.dao.BoardDAO; import java.util.List; import java.util.Map; import javax.annotation.Resource; import org.apache.log4j.Logger; @Service("boardService") public class BoardServiceImpl implements BoardService { Logger log = Logger.getLogger(this.getClass()); @Resource(name = "boardDAO") private BoardDAO boardDAO; @Override public List<Map<String, Object>> selectBoardList(Map<String, Object> map) throws Exception { return boardDAO.selectList(map); } } | cs |
여기서 보시면 log를 찍어주고
@Resource(name = "boardDAO") boardDAO를 사용하겠다입니다.
BoardDAO에 가시면 @Repository 된걸 볼 수 있습니다.
그리고 interface에서 명시한 함수를 작성해줍니다.
return boardDAO.selectList(map); 이 부분이 에러가 뜰 것입니다.
boardDAO객체의 selectList(map) 함수를 실행하라는 말이여서 BoardDAO로 가서
코드를 추가해줍시다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | package com.eunbok.springproject.dao; import java.util.List; import java.util.Map; import org.springframework.stereotype.Repository; @Repository("boardDAO") public class BoardDAO extends AbstractDAO{ @SuppressWarnings("unchecked") public List<Map<String, Object>> selectList(Map<String, Object> map) { return (List<Map<String, Object>>)selectList("board.selectBoardList", map); } | cs |
selectList함수를 보시면
return (List<Map<STring,Object>>)selectList("board.selectBoardList",map);
"즉, AbstractDAO의 selectList를 상속받아서 board.selectBoardList <-- 이 말은 mapper 안에 BOARD_SQL.xml에서 네임스페이스 board를 선택해서
그 매퍼안에 id=selectBoardList를 실행시키고 map을 parameter로 넣어라" 는 말입니다.
그럼 이제 BOARD_SQL.xml로 가서 selectBoardList를 추가해 주겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="board"> <select id="selectBoardList" parameterType="hashmap" resultType="hashmap"> <![CDATA[ SELECT board_num, parent_num, title, contents, hit_cnt, del_gb, crea_date, crea_id FROM TB_BOARD WHERE
del_gb = 'N'
ORDER BY board_num DESC ]]> </select> </mapper> |
마지막으로 화면을 출력할 View를 만들겠습니다.
jsp폴더에 BoardList.jsp를 생성해주세요
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <title>first</title> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%> </head> <body> <h2>게시판 목록</h2> <table style="border:1px solid #ccc"> <colgroup> <col width="10%"/> <col width="*"/> <col width="15%"/> <col width="20%"/> </colgroup> <thead> <tr> <th scope="col">글번호</th> <th scope="col">제목</th> <th scope="col">조회수</th> <th scope="col">작성일</th> </tr> </thead> <tbody> <c:choose> <c:when test="${fn:length(list) > 0}"> <c:forEach items="${list }" var="row"> <tr> <td>${row.board_num }</td> <td>${row.title }</td> <td>${row.hit_cnt }</td> <td>${row.crea_date }</td> </tr> </c:forEach> </c:when> <c:otherwise> <tr> <td colspan="4">조회된 결과가 없습니다.</td> </tr> </c:otherwise> </c:choose> </tbody> </table> </body> </html> | cs |
(포스팅 시작했을때도 말했다시피 저는 http://addio3305.tistory.com/72 블로그에서 배워서 여러분께 Netbeans로 하는 방법을 알려드리고 있습니다. 여기 블로그에서 자세한 설명을 들으실 수 있습니다.)
이 부분은 블로그의 내용을 참조하겠습니다.
JSTL의 기본문법에 대한 설명은 넘어가도록 하겠다.
만약 JSTL이 무엇인지 모른다면 JSTL에 대한 내용은 간단하게라도 공부할 필요가 있다.
전체 조회결과가 있으면 그 결과를 보여주고, 없으면 조회된 결과가 없다는 메시지를 보여주는 화면이다.
여기서 <c:forEach item="${list}" var="row">라는 부분을 봐야한다.
Controller에서 DB에서 조회된 결과 list를 mv.addObject를 이용하여 "list"라는 이름으로 mv에 값을 저장 했었던 것을 떠올려보자. (mv.addObject("list",list); 라고 작성했었다.)
JSTL의 forEach문을 통해서 테이블의 목록을 만드려고 하는데, 여기서 사용할 아이템은 ${list}라고 되어있다. 이게 바로 우리가 mv에서 추가를 해줬던 그 list를 의미한다.
그 다음으로 var="row"라고 되어있다. 우리는 List<Map<String,Object>> 라는 형식으로 list를 선언하고, DB에서 조회된 결과를 받았다.
이 list에서 하나의 데이터쌍을 가져오면 ( Java에서 list.get(index)를 의미한다.) 그 데이터는 Map<String,Object> 형식의 데이터 한줄이 나오게 되고, 그 데이터는 row라는 이름의 변수에 저장이 된다.
그 후, row에서 원하는 데이터를 뽑아서 사용하면 된다.
row.IDX, TITLE, HIT_CNT, CREA_DTM의 이름에서 볼 수 있듯이, 이는 우리가 select 쿼리를 실행하였을 때 뽑아온 데이터의 이름이다. (대소문자를 구분한다.)
쿼리의 select 문에서 뽑아온 이름이 Map의 키(key)로 사용되고, 화면에서는 그 키를 이용하여 데이터에 접근할 수 있다.
출처: http://addio3305.tistory.com/72 [흔한 개발자의 개발 노트]
그럼 이제 F6을 눌러 실행해 보겠습니다.
url은 'contextpath'/BoardList.do 라고 치시면 됩니다.
이 화면이 뜨시면 제대로 작동한겁니다. 지금은 데이터가 없으니 하나도 없겠죠~
로그를 보면 요청 url과 사용한 쿼리, mysql 결과가 찍힙니다.
<------------------------------------------------------------------------------------------>
다음 포스트에는 글 작성, 글 상세보기를 하겠습니다.