## 67. 페이지 컨트롤러를 POJO로 전환하기
- 페이지 컨트롤러를 POJO 클래스로 변경
POJO? Plain Old Java Object (그냥 일반 자바 문법으로 만든 클래스)
- 의존 객체 주입하기
=>
ㄴ PageController 라는 이름의 Interface 생성하기
=>
PageController.java
ㄴ 페이지 컨트롤러 사용 규칙 정의하기
LoginController.java
ㄴ extends HttpServlet 대신 implements PageController 를 이용하여 PageController 를 구현하도록 함
=>
LoginController.java
ㄴ 해당 코드 제거
=>
LoginController.java
ㄴ 이제 HttpServlet 을 상속 받지 않으므로 제거
=>
LoginController.java
=>
LoginController.java
ㄴ doGet 메서드에서 viewUrl 이라는 이름으로 설정했던 파일경로를 request.getMethod() 가 "GET" 인 경우 리턴하도록 함
=>
LoginController.java
ㄴ doGet 메서드 제거하기
=>
LoginController.java
ㄴ doPost 메서드도 제거
=>
LoginController.java
ㄴ this -> request 로 변경하기
=>
LoginController.java
=>
LoginController.java
ㄴ 이제 viewUrl 로 설정하지 않고 직접 경로를 주도록 함
=>
LoginController.java
ㄴ request 에 설정하지 않고 Exception 으로 던져주도록 함
=>
LoginController.java
ㄴ loginUser 가 null 인 경우를 먼저 처리하도록 변경
DispatcherServlet.java
=>
DispatcherServlet.java
ㄴ init 메서드 오버라이딩 해주기
=>
DispatcherServlet.java
ㄴ Map 객체 생성하기
=>
DispatcherServlet.java
ㄴ 생성한 controllerMap 객체에 해당 값들 저장하기
ㄴ /auth/login 경로로 요청이 이루어지면 LoginController가 해당 요청을 처리하도록 함
=>
DispatcherServlet.java
ㄴ 클라이언트가 요청한 페이지 컨트롤러를 찾아 pageController 에 저장
=>
DispatcherServlet.java
ㄴ 클라이언트가 요청한 페이지 컨트롤러가 null 이면 "해당 요청을 처리할 수 없습니다." 라는 문구와 함께 ServletException 을 던지도록 함
=>
DispatcherServlet.java
ㄴ pageController 의 execute 메서드를 호출하여 페이지 컨트롤러를 실행함
ㄴ 오류 발생 시 ServletException 을 던지고 "요청 처리 중 오류 발생!" 이라는 문구의 예외 메시지와 원본 예외(e)를 함께 전달하도록 함
=>
DispatcherServlet.java
ㄴ pageController 의 리턴 값을 viewUrl 이라는 변수에 담도록 함
=>
DispatcherServlet.java
ㄴ 해당 코드 제거
=>
DispatcherServlet.java
ㄴ 해당 코드를 try 문 안으로 넣어주도록 함
=>
DispatcherServlet.java
ㄴ 해당 코드 제거
=>
ㄴ App 실행
=>
=>
=>
ㄴ 정상적으로 로그인 됨을 확인
=>
ㄴ 로그아웃 선택 시 해당 오류 발생
=>
LogoutController.java
ㄴ PageController 구현하기
=>
LogoutController.java
ㄴ 해당 코드 제거
=>
LogoutController.java
ㄴ 해당 코드 제거
=>
LogoutController.java
ㄴ execute 메서드 오버라이딩 하기
=>
LogoutController.java
ㄴ 해당 코드 제거
=>
LogoutController.java
ㄴ viewUrl 이름으로 설정하는 대신 execute 메서드에서 직접 전달하기
=>
DispatcherServlet.java
ㄴ /auth/logout 경로로 요청이 들어오면 LogoutController를 사용하여 요청을 처리할 수 있도록 함
=>
App 재실행
=>
ㄴ 로그인 상태에서 로그아웃 선택
=>
ㄴ 로그아웃이 정상적으로 실행됨을 확인
동일한 방식으로 MemberXxxConroller.java 파일들 모두 수정해주기
=>
MemberListController.java
package bitcamp.report.controller;
import bitcamp.report.dao.MemberDao;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MemberListController implements PageController {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
MemberDao memberDao = (MemberDao) request.getServletContext().getAttribute("memberDao");
request.setAttribute("list", memberDao.findAll());
return "/WEB-INF/jsp/member/list.jsp";
}
}
=>
DispatcherServlet.java
=>
App 재실행
=>
ㄴ 회원 목록 정상적으로 출력됨을 확인
=>
MemberListController.java
ㄴ [command] + [N] 을 이용하여 Constructor 생성하기
=>
=>
MemberListController.java
ㄴ MemberListController는 MemberDao에 의존하고 있으며, 생성자를 통해 이 의존 관계를 주입받도록 함
ㄴ 해당 코드 제거
=>
LoginController.java
=>
=>
LoginController.java
=>
LoginController.java
ㄴ 해당 코드 제거
=>
DispatcherServlet.java
ㄴ LoginController 생성자에 memberDao 객체를 전달하여 해당 컨트롤러에서 memberDao를 사용할 수 있도록 준비
=>
App 재실행
=>
=>
ㄴ 정보 입력 후 [로그인] 선택
=>
ㄴ 로그인이 정상적으로 실행됨을 확인
=>
ㄴ 회원 목록이 정상적으로 출력됨을 확인
MemberAddController.java
=>
=>
MemberAddController.java
ㄴ 생성자 만들기
=>
MemberAddController.java
package bitcamp.report.controller;
import bitcamp.report.dao.MemberDao;
import bitcamp.report.vo.Member;
import bitcamp.util.NcpObjectStorageService;
import org.apache.ibatis.session.SqlSessionFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
public class MemberAddController implements PageController {
MemberDao memberDao;
SqlSessionFactory sqlSessionFactory;
NcpObjectStorageService ncpObjectStorageService;
public MemberAddController(MemberDao memberDao, SqlSessionFactory sqlSessionFactory, NcpObjectStorageService ncpObjectStorageService) {
this.memberDao = memberDao;
this.sqlSessionFactory = sqlSessionFactory;
this.ncpObjectStorageService = ncpObjectStorageService;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (request.getMethod().equals("GET")) {
return "/WEB-INF/jsp/member/form.jsp";
}
try {
Member m = new Member();
m.setName(request.getParameter("name"));
m.setPhone(request.getParameter("phone"));
m.setPassword(request.getParameter("password"));
m.setPosition(request.getParameter("position").charAt(0));
Part photoPart = request.getPart("photo");
if (photoPart.getSize() > 0) {
String uploadFileUrl = ncpObjectStorageService.uploadFile("bitcamp-nc7-bucket-25",
"member/", photoPart);
m.setPhoto(uploadFileUrl);
}
memberDao.insert(m);
sqlSessionFactory.openSession(false).commit();
} catch (Exception e) {
sqlSessionFactory.openSession(false).rollback();
request.setAttribute("message", "회원 등록 오류!");
request.setAttribute("refresh", "2;url=list");
throw e;
}
return "redirect:list";
}
}
=>
DispatcherServlet.java
ㄴ 해당 코드 추가
=>
App 재실행
=>
=>
ㄴ 회원 등록이 정상적으로 실행됨을 확인
MemberDetailController.java
package bitcamp.report.controller;
import bitcamp.report.dao.MemberDao;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MemberDetailController implements PageController {
MemberDao memberDao;
public MemberDetailController(MemberDao memberDao) {
this.memberDao = memberDao;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
request.setAttribute("member", memberDao.findBy(Integer.parseInt(request.getParameter("no"))));
return "/WEB-INF/jsp/member/detail.jsp";
}
}
=>
DispatcherServlet.java
ㄴ 해당 코드 추가
=>
App 재실행
=>
ㄴ 회원 상세보기가 정상적으로 출력됨을 확인
MemberUpdateController.java
package bitcamp.report.controller;
import bitcamp.report.dao.MemberDao;
import bitcamp.report.vo.Member;
import bitcamp.util.NcpObjectStorageService;
import org.apache.ibatis.session.SqlSessionFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
public class MemberUpdateController implements PageController {
MemberDao memberDao;
SqlSessionFactory sqlSessionFactory;
NcpObjectStorageService ncpObjectStorageService;
public MemberUpdateController(MemberDao memberDao, SqlSessionFactory sqlSessionFactory, NcpObjectStorageService ncpObjectStorageService) {
this.memberDao = memberDao;
this.sqlSessionFactory = sqlSessionFactory;
this.ncpObjectStorageService = ncpObjectStorageService;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
Member member = new Member();
member.setNo(Integer.parseInt(request.getParameter("no")));
member.setName(request.getParameter("name"));
member.setPhone(request.getParameter("phone"));
member.setPassword(request.getParameter("password"));
member.setPosition(request.getParameter("position").charAt(0));
Part photoPart = request.getPart("photo");
if (photoPart.getSize() > 0) {
String uploadFileUrl = ncpObjectStorageService
.uploadFile("bitcamp-nc7-bucket-25", "member/", photoPart);
member.setPhoto(uploadFileUrl);
}
if (memberDao.update(member) == 0) {
throw new Exception("회원이 없습니다.");
} else {
sqlSessionFactory.openSession(false).commit();
return "redirect:list";
}
} catch (Exception e) {
sqlSessionFactory.openSession(false).rollback();
request.setAttribute("refresh", "2;url=list");
throw e;
}
}
}
=>
DispatcherServlet.java
ㄴ 해당 코드 추가
=>
App 재실행
=>
ㄴ 정보 변경 후 [변경] 선택
=>
ㄴ 회원 정보가 정상적으로 변경됨을 확인
board/list.jsp
ㄴ 이미지 없는 사람의 이미지도 출력하도록 코드 수정
=>
MemberDeleteController.java
package bitcamp.report.controller;
import bitcamp.report.dao.MemberDao;
import org.apache.ibatis.session.SqlSessionFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MemberDeleteController implements PageController {
MemberDao memberDao;
SqlSessionFactory sqlSessionFactory;
public MemberDeleteController(MemberDao memberDao, SqlSessionFactory sqlSessionFactory) {
this.memberDao = memberDao;
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
if (memberDao.delete(Integer.parseInt(request.getParameter("no"))) == 0) {
throw new Exception("해당 번호의 회원이 없습니다!");
} else {
sqlSessionFactory.openSession(false).commit();
return "redirect:list";
}
} catch (Exception e) {
sqlSessionFactory.openSession(false).rollback();
request.setAttribute("refresh", "2;url=list");
throw e;
}
}
}
=>
DispatcherServlet.java
=>
App 재실행
=>
ㄴ 회원 삭제 선택
=>
ㄴ 정상적으로 삭제됨을 확인
=> 동일한 방식으로 MemberXxxConroller.java 파일들 모두 수정해주기
BoardListController.java
package bitcamp.report.controller;
import bitcamp.report.dao.BoardDao;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class BoardListController implements PageController {
BoardDao boardDao;
public BoardListController(BoardDao boardDao) {
this.boardDao = boardDao;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
request.setAttribute("list", boardDao.findAll(Integer.parseInt(request.getParameter("category"))));
return "/WEB-INF/jsp/board/list.jsp";
} catch (Exception e) {
request.setAttribute("refresh", "1;url=/");
throw e;
}
}
}
=>
DispatcherServlet.java
ㄴ 해당 코드 추가
BoardAddController.java
package bitcamp.report.controller;
import bitcamp.report.dao.BoardDao;
import bitcamp.report.vo.AttachedFile;
import bitcamp.report.vo.Board;
import bitcamp.report.vo.Member;
import bitcamp.util.NcpObjectStorageService;
import org.apache.ibatis.session.SqlSessionFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.util.ArrayList;
public class BoardAddController implements PageController {
BoardDao boardDao;
SqlSessionFactory sqlSessionFactory;
NcpObjectStorageService ncpObjectStorageService;
public BoardAddController(BoardDao boardDao, SqlSessionFactory sqlSessionFactory, NcpObjectStorageService ncpObjectStorageService) {
this.boardDao = boardDao;
this.sqlSessionFactory = sqlSessionFactory;
this.ncpObjectStorageService = ncpObjectStorageService;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (request.getMethod().equals("GET")) {
return "/WEB-INF/jsp/board/form.jsp";
}
Member loginUser = (Member) request.getSession().getAttribute("loginUser");
if (loginUser == null) {
request.getParts(); // 일단 클라이언트가 보낸 파일을 읽는다. 그래야 응답 가능!
return "redirect:../auth/login";
}
try {
// 각각의 파트에서 값을 꺼낸다.
Board board = new Board();
board.setWriter(loginUser);
board.setTitle(request.getParameter("title"));
board.setContent(request.getParameter("content"));
board.setCategory(Integer.parseInt(request.getParameter("category")));
ArrayList<AttachedFile> attachedFiles = new ArrayList<>();
for (Part part : request.getParts()) {
if (part.getName().equals("files") && part.getSize() > 0) {
String uploadFileUrl = ncpObjectStorageService
.uploadFile("bitcamp-nc7-bucket-25", "board/", part);
AttachedFile attachedFile = new AttachedFile();
attachedFile.setFilePath(uploadFileUrl);
attachedFiles.add(attachedFile);
}
}
board.setAttachedFiles(attachedFiles);
boardDao.insert(board);
if (attachedFiles.size() > 0) {
boardDao.insertFiles(board);
}
sqlSessionFactory.openSession(false).commit();
return "redirect:list?category=" + request.getParameter("category");
} catch (Exception e) {
sqlSessionFactory.openSession(false).rollback();
request.setAttribute("message", "게시글 등록 오류!");
request.setAttribute("refresh", "2;url=list?category=" + request.getParameter("category"));
throw e;
}
}
}
=>
DispatcherServlet.java
ㄴ 해당 코드 추가
BoardDetailController.java
package bitcamp.report.controller;
import bitcamp.report.dao.BoardDao;
import bitcamp.report.vo.Board;
import org.apache.ibatis.session.SqlSessionFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class BoardDetailController implements PageController {
BoardDao boardDao;
SqlSessionFactory sqlSessionFactory;
public BoardDetailController(BoardDao boardDao, SqlSessionFactory sqlSessionFactory) {
this.boardDao = boardDao;
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
int category = Integer.parseInt(request.getParameter("category"));
int no = Integer.parseInt(request.getParameter("no"));
Board board = boardDao.findBy(category, no);
if (board != null) {
board.setViewCount(board.getViewCount() + 1);
boardDao.updateCount(board);
sqlSessionFactory.openSession(false).commit();
request.setAttribute("board", board);
}
return "/WEB-INF/jsp/board/detail.jsp";
} catch (Exception e) {
sqlSessionFactory.openSession(false).rollback();
request.setAttribute("refresh", "2;url=/board/list?category=" + request.getParameter("category"));
throw e;
}
}
}
=>
DispatcherServlet.java
ㄴ 해당 코드 추가
BoardUpdateController.java
package bitcamp.report.controller;
import bitcamp.report.dao.BoardDao;
import bitcamp.report.vo.AttachedFile;
import bitcamp.report.vo.Board;
import bitcamp.report.vo.Member;
import bitcamp.util.NcpObjectStorageService;
import org.apache.ibatis.session.SqlSessionFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.util.ArrayList;
public class BoardUpdateController implements PageController {
BoardDao boardDao;
SqlSessionFactory sqlSessionFactory;
NcpObjectStorageService ncpObjectStorageService;
public BoardUpdateController(BoardDao boardDao, SqlSessionFactory sqlSessionFactory, NcpObjectStorageService ncpObjectStorageService) {
this.boardDao = boardDao;
this.sqlSessionFactory = sqlSessionFactory;
this.ncpObjectStorageService = ncpObjectStorageService;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
Member loginUser = (Member) request.getSession().getAttribute("loginUser");
if (loginUser == null) {
request.getParts(); // 일단 클라이언트가 보낸 파일을 읽는다. 그래야 응답 가능!
return "redirect:../auth/login";
}
try {
Board board = new Board();
board.setWriter(loginUser);
board.setNo(Integer.parseInt(request.getParameter("no")));
board.setTitle(request.getParameter("title"));
board.setContent(request.getParameter("content"));
board.setCategory(Integer.parseInt(request.getParameter("category")));
ArrayList<AttachedFile> attachedFiles = new ArrayList<>();
for (Part part : request.getParts()) {
if (part.getName().equals("files") && part.getSize() > 0) {
String uploadFileUrl = ncpObjectStorageService.uploadFile(
"bitcamp-nc7-bucket-25", "board/", part);
AttachedFile attachedFile = new AttachedFile();
attachedFile.setFilePath(uploadFileUrl);
attachedFiles.add(attachedFile);
}
}
board.setAttachedFiles(attachedFiles);
if (boardDao.update(board) == 0) {
throw new Exception("게시글이 없거나 변경 권한이 없습니다.");
} else {
if (attachedFiles.size() > 0) {
boardDao.insertFiles(board);
}
sqlSessionFactory.openSession(false).commit();
return "redirect:list?category=" + request.getParameter("category");
}
} catch (Exception e) {
sqlSessionFactory.openSession(false).rollback();
request.setAttribute("refresh", "2;url=detail?category=" + request.getParameter("category") +
"&no=" + request.getParameter("no"));
throw e;
}
}
}
=>
DispatcherServlet.java
ㄴ 해당 코드 추가
BoardDeleteController.java
package bitcamp.report.controller;
import bitcamp.report.dao.BoardDao;
import bitcamp.report.vo.Board;
import bitcamp.report.vo.Member;
import org.apache.ibatis.session.SqlSessionFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class BoardDeleteController implements PageController {
BoardDao boardDao;
SqlSessionFactory sqlSessionFactory;
public BoardDeleteController(BoardDao boardDao, SqlSessionFactory sqlSessionFactory) {
this.boardDao = boardDao;
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
Member loginUser = (Member) request.getSession().getAttribute("loginUser");
if (loginUser == null) {
return "redirect:../auth/login";
}
try {
Board b = new Board();
b.setNo(Integer.parseInt(request.getParameter("no")));
b.setWriter(loginUser);
b.setCategory(Integer.parseInt(request.getParameter("category")));
boardDao.deleteFiles(b.getNo());
if (boardDao.delete(b) == 0) {
throw new Exception("해당 번호의 게시글이 없거나 삭제 권한이 없습니다.");
} else {
sqlSessionFactory.openSession(false).commit();
return "redirect:list?category=" + request.getParameter("category");
}
} catch (Exception e) {
sqlSessionFactory.openSession(false).rollback();
request.setAttribute("refresh", "2;url=list?category=" + request.getParameter("category"));
throw e;
}
}
}
=>
DispatcherServlet.java
ㄴ 해당 코드 추가
BoardFileDeleteController.java
package bitcamp.report.controller;
import bitcamp.report.dao.BoardDao;
import bitcamp.report.vo.AttachedFile;
import bitcamp.report.vo.Board;
import bitcamp.report.vo.Member;
import org.apache.ibatis.session.SqlSessionFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class BoardFileDeleteController implements PageController {
BoardDao boardDao;
SqlSessionFactory sqlSessionFactory;
public BoardFileDeleteController(BoardDao boardDao, SqlSessionFactory sqlSessionFactory) {
this.boardDao = boardDao;
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
Member loginUser = (Member) request.getSession().getAttribute("loginUser");
if (loginUser == null) {
return "redirect:../auth/login";
}
Board board = null;
try {
int category = Integer.parseInt(request.getParameter("category"));
int fileNo = Integer.parseInt(request.getParameter("no"));
AttachedFile attachedFile = boardDao.findFileBy(fileNo);
board = boardDao.findBy(category, attachedFile.getBoardNo());
if (board.getWriter().getNo() != loginUser.getNo()) {
throw new Exception("게시글 변경 권한이 없습니다!");
}
if (boardDao.deleteFile(fileNo) == 0) {
throw new Exception("해당 번호의 첨부파일이 없거나 삭제 권한이 없습니다.");
} else {
sqlSessionFactory.openSession(false).commit();
return "redirect:detail?category=" + category + "&no=" + board.getNo();
}
} catch (Exception e) {
sqlSessionFactory.openSession(false).rollback();
request.setAttribute("refresh", "2;url=detail?category=" + request.getParameter("category") +
"&no=" + board.getNo());
throw e;
}
}
}
=>
DispatcherServlet.java
ㄴ 해당 코드 추가
=>
ㄴ App 재실행
=>
게시글 관련 전체 테스트
=>
=>
=>
=>
=>
=>
=>
=>
HomeController.java
package bitcamp.report.controller;
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 java.io.IOException;
public class HomeController implements PageController {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
return "/WEB-INF/jsp/index.jsp";
}
}