2014년 8월 18일 월요일

7.(스프링4 게시판)[MyBatis적용,컨트롤러,Service,DAO,AOP로깅,AJAX,VIEW]Spring4 @MVC 게시판-멀티파일업로드,답변형,JSR303 @Valid,@Controller,@ModelAttribute,@SessionAttributes,어노테이션기반,마이바티스

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}">
     &nbsp;
     </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">
<!-- 레벨의 수만큼 글을 뒤로 민다 -->
     &nbsp;&nbsp;
     </c:forEach>
<a class="article" id="${board.seq}"
href="read.html?seq=${board.seq}" onmouseout="hidelayer();">&nbsp;${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();">&nbsp;${board.title}</a>
</c:when>
</c:choose></td>
<td align="center">&nbsp;${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>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</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>&nbsp;</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>&nbsp;</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>&nbsp;</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)자바,네트워크,웹&스프링


 

댓글 없음:

댓글 쓰기