From 57802863acbf897a999dd76b546f1a881786e43d Mon Sep 17 00:00:00 2001 From: Miseong Kim Date: Mon, 25 Sep 2023 01:09:22 +0900 Subject: [PATCH 01/13] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/servlet/mvc/tobe/AnnotationHandlerMapping.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java index 75284972db..0811ab08a8 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java @@ -33,12 +33,12 @@ public AnnotationHandlerMapping(final Object... basePackage) { @Override public void initialize() { for (final Object basePackage : basePackages) { - initHandlerExecution(basePackage); + registerHandlerWithAnnotation(basePackage); } log.info("Initialized AnnotationHandlerMapping!"); } - private void initHandlerExecution(final Object basePackage) { + private void registerHandlerWithAnnotation(final Object basePackage) { final Set> classes = getClassesByAnnotation(basePackage, Controller.class); for (final Class clazz : classes) { final List methods = getMethodsByAnnotation(clazz, RequestMapping.class); From 31952acb776dd2ad1ab0e4fc3e72e2b608108b12 Mon Sep 17 00:00:00 2001 From: Miseong Kim Date: Mon, 25 Sep 2023 14:54:25 +0900 Subject: [PATCH 02/13] =?UTF-8?q?feat:=20JsonView=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/servlet/view/JsonView.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java index b42c3466f0..30708715cd 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java @@ -1,14 +1,27 @@ package webmvc.org.springframework.web.servlet.view; +import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.View; - +import java.io.PrintWriter; import java.util.Map; +import web.org.springframework.http.MediaType; +import webmvc.org.springframework.web.servlet.View; public class JsonView implements View { + private final ObjectMapper mapper = new ObjectMapper(); + @Override - public void render(final Map model, final HttpServletRequest request, HttpServletResponse response) throws Exception { + public void render(final Map model, final HttpServletRequest request, final HttpServletResponse response) + throws Exception { + response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); + + final PrintWriter writer = response.getWriter(); + if (model.size() == 1) { + writer.write(mapper.writeValueAsString(model.values().toArray()[0])); + return; + } + writer.write(mapper.writeValueAsString(model)); } } From 839d97c30e666d60ca0878de4bed2fea28865eaf Mon Sep 17 00:00:00 2001 From: Miseong Kim Date: Mon, 25 Sep 2023 16:41:57 +0900 Subject: [PATCH 03/13] =?UTF-8?q?feat:=20ViewResolver=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/techcourse/DispatcherServlet.java | 25 +++++++++++--- .../techcourse/controller/UserController.java | 32 +++++++++++++++++ .../controller/UserControllerTest.java | 34 +++++++++++++++++++ .../web/servlet/ModelAndView.java | 6 ++-- .../servlet/mvc/tobe/HandlerExecution.java | 10 +++++- .../servlet/mvc/tobe/JsonViewResolver.java | 17 ++++++++++ .../web/servlet/mvc/tobe/JspViewResolver.java | 22 ++++++++++++ .../mvc/tobe/ManualHandlerAdapter.java | 3 +- .../web/servlet/mvc/tobe/ViewResolver.java | 10 ++++++ .../mvc/tobe/ViewResolverException.java | 8 +++++ .../mvc/tobe/ManualHandlerAdapterTest.java | 3 +- 11 files changed, 158 insertions(+), 12 deletions(-) create mode 100644 app/src/main/java/com/techcourse/controller/UserController.java create mode 100644 app/src/test/java/com/techcourse/controller/UserControllerTest.java create mode 100644 mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/JsonViewResolver.java create mode 100644 mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/JspViewResolver.java create mode 100644 mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ViewResolver.java create mode 100644 mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ViewResolverException.java diff --git a/app/src/main/java/com/techcourse/DispatcherServlet.java b/app/src/main/java/com/techcourse/DispatcherServlet.java index 82a4f9791a..f8de7ad4b1 100644 --- a/app/src/main/java/com/techcourse/DispatcherServlet.java +++ b/app/src/main/java/com/techcourse/DispatcherServlet.java @@ -17,7 +17,10 @@ import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerAdapterException; import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerMapping; import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerMappingException; -import webmvc.org.springframework.web.servlet.mvc.tobe.ManualHandlerAdapter; +import webmvc.org.springframework.web.servlet.mvc.tobe.JsonViewResolver; +import webmvc.org.springframework.web.servlet.mvc.tobe.JspViewResolver; +import webmvc.org.springframework.web.servlet.mvc.tobe.ViewResolver; +import webmvc.org.springframework.web.servlet.mvc.tobe.ViewResolverException; public class DispatcherServlet extends HttpServlet { @@ -26,6 +29,7 @@ public class DispatcherServlet extends HttpServlet { private final List handlerMappings = new ArrayList<>(); private final List handlerAdapters = new ArrayList<>(); + private final List viewResolvers = new ArrayList<>(); public DispatcherServlet() { } @@ -34,10 +38,10 @@ public DispatcherServlet() { public void init() { initHandlerMappings(); initHandlerAdapters(); + initViewResolvers(); } private void initHandlerMappings() { - handlerMappings.add(new WrappedManualHandlerMapping()); handlerMappings.add(new AnnotationHandlerMapping(getClass().getPackageName())); for (final HandlerMapping handlerMapping : handlerMappings) { handlerMapping.initialize(); @@ -45,10 +49,14 @@ private void initHandlerMappings() { } private void initHandlerAdapters() { - handlerAdapters.add(new ManualHandlerAdapter()); handlerAdapters.add(new AnnotationHandlerAdapter()); } + private void initViewResolvers() { + viewResolvers.add(new JspViewResolver()); + viewResolvers.add(new JsonViewResolver()); + } + @Override protected void service(final HttpServletRequest request, final HttpServletResponse response) throws ServletException { @@ -59,7 +67,7 @@ protected void service(final HttpServletRequest request, final HttpServletRespon final Object handler = getHandler(request); final HandlerAdapter handlerAdapter = getHandlerAdapter(handler); final ModelAndView modelAndView = handlerAdapter.handle(handler, request, response); - final View view = modelAndView.getView(); + final View view = getView(modelAndView); final Map model = modelAndView.getModel(); view.render(model, request, response); } catch (final Throwable e) { @@ -68,6 +76,15 @@ protected void service(final HttpServletRequest request, final HttpServletRespon } } + private View getView(final ModelAndView modelAndView) { + final Object view = modelAndView.getView(); + return viewResolvers.stream() + .filter(viewResolver -> viewResolver.supports(view)) + .findFirst() + .map(viewResolver -> viewResolver.resolve(view)) + .orElseThrow(() -> new ViewResolverException("해당 요청에 대한 view를 처리할 수 없습니다.")); + } + private Object getHandler(final HttpServletRequest request) { for (final HandlerMapping handlerMapping : handlerMappings) { final Object handler = handlerMapping.getHandler(request); diff --git a/app/src/main/java/com/techcourse/controller/UserController.java b/app/src/main/java/com/techcourse/controller/UserController.java new file mode 100644 index 0000000000..fded092b32 --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/UserController.java @@ -0,0 +1,32 @@ +package com.techcourse.controller; + +import com.techcourse.domain.User; +import com.techcourse.repository.InMemoryUserRepository; +import context.org.springframework.stereotype.Controller; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.view.JsonView; + +@Controller +public class UserController { + + private static final Logger log = LoggerFactory.getLogger(UserController.class); + + @RequestMapping(value = "/api/user", method = RequestMethod.GET) + public ModelAndView show(final HttpServletRequest request, final HttpServletResponse response) { + final String account = request.getParameter("account"); + log.debug("user id : {}", account); + + final ModelAndView modelAndView = new ModelAndView(new JsonView()); + final User user = InMemoryUserRepository.findByAccount(account) + .orElseThrow(); + + modelAndView.addObject("user", user); + return modelAndView; + } +} diff --git a/app/src/test/java/com/techcourse/controller/UserControllerTest.java b/app/src/test/java/com/techcourse/controller/UserControllerTest.java new file mode 100644 index 0000000000..4b1a33c9ce --- /dev/null +++ b/app/src/test/java/com/techcourse/controller/UserControllerTest.java @@ -0,0 +1,34 @@ +package com.techcourse.controller; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.techcourse.DispatcherServlet; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import org.junit.jupiter.api.Test; +import web.org.springframework.http.MediaType; +import webmvc.org.springframework.web.servlet.ModelAndView; + +class UserControllerTest { + + @Test + void 유저_정보를_반환한다() throws ServletException, IOException { + final var request = mock(HttpServletRequest.class); + final var response = mock(HttpServletResponse.class); + final ModelAndView modelAndView = mock(ModelAndView.class); + + when(request.getParameter("account")).thenReturn("gugu"); + when(request.getRequestURI()).thenReturn("/api/user"); + when(request.getMethod()).thenReturn("GET"); + + final DispatcherServlet dispatcherServlet = new DispatcherServlet(); + dispatcherServlet.init(); + dispatcherServlet.service(request, response); + + assertThat(response.getContentType()).isEqualTo(MediaType.APPLICATION_JSON_UTF8_VALUE); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java index ff8e24553f..ec371d84cc 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java @@ -6,10 +6,10 @@ public class ModelAndView { - private final View view; + private final Object view; private final Map model; - public ModelAndView(final View view) { + public ModelAndView(final Object view) { this.view = view; this.model = new HashMap<>(); } @@ -27,7 +27,7 @@ public Map getModel() { return Collections.unmodifiableMap(model); } - public View getView() { + public Object getView() { return view; } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java index 52ce9aba7d..54fdcc20e6 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java @@ -4,6 +4,7 @@ import jakarta.servlet.http.HttpServletResponse; import java.lang.reflect.Method; import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.view.JsonView; public class HandlerExecution { @@ -16,6 +17,13 @@ public HandlerExecution(final Object handler, final Method method) { } public ModelAndView handle(final HttpServletRequest request, final HttpServletResponse response) throws Exception { - return (ModelAndView) method.invoke(handler, request, response); + final Object result = method.invoke(handler, request, response); + if (result instanceof ModelAndView) { + return (ModelAndView) result; + } + if (result == null) { + return new ModelAndView(new JsonView()); + } + return new ModelAndView(result); } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/JsonViewResolver.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/JsonViewResolver.java new file mode 100644 index 0000000000..d49a6a565b --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/JsonViewResolver.java @@ -0,0 +1,17 @@ +package webmvc.org.springframework.web.servlet.mvc.tobe; + +import webmvc.org.springframework.web.servlet.View; +import webmvc.org.springframework.web.servlet.view.JsonView; + +public class JsonViewResolver implements ViewResolver { + + @Override + public boolean supports(final Object view) { + return view == null || view instanceof JsonView; + } + + @Override + public View resolve(final Object view) { + return new JsonView(); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/JspViewResolver.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/JspViewResolver.java new file mode 100644 index 0000000000..27d67d2483 --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/JspViewResolver.java @@ -0,0 +1,22 @@ +package webmvc.org.springframework.web.servlet.mvc.tobe; + +import webmvc.org.springframework.web.servlet.View; +import webmvc.org.springframework.web.servlet.view.JspView; + +public class JspViewResolver implements ViewResolver { + + private static final String JSP_SUFFIX = ".jsp"; + + @Override + public boolean supports(final Object view) { + if (view instanceof String) { + return ((String) view).endsWith(JSP_SUFFIX); + } + return false; + } + + @Override + public View resolve(final Object view) { + return new JspView((String) view); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapter.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapter.java index 2f968bccc0..80c2b87e26 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapter.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapter.java @@ -4,7 +4,6 @@ import jakarta.servlet.http.HttpServletResponse; import webmvc.org.springframework.web.servlet.ModelAndView; import webmvc.org.springframework.web.servlet.mvc.asis.Controller; -import webmvc.org.springframework.web.servlet.view.JspView; public class ManualHandlerAdapter implements HandlerAdapter { @@ -19,6 +18,6 @@ public ModelAndView handle(final Object handler, final HttpServletResponse response) throws Exception { final Controller controller = (Controller) handler; final String viewName = controller.execute(request, response); - return new ModelAndView(new JspView(viewName)); + return new ModelAndView(viewName); } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ViewResolver.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ViewResolver.java new file mode 100644 index 0000000000..319b97dc95 --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ViewResolver.java @@ -0,0 +1,10 @@ +package webmvc.org.springframework.web.servlet.mvc.tobe; + +import webmvc.org.springframework.web.servlet.View; + +public interface ViewResolver { + + boolean supports(Object view); + + View resolve(Object view); +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ViewResolverException.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ViewResolverException.java new file mode 100644 index 0000000000..9bb5194b49 --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ViewResolverException.java @@ -0,0 +1,8 @@ +package webmvc.org.springframework.web.servlet.mvc.tobe; + +public class ViewResolverException extends RuntimeException { + + public ViewResolverException(final String message) { + super(message); + } +} diff --git a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapterTest.java b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapterTest.java index 53d2b4b7df..961718ca4c 100644 --- a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapterTest.java +++ b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapterTest.java @@ -10,7 +10,6 @@ import org.junit.jupiter.api.Test; import webmvc.org.springframework.web.servlet.ModelAndView; import webmvc.org.springframework.web.servlet.mvc.asis.Controller; -import webmvc.org.springframework.web.servlet.view.JspView; class ManualHandlerAdapterTest { @@ -59,7 +58,7 @@ void setUp() { final ModelAndView modelAndView = handlerAdapter.handle(handler, request, response); // then - assertThat(modelAndView.getView().getClass()).isEqualTo(JspView.class); + assertThat(modelAndView.getView()).isEqualTo("test.jsp"); } static class TestController implements Controller { From e2ee62885cc748f89ff670f3f401876e27c3e1c7 Mon Sep 17 00:00:00 2001 From: Miseong Kim Date: Mon, 25 Sep 2023 17:04:53 +0900 Subject: [PATCH 04/13] =?UTF-8?q?refactor:=20Legacy=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/techcourse/ManualHandlerMapping.java | 38 ------------------- .../WrappedManualHandlerMapping.java | 19 ---------- .../controller/ForwardController.java | 18 +++++++++ .../controller/LoginController.java | 9 +++-- .../controller/LoginViewController.java | 9 +++-- .../controller/LogoutController.java | 9 +++-- .../controller/RegisterController.java | 9 +++-- .../controller/RegisterViewController.java | 9 +++-- .../web/servlet/mvc/asis/Controller.java | 8 ---- .../servlet/mvc/asis/ForwardController.java | 20 ---------- .../mvc/tobe/ManualHandlerAdapter.java | 23 ----------- 11 files changed, 48 insertions(+), 123 deletions(-) delete mode 100644 app/src/main/java/com/techcourse/ManualHandlerMapping.java delete mode 100644 app/src/main/java/com/techcourse/WrappedManualHandlerMapping.java create mode 100644 app/src/main/java/com/techcourse/controller/ForwardController.java delete mode 100644 mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/Controller.java delete mode 100644 mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/ForwardController.java delete mode 100644 mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapter.java diff --git a/app/src/main/java/com/techcourse/ManualHandlerMapping.java b/app/src/main/java/com/techcourse/ManualHandlerMapping.java deleted file mode 100644 index 55189ce45a..0000000000 --- a/app/src/main/java/com/techcourse/ManualHandlerMapping.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.techcourse; - -import com.techcourse.controller.LoginController; -import com.techcourse.controller.LoginViewController; -import com.techcourse.controller.LogoutController; -import com.techcourse.controller.RegisterController; -import com.techcourse.controller.RegisterViewController; -import java.util.HashMap; -import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; -import webmvc.org.springframework.web.servlet.mvc.asis.ForwardController; - -public class ManualHandlerMapping { - - private static final Logger log = LoggerFactory.getLogger(ManualHandlerMapping.class); - - private static final Map controllers = new HashMap<>(); - - public void initialize() { - controllers.put("/", new ForwardController("/index.jsp")); - controllers.put("/login", new LoginController()); - controllers.put("/login/view", new LoginViewController()); - controllers.put("/logout", new LogoutController()); - controllers.put("/register/view", new RegisterViewController()); - controllers.put("/register", new RegisterController()); - - log.info("Initialized Handler Mapping!"); - controllers.keySet() - .forEach(path -> log.info("Path : {}, Controller : {}", path, controllers.get(path).getClass())); - } - - public Controller getHandler(final String requestURI) { - log.debug("Request Mapping Uri : {}", requestURI); - return controllers.get(requestURI); - } -} diff --git a/app/src/main/java/com/techcourse/WrappedManualHandlerMapping.java b/app/src/main/java/com/techcourse/WrappedManualHandlerMapping.java deleted file mode 100644 index cf08592136..0000000000 --- a/app/src/main/java/com/techcourse/WrappedManualHandlerMapping.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.techcourse; - -import jakarta.servlet.http.HttpServletRequest; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerMapping; - -public class WrappedManualHandlerMapping implements HandlerMapping { - - private final ManualHandlerMapping handlerMapping = new ManualHandlerMapping(); - - @Override - public void initialize() { - handlerMapping.initialize(); - } - - @Override - public Object getHandler(final HttpServletRequest request) { - return handlerMapping.getHandler(request.getRequestURI()); - } -} diff --git a/app/src/main/java/com/techcourse/controller/ForwardController.java b/app/src/main/java/com/techcourse/controller/ForwardController.java new file mode 100644 index 0000000000..aa0af0112f --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/ForwardController.java @@ -0,0 +1,18 @@ +package com.techcourse.controller; + +import context.org.springframework.stereotype.Controller; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; + +@Controller +public class ForwardController { + + private static final String PATH = "/index.jsp"; + + @RequestMapping(value = "/", method = RequestMethod.GET) + public String execute(final HttpServletRequest request, final HttpServletResponse response) { + return PATH; + } +} diff --git a/app/src/main/java/com/techcourse/controller/LoginController.java b/app/src/main/java/com/techcourse/controller/LoginController.java index 0428fe109e..d08dd9da15 100644 --- a/app/src/main/java/com/techcourse/controller/LoginController.java +++ b/app/src/main/java/com/techcourse/controller/LoginController.java @@ -2,17 +2,20 @@ import com.techcourse.domain.User; import com.techcourse.repository.InMemoryUserRepository; +import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; -public class LoginController implements Controller { +@Controller +public class LoginController { private static final Logger log = LoggerFactory.getLogger(LoginController.class); - @Override + @RequestMapping(value = "/login", method = RequestMethod.POST) public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { if (UserSession.isLoggedIn(req.getSession())) { return "redirect:/index.jsp"; diff --git a/app/src/main/java/com/techcourse/controller/LoginViewController.java b/app/src/main/java/com/techcourse/controller/LoginViewController.java index 86ec26cdce..611a36c479 100644 --- a/app/src/main/java/com/techcourse/controller/LoginViewController.java +++ b/app/src/main/java/com/techcourse/controller/LoginViewController.java @@ -1,16 +1,19 @@ package com.techcourse.controller; +import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; -public class LoginViewController implements Controller { +@Controller +public class LoginViewController { private static final Logger log = LoggerFactory.getLogger(LoginViewController.class); - @Override + @RequestMapping(value = "/login/view", method = RequestMethod.GET) public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { return UserSession.getUserFrom(req.getSession()) .map(user -> { diff --git a/app/src/main/java/com/techcourse/controller/LogoutController.java b/app/src/main/java/com/techcourse/controller/LogoutController.java index 4642fd9450..00fe3933e8 100644 --- a/app/src/main/java/com/techcourse/controller/LogoutController.java +++ b/app/src/main/java/com/techcourse/controller/LogoutController.java @@ -1,12 +1,15 @@ package com.techcourse.controller; +import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; -public class LogoutController implements Controller { +@Controller +public class LogoutController { - @Override + @RequestMapping(value = "/logout", method = RequestMethod.GET) public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { final var session = req.getSession(); session.removeAttribute(UserSession.SESSION_KEY); diff --git a/app/src/main/java/com/techcourse/controller/RegisterController.java b/app/src/main/java/com/techcourse/controller/RegisterController.java index da62e5e8e9..bd0a56384b 100644 --- a/app/src/main/java/com/techcourse/controller/RegisterController.java +++ b/app/src/main/java/com/techcourse/controller/RegisterController.java @@ -2,13 +2,16 @@ import com.techcourse.domain.User; import com.techcourse.repository.InMemoryUserRepository; +import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; -public class RegisterController implements Controller { +@Controller +public class RegisterController { - @Override + @RequestMapping(value = "/register", method = RequestMethod.GET) public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { final var user = new User(2, req.getParameter("account"), diff --git a/app/src/main/java/com/techcourse/controller/RegisterViewController.java b/app/src/main/java/com/techcourse/controller/RegisterViewController.java index 136962136d..95f288158d 100644 --- a/app/src/main/java/com/techcourse/controller/RegisterViewController.java +++ b/app/src/main/java/com/techcourse/controller/RegisterViewController.java @@ -1,12 +1,15 @@ package com.techcourse.controller; +import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; -public class RegisterViewController implements Controller { +@Controller +public class RegisterViewController { - @Override + @RequestMapping(value = "/register/view", method = RequestMethod.GET) public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { return "/register.jsp"; } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/Controller.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/Controller.java deleted file mode 100644 index bdd1fde780..0000000000 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/Controller.java +++ /dev/null @@ -1,8 +0,0 @@ -package webmvc.org.springframework.web.servlet.mvc.asis; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -public interface Controller { - String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception; -} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/ForwardController.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/ForwardController.java deleted file mode 100644 index cd8f1ef371..0000000000 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/ForwardController.java +++ /dev/null @@ -1,20 +0,0 @@ -package webmvc.org.springframework.web.servlet.mvc.asis; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import java.util.Objects; - -public class ForwardController implements Controller { - - private final String path; - - public ForwardController(final String path) { - this.path = Objects.requireNonNull(path); - } - - @Override - public String execute(final HttpServletRequest request, final HttpServletResponse response) { - return path; - } -} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapter.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapter.java deleted file mode 100644 index 80c2b87e26..0000000000 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapter.java +++ /dev/null @@ -1,23 +0,0 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.ModelAndView; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; - -public class ManualHandlerAdapter implements HandlerAdapter { - - @Override - public boolean supports(final Object handler) { - return handler instanceof Controller; - } - - @Override - public ModelAndView handle(final Object handler, - final HttpServletRequest request, - final HttpServletResponse response) throws Exception { - final Controller controller = (Controller) handler; - final String viewName = controller.execute(request, response); - return new ModelAndView(viewName); - } -} From 48b38c91040ef1a2fbcea64c6dd9fc056919ec59 Mon Sep 17 00:00:00 2001 From: Miseong Kim Date: Mon, 25 Sep 2023 17:32:39 +0900 Subject: [PATCH 05/13] =?UTF-8?q?refactor:=20test=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/UserControllerTest.java | 34 --------- .../mvc/tobe/ManualHandlerAdapterTest.java | 71 ------------------- 2 files changed, 105 deletions(-) delete mode 100644 app/src/test/java/com/techcourse/controller/UserControllerTest.java delete mode 100644 mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapterTest.java diff --git a/app/src/test/java/com/techcourse/controller/UserControllerTest.java b/app/src/test/java/com/techcourse/controller/UserControllerTest.java deleted file mode 100644 index 4b1a33c9ce..0000000000 --- a/app/src/test/java/com/techcourse/controller/UserControllerTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.techcourse.controller; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.techcourse.DispatcherServlet; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import org.junit.jupiter.api.Test; -import web.org.springframework.http.MediaType; -import webmvc.org.springframework.web.servlet.ModelAndView; - -class UserControllerTest { - - @Test - void 유저_정보를_반환한다() throws ServletException, IOException { - final var request = mock(HttpServletRequest.class); - final var response = mock(HttpServletResponse.class); - final ModelAndView modelAndView = mock(ModelAndView.class); - - when(request.getParameter("account")).thenReturn("gugu"); - when(request.getRequestURI()).thenReturn("/api/user"); - when(request.getMethod()).thenReturn("GET"); - - final DispatcherServlet dispatcherServlet = new DispatcherServlet(); - dispatcherServlet.init(); - dispatcherServlet.service(request, response); - - assertThat(response.getContentType()).isEqualTo(MediaType.APPLICATION_JSON_UTF8_VALUE); - } -} diff --git a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapterTest.java b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapterTest.java deleted file mode 100644 index 961718ca4c..0000000000 --- a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapterTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import webmvc.org.springframework.web.servlet.ModelAndView; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; - -class ManualHandlerAdapterTest { - - private ManualHandlerAdapter handlerAdapter; - - @BeforeEach - void setUp() { - handlerAdapter = new ManualHandlerAdapter(); - } - - @Test - void 핸들러가_Controller_타입이면_true를_반환한다() { - // given - final Controller controller = mock(Controller.class); - - // when - final boolean result = handlerAdapter.supports(controller); - - // thend - assertThat(result).isTrue(); - } - - @Test - void 핸들러가_Controller_타입이_아니면_false를_반환한다() { - // given - final String controller = "Controller"; - - // when - final boolean result = handlerAdapter.supports(controller); - - // then - assertThat(result).isFalse(); - } - - @Test - void 인자로_들어온_핸들러의_메소드를_어댑터를_통해_실행한다() throws Exception { - // given - final var request = mock(HttpServletRequest.class); - final var response = mock(HttpServletResponse.class); - final var handlerMapping = mock(HandlerMapping.class); - - final TestController handler = new TestController(); - when(handlerMapping.getHandler(request)).thenReturn(handler); - - // when - final ModelAndView modelAndView = handlerAdapter.handle(handler, request, response); - - // then - assertThat(modelAndView.getView()).isEqualTo("test.jsp"); - } - - static class TestController implements Controller { - - @Override - public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { - return "test.jsp"; - } - } -} From d2a8bbcfd1885fab9155d361e09bb00005eb5c6d Mon Sep 17 00:00:00 2001 From: Miseong Kim Date: Mon, 25 Sep 2023 17:33:18 +0900 Subject: [PATCH 06/13] =?UTF-8?q?refactor:=20DispatcherServlet=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/techcourse/DispatcherServletInitializer.java | 5 +++-- .../web/servlet/mvc}/DispatcherServlet.java | 7 ++----- .../servlet/mvc/tobe/AnnotationHandlerMapping.java | 12 +++++------- 3 files changed, 10 insertions(+), 14 deletions(-) rename {app/src/main/java/com/techcourse => mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc}/DispatcherServlet.java (96%) diff --git a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java index 6e814cdd25..c9040e0c76 100644 --- a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java +++ b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java @@ -4,10 +4,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import web.org.springframework.web.WebApplicationInitializer; +import webmvc.org.springframework.web.servlet.mvc.DispatcherServlet; /** - * Base class for {@link WebApplicationInitializer} - * implementations that register a {@link DispatcherServlet} in the servlet context. + * Base class for {@link WebApplicationInitializer} implementations that register a {@link DispatcherServlet} in the + * servlet context. */ public class DispatcherServletInitializer implements WebApplicationInitializer { diff --git a/app/src/main/java/com/techcourse/DispatcherServlet.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java similarity index 96% rename from app/src/main/java/com/techcourse/DispatcherServlet.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java index f8de7ad4b1..acc169b362 100644 --- a/app/src/main/java/com/techcourse/DispatcherServlet.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java @@ -1,4 +1,4 @@ -package com.techcourse; +package webmvc.org.springframework.web.servlet.mvc; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; @@ -31,9 +31,6 @@ public class DispatcherServlet extends HttpServlet { private final List handlerAdapters = new ArrayList<>(); private final List viewResolvers = new ArrayList<>(); - public DispatcherServlet() { - } - @Override public void init() { initHandlerMappings(); @@ -42,7 +39,7 @@ public void init() { } private void initHandlerMappings() { - handlerMappings.add(new AnnotationHandlerMapping(getClass().getPackageName())); + handlerMappings.add(new AnnotationHandlerMapping()); for (final HandlerMapping handlerMapping : handlerMappings) { handlerMapping.initialize(); } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java index 0811ab08a8..c7c49239f0 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java @@ -32,14 +32,12 @@ public AnnotationHandlerMapping(final Object... basePackage) { @Override public void initialize() { - for (final Object basePackage : basePackages) { - registerHandlerWithAnnotation(basePackage); - } + registerHandlerWithAnnotation(basePackages); log.info("Initialized AnnotationHandlerMapping!"); } - private void registerHandlerWithAnnotation(final Object basePackage) { - final Set> classes = getClassesByAnnotation(basePackage, Controller.class); + private void registerHandlerWithAnnotation(final Object... basePackages) { + final Set> classes = getClassesByAnnotation(basePackages, Controller.class); for (final Class clazz : classes) { final List methods = getMethodsByAnnotation(clazz, RequestMapping.class); for (final Method method : methods) { @@ -50,9 +48,9 @@ private void registerHandlerWithAnnotation(final Object basePackage) { } } - private Set> getClassesByAnnotation(final Object basePackage, + private Set> getClassesByAnnotation(final Object[] basePackages, final Class annotation) { - final Reflections reflections = new Reflections(basePackage); + final Reflections reflections = new Reflections(basePackages); return reflections.getTypesAnnotatedWith(annotation); } From 3ca34d70e9f9a36808b125007881895d4ec378b8 Mon Sep 17 00:00:00 2001 From: Miseong Kim Date: Mon, 25 Sep 2023 17:41:25 +0900 Subject: [PATCH 07/13] =?UTF-8?q?refactor:=20=ED=95=B8=EB=93=A4=EB=9F=AC?= =?UTF-8?q?=20=EB=A7=A4=ED=95=91=EC=9D=98=20getHandler=EA=B0=80=20Optional?= =?UTF-8?q?=EC=9D=84=20=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/servlet/mvc/DispatcherServlet.java | 7 ++++--- .../servlet/mvc/tobe/AnnotationHandlerMapping.java | 9 +++++++-- .../web/servlet/mvc/tobe/HandlerMapping.java | 3 ++- .../mvc/tobe/AnnotationHandlerAdapterTest.java | 3 ++- .../mvc/tobe/AnnotationHandlerMappingTest.java | 12 ++++++------ 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java index acc169b362..d325eca32c 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import webmvc.org.springframework.web.servlet.ModelAndView; @@ -84,9 +85,9 @@ private View getView(final ModelAndView modelAndView) { private Object getHandler(final HttpServletRequest request) { for (final HandlerMapping handlerMapping : handlerMappings) { - final Object handler = handlerMapping.getHandler(request); - if (handler != null) { - return handler; + final Optional handler = handlerMapping.getHandler(request); + if (handler.isPresent()) { + return handler.get(); } } throw new HandlerMappingException("해당 요청에 대한 핸들러가 없습니다."); diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java index c7c49239f0..0cfce844ca 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java @@ -9,6 +9,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import org.reflections.Reflections; @@ -88,11 +89,15 @@ private Object makeHandlerInstance(final Class clazz) { } @Override - public Object getHandler(final HttpServletRequest request) { + public Optional getHandler(final HttpServletRequest request) { final HandlerKey handlerKey = new HandlerKey( request.getRequestURI(), RequestMethod.valueOf(request.getMethod()) ); - return handlerExecutions.get(handlerKey); + final HandlerExecution handler = handlerExecutions.get(handlerKey); + if (handler == null) { + return Optional.empty(); + } + return Optional.of(handler); } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMapping.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMapping.java index 2fd9df144a..cac5fbec71 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMapping.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMapping.java @@ -1,10 +1,11 @@ package webmvc.org.springframework.web.servlet.mvc.tobe; import jakarta.servlet.http.HttpServletRequest; +import java.util.Optional; public interface HandlerMapping { void initialize(); - Object getHandler(HttpServletRequest request); + Optional getHandler(HttpServletRequest request); } diff --git a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapterTest.java b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapterTest.java index 1806c63e84..c5aa294c6f 100644 --- a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapterTest.java +++ b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapterTest.java @@ -7,6 +7,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.lang.reflect.Method; +import java.util.Optional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import webmvc.org.springframework.web.servlet.ModelAndView; @@ -56,7 +57,7 @@ void setUp() { HttpServletResponse.class); final HandlerExecution handler = new HandlerExecution(getClass().getDeclaredConstructor().newInstance(), handlerMethod); - when(handlerMapping.getHandler(request)).thenReturn(handler); + when(handlerMapping.getHandler(request)).thenReturn(Optional.of(handler)); // when final ModelAndView modelAndView = handlerAdapter.handle(handler, request, response); diff --git a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMappingTest.java b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMappingTest.java index dcec215a3f..1550c9883e 100644 --- a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMappingTest.java +++ b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMappingTest.java @@ -1,14 +1,14 @@ package webmvc.org.springframework.web.servlet.mvc.tobe; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - class AnnotationHandlerMappingTest { private AnnotationHandlerMapping handlerMapping; @@ -28,7 +28,7 @@ void get() throws Exception { when(request.getRequestURI()).thenReturn("/get-test"); when(request.getMethod()).thenReturn("GET"); - final var handlerExecution = (HandlerExecution) handlerMapping.getHandler(request); + final var handlerExecution = (HandlerExecution) handlerMapping.getHandler(request).get(); final var modelAndView = handlerExecution.handle(request, response); assertThat(modelAndView.getObject("id")).isEqualTo("gugu"); @@ -43,7 +43,7 @@ void post() throws Exception { when(request.getRequestURI()).thenReturn("/post-test"); when(request.getMethod()).thenReturn("POST"); - final var handlerExecution = (HandlerExecution) handlerMapping.getHandler(request); + final var handlerExecution = (HandlerExecution) handlerMapping.getHandler(request).get(); final var modelAndView = handlerExecution.handle(request, response); assertThat(modelAndView.getObject("id")).isEqualTo("gugu"); From e510279b30acdad930f2be187d12532c7d359612 Mon Sep 17 00:00:00 2001 From: Miseong Kim Date: Mon, 25 Sep 2023 21:38:22 +0900 Subject: [PATCH 08/13] =?UTF-8?q?refactor:=20=ED=95=B8=EB=93=A4=EB=9F=AC?= =?UTF-8?q?=20=EB=A7=A4=ED=95=91=20=EC=8B=A4=ED=8C=A8=20=EC=8B=9C=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/servlet/mvc/DispatcherServlet.java | 20 ++++++++++--------- .../mvc/tobe/AnnotationHandlerMapping.java | 3 ++- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java index d325eca32c..12e9cbf4cb 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java @@ -68,21 +68,14 @@ protected void service(final HttpServletRequest request, final HttpServletRespon final View view = getView(modelAndView); final Map model = modelAndView.getModel(); view.render(model, request, response); + } catch (final HandlerMappingException e) { + throw new HandlerMappingException(e.getMessage()); } catch (final Throwable e) { log.error("Exception : {}", e.getMessage(), e); throw new ServletException(e.getMessage()); } } - private View getView(final ModelAndView modelAndView) { - final Object view = modelAndView.getView(); - return viewResolvers.stream() - .filter(viewResolver -> viewResolver.supports(view)) - .findFirst() - .map(viewResolver -> viewResolver.resolve(view)) - .orElseThrow(() -> new ViewResolverException("해당 요청에 대한 view를 처리할 수 없습니다.")); - } - private Object getHandler(final HttpServletRequest request) { for (final HandlerMapping handlerMapping : handlerMappings) { final Optional handler = handlerMapping.getHandler(request); @@ -101,4 +94,13 @@ private HandlerAdapter getHandlerAdapter(final Object handler) { } throw new HandlerAdapterException("해당 요청에 대한 핸들러 어댑터가 없습니다."); } + + private View getView(final ModelAndView modelAndView) { + final Object view = modelAndView.getView(); + return viewResolvers.stream() + .filter(viewResolver -> viewResolver.supports(view)) + .findFirst() + .map(viewResolver -> viewResolver.resolve(view)) + .orElseThrow(() -> new ViewResolverException("해당 요청에 대한 view를 처리할 수 없습니다.")); + } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java index 0cfce844ca..9bafc4a192 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java @@ -1,5 +1,6 @@ package webmvc.org.springframework.web.servlet.mvc.tobe; +import com.sun.jdi.InternalException; import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import java.lang.annotation.Annotation; @@ -84,7 +85,7 @@ private Object makeHandlerInstance(final Class clazz) { return clazz.getDeclaredConstructor().newInstance(); } catch (final NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new HandlerMappingException("handler 인스턴스 생성에 실패했습니다."); + throw new InternalException("handler 인스턴스 생성에 실패했습니다."); } } From e0ca93f68046da3593381e657c42552d3b1fb408 Mon Sep 17 00:00:00 2001 From: Miseong Kim Date: Mon, 25 Sep 2023 21:45:45 +0900 Subject: [PATCH 09/13] =?UTF-8?q?refactor:=20=EB=B7=B0=20=EB=A6=AC?= =?UTF-8?q?=EC=A1=B8=EB=B2=84=20=EC=B2=98=EB=A6=AC=20=EC=8B=A4=ED=8C=A8=20?= =?UTF-8?q?=EC=8B=9C=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../springframework/web/servlet/mvc/DispatcherServlet.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java index 12e9cbf4cb..aba4eb5658 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java @@ -68,8 +68,8 @@ protected void service(final HttpServletRequest request, final HttpServletRespon final View view = getView(modelAndView); final Map model = modelAndView.getModel(); view.render(model, request, response); - } catch (final HandlerMappingException e) { - throw new HandlerMappingException(e.getMessage()); + } catch (final HandlerMappingException | ViewResolverException e) { + throw e; } catch (final Throwable e) { log.error("Exception : {}", e.getMessage(), e); throw new ServletException(e.getMessage()); From 0c30f714fe92289a2a80bf1d48de4a31a9e23cd0 Mon Sep 17 00:00:00 2001 From: Miseong Kim Date: Tue, 26 Sep 2023 16:39:29 +0900 Subject: [PATCH 10/13] =?UTF-8?q?refactor:=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/servlet/mvc/DispatcherServlet.java | 20 +++++++++---------- .../AnnotationHandlerAdapter.java | 3 ++- .../mvc/{tobe => adapter}/HandlerAdapter.java | 2 +- .../HandlerAdapterException.java | 2 +- .../AnnotationHandlerMapping.java | 2 +- .../{tobe => handler}/HandlerExecution.java | 2 +- .../mvc/{tobe => handler}/HandlerKey.java | 17 +++++++++------- .../mvc/{tobe => handler}/HandlerMapping.java | 2 +- .../HandlerMappingException.java | 2 +- .../JsonViewResolver.java | 2 +- .../JspViewResolver.java | 2 +- .../{tobe => viewresolver}/ViewResolver.java | 2 +- .../ViewResolverException.java | 2 +- .../tobe/AnnotationHandlerAdapterTest.java | 3 +++ .../tobe/AnnotationHandlerMappingTest.java | 2 ++ 15 files changed, 37 insertions(+), 28 deletions(-) rename mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/{tobe => adapter}/AnnotationHandlerAdapter.java (84%) rename mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/{tobe => adapter}/HandlerAdapter.java (85%) rename mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/{tobe => adapter}/HandlerAdapterException.java (72%) rename mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/{tobe => handler}/AnnotationHandlerMapping.java (98%) rename mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/{tobe => handler}/HandlerExecution.java (93%) rename mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/{tobe => handler}/HandlerKey.java (72%) rename mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/{tobe => handler}/HandlerMapping.java (76%) rename mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/{tobe => handler}/HandlerMappingException.java (72%) rename mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/{tobe => viewresolver}/JsonViewResolver.java (85%) rename mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/{tobe => viewresolver}/JspViewResolver.java (89%) rename mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/{tobe => viewresolver}/ViewResolver.java (70%) rename mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/{tobe => viewresolver}/ViewResolverException.java (70%) diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java index aba4eb5658..a8ca9220cf 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java @@ -12,16 +12,16 @@ import org.slf4j.LoggerFactory; import webmvc.org.springframework.web.servlet.ModelAndView; import webmvc.org.springframework.web.servlet.View; -import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationHandlerAdapter; -import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationHandlerMapping; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerAdapter; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerAdapterException; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerMapping; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerMappingException; -import webmvc.org.springframework.web.servlet.mvc.tobe.JsonViewResolver; -import webmvc.org.springframework.web.servlet.mvc.tobe.JspViewResolver; -import webmvc.org.springframework.web.servlet.mvc.tobe.ViewResolver; -import webmvc.org.springframework.web.servlet.mvc.tobe.ViewResolverException; +import webmvc.org.springframework.web.servlet.mvc.adapter.AnnotationHandlerAdapter; +import webmvc.org.springframework.web.servlet.mvc.adapter.HandlerAdapter; +import webmvc.org.springframework.web.servlet.mvc.adapter.HandlerAdapterException; +import webmvc.org.springframework.web.servlet.mvc.handler.AnnotationHandlerMapping; +import webmvc.org.springframework.web.servlet.mvc.handler.HandlerMapping; +import webmvc.org.springframework.web.servlet.mvc.handler.HandlerMappingException; +import webmvc.org.springframework.web.servlet.mvc.viewresolver.JsonViewResolver; +import webmvc.org.springframework.web.servlet.mvc.viewresolver.JspViewResolver; +import webmvc.org.springframework.web.servlet.mvc.viewresolver.ViewResolver; +import webmvc.org.springframework.web.servlet.mvc.viewresolver.ViewResolverException; public class DispatcherServlet extends HttpServlet { diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapter.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/AnnotationHandlerAdapter.java similarity index 84% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapter.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/AnnotationHandlerAdapter.java index 5baec6cef6..712fe38291 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapter.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/AnnotationHandlerAdapter.java @@ -1,8 +1,9 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.adapter; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.mvc.handler.HandlerExecution; public class AnnotationHandlerAdapter implements HandlerAdapter { diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerAdapter.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapter.java similarity index 85% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerAdapter.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapter.java index 1b62b24042..546e4a90cf 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerAdapter.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapter.java @@ -1,4 +1,4 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.adapter; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerAdapterException.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapterException.java similarity index 72% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerAdapterException.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapterException.java index 86fba1051c..a4bda20de1 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerAdapterException.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapterException.java @@ -1,4 +1,4 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.adapter; public class HandlerAdapterException extends RuntimeException { diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/AnnotationHandlerMapping.java similarity index 98% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/AnnotationHandlerMapping.java index 9bafc4a192..cb0d9908df 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/AnnotationHandlerMapping.java @@ -1,4 +1,4 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.handler; import com.sun.jdi.InternalException; import context.org.springframework.stereotype.Controller; diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerExecution.java similarity index 93% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerExecution.java index 54fdcc20e6..d7ed02ed20 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerExecution.java @@ -1,4 +1,4 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.handler; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerKey.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerKey.java similarity index 72% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerKey.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerKey.java index 30d3c780ff..7439edf401 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerKey.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerKey.java @@ -1,8 +1,7 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; - -import web.org.springframework.web.bind.annotation.RequestMethod; +package webmvc.org.springframework.web.servlet.mvc.handler; import java.util.Objects; +import web.org.springframework.web.bind.annotation.RequestMethod; public class HandlerKey { @@ -23,10 +22,14 @@ public String toString() { } @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof HandlerKey)) return false; - HandlerKey that = (HandlerKey) o; + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof HandlerKey)) { + return false; + } + final HandlerKey that = (HandlerKey) o; return Objects.equals(url, that.url) && requestMethod == that.requestMethod; } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMapping.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMapping.java similarity index 76% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMapping.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMapping.java index cac5fbec71..1bb184acfd 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMapping.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMapping.java @@ -1,4 +1,4 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.handler; import jakarta.servlet.http.HttpServletRequest; import java.util.Optional; diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMappingException.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMappingException.java similarity index 72% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMappingException.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMappingException.java index 896dad5f4c..85b7215813 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMappingException.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMappingException.java @@ -1,4 +1,4 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.handler; public class HandlerMappingException extends RuntimeException { diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/JsonViewResolver.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/JsonViewResolver.java similarity index 85% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/JsonViewResolver.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/JsonViewResolver.java index d49a6a565b..bfce519139 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/JsonViewResolver.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/JsonViewResolver.java @@ -1,4 +1,4 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.viewresolver; import webmvc.org.springframework.web.servlet.View; import webmvc.org.springframework.web.servlet.view.JsonView; diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/JspViewResolver.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/JspViewResolver.java similarity index 89% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/JspViewResolver.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/JspViewResolver.java index 27d67d2483..bcdc5ecc09 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/JspViewResolver.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/JspViewResolver.java @@ -1,4 +1,4 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.viewresolver; import webmvc.org.springframework.web.servlet.View; import webmvc.org.springframework.web.servlet.view.JspView; diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ViewResolver.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolver.java similarity index 70% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ViewResolver.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolver.java index 319b97dc95..2aae82a68f 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ViewResolver.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolver.java @@ -1,4 +1,4 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.viewresolver; import webmvc.org.springframework.web.servlet.View; diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ViewResolverException.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolverException.java similarity index 70% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ViewResolverException.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolverException.java index 9bb5194b49..1a7d1426b2 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ViewResolverException.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolverException.java @@ -1,4 +1,4 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.viewresolver; public class ViewResolverException extends RuntimeException { diff --git a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapterTest.java b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapterTest.java index c5aa294c6f..b6e9a2eeaf 100644 --- a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapterTest.java +++ b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapterTest.java @@ -11,6 +11,9 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.mvc.adapter.AnnotationHandlerAdapter; +import webmvc.org.springframework.web.servlet.mvc.handler.HandlerExecution; +import webmvc.org.springframework.web.servlet.mvc.handler.HandlerMapping; import webmvc.org.springframework.web.servlet.view.JspView; class AnnotationHandlerAdapterTest { diff --git a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMappingTest.java b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMappingTest.java index 1550c9883e..1cc03355c2 100644 --- a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMappingTest.java +++ b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMappingTest.java @@ -8,6 +8,8 @@ import jakarta.servlet.http.HttpServletResponse; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import webmvc.org.springframework.web.servlet.mvc.handler.AnnotationHandlerMapping; +import webmvc.org.springframework.web.servlet.mvc.handler.HandlerExecution; class AnnotationHandlerMappingTest { From dca0adb07d3180f5c07a3cbd37f4a3e6acc6f7f6 Mon Sep 17 00:00:00 2001 From: Miseong Kim Date: Tue, 26 Sep 2023 17:06:08 +0900 Subject: [PATCH 11/13] =?UTF-8?q?refactor:=20=EC=9D=BC=EA=B8=89=EC=BB=AC?= =?UTF-8?q?=EB=A0=89=EC=85=98=EC=9C=BC=EB=A1=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/servlet/mvc/DispatcherServlet.java | 53 +++++++------------ .../servlet/mvc/adapter/HandlerAdapters.java | 20 +++++++ .../servlet/mvc/handler/HandlerMappings.java | 28 ++++++++++ .../mvc/viewresolver/ViewResolvers.java | 24 +++++++++ 4 files changed, 91 insertions(+), 34 deletions(-) create mode 100644 mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapters.java create mode 100644 mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMappings.java create mode 100644 mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolvers.java diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java index a8ca9220cf..61eb775adf 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java @@ -4,33 +4,31 @@ import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import webmvc.org.springframework.web.servlet.ModelAndView; import webmvc.org.springframework.web.servlet.View; import webmvc.org.springframework.web.servlet.mvc.adapter.AnnotationHandlerAdapter; import webmvc.org.springframework.web.servlet.mvc.adapter.HandlerAdapter; -import webmvc.org.springframework.web.servlet.mvc.adapter.HandlerAdapterException; +import webmvc.org.springframework.web.servlet.mvc.adapter.HandlerAdapters; import webmvc.org.springframework.web.servlet.mvc.handler.AnnotationHandlerMapping; -import webmvc.org.springframework.web.servlet.mvc.handler.HandlerMapping; import webmvc.org.springframework.web.servlet.mvc.handler.HandlerMappingException; +import webmvc.org.springframework.web.servlet.mvc.handler.HandlerMappings; import webmvc.org.springframework.web.servlet.mvc.viewresolver.JsonViewResolver; import webmvc.org.springframework.web.servlet.mvc.viewresolver.JspViewResolver; -import webmvc.org.springframework.web.servlet.mvc.viewresolver.ViewResolver; import webmvc.org.springframework.web.servlet.mvc.viewresolver.ViewResolverException; +import webmvc.org.springframework.web.servlet.mvc.viewresolver.ViewResolvers; public class DispatcherServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final Logger log = LoggerFactory.getLogger(DispatcherServlet.class); - private final List handlerMappings = new ArrayList<>(); - private final List handlerAdapters = new ArrayList<>(); - private final List viewResolvers = new ArrayList<>(); + private HandlerMappings handlerMappings; + private HandlerAdapters handlerAdapters; + private ViewResolvers viewResolvers; @Override public void init() { @@ -40,19 +38,22 @@ public void init() { } private void initHandlerMappings() { - handlerMappings.add(new AnnotationHandlerMapping()); - for (final HandlerMapping handlerMapping : handlerMappings) { - handlerMapping.initialize(); - } + handlerMappings = new HandlerMappings( + List.of(new AnnotationHandlerMapping()) + ); + handlerMappings.initialize(); } private void initHandlerAdapters() { - handlerAdapters.add(new AnnotationHandlerAdapter()); + handlerAdapters = new HandlerAdapters( + List.of(new AnnotationHandlerAdapter()) + ); } private void initViewResolvers() { - viewResolvers.add(new JspViewResolver()); - viewResolvers.add(new JsonViewResolver()); + viewResolvers = new ViewResolvers( + List.of(new JspViewResolver(), new JsonViewResolver()) + ); } @Override @@ -77,30 +78,14 @@ protected void service(final HttpServletRequest request, final HttpServletRespon } private Object getHandler(final HttpServletRequest request) { - for (final HandlerMapping handlerMapping : handlerMappings) { - final Optional handler = handlerMapping.getHandler(request); - if (handler.isPresent()) { - return handler.get(); - } - } - throw new HandlerMappingException("해당 요청에 대한 핸들러가 없습니다."); + return handlerMappings.getHandler(request); } private HandlerAdapter getHandlerAdapter(final Object handler) { - for (final HandlerAdapter handlerAdapter : handlerAdapters) { - if (handlerAdapter.supports(handler)) { - return handlerAdapter; - } - } - throw new HandlerAdapterException("해당 요청에 대한 핸들러 어댑터가 없습니다."); + return handlerAdapters.getHandlerAdapter(handler); } private View getView(final ModelAndView modelAndView) { - final Object view = modelAndView.getView(); - return viewResolvers.stream() - .filter(viewResolver -> viewResolver.supports(view)) - .findFirst() - .map(viewResolver -> viewResolver.resolve(view)) - .orElseThrow(() -> new ViewResolverException("해당 요청에 대한 view를 처리할 수 없습니다.")); + return viewResolvers.getView(modelAndView); } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapters.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapters.java new file mode 100644 index 0000000000..a6a2f680ab --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapters.java @@ -0,0 +1,20 @@ +package webmvc.org.springframework.web.servlet.mvc.adapter; + +import java.util.ArrayList; +import java.util.List; + +public class HandlerAdapters { + + private final List handlerAdapters; + + public HandlerAdapters(final List handlerAdapters) { + this.handlerAdapters = new ArrayList<>(handlerAdapters); + } + + public HandlerAdapter getHandlerAdapter(final Object handler) { + return handlerAdapters.stream() + .filter(handlerAdapter -> handlerAdapter.supports(handler)) + .findFirst() + .orElseThrow(() -> new HandlerAdapterException("해당 요청에 대한 핸들러 어댑터가 없습니다.")); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMappings.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMappings.java new file mode 100644 index 0000000000..9f7edb40db --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMappings.java @@ -0,0 +1,28 @@ +package webmvc.org.springframework.web.servlet.mvc.handler; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class HandlerMappings { + + private final List handlerMappings; + + public HandlerMappings(final List handlerMappings) { + this.handlerMappings = new ArrayList<>(handlerMappings); + } + + public void initialize() { + handlerMappings.forEach(HandlerMapping::initialize); + } + + public Object getHandler(final HttpServletRequest request) { + return handlerMappings.stream() + .map(handlerMapping -> handlerMapping.getHandler(request)) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst() + .orElseThrow(() -> new HandlerMappingException("해당 요청에 대한 핸들러가 없습니다.")); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolvers.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolvers.java new file mode 100644 index 0000000000..5ba5f83a6c --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolvers.java @@ -0,0 +1,24 @@ +package webmvc.org.springframework.web.servlet.mvc.viewresolver; + +import java.util.ArrayList; +import java.util.List; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.View; + +public class ViewResolvers { + + private final List viewResolvers; + + public ViewResolvers(final List viewResolvers) { + this.viewResolvers = new ArrayList<>(viewResolvers); + } + + public View getView(final ModelAndView modelAndView) { + final Object view = modelAndView.getView(); + return viewResolvers.stream() + .filter(viewResolver -> viewResolver.supports(view)) + .findFirst() + .map(viewResolver -> viewResolver.resolve(view)) + .orElseThrow(() -> new ViewResolverException("해당 요청에 대한 view를 처리할 수 없습니다.")); + } +} From a3fc8c27022d6fdcb4eafb802ccf95a99c23b195 Mon Sep 17 00:00:00 2001 From: Miseong Kim Date: Tue, 26 Sep 2023 17:30:10 +0900 Subject: [PATCH 12/13] =?UTF-8?q?refactor:=20=ED=95=B8=EB=93=A4=EB=9F=AC?= =?UTF-8?q?=EC=9D=98=20=EB=B0=98=ED=99=98=ED=83=80=EC=9E=85=EC=9D=B4=20Str?= =?UTF-8?q?ing=EC=9D=B8=20=EA=B2=BD=EC=9A=B0=EB=8F=84=20=EB=AA=85=EC=8B=9C?= =?UTF-8?q?=EC=A0=81=EC=9C=BC=EB=A1=9C=20=EB=82=98=ED=83=80=EB=82=B4?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/servlet/mvc/handler/HandlerException.java | 8 ++++++++ .../web/servlet/mvc/handler/HandlerExecution.java | 5 ++++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerException.java diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerException.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerException.java new file mode 100644 index 0000000000..e55afbc6e1 --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerException.java @@ -0,0 +1,8 @@ +package webmvc.org.springframework.web.servlet.mvc.handler; + +public class HandlerException extends RuntimeException { + + public HandlerException(final String message) { + super(message); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerExecution.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerExecution.java index d7ed02ed20..99771893f1 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerExecution.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerExecution.java @@ -24,6 +24,9 @@ public ModelAndView handle(final HttpServletRequest request, final HttpServletRe if (result == null) { return new ModelAndView(new JsonView()); } - return new ModelAndView(result); + if (result instanceof String) { + return new ModelAndView(result); + } + throw new HandlerException("해당 핸들러의 반환타입이 올바르지 않습니다."); } } From 206f9415326a3de72f0826a10cffb3d15e8d2d86 Mon Sep 17 00:00:00 2001 From: Miseong Kim Date: Tue, 26 Sep 2023 17:41:16 +0900 Subject: [PATCH 13/13] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../springframework/web/servlet/view/JsonView.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java index 30708715cd..01c4cbc5d6 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java @@ -1,5 +1,6 @@ package webmvc.org.springframework.web.servlet.view; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -16,12 +17,15 @@ public class JsonView implements View { public void render(final Map model, final HttpServletRequest request, final HttpServletResponse response) throws Exception { response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); - final PrintWriter writer = response.getWriter(); + final String jsonResponse = jsonToString(model); + writer.write(jsonResponse); + } + + private String jsonToString(final Map model) throws JsonProcessingException { if (model.size() == 1) { - writer.write(mapper.writeValueAsString(model.values().toArray()[0])); - return; + return mapper.writeValueAsString(model.values().toArray()[0]); } - writer.write(mapper.writeValueAsString(model)); + return mapper.writeValueAsString(model); } }