Spring 게시판 구현(게시물
본문 내용 미리보기)
구로디지털
오엔제이프로그래밍실무교육센터
(오라클,자바프레임워크
전문 강의)
1.
시작하기<?XML:NAMESPACE PREFIX = O />
- 이전 까지 만든 게시판 리스트
보기 기능에 추가로 본문 내용 미리 보기 기능을 구현해 보자
- 게시물 본문 내용 미리 보기
기능은 게시판 리스트에서 제목에 마우스를 이동하는 경우 Ajax 기능과 자바 웹 서블릿을 이용하여
미리 본문 내용을 읽어 오도록 구성 하였다.
- 먼저 JSP에 AJAX CALL을 위한 자바스크립트를 추가하고, ajax XMLHttpRequest 생성을 위한 createXMLHttpRequest.js 파일을 만들자.
- DAO단부터 Service쪽 그리고 미리 보기용 서블릿까지 따라
하면서 만들어 보자.
(이전에 만든 BoardMuitiController는 이용하지 않고 서블릿을 통해 미리 보기 기능을 구현한다.)
2.
/js/createXMLHttpRequest.js
web.xml 파일은 웹 애플리케이션(Web
Application)에 대한 전체 설정 파일이다. Web Application
XMLHttpRequest객체는 현재 대부분의 브라우저에 내장되어 있는 객체로서 자바스크립트에 대한
HTTP 클라이언트 이므로 서버로 GET, POST 요청을 비동기 적으로 할 수
있다. 즉 AJAX에서 클라이언트와 서버간의 통신을
담당하는 객체이다.
아래 js 파일은 이 객체를 생성하기 위한 코드임.
[createXMLHttpRequest.js]
function createXMLHttpRequest(){
var xmlHttp;
// 익스냐
익스
아니냐???
if(window.ActiveXObject){
try{
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e){
try{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e1){
xmlHttp = null;
}
}
}
else if(window.XMLHttpRequest){
try{
xmlHttp
= new XMLHttpRequest();
}
catch(e){
xmlHttp
= null;
}
}
if(xmlHttp == null) errorMessage();
return xmlHttp;
}
function errorMessage(){
alert("지원할
수
없는
브라우저입니다.");
}
3.
/jsp/list.jsp
수정
-
게시물 본문 내용 미리보기 기능을 위한 AJAX 요청
처리를 위해 <head></head> 사이에 아래 코드를 추가하자.
<style type="text/css">
#layer1{
position:absolute;
padding:5px;
filter:alpha(opacity=50);
width:250px; height:150px;
background-color:white;
border:2px #000000 dotted;
visibility:hidden;
}
</style>
<script language="javascript" type="text/javascript" src="../js/createXMLHttpRequest.js"></script>
<script type="text/javascript">
var xmlHttp;
var xmlDoc;
var message;
function contentprev(seq){
var url = "preView?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;
}
}
}
function showlayer(id){
if(document.all)
document.all[id].style.visibility="visible";
else if(document.layers)
document.layers[id].style.visibility="visible";
}
function hidelayer(id){
if(document.all)
document.all[id].style.visibility="hidden";
else if(document.layers)
document.layers[id].style.visibility="hidden";
}
function movetip() {
layer1.style.pixelTop=event.y+document.body.scrollTop+10;
layer1.style.pixelLeft=event.x+document.body.scrollLeft+10;
}
document.onmousemove=movetip;
</script>
코드의 핵심은 생성된 XMLHttpRequest를 이용하여 게시물 미리 보기를
위한 preView라는 이름의 자바 서블릿을 호출하는 부분이다.
XMLHttpRequest의 open() 메소드를 통해 요청을 초기화 하고 요청을
위한 URL, 요청의 종류(GET or POST)를
결정하고 비동기 요청을 위해 “true”라는 옵션을 이용했다.
실제 요청은 send()
메소드를 통해 전송되며 GET 방식의 호출이므로
send(null) 이라고 했다.
-
<body>바로 아래에 게시물
미리보기용 <div> 추가!
<div id="layer1">
게시물
본문
미리
보기
-
</div>
아래는 수정된 /jsp/list.jsp 전체 소스 코드이다.
[list.jsp]
<%@ page contentType="text/html;
charset=euc-kr" language="java"
import="java.sql.*" errorPage="" %>
<%@ page import =
"javax.rmi.* , javax.naming.* , java.util.* ,
onj.board.model.*" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>오엔제이
프로그래밍
실무학원</title>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
<style type="text/css">
#layer1{
position:absolute;
padding:5px;
filter:alpha(opacity=50);
width:250px; height:150px;
background-color:white;
border:2px #000000
dotted;
visibility:hidden;
}
</style>
<script language="javascript"
type="text/javascript"
src="/onjboard1/js/createXMLHttpRequest.js"></script>
<script type="text/javascript">
var xmlHttp;
var xmlDoc;
var message;
function contentprev(seq){
var url = "preView?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;
}
}
}
function showlayer(id){
if(document.all)
document.all[id].style.visibility="visible";
else if(document.layers)
document.layers[id].style.visibility="visible";
}
function hidelayer(id){
if(document.all)
document.all[id].style.visibility="hidden";
else if(document.layers)
document.layers[id].style.visibility="hidden";
}
function movetip() {
layer1.style.pixelTop=event.y+document.body.scrollTop+10;
layer1.style.pixelLeft=event.x+document.body.scrollLeft+10;
}
document.onmousemove=movetip;
</script>
</head>
<body>
<div id="layer1">
게시물
본문
미리
보기
</div>
<div style="width:500px;">
<div style="float:right;">
<H3>오엔제이
프로그래밍
실무교육센터
스프링
게시판</H3>
<h5>총 ${list.size()}건</h5>
<table width="600"
border="1"
align="left">
<tr align="left">
<td width="10%"
align="center">번호</td>
<td width="40%"
align="center">제목</td>
<td width="20%"
align="center">이름</td>
<td width="20%"
align="center">날짜</td>
<td width="10%"
align="center">조회</td>
</tr>
<!-- list를
가져와서
board라
명명
후
개
수
만큼
반복 -->
<c:forEach var="board"
items="${list}">
<tr>
<td align="center">
<c:if test="${board.reply_step == 0}">
${board.seq}
</c:if>
<c:if test="${board.reply_step != 0}">
</c:if>
</td>
<td> <!-- 게시물은
덧글에
따른
번호와
덧글
존재
유무로
정렬됨 -->
<c:choose>
<c:when test="${board.reply_step != 0}"><!-- 게시글이
덧글일
경우 -->
<c:forEach var="i"
begin="1"
end="${board.reply_level}" step="1"><!-- 레벨의
수만큼
글을
뒤로
민다 -->
</c:forEach>
<a href="read.html?seq=${board.seq}" onmouseover="contentprev('${board.seq}');showlayer('layer1');" onmouseout="hidelayer('layer1');">${board.title}</a>
<!-- 마우스를
올리면
게시물
번호에
따른
showlayer(게시물
미리보기
창)가
실행됨 -->
</c:when>
<c:when test="${board.reply_step == 0}">
<a href="read.html?seq=${board.seq}" onmouseover="contentprev('${board.seq}');showlayer('layer1');" onmouseout="hidelayer('layer1');">${board.title}</a>
</c:when>
</c:choose>
</td>
<td align="center">${board.name}</td>
<td align="center">${board.regdate}</td>
<td align="center">${board.readCount}</td>
</tr>
</c:forEach>
<tr>
<td align="center"><input
type="button"
value="쓰기" onclick="location.href='write.html';"></td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
</table>
</div>
</div>
</body>
</html>
4.
/WEB-INF/web.xml
web.xml에 아래 서블릿 매핑은 이미 정의했었다.
다시 한번 보자.
<!-- 게시물
미리
보기
기능을
위한
ajax 처리용
서블릿
정의 -->
<servlet>
<servlet-name>preView</servlet-name>
<servlet-class>onj.board.ajaxpreview.ContentPreview</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>preView</servlet-name>
<url-pattern>/preView</url-pattern>
</servlet-mapping>
onj.board.ajaxpreview.ContentPreview 서블릿의
이름을 preView라고 매핑하고 URL 요청에서 /preView라는 요청이 올 때 이를 실행하라는 의미이다. 물론
서블릿 매핑은 자바 애노테이션(Annotation)을 이용하여 처리하는 것도 가능한데 서블릿 클래스를 작성시 Tomcat7 이상, Servlet3.0 이상 이라면 @WebServlet(urlPatterns =
"/preView") 라고 기술하면 된다. XML과 애노테이션 둘 다 동시에
기술하면 XML쪽 매핑이 우선 한다.
5.
게시물 미리보기 기능을 위한 DAO쪽의 클래스를 만들어 보자.
[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;
}
[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.setDate(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;
}
}
6. service 쪽
클래스를
만들어
보자.
새로
추가되는
클래스가 BoardServiceHelper인데
ㅅ블릿에서
스프링의 boardService 인스턴스를
취하기
위해
이
클래스를
이용하는데
BoardServiceHelper 내에는
간단히 web.xml에서
정의
한 boardService 자바
빈을
취득해
자신을 CALL한
서블릿으로 BoardService 타입의 BoardServiceImple 객체를
리턴한다.
[BoardServiceHelper.java]
package onj.board.service;
import javax.servlet.ServletContext;
import
org.springframework.web.context.WebApplicationContext;
import
org.springframework.web.context.support.WebApplicationContextUtils;
public class BoardServiceHelper {
public
static BoardService getBoardService(ServletContext ctx) {
WebApplicationContext wac =
WebApplicationContextUtils
.getRequiredWebApplicationContext(ctx);
//boardConfig.xml에
정의된 boardService 빈을
리턴
//이
부분은
게시물
미리보기
서블릿(ContentPreview)에서
스프링의
인스턴스를
얻을
때
이용
return (BoardService) wac.getBean("boardService");
}
}
[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);
}
[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);
}
}
7.
이번에는 미리 보기 기능의 핵심기능을 구현하는 서블릿을 만들자.
이 서블릿에서는 스프링 프레임워크의 자바 빈, web.xml에서 boardService로 정의된 BoardService
타입의 BoardServiceImple 객체를 취하기 위해
BoardServiceHelper를 이용했다.
[ContentPreview.java]
package onj.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 onj.board.service.BoardService;
import onj.board.service.BoardServiceHelper;
//Servlet3.0이상, Tomcat7 이상에서는
애노테이션으로
서블릿
정의가
가능하다.
//@WebServlet(urlPatterns = "/preView")
public class ContentPreview extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
String seq =
req.getParameter("seq");
req.setCharacterEncoding("utf-8");
res.setContentType("text/html; charset=utf-8");
res.setHeader("Cache-Control", "no-cache");
BoardService boardService =
BoardServiceHelper.getBoardService(getServletContext());
PrintWriter out =
res.getWriter();
out.println("<pre>" + boardService.preView(seq) + "<pre>");
}
}
8.
작성된 기능 확인 및 이클립스 구조확인
:namespace prefix = v ns = "urn:schemas-microsoft-com:vml"
/><?XML:NAMESPACE PREFIX = V /><v:f
eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1
0"></v:f><v:f eqn="sum 0 0
@1"></v:f><v:f eqn="prod @2 1
2"></v:f><v:f eqn="prod @3 21600
pixelWidth"></v:f><v:f eqn="prod @3
21600 pixelHeight"></v:f><v:f
eqn="sum @0 0 1"></v:f><v:f
eqn="prod @6 1 2"></v:f><v:f
eqn="prod @7 21600
pixelWidth"></v:f><v:f eqn="sum @8
21600 0"></v:f><v:f eqn="prod @7
21600 pixelHeight"></v:f><v:f
eqn="sum @10 21600 0"></v:f><o:lock
v:ext="edit" aspectratio="t"></o:lock>
현재까지
만들어진 이클립스 구조
(게시판 리스트보기 + 게시물
본문내용 미리 보기)
댓글 없음:
댓글 쓰기