From 59f49c6faefa65e61d57c7890dfabaa330e22199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:54:40 +0900 Subject: [PATCH 01/19] =?UTF-8?q?refactor(JsonView):=20JSON=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=91=EB=8B=B5=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20JsonView=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../webmvc/servlet/view/JsonView.java | 10 ++- .../webmvc/servlet/view/JsonViewTest.java | 70 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 mvc/src/test/java/com/interface21/webmvc/servlet/view/JsonViewTest.java diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/view/JsonView.java b/mvc/src/main/java/com/interface21/webmvc/servlet/view/JsonView.java index b7666fe19f..6e2a698915 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/view/JsonView.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/view/JsonView.java @@ -9,6 +9,7 @@ public class JsonView implements View { + private static final int ONE_MODEL_SIZE = 1; private static final String JSON_CONTENT_TYPE = "application/json"; private static final String UTF_8_ENCODING = "UTF-8"; @@ -23,6 +24,13 @@ public void render(final Map model, final HttpServletRequest request, response.setContentType(JSON_CONTENT_TYPE); response.setCharacterEncoding(UTF_8_ENCODING); - response.getWriter().write(objectMapper.writeValueAsString(model)); + if (model.size() == ONE_MODEL_SIZE) { + String rawData = model.values().iterator().next().toString(); + response.getWriter().write(rawData); + return; + } + + String jsonFormattedData = objectMapper.writeValueAsString(model); + response.getWriter().write(jsonFormattedData); } } diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/view/JsonViewTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/view/JsonViewTest.java new file mode 100644 index 0000000000..9a11250251 --- /dev/null +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/view/JsonViewTest.java @@ -0,0 +1,70 @@ +package com.interface21.webmvc.servlet.view; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Map; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.databind.ObjectMapper; + +class JsonViewTest { + + private HttpServletRequest request; + private HttpServletResponse response; + private PrintWriter writer; + + @BeforeEach + void setUp() throws IOException { + request = mock(HttpServletRequest.class); + response = mock(HttpServletResponse.class); + writer = mock(PrintWriter.class); + + when(response.getWriter()).thenReturn(writer); + } + + @Test + @DisplayName("응답을 Json 형식으로 반환 성공: 데이터가 1개면 그대로 반환") + void render() throws Exception { + // given + Map model = Map.of("alpaca", "hihi"); + + // when + JsonView jsonView = new JsonView(); + jsonView.render(model, request, response); + + // then + verify(response).setContentType("application/json"); + verify(response).setCharacterEncoding("UTF-8"); + verify(writer).write("hihi"); + } + + @Test + @DisplayName("응답을 Json 형식으로 반환 성공: 데이터가 2개 이상이면 Map 형태의 Json으로 반환") + void rdfsender() throws Exception { + // given + Map model = Map.of( + "key1", "value1", + "key2", "value2" + ); + String expectedJson = new ObjectMapper().writeValueAsString(model); + + // when + JsonView jsonView = new JsonView(); + jsonView.render(model, request, response); + + // then + verify(response).setContentType("application/json"); + verify(response).setCharacterEncoding("UTF-8"); + verify(writer).write(expectedJson); + } +} From 526aa445aeec1616be82c1b413769744478bd4b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:09:09 +0900 Subject: [PATCH 02/19] =?UTF-8?q?refactor(LoginController):=20Annotation?= =?UTF-8?q?=20=EA=B8=B0=EB=B0=98=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/techcourse/ManualHandlerMapping.java | 4 -- .../controller/LoginController.java | 39 +++++++++++++------ .../controller/LoginViewController.java | 22 ----------- app/src/main/webapp/index.html | 2 +- app/src/main/webapp/index.jsp | 2 +- app/src/main/webapp/register.jsp | 2 +- .../com/techcourse/DispatcherServletTest.java | 2 +- 7 files changed, 32 insertions(+), 41 deletions(-) delete mode 100644 app/src/main/java/com/techcourse/controller/LoginViewController.java diff --git a/app/src/main/java/com/techcourse/ManualHandlerMapping.java b/app/src/main/java/com/techcourse/ManualHandlerMapping.java index 7390ed2b18..38a677765f 100644 --- a/app/src/main/java/com/techcourse/ManualHandlerMapping.java +++ b/app/src/main/java/com/techcourse/ManualHandlerMapping.java @@ -11,8 +11,6 @@ import com.interface21.webmvc.servlet.mvc.HandlerMapping; import com.interface21.webmvc.servlet.mvc.asis.Controller; import com.interface21.webmvc.servlet.mvc.asis.ForwardController; -import com.techcourse.controller.LoginController; -import com.techcourse.controller.LoginViewController; import com.techcourse.controller.LogoutController; public class ManualHandlerMapping implements HandlerMapping { @@ -27,8 +25,6 @@ public ManualHandlerMapping() { private void initialize() { controllers.put("/", new ForwardController("/index.jsp")); - controllers.put("/login", new LoginController()); - controllers.put("/login/view", new LoginViewController()); controllers.put("/logout", new LogoutController()); log.info("Initialized Handler Mapping!"); diff --git a/app/src/main/java/com/techcourse/controller/LoginController.java b/app/src/main/java/com/techcourse/controller/LoginController.java index a87d996693..da0a35bfd1 100644 --- a/app/src/main/java/com/techcourse/controller/LoginController.java +++ b/app/src/main/java/com/techcourse/controller/LoginController.java @@ -1,21 +1,38 @@ package com.techcourse.controller; -import com.techcourse.domain.User; -import com.techcourse.repository.InMemoryUserRepository; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import com.interface21.webmvc.servlet.mvc.asis.Controller; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class LoginController implements Controller { +import com.interface21.context.stereotype.Controller; +import com.interface21.web.bind.annotation.RequestMapping; +import com.interface21.web.bind.annotation.RequestMethod; +import com.interface21.webmvc.servlet.ModelAndView; +import com.interface21.webmvc.servlet.view.JspView; +import com.techcourse.domain.User; +import com.techcourse.repository.InMemoryUserRepository; + +@Controller +public class LoginController { private static final Logger log = LoggerFactory.getLogger(LoginController.class); - @Override - public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { + @RequestMapping(value = "/login", method = RequestMethod.GET) + public ModelAndView getLoginPage(final HttpServletRequest req, final HttpServletResponse res) { + return UserSession.getUserFrom(req.getSession()) + .map(user -> { + log.info("logged in {}", user.getAccount()); + return new ModelAndView(new JspView("redirect:/index.jsp")); + }) + .orElse(new ModelAndView(new JspView("/login.jsp"))); + } + + @RequestMapping(value = "/login", method = RequestMethod.POST) + public ModelAndView postLogin(final HttpServletRequest req, final HttpServletResponse res) { if (UserSession.isLoggedIn(req.getSession())) { - return "redirect:/index.jsp"; + return new ModelAndView(new JspView("redirect:/index.jsp")); } return InMemoryUserRepository.findByAccount(req.getParameter("account")) @@ -23,15 +40,15 @@ public String execute(final HttpServletRequest req, final HttpServletResponse re log.info("User : {}", user); return login(req, user); }) - .orElse("redirect:/401.jsp"); + .orElse(new ModelAndView(new JspView("redirect:/401.jsp"))); } - private String login(final HttpServletRequest request, final User user) { + private ModelAndView login(final HttpServletRequest request, final User user) { if (user.checkPassword(request.getParameter("password"))) { final var session = request.getSession(); session.setAttribute(UserSession.SESSION_KEY, user); - return "redirect:/index.jsp"; + return new ModelAndView(new JspView("redirect:/index.jsp")); } - return "redirect:/401.jsp"; + return new ModelAndView(new JspView("redirect:/401.jsp")); } } diff --git a/app/src/main/java/com/techcourse/controller/LoginViewController.java b/app/src/main/java/com/techcourse/controller/LoginViewController.java deleted file mode 100644 index dc71ee8e99..0000000000 --- a/app/src/main/java/com/techcourse/controller/LoginViewController.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.techcourse.controller; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.interface21.webmvc.servlet.mvc.asis.Controller; - -public class LoginViewController implements Controller { - - private static final Logger log = LoggerFactory.getLogger(LoginViewController.class); - - @Override - public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { - return UserSession.getUserFrom(req.getSession()) - .map(user -> { - log.info("logged in {}", user.getAccount()); - return "redirect:/index.jsp"; - }) - .orElse("/login.jsp"); - } -} diff --git a/app/src/main/webapp/index.html b/app/src/main/webapp/index.html index 95df361069..1ca98f1be2 100644 --- a/app/src/main/webapp/index.html +++ b/app/src/main/webapp/index.html @@ -19,7 +19,7 @@ diff --git a/app/src/main/webapp/index.jsp b/app/src/main/webapp/index.jsp index 142ee3d104..4ee84d2926 100644 --- a/app/src/main/webapp/index.jsp +++ b/app/src/main/webapp/index.jsp @@ -26,7 +26,7 @@ <% } else { %> <% } %> diff --git a/app/src/main/webapp/register.jsp b/app/src/main/webapp/register.jsp index 7e68995a56..b42e5606be 100644 --- a/app/src/main/webapp/register.jsp +++ b/app/src/main/webapp/register.jsp @@ -36,7 +36,7 @@ diff --git a/app/src/test/java/com/techcourse/DispatcherServletTest.java b/app/src/test/java/com/techcourse/DispatcherServletTest.java index 358e29cf51..cc894780ce 100644 --- a/app/src/test/java/com/techcourse/DispatcherServletTest.java +++ b/app/src/test/java/com/techcourse/DispatcherServletTest.java @@ -46,7 +46,7 @@ void service_LoginRequest() throws ServletException { dispatcherServlet.init(); when(request.getMethod()).thenReturn("GET"); - when(request.getRequestURI()).thenReturn("/login/view"); + when(request.getRequestURI()).thenReturn("/login"); dispatcherServlet.service(request, response); From 3c7e2f6c37d1748bae9eb5d9c2af217e6e9b9eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:12:24 +0900 Subject: [PATCH 03/19] =?UTF-8?q?refactor(LogoutController):=20Annotation?= =?UTF-8?q?=20=EA=B8=B0=EB=B0=98=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/techcourse/ManualHandlerMapping.java | 1 - .../techcourse/controller/LogoutController.java | 16 +++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/techcourse/ManualHandlerMapping.java b/app/src/main/java/com/techcourse/ManualHandlerMapping.java index 38a677765f..2406dfffb0 100644 --- a/app/src/main/java/com/techcourse/ManualHandlerMapping.java +++ b/app/src/main/java/com/techcourse/ManualHandlerMapping.java @@ -25,7 +25,6 @@ public ManualHandlerMapping() { private void initialize() { controllers.put("/", new ForwardController("/index.jsp")); - controllers.put("/logout", new LogoutController()); log.info("Initialized Handler Mapping!"); controllers.keySet() diff --git a/app/src/main/java/com/techcourse/controller/LogoutController.java b/app/src/main/java/com/techcourse/controller/LogoutController.java index 729d262de5..e95a4485ca 100644 --- a/app/src/main/java/com/techcourse/controller/LogoutController.java +++ b/app/src/main/java/com/techcourse/controller/LogoutController.java @@ -2,14 +2,20 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import com.interface21.webmvc.servlet.mvc.asis.Controller; -public class LogoutController implements Controller { +import com.interface21.context.stereotype.Controller; +import com.interface21.web.bind.annotation.RequestMapping; +import com.interface21.web.bind.annotation.RequestMethod; +import com.interface21.webmvc.servlet.ModelAndView; +import com.interface21.webmvc.servlet.view.JspView; - @Override - public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { +@Controller +public class LogoutController { + + @RequestMapping(value = "/logout", method = RequestMethod.GET) + public ModelAndView logout(final HttpServletRequest req, final HttpServletResponse res) throws Exception { final var session = req.getSession(); session.removeAttribute(UserSession.SESSION_KEY); - return "redirect:/"; + return new ModelAndView(new JspView("redirect:/")); } } From cc4bf4681ec2ae3e1f7e4e0e839facb7327bd59b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:22:53 +0900 Subject: [PATCH 04/19] =?UTF-8?q?refactor(IndexController):=20Annotation?= =?UTF-8?q?=20=EA=B8=B0=EB=B0=98=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/techcourse/ManualHandlerMapping.java | 5 +---- .../controller/IndexController.java | 19 +++++++++++++++++++ .../controller/LogoutController.java | 2 +- .../servlet/mvc/asis/ForwardController.java | 1 + 4 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/com/techcourse/controller/IndexController.java diff --git a/app/src/main/java/com/techcourse/ManualHandlerMapping.java b/app/src/main/java/com/techcourse/ManualHandlerMapping.java index 2406dfffb0..05e084bdc9 100644 --- a/app/src/main/java/com/techcourse/ManualHandlerMapping.java +++ b/app/src/main/java/com/techcourse/ManualHandlerMapping.java @@ -10,9 +10,8 @@ import com.interface21.webmvc.servlet.mvc.HandlerMapping; import com.interface21.webmvc.servlet.mvc.asis.Controller; -import com.interface21.webmvc.servlet.mvc.asis.ForwardController; -import com.techcourse.controller.LogoutController; +@Deprecated public class ManualHandlerMapping implements HandlerMapping { private static final Logger log = LoggerFactory.getLogger(ManualHandlerMapping.class); @@ -24,8 +23,6 @@ public ManualHandlerMapping() { } private void initialize() { - controllers.put("/", new ForwardController("/index.jsp")); - log.info("Initialized Handler Mapping!"); controllers.keySet() .forEach(path -> log.info("Path : {}, Controller : {}", path, controllers.get(path).getClass())); diff --git a/app/src/main/java/com/techcourse/controller/IndexController.java b/app/src/main/java/com/techcourse/controller/IndexController.java new file mode 100644 index 0000000000..57c8c5c730 --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/IndexController.java @@ -0,0 +1,19 @@ +package com.techcourse.controller; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import com.interface21.context.stereotype.Controller; +import com.interface21.web.bind.annotation.RequestMapping; +import com.interface21.web.bind.annotation.RequestMethod; +import com.interface21.webmvc.servlet.ModelAndView; +import com.interface21.webmvc.servlet.view.JspView; + +@Controller +public class IndexController { + + @RequestMapping(value = "/", method = RequestMethod.GET) + public ModelAndView getIndexPage(final HttpServletRequest req, final HttpServletResponse res) { + return new ModelAndView(new JspView("/index.jsp")); + } +} diff --git a/app/src/main/java/com/techcourse/controller/LogoutController.java b/app/src/main/java/com/techcourse/controller/LogoutController.java index e95a4485ca..3c3d866188 100644 --- a/app/src/main/java/com/techcourse/controller/LogoutController.java +++ b/app/src/main/java/com/techcourse/controller/LogoutController.java @@ -13,7 +13,7 @@ public class LogoutController { @RequestMapping(value = "/logout", method = RequestMethod.GET) - public ModelAndView logout(final HttpServletRequest req, final HttpServletResponse res) throws Exception { + public ModelAndView logout(final HttpServletRequest req, final HttpServletResponse res) { final var session = req.getSession(); session.removeAttribute(UserSession.SESSION_KEY); return new ModelAndView(new JspView("redirect:/")); diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ForwardController.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ForwardController.java index ecceef15af..89acdbca35 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ForwardController.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ForwardController.java @@ -5,6 +5,7 @@ import java.util.Objects; +@Deprecated public class ForwardController implements Controller { private final String path; From 9fc5a5eea201ec7d04b0499133e98210e4340df9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:23:56 +0900 Subject: [PATCH 05/19] =?UTF-8?q?refactor(/asis):=20controller=20=EC=9D=B8?= =?UTF-8?q?=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EA=B8=B0=EB=B0=98=20?= =?UTF-8?q?=EB=A0=88=EA=B1=B0=EC=8B=9C=20@Deprecated=20=EC=B2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../webmvc/servlet/mvc/HandlerAdapterRegistry.java | 3 ++- .../com/interface21/webmvc/servlet/mvc/asis/Controller.java | 1 + .../servlet/mvc/{ => asis}/ControllerHandlerAdapter.java | 5 +++-- .../webmvc/servlet/mvc/ControllerHandlerAdapterTest.java | 1 + .../webmvc/servlet/mvc/HandlerAdapterRegistryTest.java | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) rename mvc/src/main/java/com/interface21/webmvc/servlet/mvc/{ => asis}/ControllerHandlerAdapter.java (90%) diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistry.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistry.java index 57bd093c4a..a4434c265d 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistry.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistry.java @@ -3,6 +3,8 @@ import java.util.ArrayList; import java.util.List; +import com.interface21.webmvc.servlet.mvc.asis.ControllerHandlerAdapter; + public class HandlerAdapterRegistry { private final List handlerAdapters; @@ -14,7 +16,6 @@ public HandlerAdapterRegistry() { private void initialize() { handlerAdapters.add(new HandlerExecutionHandlerAdapter()); - handlerAdapters.add(new ControllerHandlerAdapter()); } public HandlerAdapter getHandlerAdapter(final Object handler) { diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/Controller.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/Controller.java index 20e714341a..84849ccd74 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/Controller.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/Controller.java @@ -3,6 +3,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +@Deprecated public interface Controller { String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception; } diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/ControllerHandlerAdapter.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ControllerHandlerAdapter.java similarity index 90% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/ControllerHandlerAdapter.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ControllerHandlerAdapter.java index 32af52f48a..b60b1bff79 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/ControllerHandlerAdapter.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ControllerHandlerAdapter.java @@ -1,13 +1,14 @@ -package com.interface21.webmvc.servlet.mvc; +package com.interface21.webmvc.servlet.mvc.asis; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import com.interface21.webmvc.servlet.ModelAndView; import com.interface21.webmvc.servlet.View; -import com.interface21.webmvc.servlet.mvc.asis.Controller; +import com.interface21.webmvc.servlet.mvc.HandlerAdapter; import com.interface21.webmvc.servlet.view.JspView; +@Deprecated public class ControllerHandlerAdapter implements HandlerAdapter { public ControllerHandlerAdapter() { diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/ControllerHandlerAdapterTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/ControllerHandlerAdapterTest.java index 74d76a59ca..209e370379 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/ControllerHandlerAdapterTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/ControllerHandlerAdapterTest.java @@ -20,6 +20,7 @@ import com.interface21.webmvc.servlet.ModelAndView; import com.interface21.webmvc.servlet.mvc.asis.Controller; +import com.interface21.webmvc.servlet.mvc.asis.ControllerHandlerAdapter; import com.interface21.webmvc.servlet.mvc.tobe.HandlerExecution; import samples.TestAnnotationController; diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistryTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistryTest.java index 2a033d6f1c..a3f7f805a9 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistryTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistryTest.java @@ -2,12 +2,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import com.interface21.webmvc.servlet.mvc.asis.ControllerHandlerAdapter; import com.interface21.webmvc.servlet.mvc.tobe.HandlerExecution; import samples.TestAnnotationController; From 295f36018dd351c303b2bc212e36de4a176d3b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:34:27 +0900 Subject: [PATCH 06/19] =?UTF-8?q?refactor(/):=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EA=B5=AC=EC=A1=B0=20=EA=B0=9C=ED=8E=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/techcourse/DispatcherServlet.java | 2 +- .../java/com/techcourse/ManualHandlerMapping.java | 4 ++-- .../com/techcourse/ManualHandlerMappingTest.java | 2 +- .../webmvc/servlet/{mvc => }/HandlerAdapter.java | 4 +--- .../webmvc/servlet/{mvc => }/HandlerMapping.java | 2 +- .../mvc/{tobe => }/AnnotationHandlerMapping.java | 4 ++-- .../servlet/mvc/{tobe => }/ClassInstantiator.java | 2 +- .../servlet/mvc/{tobe => }/ControllerScanner.java | 2 +- .../webmvc/servlet/mvc/HandlerAdapterRegistry.java | 2 +- .../servlet/mvc/{tobe => }/HandlerExecution.java | 2 +- .../servlet/mvc/HandlerExecutionHandlerAdapter.java | 2 +- .../webmvc/servlet/mvc/{tobe => }/HandlerKey.java | 2 +- .../webmvc/servlet/mvc/HandlerMappingRegistry.java | 2 +- .../servlet/mvc/{tobe => }/RequestMappingInfo.java | 2 +- .../servlet/mvc/{asis => legacy}/Controller.java | 2 +- .../{asis => legacy}/ControllerHandlerAdapter.java | 4 ++-- .../mvc/{asis => legacy}/ForwardController.java | 2 +- .../{tobe => }/AnnotationHandlerMappingTest.java | 2 +- .../mvc/{tobe => }/ClassInstantiatorTest.java | 2 +- .../servlet/mvc/ControllerHandlerAdapterTest.java | 5 ++--- .../mvc/{tobe => }/ControllerScannerTest.java | 2 +- .../servlet/mvc/HandlerAdapterRegistryTest.java | 13 ++----------- .../mvc/HandlerExecutionHandlerAdapterTest.java | 3 +-- .../mvc/{tobe => }/HandlerExecutionTest.java | 2 +- .../servlet/mvc/HandlerMappingRegistryTest.java | 2 -- .../mvc/{tobe => }/RequestMappingInfoTest.java | 2 +- .../test/java/samples/TestExtendsController.java | 2 +- 27 files changed, 31 insertions(+), 46 deletions(-) rename mvc/src/main/java/com/interface21/webmvc/servlet/{mvc => }/HandlerAdapter.java (75%) rename mvc/src/main/java/com/interface21/webmvc/servlet/{mvc => }/HandlerMapping.java (81%) rename mvc/src/main/java/com/interface21/webmvc/servlet/mvc/{tobe => }/AnnotationHandlerMapping.java (95%) rename mvc/src/main/java/com/interface21/webmvc/servlet/mvc/{tobe => }/ClassInstantiator.java (94%) rename mvc/src/main/java/com/interface21/webmvc/servlet/mvc/{tobe => }/ControllerScanner.java (92%) rename mvc/src/main/java/com/interface21/webmvc/servlet/mvc/{tobe => }/HandlerExecution.java (95%) rename mvc/src/main/java/com/interface21/webmvc/servlet/mvc/{tobe => }/HandlerKey.java (94%) rename mvc/src/main/java/com/interface21/webmvc/servlet/mvc/{tobe => }/RequestMappingInfo.java (94%) rename mvc/src/main/java/com/interface21/webmvc/servlet/mvc/{asis => legacy}/Controller.java (82%) rename mvc/src/main/java/com/interface21/webmvc/servlet/mvc/{asis => legacy}/ControllerHandlerAdapter.java (91%) rename mvc/src/main/java/com/interface21/webmvc/servlet/mvc/{asis => legacy}/ForwardController.java (90%) rename mvc/src/test/java/com/interface21/webmvc/servlet/mvc/{tobe => }/AnnotationHandlerMappingTest.java (98%) rename mvc/src/test/java/com/interface21/webmvc/servlet/mvc/{tobe => }/ClassInstantiatorTest.java (97%) rename mvc/src/test/java/com/interface21/webmvc/servlet/mvc/{tobe => }/ControllerScannerTest.java (95%) rename mvc/src/test/java/com/interface21/webmvc/servlet/mvc/{tobe => }/HandlerExecutionTest.java (96%) rename mvc/src/test/java/com/interface21/webmvc/servlet/mvc/{tobe => }/RequestMappingInfoTest.java (98%) diff --git a/app/src/main/java/com/techcourse/DispatcherServlet.java b/app/src/main/java/com/techcourse/DispatcherServlet.java index 219d148385..d43c76cc35 100644 --- a/app/src/main/java/com/techcourse/DispatcherServlet.java +++ b/app/src/main/java/com/techcourse/DispatcherServlet.java @@ -9,7 +9,7 @@ import org.slf4j.LoggerFactory; import com.interface21.webmvc.servlet.ModelAndView; -import com.interface21.webmvc.servlet.mvc.HandlerAdapter; +import com.interface21.webmvc.servlet.HandlerAdapter; import com.interface21.webmvc.servlet.mvc.HandlerAdapterRegistry; import com.interface21.webmvc.servlet.mvc.HandlerMappingRegistry; diff --git a/app/src/main/java/com/techcourse/ManualHandlerMapping.java b/app/src/main/java/com/techcourse/ManualHandlerMapping.java index 05e084bdc9..d9871f3394 100644 --- a/app/src/main/java/com/techcourse/ManualHandlerMapping.java +++ b/app/src/main/java/com/techcourse/ManualHandlerMapping.java @@ -8,8 +8,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.interface21.webmvc.servlet.mvc.HandlerMapping; -import com.interface21.webmvc.servlet.mvc.asis.Controller; +import com.interface21.webmvc.servlet.HandlerMapping; +import com.interface21.webmvc.servlet.mvc.legacy.Controller; @Deprecated public class ManualHandlerMapping implements HandlerMapping { diff --git a/app/src/test/java/com/techcourse/ManualHandlerMappingTest.java b/app/src/test/java/com/techcourse/ManualHandlerMappingTest.java index fd3a5fa2ab..72b57b4492 100644 --- a/app/src/test/java/com/techcourse/ManualHandlerMappingTest.java +++ b/app/src/test/java/com/techcourse/ManualHandlerMappingTest.java @@ -13,7 +13,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import com.interface21.webmvc.servlet.mvc.asis.Controller; +import com.interface21.webmvc.servlet.mvc.legacy.Controller; class ManualHandlerMappingTest { diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerAdapter.java b/mvc/src/main/java/com/interface21/webmvc/servlet/HandlerAdapter.java similarity index 75% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerAdapter.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/HandlerAdapter.java index a72d95c73e..4eb9a22a9b 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerAdapter.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/HandlerAdapter.java @@ -1,10 +1,8 @@ -package com.interface21.webmvc.servlet.mvc; +package com.interface21.webmvc.servlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import com.interface21.webmvc.servlet.ModelAndView; - public interface HandlerAdapter { boolean supports(final Object handler); diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerMapping.java b/mvc/src/main/java/com/interface21/webmvc/servlet/HandlerMapping.java similarity index 81% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerMapping.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/HandlerMapping.java index de5304240a..fe7a5e830f 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerMapping.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/HandlerMapping.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc; +package com.interface21.webmvc.servlet; import jakarta.servlet.http.HttpServletRequest; diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/AnnotationHandlerMapping.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/AnnotationHandlerMapping.java similarity index 95% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/AnnotationHandlerMapping.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/mvc/AnnotationHandlerMapping.java index 734e0ad30e..d16696a3e6 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/AnnotationHandlerMapping.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/AnnotationHandlerMapping.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.mvc; import java.lang.reflect.Method; import java.util.Arrays; @@ -11,7 +11,7 @@ import com.interface21.web.bind.annotation.RequestMapping; import com.interface21.web.bind.annotation.RequestMethod; -import com.interface21.webmvc.servlet.mvc.HandlerMapping; +import com.interface21.webmvc.servlet.HandlerMapping; public class AnnotationHandlerMapping implements HandlerMapping { diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/ClassInstantiator.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/ClassInstantiator.java similarity index 94% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/ClassInstantiator.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/mvc/ClassInstantiator.java index a5e011ab2d..c6c44776f1 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/ClassInstantiator.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/ClassInstantiator.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.mvc; import java.lang.reflect.Modifier; diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/ControllerScanner.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/ControllerScanner.java similarity index 92% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/ControllerScanner.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/mvc/ControllerScanner.java index 9bc51dde40..c3a17352b5 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/ControllerScanner.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/ControllerScanner.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.mvc; import java.util.Set; diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistry.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistry.java index a4434c265d..f348c7b14c 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistry.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistry.java @@ -3,7 +3,7 @@ import java.util.ArrayList; import java.util.List; -import com.interface21.webmvc.servlet.mvc.asis.ControllerHandlerAdapter; +import com.interface21.webmvc.servlet.HandlerAdapter; public class HandlerAdapterRegistry { diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerExecution.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerExecution.java similarity index 95% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerExecution.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerExecution.java index 21617810ce..88ac742b73 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerExecution.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerExecution.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.mvc; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerExecutionHandlerAdapter.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerExecutionHandlerAdapter.java index 8394061df6..8dbc6503f3 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerExecutionHandlerAdapter.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerExecutionHandlerAdapter.java @@ -3,8 +3,8 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import com.interface21.webmvc.servlet.HandlerAdapter; import com.interface21.webmvc.servlet.ModelAndView; -import com.interface21.webmvc.servlet.mvc.tobe.HandlerExecution; public class HandlerExecutionHandlerAdapter implements HandlerAdapter { diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerKey.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerKey.java similarity index 94% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerKey.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerKey.java index 55f8e593a1..3750121123 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerKey.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerKey.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.mvc; import com.interface21.web.bind.annotation.RequestMethod; diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerMappingRegistry.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerMappingRegistry.java index 60395a3871..e2fbdcfa82 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerMappingRegistry.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/HandlerMappingRegistry.java @@ -6,7 +6,7 @@ import jakarta.servlet.http.HttpServletRequest; -import com.interface21.webmvc.servlet.mvc.tobe.AnnotationHandlerMapping; +import com.interface21.webmvc.servlet.HandlerMapping; public class HandlerMappingRegistry { diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/RequestMappingInfo.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/RequestMappingInfo.java similarity index 94% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/RequestMappingInfo.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/mvc/RequestMappingInfo.java index 7ff42b130b..bf21020a8e 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/RequestMappingInfo.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/RequestMappingInfo.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.mvc; import java.util.Arrays; import java.util.List; diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/Controller.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/legacy/Controller.java similarity index 82% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/Controller.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/mvc/legacy/Controller.java index 84849ccd74..f42279f13c 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/Controller.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/legacy/Controller.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.asis; +package com.interface21.webmvc.servlet.mvc.legacy; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ControllerHandlerAdapter.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/legacy/ControllerHandlerAdapter.java similarity index 91% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ControllerHandlerAdapter.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/mvc/legacy/ControllerHandlerAdapter.java index b60b1bff79..cca84a4a84 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ControllerHandlerAdapter.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/legacy/ControllerHandlerAdapter.java @@ -1,11 +1,11 @@ -package com.interface21.webmvc.servlet.mvc.asis; +package com.interface21.webmvc.servlet.mvc.legacy; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import com.interface21.webmvc.servlet.ModelAndView; import com.interface21.webmvc.servlet.View; -import com.interface21.webmvc.servlet.mvc.HandlerAdapter; +import com.interface21.webmvc.servlet.HandlerAdapter; import com.interface21.webmvc.servlet.view.JspView; @Deprecated diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ForwardController.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/legacy/ForwardController.java similarity index 90% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ForwardController.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/mvc/legacy/ForwardController.java index 89acdbca35..ac55f325ec 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ForwardController.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/legacy/ForwardController.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.asis; +package com.interface21.webmvc.servlet.mvc.legacy; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/AnnotationHandlerMappingTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/AnnotationHandlerMappingTest.java similarity index 98% rename from mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/AnnotationHandlerMappingTest.java rename to mvc/src/test/java/com/interface21/webmvc/servlet/mvc/AnnotationHandlerMappingTest.java index 00ca0d2c86..b50c19b48e 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/AnnotationHandlerMappingTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/AnnotationHandlerMappingTest.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.mvc; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/ClassInstantiatorTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/ClassInstantiatorTest.java similarity index 97% rename from mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/ClassInstantiatorTest.java rename to mvc/src/test/java/com/interface21/webmvc/servlet/mvc/ClassInstantiatorTest.java index e2baa50e0c..609e879af4 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/ClassInstantiatorTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/ClassInstantiatorTest.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.mvc; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertInstanceOf; diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/ControllerHandlerAdapterTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/ControllerHandlerAdapterTest.java index 209e370379..cd543a5f59 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/ControllerHandlerAdapterTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/ControllerHandlerAdapterTest.java @@ -19,9 +19,8 @@ import org.mockito.ArgumentCaptor; import com.interface21.webmvc.servlet.ModelAndView; -import com.interface21.webmvc.servlet.mvc.asis.Controller; -import com.interface21.webmvc.servlet.mvc.asis.ControllerHandlerAdapter; -import com.interface21.webmvc.servlet.mvc.tobe.HandlerExecution; +import com.interface21.webmvc.servlet.mvc.legacy.Controller; +import com.interface21.webmvc.servlet.mvc.legacy.ControllerHandlerAdapter; import samples.TestAnnotationController; import samples.TestExtendsController; diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/ControllerScannerTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/ControllerScannerTest.java similarity index 95% rename from mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/ControllerScannerTest.java rename to mvc/src/test/java/com/interface21/webmvc/servlet/mvc/ControllerScannerTest.java index e8d115b753..e3ab32e54f 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/ControllerScannerTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/ControllerScannerTest.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.mvc; import static org.assertj.core.api.Assertions.assertThat; diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistryTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistryTest.java index a3f7f805a9..b1b0b15b01 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistryTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerAdapterRegistryTest.java @@ -7,8 +7,8 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import com.interface21.webmvc.servlet.mvc.asis.ControllerHandlerAdapter; -import com.interface21.webmvc.servlet.mvc.tobe.HandlerExecution; +import com.interface21.webmvc.servlet.HandlerAdapter; +import com.interface21.webmvc.servlet.mvc.legacy.ControllerHandlerAdapter; import samples.TestAnnotationController; import samples.TestExtendsController; @@ -19,15 +19,6 @@ class HandlerAdapterRegistryTest { @DisplayName("요청 Handler에 맞는 HandlerAdapter 반환") class GetHandlerAdapter { - @Test - @DisplayName("요청 Handler에 맞는 HandlerAdapter 반환 성공: ControllerHandlerAdapter") - void getHandlerAdapter_ControllerHandlerAdapter() { - final HandlerAdapterRegistry handlerAdapterRegistry = new HandlerAdapterRegistry(); - final HandlerAdapter handlerAdapter = handlerAdapterRegistry.getHandlerAdapter(new TestExtendsController()); - - assertThat(handlerAdapter).isInstanceOf(ControllerHandlerAdapter.class); - } - @Test @DisplayName("요청 Handler에 맞는 HandlerAdapter 반환 성공: HandlerExecutionHandlerAdapter") void getHandlerAdapter_HandlerExecutionHandlerAdapter() { diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerExecutionHandlerAdapterTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerExecutionHandlerAdapterTest.java index 5cfd689368..67f0283b19 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerExecutionHandlerAdapterTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerExecutionHandlerAdapterTest.java @@ -17,8 +17,7 @@ import org.junit.jupiter.api.Test; import com.interface21.webmvc.servlet.ModelAndView; -import com.interface21.webmvc.servlet.mvc.asis.Controller; -import com.interface21.webmvc.servlet.mvc.tobe.HandlerExecution; +import com.interface21.webmvc.servlet.mvc.legacy.Controller; import samples.TestAnnotationController; import samples.TestExtendsController; diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerExecutionTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerExecutionTest.java similarity index 96% rename from mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerExecutionTest.java rename to mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerExecutionTest.java index fd7694c221..4ad9ec5f3c 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerExecutionTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerExecutionTest.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.mvc; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerMappingRegistryTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerMappingRegistryTest.java index af940c1a10..0379d9075c 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerMappingRegistryTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/HandlerMappingRegistryTest.java @@ -12,8 +12,6 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import com.interface21.webmvc.servlet.mvc.tobe.HandlerExecution; - class HandlerMappingRegistryTest { @Nested diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/RequestMappingInfoTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/RequestMappingInfoTest.java similarity index 98% rename from mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/RequestMappingInfoTest.java rename to mvc/src/test/java/com/interface21/webmvc/servlet/mvc/RequestMappingInfoTest.java index 2d0b6ac981..8b18545510 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/RequestMappingInfoTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/RequestMappingInfoTest.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.mvc; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; diff --git a/mvc/src/test/java/samples/TestExtendsController.java b/mvc/src/test/java/samples/TestExtendsController.java index a8118a88c6..330bfb1bcd 100644 --- a/mvc/src/test/java/samples/TestExtendsController.java +++ b/mvc/src/test/java/samples/TestExtendsController.java @@ -3,7 +3,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import com.interface21.webmvc.servlet.mvc.asis.Controller; +import com.interface21.webmvc.servlet.mvc.legacy.Controller; public class TestExtendsController implements Controller { From 8036b93606a2624dee3da199053a3b2f22a2f55f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Mon, 30 Sep 2024 15:21:17 +0900 Subject: [PATCH 07/19] =?UTF-8?q?refactor(DispatcherServlet):=20=EC=95=A0?= =?UTF-8?q?=ED=94=8C=EB=A6=AC=EC=BC=80=EC=9D=B4=EC=85=98=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=20=ED=8C=A8=ED=82=A4=EC=A7=80=EB=A5=BC=20=EC=99=B8?= =?UTF-8?q?=EB=B6=80=EC=97=90=EC=84=9C=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DispatcherServletInitializer.java | 5 +++- .../techcourse/ManualHandlerMappingTest.java | 1 + .../webmvc/servlet}/DispatcherServlet.java | 13 +++++----- .../servlet}/DispatcherServletTest.java | 25 +++++++++---------- .../samples/TestAnnotationController.java | 2 +- 5 files changed, 25 insertions(+), 21 deletions(-) rename {app/src/main/java/com/techcourse => mvc/src/main/java/com/interface21/webmvc/servlet}/DispatcherServlet.java (85%) rename {app/src/test/java/com/techcourse => mvc/src/test/java/com/interface21/webmvc/servlet}/DispatcherServletTest.java (76%) diff --git a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java index d07ddf2033..3f4f09eb3c 100644 --- a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java +++ b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java @@ -4,6 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.interface21.web.WebApplicationInitializer; +import com.interface21.webmvc.servlet.DispatcherServlet; /** * Base class for {@link WebApplicationInitializer} @@ -13,11 +14,13 @@ public class DispatcherServletInitializer implements WebApplicationInitializer { private static final Logger log = LoggerFactory.getLogger(DispatcherServletInitializer.class); + private static final String BASE_PACKAGE = "com.techcourse"; private static final String DEFAULT_SERVLET_NAME = "dispatcher"; @Override public void onStartup(final ServletContext servletContext) { - final var dispatcherServlet = new DispatcherServlet(); + servletContext.setAttribute("basePackage", BASE_PACKAGE); + final var dispatcherServlet = new DispatcherServlet(servletContext); final var registration = servletContext.addServlet(DEFAULT_SERVLET_NAME, dispatcherServlet); if (registration == null) { diff --git a/app/src/test/java/com/techcourse/ManualHandlerMappingTest.java b/app/src/test/java/com/techcourse/ManualHandlerMappingTest.java index 72b57b4492..592d982862 100644 --- a/app/src/test/java/com/techcourse/ManualHandlerMappingTest.java +++ b/app/src/test/java/com/techcourse/ManualHandlerMappingTest.java @@ -15,6 +15,7 @@ import com.interface21.webmvc.servlet.mvc.legacy.Controller; +@Deprecated class ManualHandlerMappingTest { @Nested diff --git a/app/src/main/java/com/techcourse/DispatcherServlet.java b/mvc/src/main/java/com/interface21/webmvc/servlet/DispatcherServlet.java similarity index 85% rename from app/src/main/java/com/techcourse/DispatcherServlet.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/DispatcherServlet.java index d43c76cc35..474c194bf2 100644 --- a/app/src/main/java/com/techcourse/DispatcherServlet.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/DispatcherServlet.java @@ -1,5 +1,6 @@ -package com.techcourse; +package com.interface21.webmvc.servlet; +import jakarta.servlet.ServletContext; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; @@ -8,8 +9,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.interface21.webmvc.servlet.ModelAndView; -import com.interface21.webmvc.servlet.HandlerAdapter; import com.interface21.webmvc.servlet.mvc.HandlerAdapterRegistry; import com.interface21.webmvc.servlet.mvc.HandlerMappingRegistry; @@ -17,18 +16,20 @@ public class DispatcherServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final Logger log = LoggerFactory.getLogger(DispatcherServlet.class); + private static final String BASE_PACKAGE_KEY = "basePackage"; private final HandlerMappingRegistry handlerMappingRegistry; private final HandlerAdapterRegistry handlerAdapterRegistry; - public DispatcherServlet() { - this.handlerMappingRegistry = new HandlerMappingRegistry("com.techcourse"); + public DispatcherServlet(final ServletContext servletContext) { + String basePackage = (String) servletContext.getAttribute(BASE_PACKAGE_KEY); + this.handlerMappingRegistry = new HandlerMappingRegistry(basePackage); this.handlerAdapterRegistry = new HandlerAdapterRegistry(); } @Override public void init() { - handlerMappingRegistry.add(new ManualHandlerMapping()); + log.info("DispatcherServlet init"); } @Override diff --git a/app/src/test/java/com/techcourse/DispatcherServletTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/DispatcherServletTest.java similarity index 76% rename from app/src/test/java/com/techcourse/DispatcherServletTest.java rename to mvc/src/test/java/com/interface21/webmvc/servlet/DispatcherServletTest.java index cc894780ce..a0f00ba7df 100644 --- a/app/src/test/java/com/techcourse/DispatcherServletTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/DispatcherServletTest.java @@ -1,48 +1,47 @@ -package com.techcourse; +package com.interface21.webmvc.servlet; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import java.io.IOException; - import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletContext; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; -import org.mockito.MockitoSession; -import org.mockito.internal.matchers.CapturingMatcher; class DispatcherServletTest { private HttpServletRequest request; private HttpServletResponse response; + private ServletContext servletContext; private ArgumentCaptor argumentCaptor; @BeforeEach void setUp() { request = mock(HttpServletRequest.class); response = mock(HttpServletResponse.class); + servletContext = mock(ServletContext.class); argumentCaptor = ArgumentCaptor.forClass(String.class); when(request.getSession()).thenReturn(mock(HttpSession.class)); when(request.getRequestDispatcher(argumentCaptor.capture())).thenReturn(mock(RequestDispatcher.class)); + when(request.getServletContext()).thenReturn(servletContext); + when(servletContext.getAttribute("basePackage")).thenReturn("samples"); } @Test + @Disabled("Controller 핸들러 지원 종료") @DisplayName("Controller 핸들러의 요청 처리 성공: login.jsp로 forward") void service_LoginRequest() throws ServletException { - final DispatcherServlet dispatcherServlet = new DispatcherServlet(); + final DispatcherServlet dispatcherServlet = new DispatcherServlet(servletContext); dispatcherServlet.init(); when(request.getMethod()).thenReturn("GET"); @@ -56,14 +55,14 @@ void service_LoginRequest() throws ServletException { @Test @DisplayName("Annotation 핸들러의 요청 처리 성공: login.jsp로 forward") void service_RegisterRequest() throws ServletException { - final DispatcherServlet dispatcherServlet = new DispatcherServlet(); + final DispatcherServlet dispatcherServlet = new DispatcherServlet(servletContext); dispatcherServlet.init(); when(request.getMethod()).thenReturn("GET"); - when(request.getRequestURI()).thenReturn("/register"); + when(request.getRequestURI()).thenReturn("/get-test"); dispatcherServlet.service(request, response); - assertThat(argumentCaptor.getValue()).isEqualTo("/register.jsp"); + assertThat(argumentCaptor.getValue()).isEqualTo("/fake.jsp"); } } diff --git a/mvc/src/test/java/samples/TestAnnotationController.java b/mvc/src/test/java/samples/TestAnnotationController.java index 9c12af05b6..6137321809 100644 --- a/mvc/src/test/java/samples/TestAnnotationController.java +++ b/mvc/src/test/java/samples/TestAnnotationController.java @@ -18,7 +18,7 @@ public class TestAnnotationController { @RequestMapping(value = "/get-test", method = RequestMethod.GET) public ModelAndView findUserId(final HttpServletRequest request, final HttpServletResponse response) { log.info("test controller get method"); - final var modelAndView = new ModelAndView(new JspView("")); + final var modelAndView = new ModelAndView(new JspView("/fake.jsp")); modelAndView.addObject("id", request.getAttribute("id")); return modelAndView; } From eb72ebb31fce6f9b6f944ab96fc797198986d644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Mon, 30 Sep 2024 15:21:38 +0900 Subject: [PATCH 08/19] =?UTF-8?q?refactor(UserController):=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=EC=97=90=20=EC=A3=BC=EC=96=B4?= =?UTF-8?q?=EC=A7=84=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../techcourse/controller/UserController.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 app/src/main/java/com/techcourse/controller/UserController.java 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..4eb9332995 --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/UserController.java @@ -0,0 +1,34 @@ +package com.techcourse.controller; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.interface21.context.stereotype.Controller; +import com.interface21.web.bind.annotation.RequestMapping; +import com.interface21.web.bind.annotation.RequestMethod; +import com.interface21.webmvc.servlet.ModelAndView; +import com.interface21.webmvc.servlet.view.JsonView; +import com.techcourse.domain.User; +import com.techcourse.repository.InMemoryUserRepository; + +@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(() -> new IllegalArgumentException("해당 사용자가 존재하지 않습니다. 다시 로그인 해주세요.")); + + modelAndView.addObject("user", user); + return modelAndView; + } +} From dd7e2f6b183f0401017166e36ca26485d4483a25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Mon, 30 Sep 2024 15:51:12 +0900 Subject: [PATCH 09/19] =?UTF-8?q?refactor(JsonView):=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=EA=B0=80=201=EA=B0=9C=EC=9D=BC=20=EA=B2=BD=EC=9A=B0?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../webmvc/servlet/view/JsonView.java | 23 +++++++++++-------- .../webmvc/servlet/view/JsonViewTest.java | 20 +++++++++++----- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/view/JsonView.java b/mvc/src/main/java/com/interface21/webmvc/servlet/view/JsonView.java index 6e2a698915..de391f8c9e 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/view/JsonView.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/view/JsonView.java @@ -1,11 +1,12 @@ package com.interface21.webmvc.servlet.view; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.interface21.webmvc.servlet.View; +import java.util.Map; + import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import java.util.Map; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.interface21.webmvc.servlet.View; public class JsonView implements View { @@ -20,17 +21,21 @@ public JsonView() { } @Override - public void render(final Map model, final HttpServletRequest request, HttpServletResponse response) throws Exception { + public void render(final Map model, final HttpServletRequest request, HttpServletResponse response) + throws Exception { + final String jsonFormattedData = objectMapper.writeValueAsString(getRawData(model)); + response.getWriter().write(jsonFormattedData); response.setContentType(JSON_CONTENT_TYPE); response.setCharacterEncoding(UTF_8_ENCODING); + } + private Object getRawData(final Map model) { if (model.size() == ONE_MODEL_SIZE) { - String rawData = model.values().iterator().next().toString(); - response.getWriter().write(rawData); - return; + return model.values().stream() + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("모델이 비어있습니다. 데이터를 확인해주세요.")); } - String jsonFormattedData = objectMapper.writeValueAsString(model); - response.getWriter().write(jsonFormattedData); + return model; } } diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/view/JsonViewTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/view/JsonViewTest.java index 9a11250251..b9b212b41b 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/view/JsonViewTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/view/JsonViewTest.java @@ -1,5 +1,6 @@ package com.interface21.webmvc.servlet.view; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -34,9 +35,9 @@ void setUp() throws IOException { @Test @DisplayName("응답을 Json 형식으로 반환 성공: 데이터가 1개면 그대로 반환") - void render() throws Exception { + void renderOneData() throws Exception { // given - Map model = Map.of("alpaca", "hihi"); + Map model = Map.of("alpaca", new User("alpaca", 25)); // when JsonView jsonView = new JsonView(); @@ -45,16 +46,16 @@ void render() throws Exception { // then verify(response).setContentType("application/json"); verify(response).setCharacterEncoding("UTF-8"); - verify(writer).write("hihi"); + verify(writer).write("{\"name\":\"alpaca\",\"age\":25}"); } @Test @DisplayName("응답을 Json 형식으로 반환 성공: 데이터가 2개 이상이면 Map 형태의 Json으로 반환") - void rdfsender() throws Exception { + void renderOverTwoData() throws Exception { // given Map model = Map.of( - "key1", "value1", - "key2", "value2" + "alpaca", new User("alpaca", 25), + "moly", new User("moly", 20) ); String expectedJson = new ObjectMapper().writeValueAsString(model); @@ -66,5 +67,12 @@ void rdfsender() throws Exception { verify(response).setContentType("application/json"); verify(response).setCharacterEncoding("UTF-8"); verify(writer).write(expectedJson); + assertThat(expectedJson).contains( + "alpaca\":{\"name\":\"alpaca\",\"age\":25}", + "moly\":{\"name\":\"moly\",\"age\":20}" + ); + } + + private record User(String name, int age) { } } From 121c474322a3b6ee907afb4303139f50e5b86477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Tue, 1 Oct 2024 00:08:43 +0900 Subject: [PATCH 10/19] =?UTF-8?q?refactor(DIContainer):=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EC=A3=BC=EC=9E=85=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/di/stage3/context/DIContainer.java | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/study/src/test/java/di/stage3/context/DIContainer.java b/study/src/test/java/di/stage3/context/DIContainer.java index b62feb1ed3..ee009f5a73 100644 --- a/study/src/test/java/di/stage3/context/DIContainer.java +++ b/study/src/test/java/di/stage3/context/DIContainer.java @@ -1,6 +1,12 @@ package di.stage3.context; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import java.util.Arrays; import java.util.Set; +import java.util.stream.Collectors; /** * 스프링의 BeanFactory, ApplicationContext에 해당되는 클래스 @@ -10,11 +16,57 @@ class DIContainer { private final Set beans; public DIContainer(final Set> classes) { - this.beans = Set.of(); + this.beans = createBeans(classes); + this.beans.forEach(this::setFields); + } + + private Set createBeans(final Set> classes) { + return classes.stream() + .map(this::createInstance) + .collect(Collectors.toSet()); + } + + private Object createInstance(final Class aClass) { + try { + Constructor declaredConstructor = aClass.getDeclaredConstructor(); + declaredConstructor.setAccessible(true); + return declaredConstructor.newInstance(); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | + NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + private void setFields(final Object bean) { + Field[] declaredFields = bean.getClass().getDeclaredFields(); + Arrays.stream(declaredFields) + .filter(this::isInjectable) + .forEach(field -> injectField(field, bean)); + } + + private boolean isInjectable(final Field field) { + int modifiers = field.getModifiers(); + return !Modifier.isStatic(modifiers) && + !Modifier.isFinal(modifiers); + } + + private void injectField(final Field field, final Object bean) { + field.setAccessible(true); + Object fieldInstance = getBean(field.getType()); + + try { + field.set(bean, fieldInstance); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } } @SuppressWarnings("unchecked") public T getBean(final Class aClass) { - return null; + return beans.stream() + .filter(bean -> aClass.isAssignableFrom(bean.getClass())) + .findFirst() + .map(aClass::cast) + .orElseThrow(() -> new RuntimeException("Bean not found")); } } From 7e310c046c5ae295c1081af5bbfeb27f58c7767f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Tue, 1 Oct 2024 00:35:50 +0900 Subject: [PATCH 11/19] =?UTF-8?q?refactor(ClassPathScanner):=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EA=B2=BD=EB=A1=9C=EB=A1=9C=EB=B6=80?= =?UTF-8?q?=ED=84=B0=20=ED=95=B4=EB=8B=B9=ED=95=98=EB=8A=94=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=EB=A5=BC=20=EB=B0=98=ED=99=98=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EC=8A=A4=EC=BA=90=EB=84=88=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../stage4/annotations/ClassPathScanner.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/study/src/test/java/di/stage4/annotations/ClassPathScanner.java b/study/src/test/java/di/stage4/annotations/ClassPathScanner.java index 9dab1fd9c4..47f1ff9828 100644 --- a/study/src/test/java/di/stage4/annotations/ClassPathScanner.java +++ b/study/src/test/java/di/stage4/annotations/ClassPathScanner.java @@ -1,10 +1,35 @@ package di.stage4.annotations; +import java.lang.annotation.Annotation; +import java.util.Arrays; import java.util.Set; +import java.util.stream.Collectors; + +import org.reflections.Reflections; +import org.reflections.scanners.Scanners; public class ClassPathScanner { public static Set> getAllClassesInPackage(final String packageName) { - return null; + Reflections reflections = new Reflections(packageName); + return reflections.getSubTypesOf(Object.class); + } + + public static Set> getAnnotatedClassesInPackage( + final String packageName, + final Class annotation + ) { + Reflections reflections = new Reflections(packageName, Scanners.TypesAnnotated); + return reflections.getTypesAnnotatedWith(annotation); + } + + public static Set> getAnnotatedClassesInPackage( + final String packageName, + final Class... annotations + ) { + Reflections reflections = new Reflections(packageName, Scanners.TypesAnnotated); + return Arrays.stream(annotations) + .flatMap(annotation -> reflections.getTypesAnnotatedWith(annotation).stream()) + .collect(Collectors.toSet()); } } From ea54e8092fe3e417ee9fd0cbee3297b7ea6afa9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Tue, 1 Oct 2024 00:36:34 +0900 Subject: [PATCH 12/19] =?UTF-8?q?refactor(DIContainer):=20@Service,=20@Rep?= =?UTF-8?q?ository=20Component=20=EB=B9=88=20=EB=93=B1=EB=A1=9D=20?= =?UTF-8?q?=EB=B0=8F=20@Inject=20=EB=B9=88=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/di/stage3/context/DIContainer.java | 2 +- .../di/stage4/annotations/DIContainer.java | 68 ++++++++++++++++++- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/study/src/test/java/di/stage3/context/DIContainer.java b/study/src/test/java/di/stage3/context/DIContainer.java index ee009f5a73..a4dbcfabd8 100644 --- a/study/src/test/java/di/stage3/context/DIContainer.java +++ b/study/src/test/java/di/stage3/context/DIContainer.java @@ -67,6 +67,6 @@ public T getBean(final Class aClass) { .filter(bean -> aClass.isAssignableFrom(bean.getClass())) .findFirst() .map(aClass::cast) - .orElseThrow(() -> new RuntimeException("Bean not found")); + .orElseThrow(() -> new RuntimeException("Beand을 찾을 수 없습니다.")); } } diff --git a/study/src/test/java/di/stage4/annotations/DIContainer.java b/study/src/test/java/di/stage4/annotations/DIContainer.java index 9248ecad7e..9faf5fc837 100644 --- a/study/src/test/java/di/stage4/annotations/DIContainer.java +++ b/study/src/test/java/di/stage4/annotations/DIContainer.java @@ -1,24 +1,86 @@ package di.stage4.annotations; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import java.util.Arrays; import java.util.Set; +import java.util.stream.Collectors; /** * 스프링의 BeanFactory, ApplicationContext에 해당되는 클래스 */ class DIContainer { + private static final Class SERVICE_ANNOTATION = Service.class; + private static final Class REPOSITORY_ANNOTATION = Repository.class; + private static final Class INJECT_ANNOTATION = Inject.class; + private final Set beans; public DIContainer(final Set> classes) { - this.beans = Set.of(); + this.beans = createBeans(classes); + this.beans.forEach(this::setFields); } public static DIContainer createContainerForPackage(final String rootPackageName) { - return null; + Set> classes = ClassPathScanner.getAnnotatedClassesInPackage( + rootPackageName, + SERVICE_ANNOTATION, + REPOSITORY_ANNOTATION); + + return new DIContainer(classes); + } + + private Set createBeans(final Set> classes) { + return classes.stream() + .map(this::createInstance) + .collect(Collectors.toSet()); + } + + private Object createInstance(final Class aClass) { + try { + Constructor declaredConstructor = aClass.getDeclaredConstructor(); + declaredConstructor.setAccessible(true); + return declaredConstructor.newInstance(); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | + NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + private void setFields(final Object bean) { + Field[] declaredFields = bean.getClass().getDeclaredFields(); + Arrays.stream(declaredFields) + .filter(this::isInjectable) + .forEach(field -> injectField(field, bean)); + } + + private boolean isInjectable(final Field field) { + int modifiers = field.getModifiers(); + return !Modifier.isStatic(modifiers) && + !Modifier.isFinal(modifiers) && + field.isAnnotationPresent(INJECT_ANNOTATION); + } + + private void injectField(final Field field, final Object bean) { + field.setAccessible(true); + Object fieldInstance = getBean(field.getType()); + + try { + field.set(bean, fieldInstance); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } } @SuppressWarnings("unchecked") public T getBean(final Class aClass) { - return null; + return beans.stream() + .filter(bean -> aClass.isAssignableFrom(bean.getClass())) + .findFirst() + .map(aClass::cast) + .orElseThrow(() -> new RuntimeException("Beand을 찾을 수 없습니다.")); } } From d14dd84672b64b3bdd0b8e64e75b38a133c5d610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Tue, 1 Oct 2024 00:51:34 +0900 Subject: [PATCH 13/19] =?UTF-8?q?refactor(DispatcherServletInitializer):?= =?UTF-8?q?=20DispatcherServletInitializer=20=EC=9D=98=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=EB=A5=BC=20=EC=95=A0=ED=94=8C=EB=A6=AC?= =?UTF-8?q?=EC=BC=80=EC=9D=B4=EC=85=98=EC=9D=98=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=EB=A1=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/techcourse/DispatcherServletInitializer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java index 3f4f09eb3c..e137e4823a 100644 --- a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java +++ b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java @@ -14,12 +14,12 @@ public class DispatcherServletInitializer implements WebApplicationInitializer { private static final Logger log = LoggerFactory.getLogger(DispatcherServletInitializer.class); - private static final String BASE_PACKAGE = "com.techcourse"; private static final String DEFAULT_SERVLET_NAME = "dispatcher"; @Override public void onStartup(final ServletContext servletContext) { - servletContext.setAttribute("basePackage", BASE_PACKAGE); + final var basePackage = getClass().getPackage().getName(); + servletContext.setAttribute("basePackage", basePackage); final var dispatcherServlet = new DispatcherServlet(servletContext); final var registration = servletContext.addServlet(DEFAULT_SERVLET_NAME, dispatcherServlet); From a4d55f7d30470862ae6f1e1aae270ebb1c66209e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Thu, 3 Oct 2024 00:23:47 +0900 Subject: [PATCH 14/19] =?UTF-8?q?refactor(DIContainer):=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=98=A4=ED=83=80=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 --- study/src/test/java/di/stage3/context/DIContainer.java | 2 +- study/src/test/java/di/stage4/annotations/DIContainer.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/study/src/test/java/di/stage3/context/DIContainer.java b/study/src/test/java/di/stage3/context/DIContainer.java index a4dbcfabd8..6518648777 100644 --- a/study/src/test/java/di/stage3/context/DIContainer.java +++ b/study/src/test/java/di/stage3/context/DIContainer.java @@ -67,6 +67,6 @@ public T getBean(final Class aClass) { .filter(bean -> aClass.isAssignableFrom(bean.getClass())) .findFirst() .map(aClass::cast) - .orElseThrow(() -> new RuntimeException("Beand을 찾을 수 없습니다.")); + .orElseThrow(() -> new RuntimeException("Bean을 찾을 수 없습니다.")); } } diff --git a/study/src/test/java/di/stage4/annotations/DIContainer.java b/study/src/test/java/di/stage4/annotations/DIContainer.java index 9faf5fc837..4663938414 100644 --- a/study/src/test/java/di/stage4/annotations/DIContainer.java +++ b/study/src/test/java/di/stage4/annotations/DIContainer.java @@ -81,6 +81,6 @@ public T getBean(final Class aClass) { .filter(bean -> aClass.isAssignableFrom(bean.getClass())) .findFirst() .map(aClass::cast) - .orElseThrow(() -> new RuntimeException("Beand을 찾을 수 없습니다.")); + .orElseThrow(() -> new RuntimeException("Bean을 찾을 수 없습니다.")); } } From b7add773bdd2a2d9de65edc6c95b00ed7126b055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Thu, 3 Oct 2024 00:24:46 +0900 Subject: [PATCH 15/19] =?UTF-8?q?refactor(DIContainer):=20=EB=B9=88?= =?UTF-8?q?=EC=9D=84=20=EC=B0=BE=EC=9D=84=20=EC=88=98=20=EC=97=86=EB=8A=94?= =?UTF-8?q?=20=EA=B2=BD=EC=9A=B0=20IllegalArgumentException=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- study/src/test/java/di/stage3/context/DIContainer.java | 2 +- study/src/test/java/di/stage4/annotations/DIContainer.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/study/src/test/java/di/stage3/context/DIContainer.java b/study/src/test/java/di/stage3/context/DIContainer.java index 6518648777..afcba1850f 100644 --- a/study/src/test/java/di/stage3/context/DIContainer.java +++ b/study/src/test/java/di/stage3/context/DIContainer.java @@ -67,6 +67,6 @@ public T getBean(final Class aClass) { .filter(bean -> aClass.isAssignableFrom(bean.getClass())) .findFirst() .map(aClass::cast) - .orElseThrow(() -> new RuntimeException("Bean을 찾을 수 없습니다.")); + .orElseThrow(() -> new IllegalArgumentException("Bean을 찾을 수 없습니다.")); } } diff --git a/study/src/test/java/di/stage4/annotations/DIContainer.java b/study/src/test/java/di/stage4/annotations/DIContainer.java index 4663938414..df78b406c7 100644 --- a/study/src/test/java/di/stage4/annotations/DIContainer.java +++ b/study/src/test/java/di/stage4/annotations/DIContainer.java @@ -81,6 +81,6 @@ public T getBean(final Class aClass) { .filter(bean -> aClass.isAssignableFrom(bean.getClass())) .findFirst() .map(aClass::cast) - .orElseThrow(() -> new RuntimeException("Bean을 찾을 수 없습니다.")); + .orElseThrow(() -> new IllegalArgumentException("Bean을 찾을 수 없습니다.")); } } From af782c8775e4865c90b64122f99bbf1c3ea15f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Thu, 3 Oct 2024 00:26:28 +0900 Subject: [PATCH 16/19] =?UTF-8?q?refactor(ClassPathScanner):=20=EA=B0=80?= =?UTF-8?q?=EB=B3=80=20=EC=9D=B8=EC=9E=90=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=A7=8C=20=EB=82=A8=EA=B8=B0=EA=B3=A0=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/java/di/stage4/annotations/ClassPathScanner.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/study/src/test/java/di/stage4/annotations/ClassPathScanner.java b/study/src/test/java/di/stage4/annotations/ClassPathScanner.java index 47f1ff9828..58e5e75092 100644 --- a/study/src/test/java/di/stage4/annotations/ClassPathScanner.java +++ b/study/src/test/java/di/stage4/annotations/ClassPathScanner.java @@ -15,14 +15,6 @@ public static Set> getAllClassesInPackage(final String packageName) { return reflections.getSubTypesOf(Object.class); } - public static Set> getAnnotatedClassesInPackage( - final String packageName, - final Class annotation - ) { - Reflections reflections = new Reflections(packageName, Scanners.TypesAnnotated); - return reflections.getTypesAnnotatedWith(annotation); - } - public static Set> getAnnotatedClassesInPackage( final String packageName, final Class... annotations From d89ecb7d7cef029062e23204c190666d6f9ef4ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Thu, 3 Oct 2024 00:31:07 +0900 Subject: [PATCH 17/19] =?UTF-8?q?refactor(ClassPathScanner):=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/java/di/stage4/annotations/ClassPathScanner.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/study/src/test/java/di/stage4/annotations/ClassPathScanner.java b/study/src/test/java/di/stage4/annotations/ClassPathScanner.java index 58e5e75092..6858059341 100644 --- a/study/src/test/java/di/stage4/annotations/ClassPathScanner.java +++ b/study/src/test/java/di/stage4/annotations/ClassPathScanner.java @@ -10,11 +10,6 @@ public class ClassPathScanner { - public static Set> getAllClassesInPackage(final String packageName) { - Reflections reflections = new Reflections(packageName); - return reflections.getSubTypesOf(Object.class); - } - public static Set> getAnnotatedClassesInPackage( final String packageName, final Class... annotations From 16c2c7b10cf31e99a84bdb55d340ccc096e13242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Thu, 3 Oct 2024 00:35:18 +0900 Subject: [PATCH 18/19] =?UTF-8?q?refactor(JsonView):=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=EA=B0=80=20=EC=97=86=EB=8A=94=20=EA=B2=BD=EC=9A=B0=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=EA=B0=80=20=EC=95=84=EB=8B=8C=20null?= =?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?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/interface21/webmvc/servlet/view/JsonView.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/view/JsonView.java b/mvc/src/main/java/com/interface21/webmvc/servlet/view/JsonView.java index de391f8c9e..588f2a0f62 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/view/JsonView.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/view/JsonView.java @@ -33,7 +33,8 @@ private Object getRawData(final Map model) { if (model.size() == ONE_MODEL_SIZE) { return model.values().stream() .findFirst() - .orElseThrow(() -> new IllegalArgumentException("모델이 비어있습니다. 데이터를 확인해주세요.")); + .orElse(null); + } return model; From e3407a2160164c01611d55bacfd200f6307f36b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98jminkkk=E2=80=99?= <102847513+jminkkk@users.noreply.github.com> Date: Thu, 3 Oct 2024 00:37:52 +0900 Subject: [PATCH 19/19] =?UTF-8?q?test(JsonView):=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=EA=B0=80=20=EC=97=86=EB=8B=A4=EB=A9=B4=20null=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=ED=95=98=EB=8A=94=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../webmvc/servlet/view/JsonViewTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/view/JsonViewTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/view/JsonViewTest.java index b9b212b41b..65571c0eff 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/view/JsonViewTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/view/JsonViewTest.java @@ -33,6 +33,22 @@ void setUp() throws IOException { when(response.getWriter()).thenReturn(writer); } + @Test + @DisplayName("응답을 Json 형식으로 반환 성공: 데이터가 없다면 null 반환") + void renderNotData() throws Exception { + // given + Map model = Map.of(); + + // when + JsonView jsonView = new JsonView(); + jsonView.render(model, request, response); + + // then + verify(response).setContentType("application/json"); + verify(response).setCharacterEncoding("UTF-8"); + verify(writer).write("{}"); + } + @Test @DisplayName("응답을 Json 형식으로 반환 성공: 데이터가 1개면 그대로 반환") void renderOneData() throws Exception {