From d1191798834fd0a1cc6ac8b09ab4b748e575bfa6 Mon Sep 17 00:00:00 2001 From: Gyumin Kim Date: Sun, 2 Aug 2020 23:56:12 +0900 Subject: [PATCH 1/2] =?UTF-8?q?8=EC=9E=A5=20MVC=20=ED=94=84=EB=A0=88?= =?UTF-8?q?=EC=9E=84=EC=9B=8C=ED=81=AC=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD=202=EB=8B=A8=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * `View` 인터페이스 및 구현체(`JspView`, `JsonView`) 추가 * 모든 Controller에서 `View` 타입을 리턴하도록 수정 --- src/main/java/core/mvc/Controller.java | 2 +- src/main/java/core/mvc/DispatcherServlet.java | 30 ++++------------- src/main/java/core/mvc/ForwardController.java | 6 ++-- src/main/java/core/mvc/JsonView.java | 32 +++++++++++++++++++ src/main/java/core/mvc/JspView.java | 29 +++++++++++++++++ src/main/java/core/mvc/View.java | 8 +++++ .../java/next/controller/HomeController.java | 13 +++++--- .../controller/qna/AddAnswerController.java | 26 ++++++--------- .../qna/DeleteAnswerController.java | 27 +++++++--------- .../next/controller/qna/ShowController.java | 15 +++++---- .../controller/user/CreateUserController.java | 17 +++++----- .../controller/user/ListUserController.java | 15 +++++---- .../next/controller/user/LoginController.java | 19 ++++++----- .../controller/user/LogoutController.java | 13 +++++--- .../controller/user/ProfileController.java | 13 +++++--- .../user/UpdateFormUserController.java | 12 ++++--- .../controller/user/UpdateUserController.java | 17 +++++----- 17 files changed, 180 insertions(+), 114 deletions(-) create mode 100644 src/main/java/core/mvc/JsonView.java create mode 100644 src/main/java/core/mvc/JspView.java create mode 100644 src/main/java/core/mvc/View.java diff --git a/src/main/java/core/mvc/Controller.java b/src/main/java/core/mvc/Controller.java index df7b7f2ea..4fe54694f 100644 --- a/src/main/java/core/mvc/Controller.java +++ b/src/main/java/core/mvc/Controller.java @@ -4,5 +4,5 @@ import javax.servlet.http.HttpServletResponse; public interface Controller { - String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception; + View execute(HttpServletRequest req, HttpServletResponse resp) throws Exception; } diff --git a/src/main/java/core/mvc/DispatcherServlet.java b/src/main/java/core/mvc/DispatcherServlet.java index 59e1a23ee..9a3193532 100644 --- a/src/main/java/core/mvc/DispatcherServlet.java +++ b/src/main/java/core/mvc/DispatcherServlet.java @@ -1,17 +1,14 @@ package core.mvc; -import java.io.IOException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import javax.servlet.RequestDispatcher; 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 org.slf4j.Logger; -import org.slf4j.LoggerFactory; - @WebServlet(name = "dispatcher", urlPatterns = "/", loadOnStartup = 1) public class DispatcherServlet extends HttpServlet { private static final long serialVersionUID = 1L; @@ -21,36 +18,23 @@ public class DispatcherServlet extends HttpServlet { private RequestMapping rm; @Override - public void init() throws ServletException { + public void init() { rm = new RequestMapping(); rm.initMapping(); } @Override - protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException { String requestUri = req.getRequestURI(); logger.debug("Method : {}, Request URI : {}", req.getMethod(), requestUri); Controller controller = rm.findController(requestUri); try { - String viewName = controller.execute(req, resp); - if (viewName != null) { - move(viewName, req, resp); - } + View view = controller.execute(req, resp); + view.render(req, resp); } catch (Throwable e) { - logger.error("Exception : {}", e); + logger.error("Exception: ", e); throw new ServletException(e.getMessage()); } } - - private void move(String viewName, HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - if (viewName.startsWith(DEFAULT_REDIRECT_PREFIX)) { - resp.sendRedirect(viewName.substring(DEFAULT_REDIRECT_PREFIX.length())); - return; - } - - RequestDispatcher rd = req.getRequestDispatcher(viewName); - rd.forward(req, resp); - } } diff --git a/src/main/java/core/mvc/ForwardController.java b/src/main/java/core/mvc/ForwardController.java index 83c9d89f2..aa5fd4da6 100644 --- a/src/main/java/core/mvc/ForwardController.java +++ b/src/main/java/core/mvc/ForwardController.java @@ -4,7 +4,7 @@ import javax.servlet.http.HttpServletResponse; public class ForwardController implements Controller { - private String forwardUrl; + private final String forwardUrl; public ForwardController(String forwardUrl) { this.forwardUrl = forwardUrl; @@ -14,7 +14,7 @@ public ForwardController(String forwardUrl) { } @Override - public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception { - return forwardUrl; + public View execute(HttpServletRequest req, HttpServletResponse resp) { + return new JspView(forwardUrl); } } diff --git a/src/main/java/core/mvc/JsonView.java b/src/main/java/core/mvc/JsonView.java new file mode 100644 index 000000000..7f80b5050 --- /dev/null +++ b/src/main/java/core/mvc/JsonView.java @@ -0,0 +1,32 @@ +package core.mvc; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.PrintWriter; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +public class JsonView implements View { + + @Override + public void render(final HttpServletRequest request, final HttpServletResponse response) throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + Map model = createModelFromRequest(request); + response.setContentType("application/json;charset=UTF-8"); + PrintWriter writer = response.getWriter(); + writer.print(objectMapper.writeValueAsString(model)); + } + + private Map createModelFromRequest(final HttpServletRequest request) { + Map models = new HashMap<>(); + Enumeration attributeNames = request.getAttributeNames(); + while (attributeNames.hasMoreElements()) { + String name = attributeNames.nextElement(); + models.put(name, request.getAttribute(name)); + } + return models; + } +} diff --git a/src/main/java/core/mvc/JspView.java b/src/main/java/core/mvc/JspView.java new file mode 100644 index 000000000..5b745a299 --- /dev/null +++ b/src/main/java/core/mvc/JspView.java @@ -0,0 +1,29 @@ +package core.mvc; + +import javax.servlet.RequestDispatcher; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Objects; + +public class JspView implements View { + + private static final String DEFAULT_REDIRECT_PREFIX = "redirect:"; + + private final String viewName; + + public JspView(final String viewName) { + Objects.requireNonNull(viewName, "viewName is null."); + this.viewName = viewName; + } + + @Override + public void render(final HttpServletRequest request, final HttpServletResponse response) throws Exception { + if (viewName.startsWith(DEFAULT_REDIRECT_PREFIX)) { + response.sendRedirect(viewName.substring(DEFAULT_REDIRECT_PREFIX.length())); + return; + } + + RequestDispatcher rd = request.getRequestDispatcher(viewName); + rd.forward(request, response); + } +} diff --git a/src/main/java/core/mvc/View.java b/src/main/java/core/mvc/View.java new file mode 100644 index 000000000..9bb2fc1f0 --- /dev/null +++ b/src/main/java/core/mvc/View.java @@ -0,0 +1,8 @@ +package core.mvc; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public interface View { + void render(HttpServletRequest request, HttpServletResponse response) throws Exception; +} diff --git a/src/main/java/next/controller/HomeController.java b/src/main/java/next/controller/HomeController.java index d01c085a3..c9430ce4d 100644 --- a/src/main/java/next/controller/HomeController.java +++ b/src/main/java/next/controller/HomeController.java @@ -1,16 +1,19 @@ package next.controller; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import core.mvc.Controller; +import core.mvc.JspView; +import core.mvc.View; import next.dao.QuestionDao; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + public class HomeController implements Controller { + @Override - public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception { + public View execute(HttpServletRequest req, HttpServletResponse resp) { QuestionDao questionDao = new QuestionDao(); req.setAttribute("questions", questionDao.findAll()); - return "home.jsp"; + return new JspView("home.jsp"); } } diff --git a/src/main/java/next/controller/qna/AddAnswerController.java b/src/main/java/next/controller/qna/AddAnswerController.java index e9c9acd40..1ddb0062b 100644 --- a/src/main/java/next/controller/qna/AddAnswerController.java +++ b/src/main/java/next/controller/qna/AddAnswerController.java @@ -1,34 +1,28 @@ package next.controller.qna; -import java.io.PrintWriter; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.databind.ObjectMapper; - import core.mvc.Controller; +import core.mvc.JsonView; +import core.mvc.View; import next.dao.AnswerDao; import next.model.Answer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; public class AddAnswerController implements Controller { private static final Logger log = LoggerFactory.getLogger(AddAnswerController.class); @Override - public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception { + public View execute(HttpServletRequest req, HttpServletResponse resp) { Answer answer = new Answer(req.getParameter("writer"), req.getParameter("contents"), Long.parseLong(req.getParameter("questionId"))); log.debug("answer : {}", answer); AnswerDao answerDao = new AnswerDao(); Answer savedAnswer = answerDao.insert(answer); - ObjectMapper mapper = new ObjectMapper(); - resp.setContentType("application/json;charset=UTF-8"); - PrintWriter out = resp.getWriter(); - out.print(mapper.writeValueAsString(savedAnswer)); - return null; + req.setAttribute("answer", savedAnswer); + return new JsonView(); } } diff --git a/src/main/java/next/controller/qna/DeleteAnswerController.java b/src/main/java/next/controller/qna/DeleteAnswerController.java index 169e3a617..4541c4c09 100644 --- a/src/main/java/next/controller/qna/DeleteAnswerController.java +++ b/src/main/java/next/controller/qna/DeleteAnswerController.java @@ -1,28 +1,25 @@ package next.controller.qna; -import java.io.PrintWriter; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.fasterxml.jackson.databind.ObjectMapper; - import core.mvc.Controller; +import core.mvc.JsonView; +import core.mvc.View; import next.dao.AnswerDao; import next.model.Result; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; public class DeleteAnswerController implements Controller { + private static final Logger log = LoggerFactory.getLogger(DeleteAnswerController.class); + @Override - public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception { + public View execute(HttpServletRequest req, HttpServletResponse resp) { Long answerId = Long.parseLong(req.getParameter("answerId")); AnswerDao answerDao = new AnswerDao(); - answerDao.delete(answerId); - - ObjectMapper mapper = new ObjectMapper(); - resp.setContentType("application/json;charset=UTF-8"); - PrintWriter out = resp.getWriter(); - out.print(mapper.writeValueAsString(Result.ok())); - return null; + req.setAttribute("result", Result.ok()); + return new JsonView(); } } diff --git a/src/main/java/next/controller/qna/ShowController.java b/src/main/java/next/controller/qna/ShowController.java index bdb26e683..de49f6ab0 100644 --- a/src/main/java/next/controller/qna/ShowController.java +++ b/src/main/java/next/controller/qna/ShowController.java @@ -1,20 +1,23 @@ package next.controller.qna; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import core.mvc.Controller; +import core.mvc.JspView; +import core.mvc.View; import next.dao.AnswerDao; import next.dao.QuestionDao; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + public class ShowController implements Controller { + @Override - public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception { - Long questionId = Long.parseLong(req.getParameter("questionId")); + public View execute(HttpServletRequest req, HttpServletResponse resp) { + long questionId = Long.parseLong(req.getParameter("questionId")); QuestionDao questionDao = new QuestionDao(); AnswerDao answerDao = new AnswerDao(); req.setAttribute("question", questionDao.findById(questionId)); req.setAttribute("answers", answerDao.findAllByQuestionId(questionId)); - return "/qna/show.jsp"; + return new JspView("/qna/show.jsp"); } } diff --git a/src/main/java/next/controller/user/CreateUserController.java b/src/main/java/next/controller/user/CreateUserController.java index a5db3dc06..047d6dca7 100644 --- a/src/main/java/next/controller/user/CreateUserController.java +++ b/src/main/java/next/controller/user/CreateUserController.java @@ -1,26 +1,27 @@ package next.controller.user; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import core.mvc.Controller; +import core.mvc.JspView; +import core.mvc.View; import next.dao.UserDao; import next.model.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; public class CreateUserController implements Controller { private static final Logger log = LoggerFactory.getLogger(CreateUserController.class); @Override - public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception { + public View execute(HttpServletRequest req, HttpServletResponse resp) { User user = new User(req.getParameter("userId"), req.getParameter("password"), req.getParameter("name"), req.getParameter("email")); log.debug("User : {}", user); UserDao userDao = new UserDao(); userDao.insert(user); - return "redirect:/"; + return new JspView("redirect:/"); } } diff --git a/src/main/java/next/controller/user/ListUserController.java b/src/main/java/next/controller/user/ListUserController.java index 90aec9081..c51aed3c0 100644 --- a/src/main/java/next/controller/user/ListUserController.java +++ b/src/main/java/next/controller/user/ListUserController.java @@ -1,21 +1,24 @@ package next.controller.user; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import core.mvc.Controller; +import core.mvc.JspView; +import core.mvc.View; import next.controller.UserSessionUtils; import next.dao.UserDao; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + public class ListUserController implements Controller { + @Override - public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception { + public View execute(HttpServletRequest req, HttpServletResponse resp) throws Exception { if (!UserSessionUtils.isLogined(req.getSession())) { - return "redirect:/users/loginForm"; + return new JspView("redirect:/users/loginForm"); } UserDao userDao = new UserDao(); req.setAttribute("users", userDao.findAll()); - return "/user/list.jsp"; + return new JspView("/user/list.jsp"); } } diff --git a/src/main/java/next/controller/user/LoginController.java b/src/main/java/next/controller/user/LoginController.java index 343e91e6f..1334f20ba 100644 --- a/src/main/java/next/controller/user/LoginController.java +++ b/src/main/java/next/controller/user/LoginController.java @@ -1,32 +1,35 @@ package next.controller.user; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - import core.mvc.Controller; +import core.mvc.JspView; +import core.mvc.View; import next.controller.UserSessionUtils; import next.dao.UserDao; import next.model.User; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + public class LoginController implements Controller { + @Override - public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception { + public View execute(HttpServletRequest req, HttpServletResponse resp) { String userId = req.getParameter("userId"); String password = req.getParameter("password"); UserDao userDao = new UserDao(); User user = userDao.findByUserId(userId); if (user == null) { req.setAttribute("loginFailed", true); - return "/user/login.jsp"; + return new JspView("/user/login.jsp"); } if (user.matchPassword(password)) { HttpSession session = req.getSession(); session.setAttribute(UserSessionUtils.USER_SESSION_KEY, user); - return "redirect:/"; + return new JspView("redirect:/"); } else { req.setAttribute("loginFailed", true); - return "/user/login.jsp"; + return new JspView("/user/login.jsp"); } } } diff --git a/src/main/java/next/controller/user/LogoutController.java b/src/main/java/next/controller/user/LogoutController.java index 08a8cee33..c39466cb3 100644 --- a/src/main/java/next/controller/user/LogoutController.java +++ b/src/main/java/next/controller/user/LogoutController.java @@ -1,17 +1,20 @@ package next.controller.user; +import core.mvc.Controller; +import core.mvc.JspView; +import core.mvc.View; +import next.controller.UserSessionUtils; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import core.mvc.Controller; -import next.controller.UserSessionUtils; - public class LogoutController implements Controller { + @Override - public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception { + public View execute(HttpServletRequest req, HttpServletResponse resp) { HttpSession session = req.getSession(); session.removeAttribute(UserSessionUtils.USER_SESSION_KEY); - return "redirect:/"; + return new JspView("redirect:/"); } } diff --git a/src/main/java/next/controller/user/ProfileController.java b/src/main/java/next/controller/user/ProfileController.java index cf529c3ff..7af72228f 100644 --- a/src/main/java/next/controller/user/ProfileController.java +++ b/src/main/java/next/controller/user/ProfileController.java @@ -1,15 +1,18 @@ package next.controller.user; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import core.mvc.Controller; +import core.mvc.JspView; +import core.mvc.View; import next.dao.UserDao; import next.model.User; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + public class ProfileController implements Controller { + @Override - public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception { + public View execute(HttpServletRequest req, HttpServletResponse resp) { String userId = req.getParameter("userId"); UserDao userDao = new UserDao(); User user = userDao.findByUserId(userId); @@ -17,6 +20,6 @@ public String execute(HttpServletRequest req, HttpServletResponse resp) throws E throw new NullPointerException("사용자를 찾을 수 없습니다."); } req.setAttribute("user", user); - return "/user/profile.jsp"; + return new JspView("/user/profile.jsp"); } } diff --git a/src/main/java/next/controller/user/UpdateFormUserController.java b/src/main/java/next/controller/user/UpdateFormUserController.java index 3d8650f61..7d475e6c3 100644 --- a/src/main/java/next/controller/user/UpdateFormUserController.java +++ b/src/main/java/next/controller/user/UpdateFormUserController.java @@ -1,17 +1,19 @@ package next.controller.user; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import core.mvc.Controller; +import core.mvc.JspView; +import core.mvc.View; import next.controller.UserSessionUtils; import next.dao.UserDao; import next.model.User; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + public class UpdateFormUserController implements Controller { @Override - public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception { + public View execute(HttpServletRequest req, HttpServletResponse resp) { String userId = req.getParameter("userId"); UserDao userDao = new UserDao(); User user = userDao.findByUserId(userId); @@ -19,6 +21,6 @@ public String execute(HttpServletRequest req, HttpServletResponse resp) throws E throw new IllegalStateException("다른 사용자의 정보를 수정할 수 없습니다."); } req.setAttribute("user", user); - return "/user/updateForm.jsp"; + return new JspView("/user/updateForm.jsp"); } } diff --git a/src/main/java/next/controller/user/UpdateUserController.java b/src/main/java/next/controller/user/UpdateUserController.java index 64b1ebbc8..a9d681236 100644 --- a/src/main/java/next/controller/user/UpdateUserController.java +++ b/src/main/java/next/controller/user/UpdateUserController.java @@ -1,21 +1,22 @@ package next.controller.user; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import core.mvc.Controller; +import core.mvc.JspView; +import core.mvc.View; import next.controller.UserSessionUtils; import next.dao.UserDao; import next.model.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; public class UpdateUserController implements Controller { private static final Logger log = LoggerFactory.getLogger(UpdateUserController.class); @Override - public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception { + public View execute(HttpServletRequest req, HttpServletResponse resp) { UserDao userDao = new UserDao(); User user = userDao.findByUserId(req.getParameter("userId")); if (!UserSessionUtils.isSameUser(req.getSession(), user)) { @@ -26,6 +27,6 @@ public String execute(HttpServletRequest req, HttpServletResponse resp) throws E req.getParameter("email")); log.debug("Update User : {}", updateUser); user.update(updateUser); - return "redirect:/"; + return new JspView("redirect:/"); } } From 0a12c8a9127fc8c28d5f895db3bc910ce26e6d80 Mon Sep 17 00:00:00 2001 From: Gyumin Kim Date: Fri, 7 Aug 2020 20:07:09 +0900 Subject: [PATCH 2/2] =?UTF-8?q?8=EC=9E=A5=20MVC=20=ED=94=84=EB=A0=88?= =?UTF-8?q?=EC=9E=84=EC=9B=8C=ED=81=AC=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD=202=EB=8B=A8=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * `ModelAndView` 추가 --- src/main/java/core/mvc/Controller.java | 2 +- src/main/java/core/mvc/DispatcherServlet.java | 6 ++--- src/main/java/core/mvc/ForwardController.java | 9 ++++--- src/main/java/core/mvc/JsonView.java | 3 +-- src/main/java/core/mvc/JspView.java | 9 ++++++- src/main/java/core/mvc/ModelAndView.java | 27 +++++++++++++++++++ src/main/java/core/mvc/View.java | 3 ++- .../next/controller/AbstractController.java | 16 +++++++++++ .../java/next/controller/HomeController.java | 11 ++++---- .../controller/qna/AddAnswerController.java | 14 +++++----- .../qna/DeleteAnswerController.java | 13 +++++---- .../next/controller/qna/ShowController.java | 15 +++++------ .../controller/user/CreateUserController.java | 12 ++++----- .../controller/user/ListUserController.java | 15 +++++------ .../next/controller/user/LoginController.java | 21 +++++++-------- .../controller/user/LogoutController.java | 11 ++++---- .../controller/user/ProfileController.java | 13 +++++---- .../user/UpdateFormUserController.java | 13 +++++---- .../controller/user/UpdateUserController.java | 11 ++++---- 19 files changed, 134 insertions(+), 90 deletions(-) create mode 100644 src/main/java/core/mvc/ModelAndView.java create mode 100644 src/main/java/next/controller/AbstractController.java diff --git a/src/main/java/core/mvc/Controller.java b/src/main/java/core/mvc/Controller.java index 4fe54694f..949439cc7 100644 --- a/src/main/java/core/mvc/Controller.java +++ b/src/main/java/core/mvc/Controller.java @@ -4,5 +4,5 @@ import javax.servlet.http.HttpServletResponse; public interface Controller { - View execute(HttpServletRequest req, HttpServletResponse resp) throws Exception; + ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) throws Exception; } diff --git a/src/main/java/core/mvc/DispatcherServlet.java b/src/main/java/core/mvc/DispatcherServlet.java index 9a3193532..6e4001f4a 100644 --- a/src/main/java/core/mvc/DispatcherServlet.java +++ b/src/main/java/core/mvc/DispatcherServlet.java @@ -13,7 +13,6 @@ public class DispatcherServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final Logger logger = LoggerFactory.getLogger(DispatcherServlet.class); - private static final String DEFAULT_REDIRECT_PREFIX = "redirect:"; private RequestMapping rm; @@ -30,8 +29,9 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws Controller controller = rm.findController(requestUri); try { - View view = controller.execute(req, resp); - view.render(req, resp); + ModelAndView modelAndView = controller.execute(req, resp); + View view = modelAndView.getView(); + view.render(modelAndView.getModel(), req, resp); } catch (Throwable e) { logger.error("Exception: ", e); throw new ServletException(e.getMessage()); diff --git a/src/main/java/core/mvc/ForwardController.java b/src/main/java/core/mvc/ForwardController.java index aa5fd4da6..90a701fa7 100644 --- a/src/main/java/core/mvc/ForwardController.java +++ b/src/main/java/core/mvc/ForwardController.java @@ -1,20 +1,23 @@ package core.mvc; +import next.controller.AbstractController; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -public class ForwardController implements Controller { +public class ForwardController extends AbstractController { private final String forwardUrl; public ForwardController(String forwardUrl) { this.forwardUrl = forwardUrl; + // TODO: null 체크를 생성자 첫 줄에서 하는 건 어떨까? + Objects.requireNonNull() if (forwardUrl == null) { throw new NullPointerException("forwardUrl is null. 이동할 URL을 입력하세요."); } } @Override - public View execute(HttpServletRequest req, HttpServletResponse resp) { - return new JspView(forwardUrl); + public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) { + return jspView(forwardUrl); } } diff --git a/src/main/java/core/mvc/JsonView.java b/src/main/java/core/mvc/JsonView.java index 7f80b5050..37184f72c 100644 --- a/src/main/java/core/mvc/JsonView.java +++ b/src/main/java/core/mvc/JsonView.java @@ -12,9 +12,8 @@ public class JsonView implements View { @Override - public void render(final HttpServletRequest request, final HttpServletResponse response) throws Exception { + public void render(final Map model, final HttpServletRequest request, final HttpServletResponse response) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); - Map model = createModelFromRequest(request); response.setContentType("application/json;charset=UTF-8"); PrintWriter writer = response.getWriter(); writer.print(objectMapper.writeValueAsString(model)); diff --git a/src/main/java/core/mvc/JspView.java b/src/main/java/core/mvc/JspView.java index 5b745a299..52acbdeea 100644 --- a/src/main/java/core/mvc/JspView.java +++ b/src/main/java/core/mvc/JspView.java @@ -3,7 +3,9 @@ import javax.servlet.RequestDispatcher; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.util.Map; import java.util.Objects; +import java.util.Set; public class JspView implements View { @@ -17,12 +19,17 @@ public JspView(final String viewName) { } @Override - public void render(final HttpServletRequest request, final HttpServletResponse response) throws Exception { + public void render(final Map model, final HttpServletRequest request, final HttpServletResponse response) throws Exception { if (viewName.startsWith(DEFAULT_REDIRECT_PREFIX)) { response.sendRedirect(viewName.substring(DEFAULT_REDIRECT_PREFIX.length())); return; } + Set keys = model.keySet(); + for (String key : keys) { + request.setAttribute(key, model.get(key)); + } + RequestDispatcher rd = request.getRequestDispatcher(viewName); rd.forward(request, response); } diff --git a/src/main/java/core/mvc/ModelAndView.java b/src/main/java/core/mvc/ModelAndView.java new file mode 100644 index 000000000..0bef62053 --- /dev/null +++ b/src/main/java/core/mvc/ModelAndView.java @@ -0,0 +1,27 @@ +package core.mvc; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class ModelAndView { + private final View view; + private final Map model = new HashMap<>(); + + public ModelAndView(final View view) { + this.view = view; + } + + public ModelAndView addObject(final String attributeName, final Object attributeValue) { + model.put(attributeName, attributeValue); + return this; + } + + public View getView() { + return view; + } + + public Map getModel() { + return Collections.unmodifiableMap(model); + } +} diff --git a/src/main/java/core/mvc/View.java b/src/main/java/core/mvc/View.java index 9bb2fc1f0..c7d814ee3 100644 --- a/src/main/java/core/mvc/View.java +++ b/src/main/java/core/mvc/View.java @@ -2,7 +2,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.util.Map; public interface View { - void render(HttpServletRequest request, HttpServletResponse response) throws Exception; + void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception; } diff --git a/src/main/java/next/controller/AbstractController.java b/src/main/java/next/controller/AbstractController.java new file mode 100644 index 000000000..672996d50 --- /dev/null +++ b/src/main/java/next/controller/AbstractController.java @@ -0,0 +1,16 @@ +package next.controller; + +import core.mvc.Controller; +import core.mvc.JsonView; +import core.mvc.JspView; +import core.mvc.ModelAndView; + +public abstract class AbstractController implements Controller { + protected ModelAndView jspView(String forwardUrl) { + return new ModelAndView(new JspView(forwardUrl)); + } + + protected ModelAndView jsonView() { + return new ModelAndView(new JsonView()); + } +} diff --git a/src/main/java/next/controller/HomeController.java b/src/main/java/next/controller/HomeController.java index c9430ce4d..1100b7be7 100644 --- a/src/main/java/next/controller/HomeController.java +++ b/src/main/java/next/controller/HomeController.java @@ -1,19 +1,18 @@ package next.controller; -import core.mvc.Controller; -import core.mvc.JspView; -import core.mvc.View; +import core.mvc.ModelAndView; import next.dao.QuestionDao; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -public class HomeController implements Controller { +public class HomeController extends AbstractController { @Override - public View execute(HttpServletRequest req, HttpServletResponse resp) { + public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) { QuestionDao questionDao = new QuestionDao(); req.setAttribute("questions", questionDao.findAll()); - return new JspView("home.jsp"); + return jspView("home.jsp") + .addObject("questions", questionDao.findAll()); } } diff --git a/src/main/java/next/controller/qna/AddAnswerController.java b/src/main/java/next/controller/qna/AddAnswerController.java index 1ddb0062b..2067acb22 100644 --- a/src/main/java/next/controller/qna/AddAnswerController.java +++ b/src/main/java/next/controller/qna/AddAnswerController.java @@ -1,8 +1,7 @@ package next.controller.qna; -import core.mvc.Controller; -import core.mvc.JsonView; -import core.mvc.View; +import core.mvc.ModelAndView; +import next.controller.AbstractController; import next.dao.AnswerDao; import next.model.Answer; import org.slf4j.Logger; @@ -11,18 +10,19 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -public class AddAnswerController implements Controller { +public class AddAnswerController extends AbstractController { private static final Logger log = LoggerFactory.getLogger(AddAnswerController.class); @Override - public View execute(HttpServletRequest req, HttpServletResponse resp) { + public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) { + // TODO: Answer에 Builder 패턴 적용, 아래에서 사용 Answer answer = new Answer(req.getParameter("writer"), req.getParameter("contents"), Long.parseLong(req.getParameter("questionId"))); log.debug("answer : {}", answer); AnswerDao answerDao = new AnswerDao(); Answer savedAnswer = answerDao.insert(answer); - req.setAttribute("answer", savedAnswer); - return new JsonView(); + return jsonView() + .addObject("answer", savedAnswer); } } diff --git a/src/main/java/next/controller/qna/DeleteAnswerController.java b/src/main/java/next/controller/qna/DeleteAnswerController.java index 4541c4c09..a946e33ca 100644 --- a/src/main/java/next/controller/qna/DeleteAnswerController.java +++ b/src/main/java/next/controller/qna/DeleteAnswerController.java @@ -1,8 +1,7 @@ package next.controller.qna; -import core.mvc.Controller; -import core.mvc.JsonView; -import core.mvc.View; +import core.mvc.ModelAndView; +import next.controller.AbstractController; import next.dao.AnswerDao; import next.model.Result; import org.slf4j.Logger; @@ -11,15 +10,15 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -public class DeleteAnswerController implements Controller { +public class DeleteAnswerController extends AbstractController { private static final Logger log = LoggerFactory.getLogger(DeleteAnswerController.class); @Override - public View execute(HttpServletRequest req, HttpServletResponse resp) { + public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) { Long answerId = Long.parseLong(req.getParameter("answerId")); AnswerDao answerDao = new AnswerDao(); answerDao.delete(answerId); - req.setAttribute("result", Result.ok()); - return new JsonView(); + return jsonView() + .addObject("result", Result.ok()); } } diff --git a/src/main/java/next/controller/qna/ShowController.java b/src/main/java/next/controller/qna/ShowController.java index de49f6ab0..2e0b64795 100644 --- a/src/main/java/next/controller/qna/ShowController.java +++ b/src/main/java/next/controller/qna/ShowController.java @@ -1,23 +1,22 @@ package next.controller.qna; -import core.mvc.Controller; -import core.mvc.JspView; -import core.mvc.View; +import core.mvc.ModelAndView; +import next.controller.AbstractController; import next.dao.AnswerDao; import next.dao.QuestionDao; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -public class ShowController implements Controller { +public class ShowController extends AbstractController { @Override - public View execute(HttpServletRequest req, HttpServletResponse resp) { + public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) { long questionId = Long.parseLong(req.getParameter("questionId")); QuestionDao questionDao = new QuestionDao(); AnswerDao answerDao = new AnswerDao(); - req.setAttribute("question", questionDao.findById(questionId)); - req.setAttribute("answers", answerDao.findAllByQuestionId(questionId)); - return new JspView("/qna/show.jsp"); + return jspView("/qna/show.jsp") + .addObject("question", questionDao.findById(questionId)) + .addObject("answers", answerDao.findAllByQuestionId(questionId)); } } diff --git a/src/main/java/next/controller/user/CreateUserController.java b/src/main/java/next/controller/user/CreateUserController.java index 047d6dca7..109975b3e 100644 --- a/src/main/java/next/controller/user/CreateUserController.java +++ b/src/main/java/next/controller/user/CreateUserController.java @@ -1,8 +1,7 @@ package next.controller.user; -import core.mvc.Controller; -import core.mvc.JspView; -import core.mvc.View; +import core.mvc.ModelAndView; +import next.controller.AbstractController; import next.dao.UserDao; import next.model.User; import org.slf4j.Logger; @@ -11,17 +10,18 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -public class CreateUserController implements Controller { +public class CreateUserController extends AbstractController { private static final Logger log = LoggerFactory.getLogger(CreateUserController.class); @Override - public View execute(HttpServletRequest req, HttpServletResponse resp) { + public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) { + // TODO: User에 Builder 패턴 적용, 아래에서 사용 User user = new User(req.getParameter("userId"), req.getParameter("password"), req.getParameter("name"), req.getParameter("email")); log.debug("User : {}", user); UserDao userDao = new UserDao(); userDao.insert(user); - return new JspView("redirect:/"); + return jspView("redirect:/"); } } diff --git a/src/main/java/next/controller/user/ListUserController.java b/src/main/java/next/controller/user/ListUserController.java index c51aed3c0..4ad179b2a 100644 --- a/src/main/java/next/controller/user/ListUserController.java +++ b/src/main/java/next/controller/user/ListUserController.java @@ -1,24 +1,23 @@ package next.controller.user; -import core.mvc.Controller; -import core.mvc.JspView; -import core.mvc.View; +import core.mvc.ModelAndView; +import next.controller.AbstractController; import next.controller.UserSessionUtils; import next.dao.UserDao; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -public class ListUserController implements Controller { +public class ListUserController extends AbstractController { @Override - public View execute(HttpServletRequest req, HttpServletResponse resp) throws Exception { + public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) throws Exception { if (!UserSessionUtils.isLogined(req.getSession())) { - return new JspView("redirect:/users/loginForm"); + return jspView("redirect:/users/loginForm"); } UserDao userDao = new UserDao(); - req.setAttribute("users", userDao.findAll()); - return new JspView("/user/list.jsp"); + return jspView("/user/list.jsp") + .addObject("users", userDao.findAll()); } } diff --git a/src/main/java/next/controller/user/LoginController.java b/src/main/java/next/controller/user/LoginController.java index 1334f20ba..207077c86 100644 --- a/src/main/java/next/controller/user/LoginController.java +++ b/src/main/java/next/controller/user/LoginController.java @@ -1,8 +1,7 @@ package next.controller.user; -import core.mvc.Controller; -import core.mvc.JspView; -import core.mvc.View; +import core.mvc.ModelAndView; +import next.controller.AbstractController; import next.controller.UserSessionUtils; import next.dao.UserDao; import next.model.User; @@ -11,25 +10,25 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -public class LoginController implements Controller { +public class LoginController extends AbstractController { @Override - public View execute(HttpServletRequest req, HttpServletResponse resp) { + public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) { String userId = req.getParameter("userId"); String password = req.getParameter("password"); UserDao userDao = new UserDao(); User user = userDao.findByUserId(userId); if (user == null) { - req.setAttribute("loginFailed", true); - return new JspView("/user/login.jsp"); + return jspView("/user/login.jsp") + .addObject("loginFailed", true); } if (user.matchPassword(password)) { HttpSession session = req.getSession(); - session.setAttribute(UserSessionUtils.USER_SESSION_KEY, user); - return new JspView("redirect:/"); + return jspView("redirect:/") + .addObject(UserSessionUtils.USER_SESSION_KEY, user); } else { - req.setAttribute("loginFailed", true); - return new JspView("/user/login.jsp"); + return jspView("/user/login.jsp") + .addObject("loginFailed", true); } } } diff --git a/src/main/java/next/controller/user/LogoutController.java b/src/main/java/next/controller/user/LogoutController.java index c39466cb3..77ca7ff30 100644 --- a/src/main/java/next/controller/user/LogoutController.java +++ b/src/main/java/next/controller/user/LogoutController.java @@ -1,20 +1,19 @@ package next.controller.user; -import core.mvc.Controller; -import core.mvc.JspView; -import core.mvc.View; +import core.mvc.ModelAndView; +import next.controller.AbstractController; import next.controller.UserSessionUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -public class LogoutController implements Controller { +public class LogoutController extends AbstractController { @Override - public View execute(HttpServletRequest req, HttpServletResponse resp) { + public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) { HttpSession session = req.getSession(); session.removeAttribute(UserSessionUtils.USER_SESSION_KEY); - return new JspView("redirect:/"); + return jspView("redirect:/"); } } diff --git a/src/main/java/next/controller/user/ProfileController.java b/src/main/java/next/controller/user/ProfileController.java index 7af72228f..1ec0842c2 100644 --- a/src/main/java/next/controller/user/ProfileController.java +++ b/src/main/java/next/controller/user/ProfileController.java @@ -1,25 +1,24 @@ package next.controller.user; -import core.mvc.Controller; -import core.mvc.JspView; -import core.mvc.View; +import core.mvc.ModelAndView; +import next.controller.AbstractController; import next.dao.UserDao; import next.model.User; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -public class ProfileController implements Controller { +public class ProfileController extends AbstractController { @Override - public View execute(HttpServletRequest req, HttpServletResponse resp) { + public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) { String userId = req.getParameter("userId"); UserDao userDao = new UserDao(); User user = userDao.findByUserId(userId); if (user == null) { throw new NullPointerException("사용자를 찾을 수 없습니다."); } - req.setAttribute("user", user); - return new JspView("/user/profile.jsp"); + return jspView("/user/profile.jsp") + .addObject("user", user); } } diff --git a/src/main/java/next/controller/user/UpdateFormUserController.java b/src/main/java/next/controller/user/UpdateFormUserController.java index 7d475e6c3..568caee96 100644 --- a/src/main/java/next/controller/user/UpdateFormUserController.java +++ b/src/main/java/next/controller/user/UpdateFormUserController.java @@ -1,8 +1,7 @@ package next.controller.user; -import core.mvc.Controller; -import core.mvc.JspView; -import core.mvc.View; +import core.mvc.ModelAndView; +import next.controller.AbstractController; import next.controller.UserSessionUtils; import next.dao.UserDao; import next.model.User; @@ -10,17 +9,17 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -public class UpdateFormUserController implements Controller { +public class UpdateFormUserController extends AbstractController { @Override - public View execute(HttpServletRequest req, HttpServletResponse resp) { + public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) { String userId = req.getParameter("userId"); UserDao userDao = new UserDao(); User user = userDao.findByUserId(userId); if (!UserSessionUtils.isSameUser(req.getSession(), user)) { throw new IllegalStateException("다른 사용자의 정보를 수정할 수 없습니다."); } - req.setAttribute("user", user); - return new JspView("/user/updateForm.jsp"); + return jspView("/user/updateForm.jsp") + .addObject("user", user); } } diff --git a/src/main/java/next/controller/user/UpdateUserController.java b/src/main/java/next/controller/user/UpdateUserController.java index a9d681236..ecaf82c5b 100644 --- a/src/main/java/next/controller/user/UpdateUserController.java +++ b/src/main/java/next/controller/user/UpdateUserController.java @@ -1,8 +1,7 @@ package next.controller.user; -import core.mvc.Controller; -import core.mvc.JspView; -import core.mvc.View; +import core.mvc.ModelAndView; +import next.controller.AbstractController; import next.controller.UserSessionUtils; import next.dao.UserDao; import next.model.User; @@ -12,11 +11,11 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -public class UpdateUserController implements Controller { +public class UpdateUserController extends AbstractController { private static final Logger log = LoggerFactory.getLogger(UpdateUserController.class); @Override - public View execute(HttpServletRequest req, HttpServletResponse resp) { + public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) { UserDao userDao = new UserDao(); User user = userDao.findByUserId(req.getParameter("userId")); if (!UserSessionUtils.isSameUser(req.getSession(), user)) { @@ -27,6 +26,6 @@ public View execute(HttpServletRequest req, HttpServletResponse resp) { req.getParameter("email")); log.debug("Update User : {}", updateUser); user.update(updateUser); - return new JspView("redirect:/"); + return jspView("redirect:/"); } }