2013년 7월 28일 일요일

12. (Spring Framework Board스프링게시판)게시글 읽기,상세보기 페이지 구현, Spring Board 소스, 강좌

Spring 게시판 구현(게시 글 내용 읽기, 상세보기 페이지 작성)
구로디지털 오엔제이프로그래밍실무교육센터
(오라클,자바프레임워크 전문 강의)
1.     시작하기
-       이전 까지 만든 게시판 기능(게시판리스트보기+글 내용 미리 보기)에 추가로 제목을 클릭할 때 본문 내용을 읽을 수 있는 게시글 상세보기기능을 만들어 보자.
-       이전의 내용을 참고 한다면 어렵지 않게 구현할 수 있다.
-       DAO, service, 컨트롤러 수정, 뷰 페이지 신규작성, action-servlet.xml 수정 순서로 만들어 보자.
2.     먼저 DAO단의 BoardDAO.java, SpringBoardDAO.java를 수정하자.
인터페이스인 BoardDAO.java 파일에 게시물 읽기 메소드 readContent(), 읽은 글의 조회수를 1증가 하기 위한 메소드 updateReadCount() 메소드를 정의하고 이를 SpringBoardDAO에서 구현하자.
[BoardDAO.java]
소스 코드 빨강색 부분이 게시글 상세보기( 읽기) 기능을 위해 추가된 부분
package onj.board.dao;
import java.util.List;
import onj.board.model.BoardDTO;
import org.springframework.dao.DataAccessException;
public interface BoardDAO {
           //게시물 리스트 보기
           public List<BoardDTO> boardList() throws DataAccessException;
          
           //게시물 본문 미리보기
           public String preView(String seq) throws DataAccessException;
          
           //게시물 본문 읽기
           public BoardDTO readContent(String seq) throws DataAccessException;
          
           //읽은 글의 조회수 1증가
           public int updateReadCount(String seq) throws DataAccessException;
}
[SpringBoardDAO.java]
소스 코드 빨강색 부분이 게시글 상세보기( 읽기) 기능을 위해 추가된 부분
package onj.board.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import onj.board.model.BoardDTO;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
public class SpringBoardDAO implements BoardDAO {
       private JdbcTemplate jdbcTemplate;
       public void setDataSource(DataSource dataSource) {
             this.jdbcTemplate = new JdbcTemplate(dataSource);
       }
       // /게시판 전체 리스트 보기(list.html)
       public List<BoardDTO> boardList() throws DataAccessException {
             List<BoardDTO> boardList = null;
             String sql = "select * from board";
             boardList = jdbcTemplate.query(sql, new RowMapper() {
                    public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
                           BoardDTO board = new BoardDTO();
                           board.setSeq(rs.getInt("seq"));
                           board.setName(rs.getString("name"));
                           board.setPasswd(rs.getString("passwd"));
                           board.setTitle(rs.getString("title"));
                           board.setContent(rs.getString("content"));
                           board.setFileName(rs.getString("filename"));
                           board.setRegDate(rs.getString("regdate"));
                           board.setReadCount(rs.getInt("readcount"));
                           board.setReply(rs.getInt("reply"));
                           board.setReply_step(rs.getInt("reply_step"));
                           board.setReply_level(rs.getInt("reply_level"));
                           return board;
                    }
             });
             return boardList;
       }
       // 게시물 본문내용 미리보기(/preView)
       public String preView(String seq) throws DataAccessException {
             String sql = "select * from board where seq = ?";
             String preContent = (String) jdbcTemplate.queryForObject(sql,
                           new Object[] { seq }, new RowMapper() {
                                 public Object mapRow(ResultSet rs, int rowNum)
                                              throws SQLException {
                                        return rs.getString("content");
                                 }
                           });
             return preContent;
       }
       // 게시판 상세보기, 게시글 읽기
       public BoardDTO readContent(String seq) throws DataAccessException {
             String sql = "select * from board where seq = ?";
             BoardDTO boardDTO = (BoardDTO) jdbcTemplate.queryForObject(sql,
                           new Object[] { seq }, new RowMapper() {
                                 public Object mapRow(ResultSet rs, int rowNum)
                                              throws SQLException {
                                        BoardDTO board = new BoardDTO();
                                        board.setSeq(rs.getInt("seq"));
                                        board.setName(rs.getString("name"));
                                        board.setPasswd(rs.getString("passwd"));
                                        board.setTitle(rs.getString("title"));
                                        board.setContent(rs.getString("content"));
                                        board.setFileName(rs.getString("filename"));
                                        board.setRegDate(rs.getString("regdate"));
                                        board.setReadCount(rs.getInt("readcount"));
                                        board.setReply(rs.getInt("reply"));
                                        board.setReply_step(rs.getInt("reply_step"));
                                        board.setReply_level(rs.getInt("reply_level"));
                                        return board;
                                 }
                           });
             // 조회수 1증가
             this.updateReadCount(new Integer(boardDTO.getSeq()).toString());
            
             return boardDTO;
       }
       //읽은 글의 조회수를 1증가
       public int updateReadCount(String seq) throws DataAccessException {
             String sql = "update board set readcount = nvl(readcount,0) + 1 where seq = ?";
             Object[] obj = { seq };
            
             return jdbcTemplate.update(sql, obj);
       }
}
3.  service 클래스를 만들어 보자.
새로 추가되는 클래스는 없으니 편안한 마음으로 수정하자.
[BoardService.java]
소스 코드 빨강색 부분이 게시글 상세보기( 읽기) 기능을 위해 추가된 부분
package onj.board.service;
import java.util.List;
import onj.board.model.BoardDTO;
/*
 * 게시판에서 구현할 기능을 인터페이스로 정의
 */
public interface BoardService {
       //게시판 리스트 보기
       public List<BoardDTO> boardList();     
      
       //게시물 미리보기
       public String preView(String seq);
      
       //게시판 본문 내용보기, 게시글 읽기
       public BoardDTO readContent(String seq);
}
[SpringServiceImpl.java]
소스 코드 빨강색 부분이 게시글 상세보기( 읽기) 기능을 위해 추가된 부분
package onj.board.service;
import java.util.List;
import onj.board.dao.BoardDAO;
import onj.board.model.BoardDTO;
public class BoardServiceImpl implements BoardService {
    private BoardDAO boardDAO;
   
    public void setBoardDAO(BoardDAO boardDAO) {
        this.boardDAO = boardDAO;
    }
   
    //게시물 리스트 보기
    public List<BoardDTO> boardList() {
        return boardDAO.boardList();
    }
   
    //게시물 본문 내용 미리보기
    public String preView(String seq) {
        return boardDAO.preView(seq);
    }
    //게시글 읽기
public BoardDTO readContent(String seq) {
       return boardDAO.readContent(seq);
}   
}
4.     이번에는 컨트롤러를 수정하자.
[BoardMultiController.java]
소스 코드 빨강색 부분이 게시글 상세보기( 읽기) 기능을 위해 추가된 부분
package onj.board.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import onj.board.service.BoardService;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
/*
 * MultiActionController는 비슷하거나 관련있는 로직을 수행하는
 * 다수의 액션을 가지고 있을 때 사용하는 컨트롤러
 * 연관된 요청(Request)를 묶을 때 용이함
 */
public class BoardMultiController extends MultiActionController {
           private BoardService boardService;
          
           public void setBoardService(BoardService boardService) {
                     this.boardService = boardService;
           }
          
           //게시판 리스트 보기, 페이징 기능은 구현 안함 
           public ModelAndView list(HttpServletRequest req, HttpServletResponse res) throws Exception {                     
                    
                     ModelAndView mv = new ModelAndView("list" , "list" , boardService.boardList());
                     return mv;                  
           }         
          
           //게시글 읽기
           public ModelAndView read(HttpServletRequest req, HttpServletResponse res) throws Exception {                          
           ModelAndView mav = new ModelAndView("read",                             "read" ,   boardService.readContent(req.getParameter("seq")));
                    
           return mav;
                    
           }
}
컨트롤러에서 read() 메소드를 추가 했는데 글을 읽고자 하는 게시물 번호를 seq로 받아 boardService readContent를 호출하고 boardService에서는 BoardDAO를 호출함으로서 결과를 받아 올 것이다.
ModelAndView의 첫번째 인자가 클라이언트에 보여질 뷰이름(read)인데 action-servlet.xml에 정의 된 viewResolver를 통해 접두, 접미어가 붙어  /jsp/read.jsp로 해석 된다.
두번째 인자는 readContent를 통해 리턴되는 BoardDTO 개체를 담을 이름(read)이다. 이 이름은 read.jsp 에서 데이터를 뿌릴 때 이용할 것이다.
[참고]
@RequestMapping 애노테이션을 이용하면 단순한 View 네임을 리턴 타입으로 갖는 것이 가능하다. 그러므로 출력 값을 위임할(뷰가 될 페이지) JSP의 이름을 문자열로 리턴 하며 결과 값은 ModelMap에 속성으로 add하면 ModelAndView를 통해 뷰 를 정의하지 않아도 된다.
5.     뷰페이지 read.jsp를 작성하자.
[read.jsp]
<%@ page contentType="text/html; charset=euc-kr" language="java" import="java.sql.*" errorPage="" %>
<%@ page import = "onj.board.model.* , onj.board.service.* , java.util.*" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>게시물 읽기</title>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
<script>
       function write_ok(){
             writeform.submit();
       }
</script>
</head>
<body>
<div style="width:600px;">
<div style="float:enter;">
<table width="600" height="420" border="1" align="center">
  <tr height="20"><h2>오엔제이프로그래밍실무교육센터 게시판</h2></tr>
  <tr>
    <td width="100">* 이름</td>
    <td width="500">: <input name="name" type="text" value="${read.name}" size="50" readonly>
      </td>
  </tr>
  <tr>
    <td>* 제목</td>
    <td>:
    <input name="title" type="text" value="${read.title}" size="50" readonly></td>
  </tr>
  <tr align="center">
    <td colspan="2"><textarea name="content" cols="80" rows="12" readonly>${read.content}</textarea></td>
  </tr>
  <tr>
    <td>* 파일</td>
    <td>:
                    <c:choose>
                           <c:when test="${read.fileName != null}">
                                 ${read.fileName}                                    
                           </c:when>
                           <c:when test="${read.fileName == null}">
                                 파일 없음
                           </c:when>
                    </c:choose>
       </td>
  </tr>
  <tr>
    <td> </td>
    <td><input name="button" type="button" onClick="location.href='./reply.html?seq=${read.seq}'" value="답변">
|
  <input name="button" type="button" value="수정">
|
<input name="button" type="button" onClick="location.href='./delete.jsp?seq=${read.seq}'" value="삭제">
|
<input name="button" type="button" onClick="location.href='./list.html'" value="목록"></td>
  </tr>
  <tr>
    <td height="99" colspan="2">
   
    <form method="post" action="commok.html">
           <table border="1">
             <tr>
               <td>이름 : </td>
               <td><input type="text" name="name"></td>
               <td>코멘트:</td>
               <td><input type="text" name="comm"></td>
               <td><input type="submit" name="Button" value="쓰기"></td>
             </tr>
           </table>
           <input type="hidden" name="seq" value="${read.seq}">
    </form>
      </td>
    </tr>
   
</table>
<br><br>
<table><tr><td><tr><b>http://www.onjprogramming.co.kr</tr></td></tr></table>
<input type="hidden" name="seq" value="${read.seq}">
<input type="hidden" name="reply" value="${read.reply}">
<input type="hidden" name="reply_step" value="${read.reply_step}">
<input type="hidden" name="reply_level" value="${read.reply_level}">
</div>
</div>
</body>
</html>
6.     Action-servlet.xml을 수정하자.
소스 코드 빨강색 부분이 게시글 상세보기( 읽기) 기능을 위해 추가된 부분
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
<beans>
       <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
             destroy-method="close">
             <property name="driverClassName">
                    <value>oracle.jdbc.driver.OracleDriver</value>
             </property>
             <property name="url">
                    <value>jdbc:oracle:thin:@127.0.0.1:1521:onj</value>
             </property>
             <property name="username">
                    <value>scott</value>
             </property>
             <property name="password">
                    <value>tiger</value>
             </property>
       </bean>
       <!-- 넘어오는 URL 따라 컨트롤러에서 실행될 메소드 매핑 -->
       <!-- PropertiesMethodNameResolver prop key 넘어오는 url 대해 실행할 컨트롤러의 메소드
             정의 -->
       <bean id="userControllerMethodNameResolver"
              class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
             <property name="mappings">
               <props>
                    <!-- list.html 요청이 오면 컨트롤러의 list 메소드 실행 -->
                    <prop key="/list.html">list</prop>
                          
                    <!-- read.html 요청이 오면 컨트롤러의 read 메소드 실행 -->
                    <prop key="/read.html">read</prop>
             </props>
             </property>
       </bean>
       <!-- 리졸버 -->
       <bean id="viewResolver"
             class="org.springframework.web.servlet.view.InternalResourceViewResolver">
             <property name="prefix">
                    <value>/jsp/</value>
             </property>
             <property name="suffix">
                    <value>.jsp</value>
             </property>
       </bean>
       <!-- 컨트롤러 매핑 -->
       <bean name="/list.html /read.html" class="onj.board.controller.BoardMultiController">
             <property name="methodNameResolver">
                    <ref local="userControllerMethodNameResolver" />
             </property>
             <property name="boardService">
                    <ref bean="boardService" />
             </property>
       </bean>
      
</beans>
실행결과 및 현재까지 만들어진 이클립스 구조
(게시판 리스트보기 + 게시물 본문내용 미리 보기 + 게시글 상세보기)






댓글 없음:

댓글 쓰기