2014년 1월 13일 월요일

B. Srping Framework 게시판 만들기 (Ajax,HttpServlet을 이용하여 미리보기 기능 추가), 스프링3.X 게시판강좌,교육

B. Srping Framework 게시판 만들기 (Ajax,HttpServlet을 이용하여 미리보기 기능 추가), 스프링3.X 게시판강좌,교육 


1. 시작하기
-       이전 까지 만든 게시판 리스트 보기 기능에 추가로 본문 내용 미리 보기 기능을 구현해 보자
-       게시물 본문 내용 미리 보기 기능은 게시판 리스트에서 제목에 마우스를 이동하는 경우 Ajax 기능과 자바 웹 서블릿을 이용하여 미리 본문 내용을 읽어 오도록 구성 하였다.
-       먼저 JSP AJAX CALL을 위한 자바스크립트를 추가하고, ajax XMLHttpRequest 생성을 위한 createXMLHttpRequest.js 파일을 만들자.
-       DAO단부터 Service쪽 그리고 미리 보기용 서블릿까지 따라 하면서 만들어 보자.
(이전에 만든 BoardMuitiController는 이용하지 않고 서블릿을 통해 미리 보기 기능을 구현한다.)


2. [/js/boardActionJs.js] / [/WEB-INF/js/list.jsp] / [/css/boardCss.css]

  
// 검색 
function boardListSearchGo(){

document.listForm.action ="/board/list.html"; 
document.listForm.submit();
// 검색Text입력 후 바로 엔터 가능하게 하는 이벤트
function enterEvent(){
if(window.event.keyCode == 13){
boardListSearchGo();
}
}

// 미리보기(Ajax) 
var xmlHttp = null;
var xmlDoc  = null;
var message = null;

function createXMLHttpRequest(){

// 익스플로러이면 if 그외 브라우저이면 else
if(window.ActiveXObject){
try{
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); // IE 5.0 이하 버전
}catch(e){
try{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); // IE 5.0 이상 버전
}catch(el){xmlHttp = null;}
}
}else if(window.XMLHttpRequest){
try{
xmlHttp = new XMLHttpRequest();
}catch(e){
xmlHttp = null;
}
}
if(xmlHttp == null){errorMessage();}
  
return xmlHttp;
}
 
function errorMessage(){alert("지원할 수 없는 브라우저 입니다.");}


function contentprev(seq){ 
 
var url = "ContentPreview?seq="+seq;
xmlHttp = createXMLHttpRequest();
xmlHttp.onreadystatechange = handleStateChange;
xmlHttp.open("get",url,true);
xmlHttp.send(null);
}

function handleStateChange(){ 
if(xmlHttp.readyState == 4){
if(xmlHttp.status == 200){ 
xmlDoc = xmlHttp.responseText; 
document.getElementById("layer1").innerHTML = xmlDoc;
showlayer();
}

// 게시판 글제목에서 마우스가 올라갔을 경우 발생
function showlayer(){
    document.getElementById("layer1").style.visibility="visible";
}
  
// 게시판 글제목에 마우스가 떨어져 있을 경우 발생
function hidelayer(){
    document.getElementById("layer1").style.visibility="hidden";
}
//화면에서 마우스가 움직일때 movetip()함수 발생  
document.onmousemove = movetip;

// 미리보기 위치 
function movetip(){
document.getElementById("layer1").style.pixelTop  = event.y+document.body.scrollTop+20;
document.getElementById("layer1").style.pixelLeft = event.x+document.body.scrollLeft+20;
------------------------------------------------------------------------------------------
   <%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%@ 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>
 
<link rel="stylesheet" type="text/css" href="/board/css/boardCss.css">

<script type="text/javascript" src="/board/js/boardActionJs.js"></script>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<!-- 미리보기 -->
<div id="layer1">
게시물 본문 미리보기
</div>   

<form name="listForm" method="get">
<table class="listTable">  
<tr> 
<td colspan="5" align="right" id="boardListCount">게시글 수 : ${boardCount} 건</td>
</tr>
</table>
<table class="listTable" border="1" cellpadding="0" cellspacing="0"> 
<tr>
<th>번호</th>
<th>글제목</th>
<th>작성자</th> 
<th>작성일</th>
<th>조회수</th>
</tr>
<tr> 
<c:if var="boardCountZroe" test="${boardCount == 0}">
<td colspan="5">
<font color="red">게시글이 없습니다.</font>
</td>
</c:if>
</tr>
<c:if test="${!boardCountZroe}">
<c:forEach var="list" items="${list}">  
<tr>
<td>${list.seq}</td>
<td>
<a href="/board/read.html?seq=${list.seq}" onmouseover="contentprev('${list.seq}');" onmouseout="hidelayer();">${list.title}</a>
</td>  
<td>${list.name}</td>
<td>${list.regdate}</td>  
<td>${list.readcount}</td>
</tr>
</c:forEach> 
</c:if>
</table>
<!-- 페이지 -->
<c:if test="${!boardCountZroe}">
<table class="listTable">
<tr>
<td colspan="5" align="center">
<c:if test="${startPage > 1}">
<span>
<a href="/board/list.html?pageNumber=${startPage - 1}">이전</a>
</span>
</c:if>
<c:forEach var="i" begin="${startPage}" end="${endPage}">
<c:choose>
<c:when test="${pageNumber == i }">
<span>
<a href="/board/list.html?pageNumber=${i}" id="boardList_a">${i}</a>&nbsp;
</span>
</c:when>
<c:otherwise>
<span>
<a href="/board/list.html?pageNumber=${i}">${i}</a>&nbsp;
</span>
</c:otherwise>
</c:choose>
</c:forEach>
<c:if test="${endPage < totalPageCount}">
<span> 
<a href="/board/list.html?pageNumber=${endPage + 1}">다음</a>
</span> 
</c:if>
</td>
</tr>
</table>
</c:if>
<!-- 검색 -->
<table class="listTable">
<tr>
<td colspan="5" align="center">
<select name="boardListSelect">
<option value="name">작성자</option>
<option value="title">글제목</option>
<option value="seq">글번호</option>
</select> 
<input type="text" id="boardListSearchText" name="boardListSearchText" onkeydown="enterEvent();"> 
<input type="button" value="검색" onclick="boardListSearchGo();">
/
<input type="button" value="글 입력" onclick="Location.href='#'"> 
</td>
</tr>
</table>
</form>
</body>
</html>
------------------------------------------------------------------------------------------
@CHARSET "EUC-KR";

td{text-align: center;}
th{text-align: center;}

 
a:link{ text-decoration:none;    color: #5D5D5D;}
a:visited{ text-decoration:none; color: #5D5D5D;}
a:active{ text-decoration:none;  color: #47C83E;}
a:hover{ text-decoration:none;   color: #47C83E;}

.listTable{width:600px;}

#boardListCount{text-align: right;}
#boardList_a{font-weight: bold; color:#8041D9;}


#layer1{
position: absolute;
padding: 5px;
filter: alpha(opacity=50);
width: 250px; height: 150px;
background-color: white;
border: 2px #000000 dotted;
visibility: hidden; 

3. [web.xml]

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
 
  <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>
 
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
/WEB-INF/spring/root-context.xml
/WEB-INF/spring/appServlet/servlet-context.xml 
</param-value>
  </context-param>
  
  <servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <url-pattern>*.html</url-pattern>
  </servlet-mapping>
  
  <!-- 게시물 미리보기 기능을 위한 ajax 처리용 서블릿 정의 -->
  <servlet>
    <servlet-name>ContentPreview</servlet-name>
    <servlet-class>com.board.ajaxpreview.ContentPreview</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ContentPreview</servlet-name>
    <url-pattern>/ContentPreview</url-pattern>
  </servlet-mapping>

</web-app>

4. [BoardDAO.java] / [BoardDAOImple.java]
package com.board.dao;

import java.util.List;
import java.util.Map;

import org.springframework.dao.DataAccessException;

import com.board.model.BoardDTO;

public interface BoardDAO {
// 전체 게시글 수
public int boardCount(Map<String, Object>searchMap)throws DataAccessException;
// 게시판 리스트
public List<BoardDTO> boardList(Map<String, Object>searchMap) throws DataAccessException;
// 게시물 본문 미리보기
public String preView(String seq)throws DataAccessException;
}

------------------------------------------------------------------------------------------
package com.board.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import com.board.model.BoardDTO;

public class BoardDAOImple implements BoardDAO {

private JdbcTemplate jdbaTemplate;
public void setDataSource(DataSource dataSource){
this.jdbaTemplate = new JdbcTemplate(dataSource);
}
// 게시글 수
public int boardCount(Map<String, Object>searchMap)throws DataAccessException{
int count = 0;
String sql = "";
if(searchMap.get("boardListSearchText") == null){
sql = "select count(*) from board02";
count = jdbaTemplate.queryForObject(sql,
Integer.class
);
}else{
String boardListSelect = (String) searchMap.get("boardListSelect");
String boardListSearchText = (String) searchMap.get("boardListSearchText");
sql = "select count(*) from board02 where "+boardListSelect+" like '%"+boardListSearchText+"%'";
count = jdbaTemplate.queryForObject(sql,Integer.class);
 
return count;
}
// 게시판 리스트
public List<BoardDTO> boardList(Map<String, Object>searchMap) throws DataAccessException {
List<BoardDTO> boardList = null;
String sql = "";
Object[] obj;

if(searchMap.get("boardListSearchText") == null){
sql = "select * from ("
+ " select  b.seq ,b.name,b.title ,TO_CHAR(b.regdate,'YYYY/MM/DD')as regdate, b.readcount, "
+ "         r.reply_level"
+ " from board02 b, reply r"
+ " where b.seq = r.reply"
+ " order by r.reply desc, r.reply_step asc"
+ " )"
+ " where ROWNUM BETWEEN ? AND ?";
obj = new Object[] {searchMap.get("startRow"),searchMap.get("endRow")};

}else{
String boardListSelect = (String) searchMap.get("boardListSelect");
String boardListSearchText = (String) searchMap.get("boardListSearchText");
sql = "select * from ("
+ " select  b.seq ,b.name,b.title ,TO_CHAR(b.regdate,'YYYY/MM/DD')as regdate, b.readcount, "
+ "         r.reply_level"
+ " from board02 b, reply r"
+ " where b.seq = r.reply"
+ "   and  "+boardListSelect+" like '%"+boardListSearchText+"%'" 
+ " order by r.reply desc, r.reply_step asc"
+ " )"
+ " where ROWNUM BETWEEN ? AND ?";
 
obj = new Object[] {searchMap.get("startRow"),searchMap.get("endRow")};
}   
boardList = jdbaTemplate.query(sql, 
  obj, 
  new RowMapper<BoardDTO>(){
  public BoardDTO mapRow(ResultSet rs, int rowNum)throws SQLException{
 
  BoardDTO boardDTO = new BoardDTO(rs.getString("seq"),
rs.getString("name"),
rs.getString("title"),
rs.getString("regdate"),
rs.getInt("readcount"),
rs.getInt("reply_level")
  );
  return boardDTO;
  }
});
return boardList;
}
// 게시물 본문내용 미리보기
public String preView(String seq) throws DataAccessException{
String sql = "select content from board02 where seq = ?";
String preContent = "";
Object obj[] = {seq};
preContent = jdbaTemplate.queryForObject(sql,obj,String.class);
return preContent;
}
}

5. [BoardServiceHelper.java] / [BoardService.java] / [BoardServiceImple.java]

BoardServiceHelper.java는 새로 만들어야됨.

package com.board.service;

import javax.servlet.ServletContext;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

//ContentPreview 서블릿에서 root-context.xml에서 생성한 boardService Been객체를 사용하기 
// 위해서 생성한 클레스이다.
public class BoardServiceHelper {
public static BoardService getBoardService(ServletContext ctx){
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(ctx);
return (BoardService) wac.getBean("boardService");
}
}

------------------------------------------------------------------------------------------

package com.board.service;

import java.util.List;
import java.util.Map;

import com.board.model.BoardDTO;

public interface BoardService {

// 게시글 수
public int boardCount(Map<String, Object>searchMap)throws Exception;
// 게시판 리스트
public List<BoardDTO> boardList(Map<String, Object>searchMap)throws Exception;
//게시물 미리보기
public String preView(String seq)throws Exception;
}

------------------------------------------------------------------------------------------

package com.board.service;

import java.util.List;
import java.util.Map;

import com.board.dao.BoardDAO;
import com.board.model.BoardDTO;

public class BoardServiceImple implements BoardService {

private BoardDAO boardDAO;
public void setBoardDAO(BoardDAO boardDAO){
this.boardDAO = boardDAO;
}
// 게시글 수
public int boardCount(Map<String, Object> searchMap) throws Exception {
return boardDAO.boardCount(searchMap);
}

// 게시판 리스트
public List<BoardDTO> boardList(Map<String, Object> searchMap) throws Exception {
return boardDAO.boardList(searchMap);
}
// 게시물 미리보기
public String preView(String seq){
return boardDAO.preView(seq);
}
}

6.[ContentPreview.java]
 ContentPreview.java 새로 만들어야될 클레스
package com.board.ajaxpreview;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.board.service.BoardService;
import com.board.service.BoardServiceHelper;


public class ContentPreview extends HttpServlet {
private static final long serialVersionUID = 1L;
       
    public ContentPreview() {super();}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html; charset=utf-8");
response.setHeader("Cache-control", "no-cache"); 
String seq = request.getParameter("seq");
BoardService boardService = BoardServiceHelper.getBoardService(getServletContext());
PrintWriter out = response.getWriter();
try {
out.println("<pre>"+boardService.preView(seq)+"</pre>");
} catch (Exception e) {
e.printStackTrace();
}
}
 
}



댓글 없음:

댓글 쓰기