A. Srping Framework 게시판 만들기 (리스트,페이징,검색) , 스프링 게시판 소스, 리스트보기, 스프링공부, Spring학원
1. 시작하기
- 이클립스
프로젝트명(Context명)은 onjboard1
- 이클립스 STS
Plug-In을 설치 하였으며 MAVEN, MAVEN Plug-In도 설치하였음
- Spring MVC
Project를 작성(프로젝트 이름은 onjboard1)
- Spring Version은
3.2.3
- 오라클에 접속하여 scott
계정에서 게시판용 테이블 및 데이터 2건 만들자
--
게시판
-- 게시글번호,
작성자, 비밀번호, 글제목, 글내용, 파일이름, 작성일, 조회수
create table
board02(
seq
varchar2(1000),
name
varchar2(20) not null,
passwd
varchar2(20) not null,
title
varchar2(500)not null,
content clob
not null,
filename
varchar2(100)not null,
regdate date
default sysdate,
readcount number(10)
default 0,
constraint b_seq_pk
primary key(seq)
);
create sequence
sequence_board_seq
start with 1 increment
by 1;
--
댓글
-- 댓글 입력한
게시글 번호, 댓글 깊이, 댓글 출력순서
create table
reply(
reply
varchar2(1000) not null,
reply_step
number(10) default 0,
reply_level
number(10) default 0,
constraint
reply_seq_fk foreign key(reply) references board02(seq)
);
--
코멘트
-- 코멘트 입력
번호, 코멘트 작성자, 코멘트 내용, 코멘트 입력된 게시글번호
create table
comment_t02(
comment_seq
varchar2(1000),
comment_name
varchar2(20) not null,
comment_comm
varchar2(4000) not null,
seq
varchar2(1000) not null,
constraint
comment_t_comment_seq_pk primary key(comment_seq),
constraint
comment_t_seq_fk foreign key(seq) references board02(seq)
);
create sequence
sequence_comment_seq
start with 1 increment
by 1;
INSERT
ALL
INTO board02
VALUES(sequence_board_seq.nextval,name,passwd,title,content,filename,regdate,readcount)
INTO reply
VALUES(sequence_board_seq.currval,reply_step,reply_level)
SELECT '오엔제이' AS name,
'1111' AS passwd, '질문입니다.' AS title, 'SQL을 배울 수 있느 과정이 뭐죠??'AS content, ' ' As
filename, SYSDATE AS regdate, 0 AS readcount,
0 AS reply_step,
0 AS reply_level
FROM
DUAL;
INSERT
ALL
INTO board02
VALUES(sequence_board_seq.nextval,name,passwd,title,content,filename,regdate,readcount)
INTO reply
VALUES(sequence_board_seq.currval,reply_step,reply_level)
SELECT '오엔제이2' AS name,
'1111' AS passwd, 'JAVA 질문입니다.' AS title, 'JAVA을 배울 수 있느 과정이 뭐죠??'AS content, '
' As filename, SYSDATE AS regdate, 0 AS readcount,
0 AS reply_step,
0 AS reply_level
FROM
DUAL;
commit;
2. /WEB-INF/web.xml 만들기
<?xml version="1.0"
encoding="UTF-8"?>
<web-app
version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<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>
<!--
Creates the Spring Container shared by all Servlets and Filters
-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--
The definition of the Root Spring Container shared by all Servlets and Filters
-->
<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>
<!--
Processes application requests -->
<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>
</web-app>
3.
/WEB-INF/spring/appServlet/servlet-context.xml
<?xml version="1.0"
encoding="UTF-8"?>
<beans:beans
xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!-- Handles HTTP GET
requests for /resources/** by efficiently serving up static resources in the
${webappRoot}/resources directory -->
<resources
mapping="/resources/**" location="/resources/" />
<beans:bean
id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<beans:property
name="driverClassName"
value="oracle.jdbc.driver.OracleDriver"/>
<beans:property
name="url"
value="jdbc:oracle:thin:@localhost:1521:ex"/>
<beans:property
name="username" value="study"/>
<beans:property
name="password" value="study"/>
</beans:bean>
<!-- Resolves views
selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views
directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property
name="prefix" value="/WEB-INF/jsp/"/>
<beans:property
name="suffix" value=".jsp" />
</beans:bean>
<!-- 넘어오는 URL에 따라 컨트롤러에서
실행될 메소드 매핑 -->
<!--
PropertiesMethodNameResolver는 prop key로 넘어오는 url에 대해 실행할 컨트롤러의 메소드 정의
-->
<beans:bean
id="userControllerMethodNameResolver"
class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
<beans:property
name="mappings">
<beans:props>
<beans:prop
key="/list.html">list</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<!--
controller mapping -->
<beans:bean
name="/list.html"
class="com.onj.board.BoardMultiController">
<beans:property
name="methodNameResolver"
ref="userControllerMethodNameResolver"/>
<beans:property
name="boardService" ref="boardService"/>
<beans:property
name="pageHandler" ref="pageHandler"/>
</beans:bean>
</beans:beans>
4.
/WEB-INF/spring/boardConfig.xml
<?xml version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="boardDAO"
class="com.board.dao.BoardDAOImple">
<property
name="dataSource">
<ref
bean="dataSource"/>
</property>
</bean>
<bean id="boardService"
class="com.board.service.BoardServiceImple">
<property
name="boardDAO">
<ref
bean="boardDAO"/>
</property>
</bean>
<bean id="pageHandler"
class="com.board.util.PageHandler">
<property
name="boardDAO">
<ref
bean="boardDAO"/>
</property>
</bean>
</beans>
5. [BoardDTO.java]
package
com.board.model;
public class BoardDTO
{
private String
seq;
private String
name;
private String
passwd;
private String
title;
private String
content;
private String
filename;
private String
regdate;
private int
readcount;
private String
reply;
private int
reply_step;
private int
reply_level;
public
BoardDTO(){};
public BoardDTO(String seq,
String name, String title, String regdate, int readcount,
int reply_level)
{
super();
this.seq =
seq;
this.name =
name;
this.title =
title;
this.regdate =
regdate;
this.readcount =
readcount;
this.reply_level =
reply_level;
}
public String getSeq()
{
return
seq;
}
public void setSeq(String
seq) {
this.seq =
seq;
}
public String getName()
{
return
name;
}
public void setName(String
name) {
this.name =
name;
}
public String getPasswd()
{
return
passwd;
}
public void
setPasswd(String passwd) {
this.passwd =
passwd;
}
public String getTitle()
{
return
title;
}
public void setTitle(String
title) {
this.title =
title;
}
public String getContent()
{
return
content;
}
public void
setContent(String content) {
this.content =
content;
}
public String getFilename()
{
return
filename;
}
public void
setFilename(String filename) {
this.filename =
filename;
}
public String getRegdate()
{
return
regdate;
}
public void
setRegdate(String regdate) {
this.regdate =
regdate;
}
public int getReadcount()
{
return
readcount;
}
public void
setReadcount(int readcount) {
this.readcount =
readcount;
}
public String getReply()
{
return
reply;
}
public void setReply(String
reply) {
this.reply =
reply;
}
public int getReply_step()
{
return
reply_step;
}
public void
setReply_step(int reply_step) {
this.reply_step =
reply_step;
}
public int getReply_level()
{
return
reply_level;
}
public void
setReply_level(int reply_level) {
this.reply_level =
reply_level;
}
}
6.
[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;
}
------------------------------------------------------------------------------------------
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;
}
}
7.
[EncodingHandler.java], [PageHandler.java]
package
com.board.util;
import
java.io.UnsupportedEncodingException;
public class
EncodingHandler {
public static String
toKor(String str){
String s =
null;
try{
s = new
String(str.getBytes("8859_1"),"euc-kr");
}catch(UnsupportedEncodingException
e){e.printStackTrace();}
return s;
}
}
------------------------------------------------------------------------------------------
package
com.board.util;
import
java.util.ArrayList;
import
java.util.List;
import
java.util.Map;
import
com.board.dao.BoardDAO;
public class
PageHandler {
private BoardDAO
boardDAO;
public void
setBoardDAO(BoardDAO boardDAO){this.boardDAO = boardDAO;}
// 페이지
사이즈, 페이지 그룹
private final int PAGESIZE
= 3;
private final int PAGEGROUP
= 5;
// 전체
게시글 수
public int
boardAllNumber(Map<String, Object>searchMap)throws
Exception{
int count =
boardDAO.boardCount(searchMap);
return
count;
}
// 페이지
갯수
public int
boardPageCount(Map<String, Object>searchMap)throws
Exception{
int pageCount =
boardAllNumber(searchMap) / PAGESIZE;
if(boardAllNumber(searchMap) % PAGESIZE
!=0){pageCount++;}
return
pageCount;
}
//
startPage
public int
boardStartPage(int pageNum)throws Exception{
int startPage = (pageNum -
1) / PAGEGROUP * PAGEGROUP +1;
return
startPage;
}
//
endPage
public int boardEndPage(int
pageNum, Map<String, Object>searchMap)throws Exception{
int endPage =
boardStartPage(pageNum)+ (PAGEGROUP-1);
if(endPage >
boardPageCount(searchMap)){ endPage = boardPageCount(searchMap); }
return
endPage;
}
// 처음,
마지막 rowNumber
public List<Object>
boardSetPageNumber(int pageNum)throws Exception{
List<Object> list =
new ArrayList<Object>();
int endRow =
PAGESIZE*pageNum;
int startRow = endRow -
PAGESIZE+1;
list.add(startRow);
list.add(endRow);
return
list;
}
}
8.
[BoardService.java],[BoardServiceImple.java]
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;
}
------------------------------------------------------------------------------------------
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);
}
}
9. [BoardMultiController.java]
package
com.onj.board;
import
java.util.ArrayList;
import
java.util.HashMap;
import
java.util.List;
import
java.util.Map;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
import
org.springframework.web.servlet.ModelAndView;
import
org.springframework.web.servlet.mvc.multiaction.MultiActionController;
import
com.board.model.BoardDTO;
import
com.board.service.BoardService;
import
com.board.util.EncodingHandler;
import
com.board.util.PageHandler;
public class
BoardMultiController extends MultiActionController{
private BoardService
boardService;
private PageHandler
pageHandler;
public void
setBoardService(BoardService boardService){this.boardService =
boardService;}
public void
setPageHandler(PageHandler pageHandler) {this.pageHandler = pageHandler;}
ModelAndView mav =
null;
// 게시판
리스트
public ModelAndView
list(HttpServletRequest request, HttpServletResponse response)throws
Exception{
mav = new
ModelAndView();
List<BoardDTO> list =
null;
//
검색select , 검색Text
String boardListSelect =
request.getParameter("boardListSelect");
String boardListSearchText
=
request.getParameter("boardListSearchText");
Map<String, Object>
searchMap = new HashMap<String, Object>();
if(boardListSearchText !=
null){
searchMap.put("boardListSearchText",
EncodingHandler.toKor(boardListSearchText));
searchMap.put("boardListSelect",
boardListSelect);
}
String pageNumber =
request.getParameter("pageNumber");
int pageNum =
1;
if(pageNumber !=
null){pageNum = Integer.parseInt(pageNumber);}
// 게시글
수
int totalCount =
pageHandler.boardAllNumber(searchMap);
// 페이지
갯수
int totalPageCount =
pageHandler.boardPageCount(searchMap);
// startPage ,
endPage
int startPage =
pageHandler.boardStartPage(pageNum);
int endPage =
pageHandler.boardEndPage(pageNum,searchMap);
// 처음,
마지막 rowNumber
List<Object>
rowNumberList = new ArrayList<Object> ();
rowNumberList =
pageHandler.boardSetPageNumber(pageNum);
searchMap.put("startRow",
rowNumberList.get(0));
searchMap.put("endRow",
rowNumberList.get(1));
// 글 전체
출력
list =
boardService.boardList(searchMap);
mav.addObject("pageNumber",pageNum);
mav.addObject("boardCount",totalCount);
mav.addObject("totalPageCount",
totalPageCount);
mav.addObject("startPage",
startPage);
mav.addObject("endPage",
endPage);
mav.addObject("list",
list);
mav.setViewName("list");
return
mav;
}
}
10. [WEB-INF/jsp/list.jsp], [/js/boardActionJs.js],
[/css/boardCss.css]
<%@ 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>
<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="">${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>
</span>
</c:when>
<c:otherwise>
<span>
<a
href="/board/list.html?pageNumber=${i}">${i}</a>
</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>
------------------------------------------------------------------------------------------
//
검색
function
boardListSearchGo(){
document.listForm.action
="/board/list.html";
document.listForm.submit();
}
//
검색Text입력 후 바로 엔터 가능하게 하는 이벤트
function
enterEvent(){
if(window.event.keyCode ==
13){
boardListSearchGo();
}
}
------------------------------------------------------------------------------------------
@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;}
댓글 없음:
댓글 쓰기