7.(스프링4 게시판)[MyBatis적용,컨트롤러,Service,DAO,AOP로깅,AJAX,VIEW]Spring4 @MVC 게시판-멀티파일업로드,답변형,JSR303 @Valid,@Controller,@ModelAttribute,@SessionAttributes,어노테이션기반,마이바티스
1. 게시물 미리 보기용 서블릿
package onj.board.ajaxpreview;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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>");
}
}
2. Spring AOP구현체(로깅 Aspect)
package onj.board.aop;
import onj.board.dao.BoardDAO;
import onj.board.dao.LoggingDAO;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;
import org.springframework.beans.factory.annotation.Autowired;
@Aspect
public class LoggingAspect {
@Autowired
private LoggingDAO loggingDAO;
@Autowired
private BoardDAO boardDAO;
// 사후충고(반드시 정상 리턴 후 호출)
// SpringBoardDAO의 모든메소드중 파라미터가 1개 있는 메소드가 충고받을 포인트컷
// 본 게시판에는 리스트보기와 , getSql() 만 메소드 파라미터가 없어 충고 적용 안됨
@AfterReturning(pointcut="execution(* onj.board.dao.BoardDAOImpl.*(*))", returning="result")
public void logAfterReturning(JoinPoint joinPoint) {
System.out.println("<<<<<<<<< DAO 로깅 충고 실행");
loggingDAO.writeLog(joinPoint.getSignature().getName(), boardDAO.getSql());
}
}
3. 컨트롤러
package onj.board.controller;
import java.io.File;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import onj.board.model.BoardDTO;
import onj.board.model.CommentDTO;
import onj.board.service.BoardService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
@Controller
@SessionAttributes("read") //게시물읽기에서 읽은 게시물을 수정을 위해 세션에 보관
public class BoardMultiController {
@Autowired
private BoardService boardService;
// 게시판 리스트 보기, 페이징 기능은 구현 안함
@RequestMapping("/list")
public ModelAndView list() {
ModelAndView mv = new ModelAndView("list", "list",
boardService.boardList());
return mv;
}
// 게시글 읽기
@RequestMapping("/read")
public String read(@RequestParam("seq") String seq, Model model) {
// 게시물 한건 내용, "read"라는 이름으로 세션에 저장된다.(@SessionAttributes)
model.addAttribute("read", boardService.readContent(seq));
// comments(ArrayList에 CommentDTO가 담겨져 있다.)
model.addAttribute("comments", boardService.commentList(seq));
return "read";
}
// 커멘트쓰기
@RequestMapping("/comment")
public ModelAndView comment(@ModelAttribute CommentDTO commentDTO,
@ModelAttribute BoardDTO read) {
boardService.insertComment(commentDTO);
return new ModelAndView("redirect:/read.html?seq=" + read.getSeq());
}
// 게시판 글쓰기 화면
@RequestMapping(value = "/write", method = RequestMethod.GET)
public String write_view(Model model) {
if (!model.containsAttribute("uploadForm")) {
model.addAttribute("uploadForm", new BoardDTO());
}
return "write";
}
@RequestMapping(value = "/writeok", method = RequestMethod.POST)
public ModelAndView writeok(
@ModelAttribute("uploadForm") @Valid BoardDTO uploadForm ,
BindingResult result ) throws Exception {
if (result.hasErrors()) return new ModelAndView("write");
// 먼저 파일 업로드, 폴더는 미리 만드세요
// 스프링의 MultipartFile을 이용한 업로드
List<MultipartFile> files = uploadForm.getFiles();
if (null != files && files.size() > 0) {
int i = 0;
for (MultipartFile multipartFile : files) {
i++;
String fileName = multipartFile.getOriginalFilename();
if (!"".equals(fileName)) {
String path = "c:/java/project/spring4board/upload/"
+ fileName;
File f = new File(path);
multipartFile.transferTo(f);
if (i == 1) {
uploadForm.setFileName1(fileName);
} else if (i == 2) {
uploadForm.setFileName2(fileName);
} else if (i == 3) {
uploadForm.setFileName3(fileName);
}
}
}
}
boardService.insertBoard(uploadForm);
return new ModelAndView("redirect:/list.html");
}
// 게시글 수정, 세션에 있는 read 객체(BoardDTO, 게시물한건)가
// 사용자 파라미터 값을 받아 인자로 삽입된다.
@RequestMapping("/update")
public ModelAndView update(@ModelAttribute BoardDTO read) {
boardService.updateBoard(read);
return new ModelAndView("redirect:/read.html?seq=" + read.getSeq());
}
// 게시글 삭제
@RequestMapping("/delete")
public ModelAndView delete(@ModelAttribute BoardDTO read, HttpServletResponse res)
throws Exception {
int result = boardService.deleteBoard(read);
if (result != 1) {
PrintWriter out = res.getWriter();
out.println("<script>alert('password not correct');</script>");
out.println("<script>history.go(-1);</script>");
return null;
} else {
return new ModelAndView("redirect:/list.html");
}
}
// 게시물상세보기에서 답변 클릭시 호출되어 답변달 reply.jsp로 연결
@RequestMapping("/reply")
public String reply(Model model) {
if (!model.containsAttribute("replyForm")) {
model.addAttribute("replyForm", new BoardDTO());
}
return "reply";
}
// 답글 저장
@RequestMapping("/replyok")
public ModelAndView replyok(@ModelAttribute("replyForm") @Valid BoardDTO replyForm,
BindingResult result) {
if (result.hasErrors()) return new ModelAndView("reply");
boardService.replyBoard(replyForm);
return new ModelAndView("redirect:/list.html");
}
}
4. DAO단 인터페이스, 클래스
package onj.board.dao;
import java.util.List;
import onj.board.model.BoardDTO;
import onj.board.model.CommentDTO;
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;
//Comment저장
public int insertComment(CommentDTO commentDTO) throws DataAccessException ;
//Comment조회
public List<CommentDTO> commentList(String seq) throws DataAccessException;
//게시글 입력
public int insertBoard(BoardDTO board) throws DataAccessException;
//글 수정
public int updateBoard(BoardDTO board) throws DataAccessException;
//글 삭제
public int deleteBoard(BoardDTO boardDTO) throws DataAccessException;
//현재 답변의 단 게시물 보다 더 높은 스텝의 게시물이 있다면 스탭을 하나씩 상승시킴
public void replyBoardStep(BoardDTO board) throws DataAccessException;
//답글 달기
public int replyBoard(BoardDTO board) throws DataAccessException;
//SQL리턴용
public String getSql();
}
package onj.board.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.annotation.Resource;
import javax.sql.DataSource;
import onj.board.model.BoardDTO;
import onj.board.model.CommentDTO;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlProvider;
import org.springframework.stereotype.Repository;
//아래 SqlProvider는 jdbcTemplate이 실행될 때의 SQL문장을 받아내기 위하여 구현, getSql()
@Repository("boardDAO")
public class BoardDAOImpl implements BoardDAO, SqlProvider {
@Resource(name="sqlSession")
private SqlSession sqlSessionTemplate;
String sql = "";
@Autowired
private DataSource dataSource;
@Override
public String getSql() {
// TODO Auto-generated method stub
return sql;
}
// /게시판 전체 리스트 보기(list.html)
public List<BoardDTO> boardList() throws DataAccessException {
List<BoardDTO> boardList = null;
BoardDAO boardDao = sqlSessionTemplate.getMapper(BoardDAO.class);
boardList = boardDao.boardList();
return boardList;
}
// 게시물 본문내용 미리보기(/preView)
public String preView(String seq) throws DataAccessException {
String preContent;
BoardDAO boardDao = sqlSessionTemplate.getMapper(BoardDAO.class);
preContent = boardDao.preView(seq);
return preContent;
}
// 게시판 상세보기, 게시글 읽기
public BoardDTO readContent(String seq) throws DataAccessException {
BoardDTO boardDto = null;
BoardDAO boardDao = sqlSessionTemplate.getMapper(BoardDAO.class);
boardDto = boardDao.readContent(seq);
//글조회수 1증가
this.updateReadCount(new Integer(seq).toString());
return boardDto;
}
// 읽은 글의 조회수를 1증가
public int updateReadCount(String seq) throws DataAccessException {
int count = 0;
BoardDAO boardDao = sqlSessionTemplate.getMapper(BoardDAO.class);
count = boardDao.updateReadCount(seq);
return count;
}
// 커맨트 입력
public int insertComment(CommentDTO commentDTO) throws DataAccessException {
int re = 0;
BoardDAO boardDao = sqlSessionTemplate.getMapper(BoardDAO.class);
re = boardDao.insertComment(commentDTO);
return re;
}
// 커맨트 조회
public List<CommentDTO> commentList(String seq) throws DataAccessException {
List<CommentDTO> list = null;
BoardDAO boardDao = sqlSessionTemplate.getMapper(BoardDAO.class);
list = boardDao.commentList(seq);
return list;
}
// 글쓰기
public int insertBoard(BoardDTO board) throws DataAccessException {
int re = 0;
BoardDAO boardDao = sqlSessionTemplate.getMapper(BoardDAO.class);
re = boardDao.insertBoard(board);
return re;
}
// 게시글 수정
public int updateBoard(BoardDTO board) throws DataAccessException {
int re = 0;
BoardDAO boardDao = sqlSessionTemplate.getMapper(BoardDAO.class);
re = boardDao.updateBoard(board);
return re;
}
// 게시글 삭제
public int deleteBoard(BoardDTO boardDTO)
throws DataAccessException {
int re = 0;
BoardDAO boardDao = sqlSessionTemplate.getMapper(BoardDAO.class);
re = boardDao.deleteBoard(boardDTO);
return re;
}
//현재 답변의 단 게시물 보다 더 높은 스텝의 게시물이 있다면 스탭을 하나씩 상승시킴
public void replyBoardStep(BoardDTO boardDto) throws DataAccessException {
BoardDAO boardDao = sqlSessionTemplate.getMapper(BoardDAO.class);
boardDao.replyBoardStep(boardDto);
}
// 답글달기
public int replyBoard(BoardDTO boardDTO) throws DataAccessException {
int re = 0;
this.replyBoardStep(boardDTO);
BoardDAO boardDao = sqlSessionTemplate.getMapper(BoardDAO.class);
re = boardDao.replyBoard(boardDTO);
return re;
}
}
package onj.board.dao;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository("loggingDAO")
public class LoggingDAO {
private JdbcTemplate jdbcTemplate;
@Autowired
private DataSource dataSource;
public JdbcTemplate getTemplate() {
if (jdbcTemplate == null) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
return jdbcTemplate;
}
// DAO단 쿼리 로깅
public int writeLog(String mehtodName, String dml)
throws DataAccessException {
//로그용 테이블에 로그 저장
String sql = "insert into boardlog(method, sql, ilsi) values (? , ? ,sysdate) ";
Object[] obj = { mehtodName, dml };
return getTemplate().update(sql, obj);
}
}
5. 모델쪽 클래스
package onj.board.model;
import java.io.Serializable;
import java.util.List;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.web.multipart.MultipartFile;
public class BoardDTO implements Serializable {
private static final long serialVersionUID = 3297423984732894L;
private int seq;
@NotEmpty //Spring JSR303 Validation Check를 위한 어노테이션, 필수입력
private String name;
@NotEmpty
@Size(min = 1, max = 20) //들어올 값의 범위를 지정
private String passwd;
@NotEmpty
@Size(min = 1, max = 500)
private String title;
@NotEmpty
@Size(min = 1, max = 4000)
private String content;
private List<MultipartFile> files;
private String fileName1;
private String fileName2;
private String fileName3;
private String regdate;
private int readCount;
private int reply;
private int reply_step;
private int reply_level;
public BoardDTO() {}
public BoardDTO(String name, String passwd, String title, String content, String fileName1, String fileName2, String fileName3) {
this.name = name;
this.passwd = passwd;
this.title = title;
this.content = content;
this.fileName1 = fileName1;
this.fileName2 = fileName2;
this.fileName3 = fileName3;
}
public BoardDTO(String name, String passwd, String title, String content, String fileName1, String fileName2, String fileName3, int readCount) {
this.name = name;
this.passwd = passwd;
this.title = title;
this.content = content;
this.fileName1 = fileName1;
this.fileName2 = fileName2;
this.fileName3 = fileName3;
this.readCount = readCount;
}
public int getSeq() {
return seq;
}
public void setSeq(int 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 List<MultipartFile> getFiles() {
return files;
}
public void setFiles(List<MultipartFile> files) {
this.files = files;
}
public String getFileName1() {
return fileName1;
}
public void setFileName1(String fileName1) {
this.fileName1 = fileName1;
}
public String getFileName2() {
return fileName2;
}
public void setFileName2(String fileName2) {
this.fileName2 = fileName2;
}
public String getFileName3() {
return fileName3;
}
public void setFileName3(String fileName3) {
this.fileName3 = fileName3;
}
public String getRegdate() {
return regdate.substring(0, 10); //2013-07-15 형태
}
public void setRegDate(String regdate) {
this.regdate = regdate;
}
public int getReadCount() {
return readCount;
}
public void setReadCount(int readCount) {
this.readCount = readCount;
}
public int getReply() {
return reply;
}
public void setReply(int 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;
}
}
package onj.board.model;
public class CommentDTO {
public String seq; //게시글 번호
public String name; //이름
public String comment;//커맨트
public CommentDTO() {}
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 getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
}
6. 서비스계층 인터페이스, 클래스
package onj.board.service;
import java.util.List;
import onj.board.model.BoardDTO;
import onj.board.model.CommentDTO;
public interface BoardService {
//게시판 리스트 보기
public List<BoardDTO> boardList();
//게시물 미리보기
public String preView(String seq);
//게시판 본문 내용보기, 게시글 읽기
public BoardDTO readContent(String seq);
//커맨트 입력
public int insertComment(CommentDTO commentDTO);
//커맨트 조회
public List<CommentDTO> commentList(String seq);
//게시글 입력
public int insertBoard(BoardDTO board);
//게시글 수정
public int updateBoard(BoardDTO board);
//게시글 삭제
public int deleteBoard(BoardDTO board);
//답글 등록
public int replyBoard(BoardDTO board);
}
package onj.board.service;
import java.util.List;
import onj.board.dao.BoardDAO;
import onj.board.model.BoardDTO;
import onj.board.model.CommentDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("boardService")
public class BoardServiceImpl implements BoardService {
@Autowired
private 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);
}
//커맨트 입력
public int insertComment(CommentDTO commentDTO) {
return boardDAO.insertComment(commentDTO);
}
//커맨트 조회
public List<CommentDTO> commentList(String seq) {
return boardDAO.commentList(seq);
}
//게시글 입력
public int insertBoard(BoardDTO board) {
return boardDAO.insertBoard(board);
}
//게시글 수정
public int updateBoard(BoardDTO board) {
return boardDAO.updateBoard(board);
}
//게시글 삭제
public int deleteBoard(BoardDTO boardDTO) {
return boardDAO.deleteBoard(boardDTO);
}
//답글 등록
public int replyBoard(BoardDTO board){
return boardDAO.replyBoard(board);
}
}
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");
}
}
7. 뷰 역할을 하는 JSP들 (webapps/jsp/ 아래)
- delete.jsp
<%@ page contentType="text/html; charset=utf-8" language="java" %>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<html>
<head>
<title>오라클자바커뮤니티 멀티파일업로드 게시판<br>(글삭제)</title>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
<script>
function check(){
if(document.delform.passwd.value == ""){
alert("비밀번호를 입력하세요.");
return;
} else {
delform.submit();
}
}
</script>
</head>
<body>
<form:form method="post" name="delform" action="/spring4board/delete.html">
<table border="1" align="center">
<tr>
<td>비밀번호</td>
<td><input type="password" name="passwd"></td>
<td>
<input type="button" value="확인" onClick="check();">
<input name="button" type="reset" value="취소" ></td>
</tr>
</table>
<table align="center"><tr><td><a href="/spring4board/list.html">목록보기</a></td></tr></table>
<input type="hidden" name="seq" value="${param.seq}">
</form:form>
</body>
</html>
- list.jsp
<%@ page contentType="text/html; charset=utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<html>
<head>
<title>오라클자바커뮤니티 교육센터</title>
<style type="text/css">
.tooltip {
position: absolute;
z-index: 3;
background: #E8E8E8;
border: 1px solid #434343;
padding: 3px;
}
</style>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script language="javascript">
$(document).ready(function() {
// 모든 글의 a 태그에 마우스 오버 바인딩
$('a.article').mouseover(function(event) {
contentprev($(this).attr('id'), event);
});
});
// 마우스 오버시 바인딩 될 function
function contentprev(seq, event) {
var data_string = '';
$.ajax({
type : 'GET',
url : 'preView?' + 'seq=' + seq,
data : data_string,
//dataType: 'JSON',
dataType : 'text',
beforeSend : function() {
},
success : function(data) {
showlayer(data, event);
},
error : function(error) {
//alert(error.responseText);
}
});
}
// showlayer 가 호출된 후 전달받은 마우스 이벤트의 좌표로 레이어를 이동
function moveTooltip(event) {
var posX = event.pageX;
var posY = event.pageY + 20;
//alert(posX + ', ' + posY);
$('div.tooltip').css({
top : posY,
left : posX
});
}
// 기존 레이어를 삭제 후 새로 레이어를 생성
function showlayer(value, event) {
//
$('div.tooltip').remove();
$('<div class="tooltip">' + value.replace(/\r\n/gi, '<br>') + '</div>')
.appendTo('body');
moveTooltip(event);
}
// 레이어 삭제
function hidelayer() {
$('div.tooltip').remove();
}
</script>
</head>
<body>
<div style="width: 500px;">
<div style="float: right;">
<H3>오라클자바커뮤니티 멀티파일업로드 게시판<br>(글리스트보기)</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>
<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 class="article" id="${board.seq}"
href="read.html?seq=${board.seq}" onmouseout="hidelayer();"> ${board.title}</a>
</c:when>
<c:when test="${board.reply_step == 0}">
<a class="article" id="${board.seq}"
href="read.html?seq=${board.seq}" onmouseout="hidelayer();"> ${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>
- read.jsp
<%@ page contentType="text/html; charset=utf-8" language="java" errorPage="" %>
<%@ 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>
<script>
function write_ok(){
writeform.submit();
}
function update_ok(){
document.viewform.action = '/spring4board/update.html';
document.viewform.submit();
}
</script>
</head>
<body>
<div style="width:600px;">
<div style="float:enter;">
<table width="600" height="420" border="1" align="center">
<tr height="20"><h3>오라클자바커뮤니티 멀티파일업로드 게시판<br>(글읽기)</h3></tr>
<form name="viewform" method="post">
<input type="hidden" name="seq" value="${read.seq}">
<input type="hidden" name="passwd" value="${read.passwd}">
<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}">
<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" ></td>
</tr>
<tr align="center">
<td colspan="2"><textarea name="content" cols="80" rows="12" >${read.content}</textarea></td>
</tr>
<!-- 게시물 수정인 경우 업로드한 파일은 수정이 안됨 -->
<tr>
<td>* 파일1</td>
<td>:
<c:choose>
<c:when test="${read.fileName1 != null}">
${read.fileName1}
</c:when>
<c:when test="${read.fileName1 == null}">
파일 없음
</c:when>
</c:choose>
</td>
</tr>
<tr>
<td>* 파일2</td>
<td>:
<c:choose>
<c:when test="${read.fileName2 != null}">
${read.fileName2}
</c:when>
<c:when test="${read.fileName2 == null}">
파일 없음
</c:when>
</c:choose>
</td>
</tr>
<tr>
<td>* 파일3</td>
<td>:
<c:choose>
<c:when test="${read.fileName3 != null}">
${read.fileName3}
</c:when>
<c:when test="${read.fileName3 == null}">
파일 없음
</c:when>
</c:choose>
</td>
</tr>
<tr>
<td> </td>
<td><input name="button" type="button" onClick="location.href='/spring4board/reply.html?seq=${read.seq}'" value="답변">
|
<input name="button" type="button" onClick="update_ok()" value="수정">
<input name="button" type="button" onClick="location.href='/spring4board/jsp/delete.jsp?seq=${read.seq}'" value="삭제">
|
<input name="button" type="button" onClick="location.href='/spring4board/list.html'" value="목록"></td>
</tr>
</form>
<tr>
<td height="99" colspan="2">
<!-- BoardMultiController의 comment() 메소드 호출 -->
<form method="post" action="comment.html">
<table border="1">
<tr>
<td>이름 : </td>
<td><input type="text" name="name"></td>
<td>코멘트:</td>
<td><input type="text" name="comment"></td>
<td><input type="submit" name="Button" value="쓰기"></td>
</tr>
</table>
<input type="hidden" name="seq" value="${read.seq}">
</form>
<!-- 달려있는 커맨트 보기 -->
<table width="789" border="1">
<c:forEach var="comment" items="${comments}">
<tr>
<td width="42" align="center">*</td>
<td width="86">${comment.name}</td>
<td width="639">${comment.comment}</td>
</tr>
</c:forEach>
</table>
</td>
</tr>
</table>
<br><br>
<table><tr><td><tr><b>http://www.oraclejavacommunity.com</tr></td></tr></table>
</div>
</div>
</body>
</html>
- reply.jsp
<%@ page contentType="text/html; charset=utf-8" language="java" %>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<html>
<head>
<title>답변 달기</title>
</head>
<body>
<div style="width:600px;">
<form:form modelAttribute="replyForm" method="post" name="form" action="replyok.html">
<table><tr><td><h2>오라클자바커뮤니티 멀티파일업로드 게시판<br>(답글달기)</h2><tr><td></table>
<table width="600" height="277" border="1" align="center">
<tr>
<td width="120">* 이름</td>
<td width="480">: <form:input path="name" size="50"/></td>
</tr>
<tr><td colspan="2"><font color="red"><form:errors path="name"/></font></td></tr>
<tr>
<td>* 제목</td>
<td>:
<form:input path="title" value="Re: ${read.title}" size="50"/></td>
</tr>
<tr><td colspan="2"><font color="red"><form:errors path="title"/></font></td></tr>
<tr align="center">
<td colspan="2">
<form:textarea path="content" cols="80" rows="10" />
</td>
</tr>
<tr><td colspan="2"><font color="red"><form:errors path="content"/></font></td></tr>
<tr>
<td>* 비밀번호</td>
<td>:
<form:password path="passwd"/></td>
</tr>
<tr><td colspan="2"><font color="red"><form:errors path="passwd"/></font></td></tr>
<tr>
<td> </td>
<td><input type="submit" value="답변"> |
<input type="reset" value="취소">
<input type="button" onClick="location.href='/spring4board/list.html'" value="목록">
</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}">
</form:form>
</div>
<br><br>
<table><tr><td><tr><b>http://www.oraclejavacommunity.com</tr></td></tr></table>
</body>
</html>
- write.jsp
<%@ page contentType="text/html; charset=utf-8" language="java" %>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<html>
<head>
<title>게시물 쓰기</title>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
<!-- jquery로 파일 첨부 추가 -->
$(document).ready(function() {
//add more file components if Add is clicked
$('#addFile').click(function() {
var fileIndex = $('#fileview tr').length;
if (Number(fileIndex) >= '3') {
alert('FILE UPLOAD는 3개만 가능 합니다.');
return;
}
$('#fileview').append(
'<tr><td>'+
' <input type="file" name="files['+ fileIndex +']" />'+
'</td></tr>');
});
});
</script>
</head>
<body>
<H3>오라클자바커뮤니티 멀티파일업로드 게시판<br>(글쓰기)</H3>
<form:form method="post" action="writeok.html" name="form"
modelAttribute="uploadForm"
enctype="multipart/form-data">
<table width="580" height="277" border="1" align="center">
<tr>
<td width="100">* 이 름</td>
<td width="580">: <form:input path="name" size="50"/>
</td>
</tr>
<tr><td colspan="2"><font color="red"><form:errors path="name"/></font></td></tr>
<tr>
<td>* 제 목</td>
<td>: <form:input path="title" size="50"/>
</tr>
<tr><td colspan="2"><font color="red"><form:errors path="title"/></font></td></tr>
<tr align="center">
<td colspan="2">
<form:textarea path="content" cols="80" rows="10"/>
</td>
</tr>
<tr><td colspan="2"><font color="red"><form:errors path="content"/></font></td></tr>
<tr><input id="addFile" type="button" value="File Add" /> </tr>
<tr>
<td>* 파 일 : </td>
<td><table id="fileview">
<tr>
<td>
<input name="files[0]" type="file" />
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>* 비밀번호</td>
<td>: <form:password path="passwd"/></td>
</tr>
<tr><td colspan="2"><font color="red"><form:errors path="passwd"/></font></td></tr>
<tr>
<td> </td>
<td>
<input type="submit" value="저장"/>
<input type="reset" value="취소">
<input type="button" onClick="location.href='/spring4board/list.html'" value="목록">
</td>
</tr>
</table>
</form:form>
</body>
</html>
http://www.oraclejavacommunity.co.kr/bbs/board.php?bo_table=LecSpring&wr_id=437
평일주간[100%환급과정]
(8/25)C#4.0,WinForm,ADO.NET(8/25)안드로이드개발자과정
(8/25)SQL기초에서 Schema Object까지
(8/29)Spring,MyBatis,Hibernate실무과정
(8/29)자바기초JDBC,Servlet/JSP까지
(8/29)PL/SQL,ORACLE HINT,TUNING
(8/25)오라클자바채용확정교육
평일야간[개인80%환급]
(8/21)Spring, MyBatis, Hibernate
(8/21)HTML5,CSS3,Ajax,jQuery마스터
(8/21)C#,Network,ADO.NET,ASP.NET
(8/26)SQL기초에서실무까지
(8/26)안드로이드개발자과정
(8/28)자바JSP,jQuery,Spring,MyBatis
주말주간[개인80%환급]
(8/23)자바웹&스프링,마이바티스
(8/23)Spring, MyBatis, Hibernate
(8/23)SQL기초에서실무까지
(8/23)자바,네트워크,웹&스프링
(8/30)안드로이드개발자과정
(8/30)C#,ASP.NET마스터(8/30)웹퍼블리싱 마스터
주말야간[개인80%환급]
(8/23)SQL기초에서실무까지
(8/23)자바,네트워크,웹&스프링
댓글 없음:
댓글 쓰기