3.(스프링4 답변형게시판)[컨트롤러, AOP,미리보기서블릿]Spring JDBC]Spring4@MVC-멀티파일업로드,답변형,JSR303 @Valid,@Controller,@ModelAttribute,@SessionAttributes,어노테이션기반,자바교육,스프링학원
스프링프레임워크 실무교육 오라클자바커뮤니티교육센터(www.ojcedu.com)에서 받으세요~
1. 리스트보기에서 본문 미리보기용 서블릿(ajax)
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클래스
[onj.board.aop.LoggingAspect.java]
package onj.board.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
@Aspect
public class LoggingAspect {
private final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);
// 사전충고
// Spring Framework의 JdbcOperations을 포인트컷으로 해서 모든 SQL에 대해 로깅 충고가 적용
@Before("execution(* org.springframework.jdbc.core.JdbcOperations.*(String, ..))")
public void logBefore(JoinPoint joinPoint) {
logger.info("<<<<<<<<<<<<<<<<< DAO 로깅 충고 실행");
Object[] methodArgs = joinPoint.getArgs(), sqlArgs = null;
// 실행시킨 SQL 문장
String statement = methodArgs[0].toString(); // ? 가 포함된 SQL문
// find the SQL arguments (parameters)
for (int i = 1, n = methodArgs.length; i < n; i++) {
Object arg = methodArgs[i];
if (arg instanceof Object[]) {
sqlArgs = (Object[]) arg;
break;
}
}
// '?' 대신 파라미터로 대체
String completedStatement = (sqlArgs == null ?
statement : fillParameters(statement, sqlArgs));
logger.info(completedStatement);
}
//SQL문장의 ?를 넘겨주는 파라미터로 대체해서 최종SQL문을 리턴
private String fillParameters(String statement, Object[] sqlArgs) {
// initialize a StringBuilder with a guesstimated final length
StringBuilder completedSqlBuilder = new StringBuilder(Math.round(statement.length() * 1.2f));
int index, // will hold the index of the next ?
prevIndex = 0; // will hold the index of the previous ? + 1
// loop through each SQL argument
for (Object arg : sqlArgs) {
index = statement.indexOf("?", prevIndex);
if (index == -1)
break; // bail out if there's a mismatch in # of args vs. ?'s
// append the chunk of SQL coming before this ?
completedSqlBuilder.append(statement.substring(prevIndex, index));
// append the replacement for the ?
if (arg == null)
completedSqlBuilder.append("NULL");
else
completedSqlBuilder.append(":"+arg.toString());
prevIndex = index + 1;
}
// add the rest of the SQL if any
if (prevIndex != statement.length())
completedSqlBuilder.append(statement.substring(prevIndex));
return completedSqlBuilder.toString();
}
}
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;
/**
* @author 오라클자바커뮤니티
* Spring @MVC 게시판 컨트롤러
* - 글입력(멀티파일업로드), 글수정, 글삭제, 글리스트보기
* - 답변글 쓰기
* - 커멘트 쓰기
* - @ModelAttribute, @SessionAttributes를 사용해 전반적으로 컨트롤러가 단순해졌다.
*/
@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";
}
/****************************************************************
* 새글(게시글) 입력 기존 게시판과 다르게
* Spring MVC의 MultipartFile upload 기능을 이용 다중파일업로드 구현
* @ModelAttribute적용
***************************************************************/
@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(@RequestParam("seq") String seq,
@RequestParam("passwd") String passwd, HttpServletResponse res)
throws Exception {
int result = boardService.deleteBoard(seq, passwd);
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");
}
}
댓글 없음:
댓글 쓰기