개발자입니다
[비트캠프] 78일차(16주차5일) - myapp-51~53(서비스 객체 도입, Front controller, Page Controller) 본문
[비트캠프] 78일차(16주차5일) - myapp-51~53(서비스 객체 도입, Front controller, Page Controller)
끈기JK 2023. 2. 24. 18:42
51. 서비스 객체 도입 - 비즈니스 로직 분리
BoardInsertServlet 에서 BoardDao 로 insert() 한다. 그리고 BoardFileDao 로 insertList() 한다. 이를 Tx 로 묶는다.
BoardInsertServlet 역할은
- 입력값 가공
- 업무 흐름 제어 (+트랜잭션 제어)
- 출력 제어
-----Dao 역할은
- 데이터 처리
- 회사마다 업무 흐름이 다르다.
- 업무 흐름은 자주 변경된다.
기능 변경
↓ 계속 자주 변경 → 회사마다 변경해야 한다 → Controller 에서 비즈니스 로직을 분리! 여러 서블릿이 비즈니스 로직을 재사용 할 수 있다. 서블릿 기술과 상관없이 사용할 수 있다.
업무 흐름 제어
BoardInsertServlet 역할
- 입력값 가공
- 출력 제어
BoardService ← 서비스 객체
- 업무 흐름 제어
- 트랜잭션 제어
insert() 를 BoardDao 로 한다.
insertList() 를 BoardFileDao 로 한다.
Dao 는 데이터 처리 관련 용어를 쓰는게 좋다.
Service 는 업무 처리 관련 용어를 쓰는게 좋다.
51. Servlet - Service - DAO
(Servlet, JSP, CLI) → Service → DAO → Table 로 흐름이 갈 수 있다.
하지만 Service ↔ Service 로 흐름이 진행되면 안된다.
51 Service 객체 교체하기 쉽게 변경 - 인터페이스 도입
BoardInsertServlet 에서 《interface》BoardService 를 사용한다.
구현체로 DefaultBoardService (첨부파일 다루는 서비스), SimpleBoardServiceImpl (첨부파일을 다루지 않는 서비스) 가 사용된다.
### 51-1. Controller에서 비즈니스 로직 분리하기: 서비스 컴포넌트 도입
- Controller에서 비즈니스 로직을 분리하는 이유
- 서비스 컴포넌트의 역할 이해
### 51-2. 서비스 객체에 인터페이스 적용하기: 서비스 객체를 교체하기 쉽게 만들기
- 서비스 객체에 인터페이스를 적용하는 이유와 방법
BoardListServlet 과 DAO 사이에 Service 객체를 생성한다.
BoardService 객체는 리스너에 생성해서 ServletContext 보관소에 저장한다.
@WebListener
public class ContextLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
try {
InputStream mybatisConfigInputStream = Resources.getResourceAsStream(
"bitcamp/myapp/config/mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
BitcampSqlSessionFactory sqlSessionFactory = new BitcampSqlSessionFactory(
builder.build(mybatisConfigInputStream));
TransactionManager txManager = new TransactionManager(sqlSessionFactory);
BoardDao boardDao = new DaoGenerator(sqlSessionFactory).getObject(BoardDao.class);
MemberDao memberDao = new DaoGenerator(sqlSessionFactory).getObject(MemberDao.class);
StudentDao studentDao = new DaoGenerator(sqlSessionFactory).getObject(StudentDao.class);
TeacherDao teacherDao = new DaoGenerator(sqlSessionFactory).getObject(TeacherDao.class);
BoardFileDao boardFileDao = new DaoGenerator(sqlSessionFactory).getObject(BoardFileDao.class);
BoardService boardService = new DefaultBoardService(txManager, boardDao, boardFileDao);
StudentService studentService = new DefaultStudentService(txManager, memberDao, studentDao);
TeacherService teacherService = new DefaultTeacherService(txManager, memberDao, teacherDao);
// 서블릿 컨텍스트 보관소를 알아낸다.
ServletContext ctx = sce.getServletContext();
// 서블릿들이 공유할 객체를 이 보관소에 저장한다.
ctx.setAttribute("boardService", boardService);
ctx.setAttribute("studentService", studentService);
ctx.setAttribute("teacherService", teacherService);
/* 후략 */
BoardService 인터페이스 정의한다.
package bitcamp.myapp.service;
import java.util.List;
import bitcamp.myapp.vo.Board;
public interface BoardService {
void add(Board board);
List<Board> list(String keyword);
Board get(int no);
void update(Board board);
void delete(int no);
void deleteFile(int fileNo);
}
BoardService 구현체를 생성한다.
트랜잭션 처리 및 Dao 접근을 담당한다.
public class DefaultBoardService implements BoardService {
private TransactionManager txManager;
private BoardDao boardDao;
private BoardFileDao boardFileDao;
public DefaultBoardService(TransactionManager txManager, BoardDao boardDao, BoardFileDao boardFileDao) {
this.txManager = txManager;
this.boardDao = boardDao;
this.boardFileDao = boardFileDao;
}
@Override
public void add(Board board) {
try {
txManager.startTransaction();
boardDao.insert(board);
if (board.getAttachedFiles().size() > 0) {
for (BoardFile boardFile : board.getAttachedFiles()) {
boardFile.setBoardNo(board.getNo());
}
boardFileDao.insertList(board.getAttachedFiles());
}
txManager.commit();
} catch (Exception e) {
txManager.rollback();
throw new RuntimeException(e);
}
}
@Override
public List<Board> list(String keyword) {
return boardDao.findAll(keyword);
}
@Override
public Board get(int no) {
Board b = boardDao.findByNo(no);
if (b != null) {
boardDao.increaseViewCount(no);
}
return b;
}
@Override
public void update(Board board) {
try {
txManager.startTransaction();
if (boardDao.update(board) == 0) {
throw new RuntimeException("게시글이 존재하지 않습니다!");
}
if (board.getAttachedFiles().size() > 0) {
boardFileDao.insertList(board.getAttachedFiles());
}
txManager.commit();
} catch (Exception e) {
txManager.rollback();
throw e;
}
}
@Override
public void delete(int no) {
try {
txManager.startTransaction();
boardFileDao.deleteOfBoard(no);
if (boardDao.delete(no) == 0) {
throw new RuntimeException("게시글이 존재하지 않습니다!");
}
txManager.commit();
} catch (Exception e) {
txManager.rollback();
throw e;
}
}
@Override
public void deleteFile(int fileNo) {
boardFileDao.delete(fileNo);
}
}
BoardListServlet 는 Dao 는 모르고 단지 boardService.list() 를 호출 할 뿐이다.
나머지 form, insert, update, delete 또한 마찬가지이다.
@WebServlet("/board/list")
public class BoardListServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private BoardService boardService;
@Override
public void init() {
boardService = (BoardService) getServletContext().getAttribute("boardService");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setAttribute("boards",
boardService.list(request.getParameter("keyword")));
request.getRequestDispatcher("/board/list.jsp").forward(request, response);
}
}
@WebServlet("/board/form")
public class BoardFormServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.getRequestDispatcher("/board/form.jsp").forward(request, response);
}
}
@WebServlet("/board/insert")
public class BoardInsertServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private BoardService boardService;
@Override
public void init() {
boardService = (BoardService) getServletContext().getAttribute("boardService");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> items = upload.parseRequest(request);
Map<String,String> paramMap = new HashMap<>();
List<FileItem> files = new ArrayList<>();
for (FileItem item : items) {
if (item.isFormField()) {
paramMap.put(item.getFieldName(), item.getString("UTF-8"));
} else {
files.add(item);
}
}
Board board = new Board();
board.setTitle(paramMap.get("title"));
board.setContent(paramMap.get("content"));
Member loginUser = (Member) request.getSession().getAttribute("loginUser");
Member writer = new Member();
writer.setNo(loginUser.getNo());
board.setWriter(writer);
List<BoardFile> boardFiles = new ArrayList<>();
for (FileItem file : files) {
if (file.getSize() == 0) {
continue;
}
String filename = UUID.randomUUID().toString();
file.write(new File(getServletContext().getRealPath("/board/upload/" + filename)));
BoardFile boardFile = new BoardFile();
boardFile.setOriginalFilename(file.getName());
boardFile.setFilepath(filename);
boardFile.setMimeType(file.getContentType());
boardFiles.add(boardFile);
}
board.setAttachedFiles(boardFiles);
boardService.add(board);
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("error", "data");
}
request.getRequestDispatcher("/board/insert.jsp").forward(request, response);
}
}
@WebServlet("/board/view")
public class BoardViewServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private BoardService boardService;
@Override
public void init() {
boardService = (BoardService) getServletContext().getAttribute("boardService");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setAttribute("board",
boardService.get(Integer.parseInt(request.getParameter("no"))));
request.getRequestDispatcher("/board/view.jsp").forward(request, response);
}
}
@MultipartConfig(maxFileSize = 1024 * 1024 * 50)
@WebServlet("/board/update")
public class BoardUpdateServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private BoardService boardService;
@Override
public void init() {
boardService = (BoardService) getServletContext().getAttribute("boardService");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
Member loginUser = (Member) request.getSession().getAttribute("loginUser");
Board board = new Board();
board.setNo(Integer.parseInt(request.getParameter("no")));
board.setTitle(request.getParameter("title"));
board.setContent(request.getParameter("content"));
Board old = boardService.get(board.getNo());
if (old.getWriter().getNo() != loginUser.getNo()) {
response.sendRedirect("../auth/fail");
return;
}
Collection<Part> parts = request.getParts();
List<BoardFile> boardFiles = new ArrayList<>();
for (Part part : parts) {
if (!part.getName().equals("files") || part.getSize() == 0) {
continue;
}
String filename = UUID.randomUUID().toString();
part.write(this.getServletContext().getRealPath("/board/upload/" + filename));
BoardFile boardFile = new BoardFile();
boardFile.setOriginalFilename(part.getSubmittedFileName());
boardFile.setFilepath(filename);
boardFile.setMimeType(part.getContentType());
boardFile.setBoardNo(board.getNo());
boardFiles.add(boardFile);
}
board.setAttachedFiles(boardFiles);
boardService.update(board);
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("error", "data");
}
request.getRequestDispatcher("/board/update.jsp").forward(request, response);
}
}
@WebServlet("/board/filedelete")
public class BoardFileDeleteServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private BoardService boardService;
@Override
public void init() {
boardService = (BoardService) getServletContext().getAttribute("boardService");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Member loginUser = (Member) request.getSession().getAttribute("loginUser");
int boardNo = Integer.parseInt(request.getParameter("boardNo"));
Board old = boardService.get(boardNo);
if (old.getWriter().getNo() != loginUser.getNo()) {
response.sendRedirect("../auth/fail");
return;
}
boardService.deleteFile(Integer.parseInt(request.getParameter("fileNo")));
response.sendRedirect("view?no=" + boardNo);
}
}
@MultipartConfig(maxFileSize = 1024 * 1024 * 50)
@WebServlet("/board/delete")
public class BoardDeleteServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private BoardService boardService;
@Override
public void init() {
boardService = (BoardService) getServletContext().getAttribute("boardService");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
Member loginUser = (Member) request.getSession().getAttribute("loginUser");
int boardNo = Integer.parseInt(request.getParameter("no"));
Board old = boardService.get(boardNo);
if (old.getWriter().getNo() != loginUser.getNo()) {
response.sendRedirect("../auth/fail");
return;
}
boardService.delete(boardNo);
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("error", "data");
}
request.getRequestDispatcher("/board/delete.jsp").forward(request, response);
}
}
teacher, student 는 생략
52 Front Controller 도입
BoardInsertServlet, BoardListServlet, BoardViewServlet, ... 의 공통 기능을 추출하여 분리 → 《Front Controller》DispatcherServlet 을 생성한다.
DispatcherServlet 에 요청이 들어오면 각 Servlet 으로 위임한다. 그리고 forwarding 을 JSP 로 한다.
다른 컨트롤러 앞쪽에서 요청을 대신 받고, JSP 실행을 제어 = "Front(앞쪽) Controller"
특정 페이지의 요청 처리를 담당 = "Page Controller"
52 Front Controller 도입 - 가장 큰 이점?
《Front Controller》DispatcherServlet 에 요청한다. 모든 요청은 프론트 컨트롤러가 받는다.
여기서 Board----Servlet 으로 위임할 필요는 없다.
페이지 컨트롤러는 굳이 서블릿이 될 필요가 없다! → 페이지 컨트롤러의 관리는 별도의 객체로 분리할 수 있다.
/app/board/list 로 ① 요청 들어오면 DispatcherServlet (/app/*) 가 실행된다. 여기서 ② forward() include() (한 번 forward 되면 다른 서블릿으로 forward 할 수 없다) 를 BoardListServlet 으로 한다. 여기서 ③ 실행 하고 ④ 리턴 을 DispatcherServlet 으로 한다. ⑤ forward 를 list.jsp 로 하고 ⑥ 리턴 받아 ⑦ 응답 한다.
DispatcherServlet, BoardListServlet, list.jsp 모두 ServletRequest 를 공유한다.
### 52. Front Controller 디자인 패턴 도입하기
- Front Controller 디자인 패턴의 효과 및 적용 방법
BoardListServlet, BoardInsertServlet, ... 각 서블릿이 요청을 받지 않고 DispatcherServlet 이 모든 요청을 받아 전달한다.
pathInfo 를 뽑아내서 .include(...) 로 다른 서블릿으로 보낸다.
@MultipartConfig(maxFileSize = 1024 * 1024 * 50)
@WebServlet("/app/*")
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 요청 URL => http://localhost:8080/web/app/board/list
// - Context Root: /web
// - ServletPath: /app
// - PathInfo: /board/list
String pathInfo = request.getPathInfo();
// 페이지 컨트롤러 실행
if (pathInfo.equals("/")) {
response.sendRedirect(request.getContextPath() + "/");
return;
}
request.getRequestDispatcher(pathInfo).include(request, response);
// 쿠키 처리
@SuppressWarnings("unchecked")
List<Cookie> cookies = (List<Cookie>) request.getAttribute("cookies");
if (cookies != null) {
for (Cookie cookie : cookies) {
response.addCookie(cookie);
}
}
String view = (String) request.getAttribute("view");
// 뷰 컴포넌트 실행
if (view != null) {
if (view.startsWith("redirect:")) {
response.sendRedirect(view.substring(9));
} else {
request.getRequestDispatcher(view).forward(request, response);
}
}
}
}
53 Front Controller 와 Page Controller (POJO)
《Front Controller》DispatcherServlet 에서 《interface》PageController 구현체에게 execute 지시한다. 구현체로 BoardListController, BoardViewController, ... 가 있다.
Page Controller 가 직접 요청을 받지 않기 때문에 => Page Controller 를 POJO (Plain Old Java Object)로 전환
### 53. 페이지 컨트롤러를 POJO로 전환하기
- 프론트 컨트롤러 구조에서 페이지 컨트롤러를 POJO로 전환하는 방법
- POJO? Plain Old Java Object (그냥 일반 자바 문법으로 만든 클래스)
URL 주소에 해당하는 요청을 pathInfo 에 저장한 뒤 ServletContext 에서 해당하는 페이지 컨트롤러를 가져온다.
@MultipartConfig(maxFileSize = 1024 * 1024 * 50)
@WebServlet("/app/*")
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 요청 URL => http://localhost:8080/web/app/board/list
// - Context Root: /web
// - ServletPath: /app
// - PathInfo: /board/list
String pathInfo = request.getPathInfo();
// 페이지 컨트롤러 실행
if (pathInfo.equals("/")) {
response.sendRedirect(request.getContextPath() + "/");
return;
}
ServletContext ctx = getServletContext();
// 클라이언트가 요청한 URL을 가지고 페이지 컨트롤러를 찾는다.
PageController controller = (PageController) ctx.getAttribute(pathInfo);
if (controller == null) {
request.getRequestDispatcher("/NotFoundController.jsp").forward(request, response);
return;
}
// 페이지 컨트롤러 실행
String view = controller.execute(request, response);
// 쿠키 처리
@SuppressWarnings("unchecked")
List<Cookie> cookies = (List<Cookie>) request.getAttribute("cookies");
if (cookies != null) {
for (Cookie cookie : cookies) {
response.addCookie(cookie);
}
}
// 뷰 컴포넌트 실행
if (view != null) {
if (view.startsWith("redirect:")) {
response.sendRedirect(view.substring(9));
} else {
request.getRequestDispatcher(view).forward(request, response);
}
}
}
}
페이지 컨트롤러 인터페이스 정의한다.
public interface PageController {
String execute(HttpServletRequest request, HttpServletResponse response);
}
서블릿을 컨트롤러로 변경한다.
페이지 컨트롤러 구현체를 만든다.
내부적으로 작업 수행 후 jsp 주소 리턴한다.
public class LoginFormController implements PageController {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
return "/auth/form.jsp";
}
}
리스너에 페이지 컨트롤러 생성해서 보관한다.
@WebListener
public class ContextLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
try {
InputStream mybatisConfigInputStream = Resources.getResourceAsStream(
"bitcamp/myapp/config/mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
BitcampSqlSessionFactory sqlSessionFactory = new BitcampSqlSessionFactory(
builder.build(mybatisConfigInputStream));
TransactionManager txManager = new TransactionManager(sqlSessionFactory);
BoardDao boardDao = new DaoGenerator(sqlSessionFactory).getObject(BoardDao.class);
MemberDao memberDao = new DaoGenerator(sqlSessionFactory).getObject(MemberDao.class);
StudentDao studentDao = new DaoGenerator(sqlSessionFactory).getObject(StudentDao.class);
TeacherDao teacherDao = new DaoGenerator(sqlSessionFactory).getObject(TeacherDao.class);
BoardFileDao boardFileDao = new DaoGenerator(sqlSessionFactory).getObject(BoardFileDao.class);
BoardService boardService = new DefaultBoardService(txManager, boardDao, boardFileDao);
StudentService studentService = new DefaultStudentService(txManager, memberDao, studentDao);
TeacherService teacherService = new DefaultTeacherService(txManager, memberDao, teacherDao);
LoginFormController loginFormController = new LoginFormController();
LoginController loginController = new LoginController(studentService, teacherService);
LogoutController logoutController = new LogoutController();
AuthFailController authFailController = new AuthFailController();
BoardListController boardListController = new BoardListController(boardService);
BoardFormController boardFormController = new BoardFormController();
BoardInsertController boardInsertController = new BoardInsertController(boardService);
BoardViewController boardViewController = new BoardViewController(boardService);
BoardUpdateController boardUpdateController = new BoardUpdateController(boardService);
BoardDeleteController boardDeleteController = new BoardDeleteController(boardService);
BoardFileDeleteController boardFileDeleteController = new BoardFileDeleteController(boardService);
// 서블릿 컨텍스트 보관소를 알아낸다.
ServletContext ctx = sce.getServletContext();
// 프론트 컨트롤러가 사용할 페이지 컨트롤러를 보관한다.
ctx.setAttribute("/auth/form", loginFormController);
ctx.setAttribute("/auth/login", loginController);
ctx.setAttribute("/auth/logout", logoutController);
ctx.setAttribute("/auth/fail", authFailController);
ctx.setAttribute("/board/list", boardListController);
ctx.setAttribute("/board/form", boardFormController);
ctx.setAttribute("/board/insert", boardInsertController);
ctx.setAttribute("/board/view", boardViewController);
ctx.setAttribute("/board/update", boardUpdateController);
ctx.setAttribute("/board/delete", boardDeleteController);
ctx.setAttribute("/board/filedelete", boardFileDeleteController);
} catch (Exception e) {
System.out.println("웹 애플리케이션 자원을 준비하는 중에 오류 발생!");
e.printStackTrace();
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// 웹 애플리케이션이 종료될 때 서블릿 컨테이너가 호출한다.
System.out.println("ContextLoaderListener.contextDestroyed() 호출됨!");
}
}
각 서블릿을 컨트롤러로 만든다.
public class LoginController implements PageController {
private StudentService studentService;
private TeacherService teacherService;
public LoginController(StudentService studentService, TeacherService teacherService) {
this.studentService = studentService;
this.teacherService = teacherService;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
String usertype = request.getParameter("usertype");
String email = request.getParameter("email");
String password = request.getParameter("password");
if (request.getParameter("saveEmail") != null) {
Cookie cookie = new Cookie("email", email);
cookie.setMaxAge(60 * 60 * 24 * 30); // 30일 동안 유지
response.addCookie(cookie);
} else {
Cookie cookie = new Cookie("email", "");
cookie.setMaxAge(0);
response.addCookie(cookie);
}
Member member = null;
switch (usertype) {
case "student":
member = studentService.get(email, password);
break;
case "teacher":
member = teacherService.get(email, password);
break;
}
if (member != null) {
HttpSession session = request.getSession();
session.setAttribute("loginUser", member);
return "redirect:../";
} else {
request.setAttribute("error", "loginfail");
return "/auth/form.jsp";
}
}
}
public class LogoutController implements PageController {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
request.getSession().invalidate();
return "redirect:../";
}
}
public class AuthFailController implements PageController {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
return "/auth/fail.jsp";
}
}
public class BoardListController implements PageController {
private BoardService boardService;
public BoardListController(BoardService boardService) {
this.boardService = boardService;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
request.setAttribute("boards",
boardService.list(request.getParameter("keyword")));
return "/board/list.jsp";
}
}
public class BoardFormController implements PageController {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
return "/board/form.jsp";
}
}
public class BoardViewController implements PageController {
private BoardService boardService;
public BoardViewController(BoardService boardService) {
this.boardService = boardService;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
request.setAttribute("board",
boardService.get(Integer.parseInt(request.getParameter("no"))));
return"/board/view.jsp";
}
}
public class BoardInsertController implements PageController {
private BoardService boardService;
public BoardInsertController(BoardService boardService) {
this.boardService = boardService;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
try {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> items = upload.parseRequest(request);
Map<String,String> paramMap = new HashMap<>();
List<FileItem> files = new ArrayList<>();
for (FileItem item : items) {
if (item.isFormField()) {
paramMap.put(item.getFieldName(), item.getString("UTF-8"));
} else {
files.add(item);
}
}
Board board = new Board();
board.setTitle(paramMap.get("title"));
board.setContent(paramMap.get("content"));
Member loginUser = (Member) request.getSession().getAttribute("loginUser");
Member writer = new Member();
writer.setNo(loginUser.getNo());
board.setWriter(writer);
List<BoardFile> boardFiles = new ArrayList<>();
for (FileItem file : files) {
if (file.getSize() == 0) {
continue;
}
String filename = UUID.randomUUID().toString();
file.write(new File(request.getServletContext().getRealPath("/board/upload/" + filename)));
BoardFile boardFile = new BoardFile();
boardFile.setOriginalFilename(file.getName());
boardFile.setFilepath(filename);
boardFile.setMimeType(file.getContentType());
boardFiles.add(boardFile);
}
board.setAttachedFiles(boardFiles);
boardService.add(board);
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("error", "data");
}
return "/board/insert.jsp";
}
}
public class BoardUpdateController implements PageController {
private BoardService boardService;
public BoardUpdateController(BoardService boardService) {
this.boardService = boardService;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
try {
Member loginUser = (Member) request.getSession().getAttribute("loginUser");
Board board = new Board();
board.setNo(Integer.parseInt(request.getParameter("no")));
board.setTitle(request.getParameter("title"));
board.setContent(request.getParameter("content"));
Board old = boardService.get(board.getNo());
if (old.getWriter().getNo() != loginUser.getNo()) {
return "redirect:../auth/fail";
}
Collection<Part> parts = request.getParts();
List<BoardFile> boardFiles = new ArrayList<>();
for (Part part : parts) {
if (!part.getName().equals("files") || part.getSize() == 0) {
continue;
}
String filename = UUID.randomUUID().toString();
part.write(request.getServletContext().getRealPath("/board/upload/" + filename));
BoardFile boardFile = new BoardFile();
boardFile.setOriginalFilename(part.getSubmittedFileName());
boardFile.setFilepath(filename);
boardFile.setMimeType(part.getContentType());
boardFile.setBoardNo(board.getNo());
boardFiles.add(boardFile);
}
board.setAttachedFiles(boardFiles);
boardService.update(board);
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("error", "data");
}
return "/board/update.jsp";
}
}
public class BoardFileDeleteController implements PageController {
private BoardService boardService;
public BoardFileDeleteController(BoardService boardService) {
this.boardService = boardService;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
Member loginUser = (Member) request.getSession().getAttribute("loginUser");
int boardNo = Integer.parseInt(request.getParameter("boardNo"));
Board old = boardService.get(boardNo);
if (old.getWriter().getNo() != loginUser.getNo()) {
return "redirect:../auth/fail";
} else {
boardService.deleteFile(Integer.parseInt(request.getParameter("fileNo")));
return "redirect:view?no=" + boardNo;
}
}
}
public class BoardDeleteController implements PageController {
private BoardService boardService;
public BoardDeleteController(BoardService boardService) {
this.boardService = boardService;
}
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
try {
Member loginUser = (Member) request.getSession().getAttribute("loginUser");
int boardNo = Integer.parseInt(request.getParameter("no"));
Board old = boardService.get(boardNo);
if (old.getWriter().getNo() != loginUser.getNo()) {
return "redirect:../auth/fail";
}
boardService.delete(boardNo);
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("error", "data");
}
return "/board/delete.jsp";
}
}
조언
*특수한 기술을 이용한 웹을 만들지 말라. 모바일로 가고싶으면 웹 페이지를 만들고 리액트를 이용해서 모바일을 적용하는 시도를 하라.
*웹 개발자 포트폴리오를 만들려면 관리시스템을 만들라. DB 많이 쓰고 CRUD 많이 사용하는 것을 만들라.
*디자인 툴(가구배치 등) 이런거 만들지 말라.
*주제 선정시 말로 아이디어만 내지 말고 카카오 오븐 등으로 UI 프로토타입 제시하는 룰을 지켜라.
*AI 를 주로 하든 보조로 하든 포트폴리오에 녹여내는게 좋다.
예) 게시글 쓰면 영어로 번역한 것이 나오게. 음성 인식해서 텍스트로 변환해주는 것. 내가 쓴 게시글 요약해 주는 것. 로그인 시 캡챠 또는 안면 인식 사용.
*면접시 질문
백엔드: 스프링 프레임워크 다뤄봤는지? SQL 다뤄봤는지? INNER JOIN, OUTER JOIN 차이를 아는지?
프론트엔드: 제이쿼리 다뤄봤는지? 부트스트랩 다뤄봤는지? 리액트 다뤄봤는지?
과제
TeacherController, StudentController 마이그레이션 하기
'네이버클라우드 AIaaS 개발자 양성과정 1기 > DBMS, SQL, JDBC, Servlet' 카테고리의 다른 글
[Java] 예제 소스 정리 - Reflect (0) | 2023.02.27 |
---|---|
[비트캠프] 79일차(17주차1일) - Servlet(리플렉션 API, 애노테이션), myapp-54~58 (0) | 2023.02.27 |
[비트캠프] 77일차(16주차4일) - Servlet(파일 업로드, 멀티파트), myapp-50(파일 업로드) (0) | 2023.02.23 |
[비트캠프] 76일차(16주차3일) - Servlet(세션, 쿠키, 리다이렉트), myapp-49(로그인, 권한별 기능 제한) (0) | 2023.02.22 |
[Java] 예제 소스 정리 - EL, JSTL (0) | 2023.02.21 |