48일차
답변형 게시판
ReboardController.java
package kr.co.khi.controller;
import java.util.*;
import kr.co.khi.dao.*;
import kr.co.khi.dto.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
import org.springframework.ui.*;
import org.springframework.validation.*;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/re")
// 안쪽에 적은 RequestMapping은 /re 이후의 주소이다.
public class ReboardController {
@Autowired
private ReboardDao dao;
// /re/list 란 주소가 된다.
@RequestMapping(value = "/list")
public String list(@ModelAttribute("item") ReboardDto dto, ModelMap map) {
int page = 1; // 현재 페이지
int pageSize = 7; // 페이지당 글 개수
int firstRow = 0; // 보여질 첫번째 글순서
int lastRow = 0; // 보여질 마지막 글순서
int totSize = 0; // 전체 글 개수
int totPage = 0; // 전체 페이지수
String strPage = dto.getPage();
// null 처리 : /bd/list 로 호출시 page 에는 null 이 들어옴
if (strPage != null && !"".equals(strPage))
page = Integer.parseInt(strPage);
lastRow = page * pageSize;
firstRow = lastRow - (pageSize - 1);
// firstRow = (page-1) * pageSize + 1;
dto.setFirstRow(firstRow);
dto.setLastRow(lastRow);
totSize = dao.getTotSize(dto);
totPage = (totSize - 1) / pageSize + 1;
List<ReboardDto> list = dao.getList(dto);
map.addAttribute("list", list);
map.addAttribute("page", page);
map.addAttribute("totPage", totPage);
return "reboard/list";
}
@RequestMapping(value = "/create", method = RequestMethod.GET)
public String precreate() {
return "reboard/update";
}
// create 를 POST 방식으로 받게끔
// public String create(ReboardDto dto) 해서 dao.create 하세요
@RequestMapping(value = "/create", method = RequestMethod.POST)
public String create(ReboardDto dto) {
if (dao.create(dto))
System.out.println("삽입완료");
return "redirect:/re/list";
}
// 주소로 모든 자원에 접근할 수 있게끔 해주는 방식 : RESTful 방식
@RequestMapping(value = "/read/{no}", method = { RequestMethod.GET,
RequestMethod.POST })
public String read(@PathVariable String no, ModelMap map) {
if (dao.addRcount(no)) {
ReboardDto dto = dao.read(no);
map.addAttribute("item", dto);
}
return "reboard/read";
}
@RequestMapping(value = "/update/{no}", method = RequestMethod.GET)
public String preupdate(@PathVariable String no, ModelMap map) {
map.addAttribute("item", dao.read(no));
return "reboard/update";
}
@RequestMapping(value = "/update", method = RequestMethod.POST)
public String update(ReboardDto dto) {
if (dao.update(dto)) {
System.out.println("수정완료");
}
return "redirect:/re/list";
}
@RequestMapping(value = "/reply/{no}", method = RequestMethod.GET)
public String prereply(@PathVariable String no, ModelMap map) {
ReboardDto dto = dao.read(no);
// 수정과 차별하기 위해서 writer(혹은 no)를 없앤다.
dto.setWriter("");
dto.setTitle("RE: " + dto.getTitle());
dto.setContent("-----원본글 내용-----<br />" + dto.getContent()
+ "<br />-----원본글 끝-----<br />");
map.addAttribute("item", dto);
return "reboard/update";
}
@RequestMapping(value = "/reply", method = RequestMethod.POST)
public String reply(ReboardDto dto) {
dao.reply(dto);
return "redirect:/re/list";
}
}
ReboardDao.java
package kr.co.khi.dao;
import java.util.*;
import kr.co.khi.dto.*;
import org.apache.ibatis.session.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
@Repository
public class ReboardDao {
@Autowired private SqlSession mapper;
public int getTotSize(ReboardDto dto) {
return mapper.selectOne("reboard.getTotSize",dto);
}
public List<ReboardDto> getList(ReboardDto dto) {
return mapper.selectList("reboard.getList", dto);
}
public boolean create(ReboardDto dto) {
return mapper.insert("reboard.create",dto) > 0;
}
public ReboardDto read(String no) {
return mapper.selectOne("reboard.read",no);
}
public boolean addRcount(String no) {
return mapper.update("reboard.addRcount",no) > 0;
}
public boolean update(ReboardDto dto) {
return mapper.update("reboard.update",dto) > 0;
}
public void reply(ReboardDto dto) {
// transaction 처리 필요
// update step+1(원본글보다 큰건 다 +1)
mapper.update("reboard.addStep",dto);
// insert
mapper.insert("reboard.reply",dto);
}
}
ReboardDto.java
package kr.co.khi.dto;
public class ReboardDto {
private String no;
private String title;
private String content;
private String writer;
private String wdate;
private String rcount;
private int step;
private int depth;
private String ref;
// 테이블에 없는 것들
private String page;
private int firstRow;
private int lastRow;
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
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 getWriter() {
return writer;
}
public void setWriter(String writer) {
this.writer = writer;
}
public String getWdate() {
return wdate;
}
public void setWdate(String wdate) {
this.wdate = wdate;
}
public String getRcount() {
return rcount;
}
public void setRcount(String rcount) {
this.rcount = rcount;
}
public int getStep() {
return step;
}
public void setStep(int step) {
this.step = step;
}
public int getDepth() {
return depth;
}
public void setDepth(int depth) {
this.depth = depth;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public int getFirstRow() {
return firstRow;
}
public void setFirstRow(int firstRow) {
this.firstRow = firstRow;
}
public int getLastRow() {
return lastRow;
}
public void setLastRow(int lastRow) {
this.lastRow = lastRow;
}
}
reboard.xml
<?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="reboard"> <!-- namespace 는 중복 안됨 -->
<select id="getTotSize" resultType="int" parameterType="kr.co.khi.dto.ReboardDto">
select
count(no) from reboard
</select>
<select id="getList" resultType="kr.co.khi.dto.ReboardDto"
parameterType="kr.co.khi.dto.ReboardDto">
select * from reboard order by ref desc, step asc
</select>
<insert id="create" parameterType="kr.co.khi.dto.ReboardDto">
insert into
reboard(no,title,content,writer,step,depth,ref)
values(seq_re.nextval, #{title}, #{content}, #{writer},0,0,seq_re.currval)
</insert>
<select id="read" resultType="kr.co.khi.dto.ReboardDto"
parameterType="string">
select * from reboard where no=#{value}
</select>
<update id="addRcount" parameterType="string">
update reboard set rcount =
rcount + 1 where no = #{value}
</update>
<update id="update" parameterType="kr.co.khi.dto.ReboardDto">
update reboard set
title = #{title}
,content = #{content}
where no = #{no}
</update>
<update id="addStep" parameterType="kr.co.khi.dto.ReboardDto">
update reboard set step = step + 1
where ref = #{ref} and step > #{step}
<!-- 이렇게 넣을수도 있다.
<![CDATA[ update reboard set step = step + 1 where ref=#{ref}
and step > #{step} ]]> -->
</update>
<insert id="reply" parameterType="kr.co.khi.dto.ReboardDto">
insert into
reboard(no,title,content,writer,step,depth,ref)
values(seq_re.nextval, #{title}, #{content}, #{writer}
,#{step}+1,#{depth}+1,#{ref})
</insert>
</mapper>
list.jsp
<?xml version="1.0" encoding="UTF-8" ?>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>게시판 목록</title>
<style type="text/css">
.mainouter {
background-image:
url("http://cfs.tistory.com/custom/blog/92/928179/skin/images/");
}
.footer {
background-image:
url("http://cfs.tistory.com/custom/blog/92/928179/skin/images/");
}
.myBoard th {
text-align: center;
border-style: none;
border-color: #c55;
padding: 7px 3px;
}
.myBoard td {
text-align: center;
border-style: none;
border-color: #c55;
padding: 6px;
}
.myBoard tr {
border-style: dashed;
border-color: #c55;
background-color: #fff4f4;
}
#line td {
}
/* 아직 안가본 곳, 가본 곳 */
/*
.myBoard a:LINK, .myBoard a:VISITED {
text-decoration: none; color: black;
}
*/
.myBoard a:HOVER { /* 마우스 커서 올렸을때 */
text-decoration: underline;
color: #366;
font-weight: bold;
}
.myBoard a:ACTIVE { /* 마우스 버튼을 눌렀을때 */
text-decoration: none;
color: black;
}
</style>
<script type="text/javascript">
function init() {
no = setInterval(setTime, 1000);
}
function setTime() {
var target = document.getElementById('target');
var date = new Date();
target.innerHTML = date.toLocaleString();
}
function doList(page) {
document.forms['listForm'].page.value = page;
document.forms['listForm'].submit();
}
function doRead(no) {
var f = document.forms['listForm'];
f.action = '<%=cp%>
/re/read/' + no;
f.submit();
}
</script>
</head>
<body onload="init();">
<form action="<%=cp%>/re/list" name="listForm">
<input type="hidden" name="key" value="${param.key }" />
<%
String value = request.getParameter("value") == null ? "" : request
.getParameter("value");
if (value != null && !"".equals(value))
value = new String(value.getBytes("iso-8859-1"), "UTF-8");
%>
<input type="hidden" name="value" value="<%=value%>" /> <input
type="hidden" name="page" value="${param.page }" />
</form>
<div class="mainouter" align="center">
<h1>게시판 목록</h1>
<div style="width: 640px;" align="left">
<p>
<a href="<%=cp%>/re/create"><input type="button" value="글쓰기" /></a>
</p>
</div>
<table class="myBoard" width="640" border="3">
<tr style="background-color: #fcc">
<th width="10%">글번호</th>
<th width="36%">글제목</th>
<th width="15%">글쓴이</th>
<th width="29%">작성일</th>
<th width="10%">조회수</th>
</tr>
<!-- <tr id="line" style="height: 1px;"> -->
<!-- <td colspan="5" bgcolor="#c55"></td> -->
<!-- </tr> -->
<c:forEach var="item" items="${list }">
<tr>
<td>${item.no }</td>
<%-- <td style="text-align: left; padding-left: 20px;"><a href="<%=cp %>/re/read?no=${item.no}"> ${item.title } (<span style="color: red;">${item.replycount}</span>)</a></td> --%>
<td style="text-align: left; padding-left: 20px;"><a
href="javascript:doRead('${item.no}');"> ${item.title } </a></td>
<td>${item.writer }</td>
<td>${item.wdate }</td>
<td>${item.rcount }</td>
</tr>
</c:forEach>
<!-- <tr id="line" style="height: 1px;"> -->
<!-- <td colspan="5" bgcolor="#c55"></td> -->
<!-- </tr> -->
<tr>
<td colspan="5" align="center">< <c:forEach var="i"
begin="1" end="${totPage }">
<c:if test="${page != i }">
<!-- 현재 페이지가 아닐때 -->
<a href="javascript:doList('${i }');">${i }</a>
</c:if>
<c:if test="${page == i }">
<!-- 현재 페이지 -->
<span style="font-weight: bold; color: red;">${i }</span>
</c:if>
</c:forEach> >
</td>
</tr>
<tr>
<td colspan="5" align="center">
<form action="<%=cp%>/re/list">
<select name="key">
<option value="title">제목</option>
<option value="content">내용</option>
<option value="writer">글쓴이</option>
</select> <input type="text" name="value" /> <input type="submit"
value="검색" />
</form>
</td>
</tr>
</table>
</div>
<div align="right" style="padding-right: 20px;">
<h5 id="target"></h5>
</div>
<div id="footer">
<img
src="http://cfs.tistory.com/custom/blog/92/928179/skin/images/Java7.png"
alt="백그라운드" />
</div>
</body>
</html>
read.jsp
<?xml version="1.0" encoding="UTF-8" ?>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>게시물 보기</title>
<link type="text/css"
href="/pp/css/custom-theme/jquery-ui-1.8.23.custom.css"
rel="stylesheet" />
<script type="text/javascript" src="/pp/js/jquery-1.8.0.min.js"></script>
<script type="text/javascript"
src="/pp/js/jquery-ui-1.8.23.custom.min.js"></script>
<script type="text/javascript" src="/pp/js/jquery.ui.datepicker-ko.js"></script>
<script type="text/javascript">
function doList() {
document.forms['listForm'].submit();
}
</script>
<style type="text/css">
#content {
border-style: dotted;
border-color: #3aa;
padding: 10px;
}
#rp_content {
width: 440px;
border-style: double;
border-color: #8cc;
padding: 10px;
}
#rp_head {
background-color: #fcc;
}
</style>
</head>
<body>
<form action="<%=cp%>/re/list" name="listForm">
<input type="hidden" name="key" value="${param.key }" />
<%
String value = request.getParameter("value") == null ? "" : request
.getParameter("value");
if (value != null && !"".equals(value))
value = new String(value.getBytes("iso-8859-1"), "UTF-8");
%>
<input type="hidden" name="value" value="<%=value%>" /> <input
type="hidden" name="page" value="${param.page }" />
</form>
번호 : ${item.no }
<br /> 제목 : ${item.title }
<br /> 글쓴이 : ${item.writer }
<br /> 작성일 : ${item.wdate }
<br /> 조회수 : ${item.rcount }
<br />
<br /> 내용 :
<br />
<div id="content">
<p>
${item.content } <br />
</p>
</div>
<p align="left">
<input type="button" value="목록" onclick="doList();" /> <input
type="button" value="수정"
onclick="location.href='<%=cp %>/re/update/${item.no }'" /> <input
type="button" value="답글"
onclick="location.href='<%=cp %>/re/reply/${item.no }'" /> <input
type="button" value="삭제"
onclick="location.href='<%=cp %>/re/delete/${item.no }'" />
</p>
</body>
</html>
update.jsp
<?xml version="1.0" encoding="UTF-8" ?>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<% String cp = request.getContextPath(); %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>글쓰기 / 수정</title>
<!-- ck editor 사용 위한 세팅 -->
<script type="text/javascript" src="/pp/ckeditor/ckeditor.js"></script>
<!-- -->
</head>
<body>
<c:if test="${not empty item && not empty item.writer}">
<!-- item 이 비어있지 않으면 -->
<h1>게시판 수정</h1>
<form action="<%=cp%>/re/update" method="post">
<input type="hidden" name="no" value="${item.no }" />
</c:if>
<c:if test="${not empty item && empty item.writer }">
<!-- item 이 비어있으면 -->
<h1>게시판 답변</h1>
<form action="<%=cp%>/re/reply" method="post">
<input type="hidden" name="step" value="${item.step }" /> <input
type="hidden" name="depth" value="${item.depth }" /> <input
type="hidden" name="ref" value="${item.ref }" />
</c:if>
<c:if test="${empty item }">
<!-- item 이 비어있으면 -->
<h1>게시판 쓰기</h1>
<form action="<%=cp%>/re/create" method="post">
</c:if>
<!--
<c:choose>
<c:when test="">
</c:when>
</c:choose>
-->
<div>
제목 : <input type="text" name="title" value="${item.title }" />
</div>
<div>
글쓴이 : <input type="text" name="writer" value="${item.writer }" />
</div>
<div>
파일첨부 : <input type="file" name="file" />
</div>
<br />
<div>
<label for="content">내용 </label><br />
<!-- ck editor 사용 위한 세팅 -->
<textarea rows="10" cols="60" name="content" id="content">${item.content }</textarea>
<script type="text/javascript">
CKEDITOR.replace('content');
</script>
<!-- -->
</div>
<div>
<input type="submit" value="저장" /> <input type="button" value="목록"
onclick="location.href='<%=cp %>/re/list'" />
</div>
</form>
</body>
</html>
ModelMap을 쓰면 테스트를 할때 request mock(목)객체를 쓸 필요가 없어서 좋다.
( ModelMap 객체는 만들기 쉽다. )
// 주소로 모든 자원에 접근할 수 있게끔 해주는 방식 : RESTful 방식
@RequestMapping(value="/read/{cat}/{no}",method={RequestMethod.GET,RequestMethod.POST})
public String read(@PathVariable String cat, @PathVariable String no, ModelMap map) {
return "reboard/read";
}
ReboardController
create, read, preupdate, update 만들었음
답변쓰기
xml에서는 > 등의 부등호 표시 쓸 수 없음
> 이런식으로 쓰는 방법
<![CDATA[>]]> 이런 식으로 쓰는 방법 두가지 있음
'Dev. 640시간 뭉개기 > 강의내용정리' 카테고리의 다른 글
[WEB/SPRING] 50일차 - include, 게시판 페이징 기능, 로그인/로그아웃시 원래 화면 그대로 가기, 동적쿼리(dynamic query)만들기 (0) | 2012.12.03 |
---|---|
[SPRING/TILES] 49일차 - 웹화면구성 프레임워크(Tiles) (0) | 2012.12.03 |
[WEB/SPRING] 47일차 - 회원 로그인 기능 구현, 답변형 게시판 만들기 (0) | 2012.10.05 |
[WEB/SPRING] 46일차 - AbstractWizardFormController을 활용한 회원가입, 로그인 만들기 (0) | 2012.10.05 |
[WEB/SPRING] 45일차 - AbstractWizardFormController을 활용한 회원가입 만들기 (0) | 2012.10.05 |