From 68dff5ff6192f6765cb2b25203bee3dc9a23739e Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 21:16:51 +0900 Subject: [PATCH 01/21] feat: impl json view with jsonMapper --- .../webmvc/servlet/view/JsonView.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 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 ffe5ae6fe2..8d29230dc2 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,14 +1,27 @@ package com.interface21.webmvc.servlet.view; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.interface21.web.http.MediaType; import com.interface21.webmvc.servlet.View; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; - +import java.io.IOException; import java.util.Map; public class JsonView implements View { + private final JsonMapper jsonMapper; + + public JsonView() { + this.jsonMapper = new JsonMapper(); + } + @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 IOException { + String json = jsonMapper.writeValueAsString(model); + + response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); + response.getWriter().write(json); } } From 5641e1895db2561c7747b3d0f4150bceef91cc42 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 21:18:57 +0900 Subject: [PATCH 02/21] test: json view rendering --- .../webmvc/servlet/view/JsonViewTest.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 mvc/src/test/java/com/interface21/webmvc/servlet/view/JsonViewTest.java 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..cc7e2f21a7 --- /dev/null +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/view/JsonViewTest.java @@ -0,0 +1,51 @@ +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; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class JsonViewTest { + + @Test + @DisplayName("Serializable 한 값을 JSON 으로 렌더링 한다.") + void renderWithPrimitive() throws IOException { + // given + HttpServletRequest request = mock(HttpServletRequest.class); + HttpServletResponse response = mock(HttpServletResponse.class); + + Skill skill = new Skill(List.of("Korean", "English"), List.of("Javascript", "Java")); + Map model = Map.of("user", "seyang", "langs", skill); + JsonView jsonView = new JsonView(); + OutputStream outputStream = new ByteArrayOutputStream(); + PrintWriter writer = new PrintWriter(outputStream); + + // when + when(response.getWriter()).thenReturn(writer); + jsonView.render(model, request, response); + writer.flush(); + + // then + verify(response).setContentType("application/json;charset=UTF-8"); + assertThat(outputStream.toString()).satisfiesAnyOf( + s -> assertThat(s).isEqualTo( + "{\"langs\":{\"langs\":[\"Korean\",\"English\"],\"codes\":[\"Javascript\",\"Java\"]},\"user\":\"seyang\"}"), + s -> assertThat(s).isEqualTo( + "{\"user\":\"seyang\",\"langs\":{\"langs\":[\"Korean\",\"English\"],\"codes\":[\"Javascript\",\"Java\"]}}") + ); + } + + record Skill(List langs, List codes) { + } +} From a98da0fdec099ac5fbb0493861cd380cad1a4bde Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 21:19:07 +0900 Subject: [PATCH 03/21] feat: add user controller on app --- .../techcourse/controller/UserController.java | 42 +++++++++++++++++++ 1 file changed, 42 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..1d77bc93c0 --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/UserController.java @@ -0,0 +1,42 @@ +package com.techcourse.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.JsonView; +import com.techcourse.domain.User; +import com.techcourse.repository.InMemoryUserRepository; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Controller +public class UserController { + + private static final Logger log = LoggerFactory.getLogger(UserController.class); + private static final String PARAM_NAME_ACCOUNT = "account"; + + @RequestMapping(value = "/api/user", method = RequestMethod.GET) + public ModelAndView show(HttpServletRequest request, HttpServletResponse response) { + if (!isValidRequest(request)) { + throw new IllegalArgumentException("Please input account as parameter"); + } + + final String account = request.getParameter(PARAM_NAME_ACCOUNT); + log.debug("user id : {}", account); + + final User user = InMemoryUserRepository.findByAccount(account) + .orElseThrow(() -> new IllegalArgumentException("User not found: " + account)); + + final ModelAndView modelAndView = new ModelAndView(new JsonView()); + modelAndView.addObject("user", user); + return modelAndView; + } + + private boolean isValidRequest(HttpServletRequest request) { + String account = request.getParameter(PARAM_NAME_ACCOUNT); + return account != null && !account.isBlank(); + } +} From b513c6c171f99ed22b63d223e6f8c95285c14608 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 21:19:32 +0900 Subject: [PATCH 04/21] feat: add argument handler exception resolver --- .../ArgumentHandlerExceptionResolver.java | 36 +++++++++++++++++++ .../exception/HandlerExceptionResolver.java | 14 ++++++++ 2 files changed, 50 insertions(+) create mode 100644 mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/exception/ArgumentHandlerExceptionResolver.java create mode 100644 mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/exception/HandlerExceptionResolver.java diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/exception/ArgumentHandlerExceptionResolver.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/exception/ArgumentHandlerExceptionResolver.java new file mode 100644 index 0000000000..625520d755 --- /dev/null +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/exception/ArgumentHandlerExceptionResolver.java @@ -0,0 +1,36 @@ +package com.interface21.webmvc.servlet.mvc.tobe.exception; + +import com.interface21.webmvc.servlet.ModelAndView; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ArgumentHandlerExceptionResolver implements HandlerExceptionResolver { + + private static final Logger log = LoggerFactory.getLogger(ArgumentHandlerExceptionResolver.class); + + @Override + public ModelAndView resolveException( + HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws ServletException { + + Throwable cause = ex.getCause(); + + try { + if (cause instanceof IllegalArgumentException) { + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + response.setContentType("text/plain"); + response.getWriter().write(cause.getMessage()); + return null; + } + } catch (IOException e) { + throw new RuntimeException(e); + } + + log.error("Exception : {}", ex.getMessage(), ex); + throw new ServletException(ex.getMessage()); + } +} diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/exception/HandlerExceptionResolver.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/exception/HandlerExceptionResolver.java new file mode 100644 index 0000000000..b57c87da6d --- /dev/null +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/exception/HandlerExceptionResolver.java @@ -0,0 +1,14 @@ +package com.interface21.webmvc.servlet.mvc.tobe.exception; + +import com.interface21.webmvc.servlet.ModelAndView; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +public interface HandlerExceptionResolver { + + ModelAndView resolveException( + HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws ServletException; + +} \ No newline at end of file From f9bc764b22599272f01c8a11c91c30963d943c90 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 21:19:40 +0900 Subject: [PATCH 05/21] feat: use handler exception resolver --- .../main/java/com/techcourse/DispatcherServlet.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/techcourse/DispatcherServlet.java b/app/src/main/java/com/techcourse/DispatcherServlet.java index 4a2c4c46d3..d04daff1a9 100644 --- a/app/src/main/java/com/techcourse/DispatcherServlet.java +++ b/app/src/main/java/com/techcourse/DispatcherServlet.java @@ -6,6 +6,8 @@ import com.interface21.webmvc.servlet.mvc.tobe.HandlerAdapterRegistry; import com.interface21.webmvc.servlet.mvc.tobe.HandlerMapping; import com.interface21.webmvc.servlet.mvc.tobe.HandlerMappingRegistry; +import com.interface21.webmvc.servlet.mvc.tobe.exception.ArgumentHandlerExceptionResolver; +import com.interface21.webmvc.servlet.mvc.tobe.exception.HandlerExceptionResolver; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; @@ -22,10 +24,12 @@ public class DispatcherServlet extends HttpServlet { private final HandlerAdapterRegistry handlerAdapterRegistry; private final HandlerMappingRegistry handlerMappingRegistry; + private final HandlerExceptionResolver handlerExceptionResolver; public DispatcherServlet() { handlerAdapterRegistry = new HandlerAdapterRegistry(); handlerMappingRegistry = new HandlerMappingRegistry(BASE_PACKAGE); + handlerExceptionResolver = new ArgumentHandlerExceptionResolver(); } @Override @@ -40,14 +44,14 @@ protected void service(final HttpServletRequest request, final HttpServletRespon final String requestURI = request.getRequestURI(); log.debug("Method : {}, Request URI : {}", request.getMethod(), requestURI); + Object handler = null; try { - Object handler = findHandler(request); + handler = findHandler(request); HandlerAdapter handlerAdapter = findHandlerAdapter(handler); ModelAndView modelAndView = handlerAdapter.handle(request, response, handler); renderViewWithModel(request, response, modelAndView); - } catch (Throwable e) { - log.error("Exception : {}", e.getMessage(), e); - throw new ServletException(e.getMessage()); + } catch (Exception e) { + handlerExceptionResolver.resolveException(request, response, handler, e); } } From 9f171bbd51aa9bce11b454d83203724222582476 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 21:43:05 +0900 Subject: [PATCH 06/21] test: user controller valid and invalid --- .../techcourse/controller/UserController.java | 2 +- .../controller/UserControllerTest.java | 89 +++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 app/src/test/java/com/techcourse/controller/UserControllerTest.java diff --git a/app/src/main/java/com/techcourse/controller/UserController.java b/app/src/main/java/com/techcourse/controller/UserController.java index 1d77bc93c0..84ffc455f4 100644 --- a/app/src/main/java/com/techcourse/controller/UserController.java +++ b/app/src/main/java/com/techcourse/controller/UserController.java @@ -19,7 +19,7 @@ public class UserController { private static final String PARAM_NAME_ACCOUNT = "account"; @RequestMapping(value = "/api/user", method = RequestMethod.GET) - public ModelAndView show(HttpServletRequest request, HttpServletResponse response) { + public ModelAndView getUser(HttpServletRequest request, HttpServletResponse response) { if (!isValidRequest(request)) { throw new IllegalArgumentException("Please input account as parameter"); } 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..02bb6f7448 --- /dev/null +++ b/app/src/test/java/com/techcourse/controller/UserControllerTest.java @@ -0,0 +1,89 @@ +package com.techcourse.controller; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import com.techcourse.TomcatStarter; +import jakarta.servlet.http.HttpServletResponse; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class UserControllerTest { + + private TomcatStarter tomcat; + + @BeforeEach + void setUp() { + tomcat = new TomcatStarter("src/main/webapp/", 8080); + tomcat.start(); + } + + @AfterEach + void tearDown() { + tomcat.stop(); + } + + @Test + @DisplayName("올바른 파라미터로 요청 시 유저 정보를 반환한다.") + void getUser() throws Exception { + // given + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:8080/api/user?account=gugu")) + .build(); + + // when + HttpResponse response = client.send(request, BodyHandlers.ofString()); + client.close(); + + // then + assertThat(response.body()).isEqualTo("{\"user\":{\"account\":\"gugu\"}}"); + } + + @Test + @DisplayName("존재하지 않는 계정 정보를 보내면 400을 반환한다.") + void getUserWithNonExistReturnBadRequest() throws Exception { + // given + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:8080/api/user?account=seyang")) + .build(); + + // when + HttpResponse response = client.send(request, BodyHandlers.ofString()); + client.close(); + + // then + assertAll( + () -> assertThat(response.statusCode()).isEqualTo(HttpServletResponse.SC_BAD_REQUEST), + () -> assertThat(response.body()).isEqualTo("User not found: seyang") + ); + } + + @Test + @DisplayName("빈 계정 정보를 보내면 400을 반환한다.") + void getUserWithEmptyReturnBadRequest() throws Exception { + // given + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:8080/api/user?account=")) + .build(); + + // when + HttpResponse response = client.send(request, BodyHandlers.ofString()); + client.close(); + + // then + assertAll( + () -> assertThat(response.statusCode()).isEqualTo(HttpServletResponse.SC_BAD_REQUEST), + () -> assertThat(response.body()).isEqualTo("Please input account as parameter") + ); + } +} \ No newline at end of file From f30adee8c405c8a4f297d528e3a17c0247a53400 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 22:11:30 +0900 Subject: [PATCH 07/21] refactor: move all entries on manual handler mapping --- .../com/techcourse/ManualHandlerMapping.java | 9 --------- .../techcourse/controller/HomeController.java | 17 ++++++++++++++++ .../controller/LoginController.java | 20 ++++++++++++------- .../controller/LoginViewController.java | 18 +++++++++++------ .../controller/LogoutController.java | 17 ++++++++++------ 5 files changed, 53 insertions(+), 28 deletions(-) create mode 100644 app/src/main/java/com/techcourse/controller/HomeController.java diff --git a/app/src/main/java/com/techcourse/ManualHandlerMapping.java b/app/src/main/java/com/techcourse/ManualHandlerMapping.java index a9a6c3cff1..3b3cf09bdb 100644 --- a/app/src/main/java/com/techcourse/ManualHandlerMapping.java +++ b/app/src/main/java/com/techcourse/ManualHandlerMapping.java @@ -1,11 +1,7 @@ package com.techcourse; import com.interface21.webmvc.servlet.mvc.asis.Controller; -import com.interface21.webmvc.servlet.mvc.asis.ForwardController; import com.interface21.webmvc.servlet.mvc.tobe.HandlerMapping; -import com.techcourse.controller.LoginController; -import com.techcourse.controller.LoginViewController; -import com.techcourse.controller.LogoutController; import jakarta.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; @@ -19,11 +15,6 @@ public class ManualHandlerMapping implements HandlerMapping { 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()); - log.info("Initialized ManualHandlerMapping!"); controllers.forEach((path, controller) -> log.info("Path : {}, Controller : {}", path, controller.getClass())); } diff --git a/app/src/main/java/com/techcourse/controller/HomeController.java b/app/src/main/java/com/techcourse/controller/HomeController.java new file mode 100644 index 0000000000..357c5febf5 --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/HomeController.java @@ -0,0 +1,17 @@ +package com.techcourse.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; + +@Controller +@RequestMapping +public class HomeController { + + @RequestMapping(method = RequestMethod.GET) + public ModelAndView getHome() { + return new ModelAndView(new JspView("/index.jsp")); + } +} diff --git a/app/src/main/java/com/techcourse/controller/LoginController.java b/app/src/main/java/com/techcourse/controller/LoginController.java index a87d996693..e490275d47 100644 --- a/app/src/main/java/com/techcourse/controller/LoginController.java +++ b/app/src/main/java/com/techcourse/controller/LoginController.java @@ -1,29 +1,35 @@ package com.techcourse.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; 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 { +@Controller +@RequestMapping("/login") +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(method = RequestMethod.GET) + public ModelAndView getLogin(final HttpServletRequest req) throws Exception { if (UserSession.isLoggedIn(req.getSession())) { - return "redirect:/index.jsp"; + return new ModelAndView(new JspView("redirect:/index.jsp")); } - return InMemoryUserRepository.findByAccount(req.getParameter("account")) + String viewName = InMemoryUserRepository.findByAccount(req.getParameter("account")) .map(user -> { log.info("User : {}", user); return login(req, user); }) .orElse("redirect:/401.jsp"); + return new ModelAndView(new JspView(viewName)); } private String login(final HttpServletRequest request, final User user) { diff --git a/app/src/main/java/com/techcourse/controller/LoginViewController.java b/app/src/main/java/com/techcourse/controller/LoginViewController.java index dc71ee8e99..0db9f647e6 100644 --- a/app/src/main/java/com/techcourse/controller/LoginViewController.java +++ b/app/src/main/java/com/techcourse/controller/LoginViewController.java @@ -1,22 +1,28 @@ package com.techcourse.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 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 { +@Controller +@RequestMapping("/login/view") +public class LoginViewController { 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()) + @RequestMapping(method = RequestMethod.GET) + public ModelAndView getLoginView(final HttpServletRequest req) throws Exception { + String viewName = UserSession.getUserFrom(req.getSession()) .map(user -> { log.info("logged in {}", user.getAccount()); return "redirect:/index.jsp"; }) .orElse("/login.jsp"); + return new ModelAndView(new JspView(viewName)); } } diff --git a/app/src/main/java/com/techcourse/controller/LogoutController.java b/app/src/main/java/com/techcourse/controller/LogoutController.java index 729d262de5..49a9528405 100644 --- a/app/src/main/java/com/techcourse/controller/LogoutController.java +++ b/app/src/main/java/com/techcourse/controller/LogoutController.java @@ -1,15 +1,20 @@ package com.techcourse.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 jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import com.interface21.webmvc.servlet.mvc.asis.Controller; -public class LogoutController implements Controller { +@Controller +@RequestMapping("/logout") +public class LogoutController { - @Override - public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { + @RequestMapping(method = RequestMethod.GET) + public ModelAndView getLogout(final HttpServletRequest req) throws Exception { final var session = req.getSession(); session.removeAttribute(UserSession.SESSION_KEY); - return "redirect:/"; + return new ModelAndView(new JspView("redirect:/")); } } From 426b0306b187eb21ae9f20d65870863bd430c4ab Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 22:12:26 +0900 Subject: [PATCH 08/21] test: get home dashboard --- .../controller/HomeControllerTest.java | 50 +++++++++++++++++++ .../controller/UserControllerTest.java | 8 +-- 2 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 app/src/test/java/com/techcourse/controller/HomeControllerTest.java diff --git a/app/src/test/java/com/techcourse/controller/HomeControllerTest.java b/app/src/test/java/com/techcourse/controller/HomeControllerTest.java new file mode 100644 index 0000000000..80578be469 --- /dev/null +++ b/app/src/test/java/com/techcourse/controller/HomeControllerTest.java @@ -0,0 +1,50 @@ +package com.techcourse.controller; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.techcourse.TomcatStarter; +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class HomeControllerTest { + + private static final String URL = "http://localhost:8080"; + + private TomcatStarter tomcat; + + @BeforeEach + void setUp() { + tomcat = new TomcatStarter("src/main/webapp/", 8080); + tomcat.start(); + } + + @AfterEach + void tearDown() { + tomcat.stop(); + } + + @Test + @DisplayName("홈 화면을 요청한다.") + void getHome() throws IOException, InterruptedException { + // given + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(URL)) + .build(); + + // when + HttpResponse response = client.send(request, BodyHandlers.ofString()); + client.close(); + + // then + assertThat(response.body()).contains("대시보드"); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/techcourse/controller/UserControllerTest.java b/app/src/test/java/com/techcourse/controller/UserControllerTest.java index 02bb6f7448..4439b3ad64 100644 --- a/app/src/test/java/com/techcourse/controller/UserControllerTest.java +++ b/app/src/test/java/com/techcourse/controller/UserControllerTest.java @@ -17,6 +17,8 @@ class UserControllerTest { + private static final String URL = "http://localhost:8080/api/user"; + private TomcatStarter tomcat; @BeforeEach @@ -36,7 +38,7 @@ void getUser() throws Exception { // given HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:8080/api/user?account=gugu")) + .uri(URI.create(URL + "?account=gugu")) .build(); // when @@ -53,7 +55,7 @@ void getUserWithNonExistReturnBadRequest() throws Exception { // given HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:8080/api/user?account=seyang")) + .uri(URI.create(URL + "?account=seyang")) .build(); // when @@ -73,7 +75,7 @@ void getUserWithEmptyReturnBadRequest() throws Exception { // given HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:8080/api/user?account=")) + .uri(URI.create(URL + "?account=")) .build(); // when From 21f152cea62747fd9daca09b488e13b89e6011b7 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 22:13:28 +0900 Subject: [PATCH 09/21] refactor: add meaning to display name --- .../test/java/com/techcourse/controller/HomeControllerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/test/java/com/techcourse/controller/HomeControllerTest.java b/app/src/test/java/com/techcourse/controller/HomeControllerTest.java index 80578be469..3e0d7aa4d4 100644 --- a/app/src/test/java/com/techcourse/controller/HomeControllerTest.java +++ b/app/src/test/java/com/techcourse/controller/HomeControllerTest.java @@ -32,7 +32,7 @@ void tearDown() { } @Test - @DisplayName("홈 화면을 요청한다.") + @DisplayName("홈 화면을 요청시 대시보드 페이지를 응답한다.") void getHome() throws IOException, InterruptedException { // given HttpClient client = HttpClient.newHttpClient(); From 52d9e540869c22cea1d361c70f61514aaeaf3c45 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 22:29:07 +0900 Subject: [PATCH 10/21] refactor: combine exception on test --- .../java/com/techcourse/controller/HomeControllerTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/test/java/com/techcourse/controller/HomeControllerTest.java b/app/src/test/java/com/techcourse/controller/HomeControllerTest.java index 3e0d7aa4d4..3b7011b827 100644 --- a/app/src/test/java/com/techcourse/controller/HomeControllerTest.java +++ b/app/src/test/java/com/techcourse/controller/HomeControllerTest.java @@ -3,7 +3,6 @@ import static org.assertj.core.api.Assertions.assertThat; import com.techcourse.TomcatStarter; -import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; @@ -33,7 +32,7 @@ void tearDown() { @Test @DisplayName("홈 화면을 요청시 대시보드 페이지를 응답한다.") - void getHome() throws IOException, InterruptedException { + void getHome() throws Exception { // given HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() From 2ccac395b059f62406150ab97f1e411352cb8295 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 22:29:31 +0900 Subject: [PATCH 11/21] fix: change request method to post --- .../main/java/com/techcourse/controller/LoginController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/techcourse/controller/LoginController.java b/app/src/main/java/com/techcourse/controller/LoginController.java index e490275d47..697002f620 100644 --- a/app/src/main/java/com/techcourse/controller/LoginController.java +++ b/app/src/main/java/com/techcourse/controller/LoginController.java @@ -17,8 +17,8 @@ public class LoginController { private static final Logger log = LoggerFactory.getLogger(LoginController.class); - @RequestMapping(method = RequestMethod.GET) - public ModelAndView getLogin(final HttpServletRequest req) throws Exception { + @RequestMapping(method = RequestMethod.POST) + public ModelAndView postLogin(final HttpServletRequest req) { if (UserSession.isLoggedIn(req.getSession())) { return new ModelAndView(new JspView("redirect:/index.jsp")); } From 9c723b37613575e06d35ff8fea2c67e4c4a14976 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 22:35:05 +0900 Subject: [PATCH 12/21] test: login with post method or invalid request --- .../controller/LoginControllerTest.java | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 app/src/test/java/com/techcourse/controller/LoginControllerTest.java diff --git a/app/src/test/java/com/techcourse/controller/LoginControllerTest.java b/app/src/test/java/com/techcourse/controller/LoginControllerTest.java new file mode 100644 index 0000000000..ec101ff09b --- /dev/null +++ b/app/src/test/java/com/techcourse/controller/LoginControllerTest.java @@ -0,0 +1,104 @@ +package com.techcourse.controller; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import com.techcourse.TomcatStarter; +import jakarta.servlet.http.HttpServletResponse; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class LoginControllerTest { + + private static final String URL = "http://localhost:8080/login"; + private static final String CONTENT_TYPE_URLENCODED = "application/x-www-form-urlencoded"; + private static final String CONTENT_TYPE_NAME = "Content-Type"; + + private TomcatStarter tomcat; + + @BeforeEach + void setUp() { + tomcat = new TomcatStarter("src/main/webapp/", 8080); + tomcat.start(); + } + + @AfterEach + void tearDown() { + tomcat.stop(); + } + + @Test + @DisplayName("올바른 계정 정보로 로그인 요청 시 대시보드 페이지로 리디렉션을 응답한다.") + void postLogin() throws Exception { + // given + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(URL)) + .header(CONTENT_TYPE_NAME, CONTENT_TYPE_URLENCODED) + .POST(BodyPublishers.ofString("account=gugu&password=password")) + .build(); + + // when + HttpResponse response = client.send(request, BodyHandlers.ofString()); + client.close(); + + // then + assertAll( + () -> assertThat(response.headers().firstValue("Location")).hasValue("/index.jsp"), + () -> assertThat(response.statusCode()).isEqualTo(HttpServletResponse.SC_FOUND) + ); + } + + @Test + @DisplayName("존재하지 않는 계정으로 요청 시 401 페이지로 리디렉션을 응답한다.") + void getLoginWithNonAccount() throws Exception { + // given + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(URL)) + .header(CONTENT_TYPE_NAME, CONTENT_TYPE_URLENCODED) + .POST(BodyPublishers.ofString("account=seyang&password=password")) + .build(); + + // when + HttpResponse response = client.send(request, BodyHandlers.ofString()); + client.close(); + + // then + assertAll( + () -> assertThat(response.headers().firstValue("Location")).hasValue("/401.jsp"), + () -> assertThat(response.statusCode()).isEqualTo(HttpServletResponse.SC_FOUND) + ); + } + + @Test + @DisplayName("틀린 비밀번호로 요청 시 401 페이지로 리디렉션을 응답한다.") + void getLoginWithInvalidPassword() throws Exception { + // given + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(URL)) + .header(CONTENT_TYPE_NAME, CONTENT_TYPE_URLENCODED) + .POST(BodyPublishers.ofString("account=gugu&password=pw")) + .build(); + + // when + HttpResponse response = client.send(request, BodyHandlers.ofString()); + response.sslSession(); + client.close(); + + // then + assertAll( + () -> assertThat(response.headers().firstValue("Location")).hasValue("/401.jsp"), + () -> assertThat(response.statusCode()).isEqualTo(HttpServletResponse.SC_FOUND) + ); + } +} From 6ea97f22ef0de28963638f4a59ca1576d59074e0 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 22:36:08 +0900 Subject: [PATCH 13/21] refactor: remove manual handler mapping --- .../DispatcherServletInitializer.java | 1 - .../com/techcourse/ManualHandlerMapping.java | 28 ------------------- 2 files changed, 29 deletions(-) delete mode 100644 app/src/main/java/com/techcourse/ManualHandlerMapping.java diff --git a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java index cee825f502..9bcd65d477 100644 --- a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java +++ b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java @@ -18,7 +18,6 @@ public class DispatcherServletInitializer implements WebApplicationInitializer { @Override public void onStartup(final ServletContext servletContext) { final var dispatcherServlet = new DispatcherServlet(); - dispatcherServlet.addHandlerMapping(new ManualHandlerMapping()); final var registration = servletContext.addServlet(DEFAULT_SERVLET_NAME, dispatcherServlet); if (registration == null) { 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 3b3cf09bdb..0000000000 --- a/app/src/main/java/com/techcourse/ManualHandlerMapping.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.techcourse; - -import com.interface21.webmvc.servlet.mvc.asis.Controller; -import com.interface21.webmvc.servlet.mvc.tobe.HandlerMapping; -import jakarta.servlet.http.HttpServletRequest; -import java.util.HashMap; -import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ManualHandlerMapping implements HandlerMapping { - - private static final Logger log = LoggerFactory.getLogger(ManualHandlerMapping.class); - - private static final Map controllers = new HashMap<>(); - - public void initialize() { - log.info("Initialized ManualHandlerMapping!"); - controllers.forEach((path, controller) -> log.info("Path : {}, Controller : {}", path, controller.getClass())); - } - - @Override - public Object getHandler(HttpServletRequest request) { - String requestURI = request.getRequestURI(); - log.debug("Request Mapping Uri : {}", requestURI); - return controllers.get(requestURI); - } -} From b245f1188a013161d23fd867f73f2c374f18dbd8 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 22:37:43 +0900 Subject: [PATCH 14/21] refactor: remove legacy asis --- .../webmvc/servlet/mvc/asis/Controller.java | 8 ----- .../servlet/mvc/asis/ForwardController.java | 20 ------------ .../mvc/tobe/ControllerHandlerAdapter.java | 22 ------------- .../mvc/tobe/HandlerAdapterRegistry.java | 1 - .../tobe/ControllerHandlerAdapterTest.java | 32 ------------------- 5 files changed, 83 deletions(-) delete mode 100644 mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/Controller.java delete mode 100644 mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ForwardController.java delete mode 100644 mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/ControllerHandlerAdapter.java delete mode 100644 mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/ControllerHandlerAdapterTest.java 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 deleted file mode 100644 index 20e714341a..0000000000 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/Controller.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.interface21.webmvc.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/com/interface21/webmvc/servlet/mvc/asis/ForwardController.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ForwardController.java deleted file mode 100644 index ecceef15af..0000000000 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/asis/ForwardController.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.interface21.webmvc.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/com/interface21/webmvc/servlet/mvc/tobe/ControllerHandlerAdapter.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/ControllerHandlerAdapter.java deleted file mode 100644 index 2b6bee4f50..0000000000 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/ControllerHandlerAdapter.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.interface21.webmvc.servlet.mvc.tobe; - -import com.interface21.webmvc.servlet.ModelAndView; -import com.interface21.webmvc.servlet.mvc.asis.Controller; -import com.interface21.webmvc.servlet.view.JspView; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -public class ControllerHandlerAdapter implements HandlerAdapter { - - @Override - public boolean supports(Object handler) { - return handler instanceof Controller; - } - - @Override - public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) - throws Exception { - String viewName = ((Controller) handler).execute(request, response); - return new ModelAndView(new JspView(viewName)); - } -} diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerAdapterRegistry.java b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerAdapterRegistry.java index 78dd2bab7e..07a41424bf 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerAdapterRegistry.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerAdapterRegistry.java @@ -14,7 +14,6 @@ public HandlerAdapterRegistry() { public void initialize() { addHandlerAdapter(new ExecutionHandlerAdapter()); - addHandlerAdapter(new ControllerHandlerAdapter()); } public void addHandlerAdapter(HandlerAdapter handlerAdapter) { diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/ControllerHandlerAdapterTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/ControllerHandlerAdapterTest.java deleted file mode 100644 index b55cd23885..0000000000 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/ControllerHandlerAdapterTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.interface21.webmvc.servlet.mvc.tobe; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.interface21.webmvc.servlet.ModelAndView; -import com.interface21.webmvc.servlet.mvc.asis.Controller; -import com.interface21.webmvc.servlet.view.JspView; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; - -class ControllerHandlerAdapterTest { - - @Test - @DisplayName("핸들러를 호출해 뷰 이름으로 JspView 만들어 반환한다.") - void handle() throws Exception { - // given - HandlerAdapter handlerAdapter = new ControllerHandlerAdapter(); - Controller loginViewController = (req, res) -> "/login.jsp"; - - // when - ModelAndView modelAndView = handlerAdapter.handle( - new MockHttpServletRequest(), - new MockHttpServletResponse(), - loginViewController); - - // then - assertThat(modelAndView.getModel()).isEmpty(); - assertThat(modelAndView.getView()).isInstanceOf(JspView.class); - } -} From 995c6adbe3266f5a9620e8f9a796dc95174a34cc Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 22:49:21 +0900 Subject: [PATCH 15/21] refactor: prepare to move dispatcher servlet to mvc package --- .../main/java/com/techcourse/DispatcherServlet.java | 12 ++++++------ .../servlet/{mvc/tobe => }/HandlerAdapter.java | 3 +-- .../exception => }/HandlerExceptionResolver.java | 3 +-- .../servlet/{mvc/tobe => }/HandlerMapping.java | 2 +- .../tobe => handler}/AnnotationHandlerMapping.java | 3 ++- .../tobe => handler}/ExecutionHandlerAdapter.java | 3 ++- .../tobe => handler}/HandlerAdapterRegistry.java | 3 ++- .../{mvc/tobe => handler}/HandlerExecution.java | 2 +- .../servlet/{mvc/tobe => handler}/HandlerKey.java | 11 +++++++---- .../tobe => handler}/HandlerMappingRegistry.java | 3 ++- .../ArgumentHandlerExceptionResolver.java | 3 ++- .../AnnotationHandlerMappingTest.java | 2 +- .../{mvc/tobe => handler}/HandlerExecutionTest.java | 2 +- .../{mvc/tobe => handler}/HandlerKeyTest.java | 2 +- .../tobe => handler}/HandlerMappingRegistryTest.java | 2 +- .../{mvc/tobe => handler}/ManualHandlerMapping.java | 3 ++- 16 files changed, 33 insertions(+), 26 deletions(-) rename mvc/src/main/java/com/interface21/webmvc/servlet/{mvc/tobe => }/HandlerAdapter.java (74%) rename mvc/src/main/java/com/interface21/webmvc/servlet/{mvc/tobe/exception => }/HandlerExceptionResolver.java (76%) rename mvc/src/main/java/com/interface21/webmvc/servlet/{mvc/tobe => }/HandlerMapping.java (76%) rename mvc/src/main/java/com/interface21/webmvc/servlet/{mvc/tobe => handler}/AnnotationHandlerMapping.java (97%) rename mvc/src/main/java/com/interface21/webmvc/servlet/{mvc/tobe => handler}/ExecutionHandlerAdapter.java (84%) rename mvc/src/main/java/com/interface21/webmvc/servlet/{mvc/tobe => handler}/HandlerAdapterRegistry.java (87%) rename mvc/src/main/java/com/interface21/webmvc/servlet/{mvc/tobe => handler}/HandlerExecution.java (97%) rename mvc/src/main/java/com/interface21/webmvc/servlet/{mvc/tobe => handler}/HandlerKey.java (81%) rename mvc/src/main/java/com/interface21/webmvc/servlet/{mvc/tobe => handler}/HandlerMappingRegistry.java (90%) rename mvc/src/main/java/com/interface21/webmvc/servlet/{mvc/tobe/exception => resolver}/ArgumentHandlerExceptionResolver.java (91%) rename mvc/src/test/java/com/interface21/webmvc/servlet/{mvc/tobe => handler}/AnnotationHandlerMappingTest.java (99%) rename mvc/src/test/java/com/interface21/webmvc/servlet/{mvc/tobe => handler}/HandlerExecutionTest.java (94%) rename mvc/src/test/java/com/interface21/webmvc/servlet/{mvc/tobe => handler}/HandlerKeyTest.java (91%) rename mvc/src/test/java/com/interface21/webmvc/servlet/{mvc/tobe => handler}/HandlerMappingRegistryTest.java (97%) rename mvc/src/test/java/com/interface21/webmvc/servlet/{mvc/tobe => handler}/ManualHandlerMapping.java (85%) diff --git a/app/src/main/java/com/techcourse/DispatcherServlet.java b/app/src/main/java/com/techcourse/DispatcherServlet.java index d04daff1a9..5efa552250 100644 --- a/app/src/main/java/com/techcourse/DispatcherServlet.java +++ b/app/src/main/java/com/techcourse/DispatcherServlet.java @@ -1,13 +1,13 @@ package com.techcourse; +import com.interface21.webmvc.servlet.HandlerAdapter; +import com.interface21.webmvc.servlet.HandlerExceptionResolver; +import com.interface21.webmvc.servlet.HandlerMapping; import com.interface21.webmvc.servlet.ModelAndView; import com.interface21.webmvc.servlet.View; -import com.interface21.webmvc.servlet.mvc.tobe.HandlerAdapter; -import com.interface21.webmvc.servlet.mvc.tobe.HandlerAdapterRegistry; -import com.interface21.webmvc.servlet.mvc.tobe.HandlerMapping; -import com.interface21.webmvc.servlet.mvc.tobe.HandlerMappingRegistry; -import com.interface21.webmvc.servlet.mvc.tobe.exception.ArgumentHandlerExceptionResolver; -import com.interface21.webmvc.servlet.mvc.tobe.exception.HandlerExceptionResolver; +import com.interface21.webmvc.servlet.handler.HandlerAdapterRegistry; +import com.interface21.webmvc.servlet.handler.HandlerMappingRegistry; +import com.interface21.webmvc.servlet.resolver.ArgumentHandlerExceptionResolver; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerAdapter.java b/mvc/src/main/java/com/interface21/webmvc/servlet/HandlerAdapter.java similarity index 74% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerAdapter.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/HandlerAdapter.java index 6acc610728..215453bc4c 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerAdapter.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/HandlerAdapter.java @@ -1,6 +1,5 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet; -import com.interface21.webmvc.servlet.ModelAndView; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/exception/HandlerExceptionResolver.java b/mvc/src/main/java/com/interface21/webmvc/servlet/HandlerExceptionResolver.java similarity index 76% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/exception/HandlerExceptionResolver.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/HandlerExceptionResolver.java index b57c87da6d..7561cb7aee 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/exception/HandlerExceptionResolver.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/HandlerExceptionResolver.java @@ -1,6 +1,5 @@ -package com.interface21.webmvc.servlet.mvc.tobe.exception; +package com.interface21.webmvc.servlet; -import com.interface21.webmvc.servlet.ModelAndView; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerMapping.java b/mvc/src/main/java/com/interface21/webmvc/servlet/HandlerMapping.java similarity index 76% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerMapping.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/HandlerMapping.java index b7db458b93..82b83b9714 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerMapping.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/HandlerMapping.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +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/handler/AnnotationHandlerMapping.java similarity index 97% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/AnnotationHandlerMapping.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/handler/AnnotationHandlerMapping.java index 85b0a034d7..b87262a578 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/AnnotationHandlerMapping.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/handler/AnnotationHandlerMapping.java @@ -1,8 +1,9 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.handler; 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.HandlerMapping; import jakarta.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.util.HashMap; diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/ExecutionHandlerAdapter.java b/mvc/src/main/java/com/interface21/webmvc/servlet/handler/ExecutionHandlerAdapter.java similarity index 84% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/ExecutionHandlerAdapter.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/handler/ExecutionHandlerAdapter.java index 120a9ba614..bf2f41070b 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/ExecutionHandlerAdapter.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/handler/ExecutionHandlerAdapter.java @@ -1,5 +1,6 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.handler; +import com.interface21.webmvc.servlet.HandlerAdapter; import com.interface21.webmvc.servlet.ModelAndView; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerAdapterRegistry.java b/mvc/src/main/java/com/interface21/webmvc/servlet/handler/HandlerAdapterRegistry.java similarity index 87% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerAdapterRegistry.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/handler/HandlerAdapterRegistry.java index 07a41424bf..9c76664a03 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerAdapterRegistry.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/handler/HandlerAdapterRegistry.java @@ -1,5 +1,6 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.handler; +import com.interface21.webmvc.servlet.HandlerAdapter; import java.util.ArrayList; import java.util.List; import java.util.Optional; diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerExecution.java b/mvc/src/main/java/com/interface21/webmvc/servlet/handler/HandlerExecution.java similarity index 97% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerExecution.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/handler/HandlerExecution.java index 8b81f8dc91..d6017feaa2 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerExecution.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/handler/HandlerExecution.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.handler; import com.interface21.webmvc.servlet.ModelAndView; import jakarta.servlet.http.HttpServletRequest; diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerKey.java b/mvc/src/main/java/com/interface21/webmvc/servlet/handler/HandlerKey.java similarity index 81% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerKey.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/handler/HandlerKey.java index 55f8e593a1..d5007cc0ce 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerKey.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/handler/HandlerKey.java @@ -1,7 +1,6 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.handler; import com.interface21.web.bind.annotation.RequestMethod; - import java.util.Objects; public class HandlerKey { @@ -24,8 +23,12 @@ public String toString() { @Override public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof HandlerKey)) return false; + if (this == o) { + return true; + } + if (!(o instanceof HandlerKey)) { + return false; + } HandlerKey that = (HandlerKey) o; return Objects.equals(url, that.url) && requestMethod == that.requestMethod; } diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerMappingRegistry.java b/mvc/src/main/java/com/interface21/webmvc/servlet/handler/HandlerMappingRegistry.java similarity index 90% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerMappingRegistry.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/handler/HandlerMappingRegistry.java index ae88841320..7c80daef7b 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerMappingRegistry.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/handler/HandlerMappingRegistry.java @@ -1,5 +1,6 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.handler; +import com.interface21.webmvc.servlet.HandlerMapping; import jakarta.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.List; diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/exception/ArgumentHandlerExceptionResolver.java b/mvc/src/main/java/com/interface21/webmvc/servlet/resolver/ArgumentHandlerExceptionResolver.java similarity index 91% rename from mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/exception/ArgumentHandlerExceptionResolver.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/resolver/ArgumentHandlerExceptionResolver.java index 625520d755..eb66e937d6 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/mvc/tobe/exception/ArgumentHandlerExceptionResolver.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/resolver/ArgumentHandlerExceptionResolver.java @@ -1,5 +1,6 @@ -package com.interface21.webmvc.servlet.mvc.tobe.exception; +package com.interface21.webmvc.servlet.resolver; +import com.interface21.webmvc.servlet.HandlerExceptionResolver; import com.interface21.webmvc.servlet.ModelAndView; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/AnnotationHandlerMappingTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/handler/AnnotationHandlerMappingTest.java similarity index 99% rename from mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/AnnotationHandlerMappingTest.java rename to mvc/src/test/java/com/interface21/webmvc/servlet/handler/AnnotationHandlerMappingTest.java index bd48f4d7ac..504eae200c 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/AnnotationHandlerMappingTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/handler/AnnotationHandlerMappingTest.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.handler; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerExecutionTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/handler/HandlerExecutionTest.java similarity index 94% rename from mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerExecutionTest.java rename to mvc/src/test/java/com/interface21/webmvc/servlet/handler/HandlerExecutionTest.java index 190cb5975c..5da313b019 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerExecutionTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/handler/HandlerExecutionTest.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.handler; import static org.assertj.core.api.Assertions.assertThatCode; diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerKeyTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/handler/HandlerKeyTest.java similarity index 91% rename from mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerKeyTest.java rename to mvc/src/test/java/com/interface21/webmvc/servlet/handler/HandlerKeyTest.java index 8f226b747d..2291b1606e 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerKeyTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/handler/HandlerKeyTest.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.handler; import static org.assertj.core.api.Assertions.assertThat; diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerMappingRegistryTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/handler/HandlerMappingRegistryTest.java similarity index 97% rename from mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerMappingRegistryTest.java rename to mvc/src/test/java/com/interface21/webmvc/servlet/handler/HandlerMappingRegistryTest.java index 6068304c08..8dcc2c4b73 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/HandlerMappingRegistryTest.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/handler/HandlerMappingRegistryTest.java @@ -1,4 +1,4 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.handler; 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/tobe/ManualHandlerMapping.java b/mvc/src/test/java/com/interface21/webmvc/servlet/handler/ManualHandlerMapping.java similarity index 85% rename from mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/ManualHandlerMapping.java rename to mvc/src/test/java/com/interface21/webmvc/servlet/handler/ManualHandlerMapping.java index e0ed1752ae..70b8a630e0 100644 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/mvc/tobe/ManualHandlerMapping.java +++ b/mvc/src/test/java/com/interface21/webmvc/servlet/handler/ManualHandlerMapping.java @@ -1,5 +1,6 @@ -package com.interface21.webmvc.servlet.mvc.tobe; +package com.interface21.webmvc.servlet.handler; +import com.interface21.webmvc.servlet.HandlerMapping; import com.interface21.webmvc.servlet.mvc.asis.Controller; import jakarta.servlet.http.HttpServletRequest; import java.util.HashMap; From 4b37adcf165117e4d4c358556591fec0831f2726 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 22:50:16 +0900 Subject: [PATCH 16/21] refactor: remove test of manual handlers --- .../handler/HandlerMappingRegistryTest.java | 54 ------------------- .../servlet/handler/ManualHandlerMapping.java | 23 -------- 2 files changed, 77 deletions(-) delete mode 100644 mvc/src/test/java/com/interface21/webmvc/servlet/handler/HandlerMappingRegistryTest.java delete mode 100644 mvc/src/test/java/com/interface21/webmvc/servlet/handler/ManualHandlerMapping.java diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/handler/HandlerMappingRegistryTest.java b/mvc/src/test/java/com/interface21/webmvc/servlet/handler/HandlerMappingRegistryTest.java deleted file mode 100644 index 8dcc2c4b73..0000000000 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/handler/HandlerMappingRegistryTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.interface21.webmvc.servlet.handler; - -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 java.util.Optional; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import samples.ManualController; - -class HandlerMappingRegistryTest { - - private static final String BASE_PACKAGE = "samples"; - - @Test - @DisplayName("서로 다른 핸들러 매핑이 존재해도 메뉴얼 핸들러를 찾을 수 있다.") - void getManualHandler() { - // given - HttpServletRequest request = mock(HttpServletRequest.class); - HandlerMappingRegistry registry = new HandlerMappingRegistry(BASE_PACKAGE); - registry.addHandlerMapping(new ManualHandlerMapping()); - registry.initialize(); - - // when - when(request.getRequestURI()).thenReturn("/manual"); - when(request.getMethod()).thenReturn("GET"); - Optional handler = registry.getHandler(request); - - // then - assertThat(handler).isPresent(); - assertThat(handler.get()).isInstanceOf(ManualController.class); - } - - @Test - @DisplayName("서로 다른 핸들러 매핑이 존재해도 어노테이션 핸들러를 찾을 수 있다.") - void getAnnotationHandler() { - // given - HttpServletRequest request = mock(HttpServletRequest.class); - HandlerMappingRegistry registry = new HandlerMappingRegistry(BASE_PACKAGE); - registry.addHandlerMapping(new ManualHandlerMapping()); - registry.initialize(); - - // when - when(request.getRequestURI()).thenReturn("/post-test"); - when(request.getMethod()).thenReturn("POST"); - Optional handler = registry.getHandler(request); - - // then - assertThat(handler).isPresent(); - assertThat(handler.get()).isInstanceOf(HandlerExecution.class); - } -} \ No newline at end of file diff --git a/mvc/src/test/java/com/interface21/webmvc/servlet/handler/ManualHandlerMapping.java b/mvc/src/test/java/com/interface21/webmvc/servlet/handler/ManualHandlerMapping.java deleted file mode 100644 index 70b8a630e0..0000000000 --- a/mvc/src/test/java/com/interface21/webmvc/servlet/handler/ManualHandlerMapping.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.interface21.webmvc.servlet.handler; - -import com.interface21.webmvc.servlet.HandlerMapping; -import com.interface21.webmvc.servlet.mvc.asis.Controller; -import jakarta.servlet.http.HttpServletRequest; -import java.util.HashMap; -import java.util.Map; -import samples.ManualController; - -public class ManualHandlerMapping implements HandlerMapping { - - private static final Map controllers = new HashMap<>(); - - public void initialize() { - controllers.put("/manual", new ManualController()); - } - - @Override - public Object getHandler(HttpServletRequest request) { - String requestURI = request.getRequestURI(); - return controllers.get(requestURI); - } -} From d1ca1562790418cd3b4798d56f2aead96dd911bf Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 22:50:40 +0900 Subject: [PATCH 17/21] refactor: remove manual controller on test --- mvc/src/test/java/samples/ManualController.java | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 mvc/src/test/java/samples/ManualController.java diff --git a/mvc/src/test/java/samples/ManualController.java b/mvc/src/test/java/samples/ManualController.java deleted file mode 100644 index 3990dd564c..0000000000 --- a/mvc/src/test/java/samples/ManualController.java +++ /dev/null @@ -1,14 +0,0 @@ -package samples; - - -import com.interface21.webmvc.servlet.mvc.asis.Controller; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -public class ManualController implements Controller { - - @Override - public String execute(HttpServletRequest req, HttpServletResponse res) { - return "/manual.jsp"; - } -} From 27e63bebb8f5a29c6b778fca799da9c3e8c28521 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Sun, 29 Sep 2024 23:04:03 +0900 Subject: [PATCH 18/21] refactor: move dispatcher servlet to mvc --- .../com/techcourse/DispatcherServletInitializer.java | 4 +++- .../webmvc/servlet}/DispatcherServlet.java | 12 +++--------- 2 files changed, 6 insertions(+), 10 deletions(-) rename {app/src/main/java/com/techcourse => mvc/src/main/java/com/interface21/webmvc/servlet}/DispatcherServlet.java (86%) diff --git a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java index 9bcd65d477..fde4af32d1 100644 --- a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java +++ b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java @@ -1,6 +1,7 @@ package com.techcourse; import com.interface21.web.WebApplicationInitializer; +import com.interface21.webmvc.servlet.DispatcherServlet; import jakarta.servlet.ServletContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,11 +14,12 @@ public class DispatcherServletInitializer implements WebApplicationInitializer { private static final Logger log = LoggerFactory.getLogger(DispatcherServletInitializer.class); + private static final String SCANNING_CONTROLLER_PACKAGE = "com.techcourse.controller"; private static final String DEFAULT_SERVLET_NAME = "dispatcher"; @Override public void onStartup(final ServletContext servletContext) { - final var dispatcherServlet = new DispatcherServlet(); + final var dispatcherServlet = new DispatcherServlet(SCANNING_CONTROLLER_PACKAGE); final var registration = servletContext.addServlet(DEFAULT_SERVLET_NAME, dispatcherServlet); if (registration == null) { diff --git a/app/src/main/java/com/techcourse/DispatcherServlet.java b/mvc/src/main/java/com/interface21/webmvc/servlet/DispatcherServlet.java similarity index 86% rename from app/src/main/java/com/techcourse/DispatcherServlet.java rename to mvc/src/main/java/com/interface21/webmvc/servlet/DispatcherServlet.java index 5efa552250..66656342a2 100644 --- a/app/src/main/java/com/techcourse/DispatcherServlet.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/DispatcherServlet.java @@ -1,10 +1,5 @@ -package com.techcourse; +package com.interface21.webmvc.servlet; -import com.interface21.webmvc.servlet.HandlerAdapter; -import com.interface21.webmvc.servlet.HandlerExceptionResolver; -import com.interface21.webmvc.servlet.HandlerMapping; -import com.interface21.webmvc.servlet.ModelAndView; -import com.interface21.webmvc.servlet.View; import com.interface21.webmvc.servlet.handler.HandlerAdapterRegistry; import com.interface21.webmvc.servlet.handler.HandlerMappingRegistry; import com.interface21.webmvc.servlet.resolver.ArgumentHandlerExceptionResolver; @@ -18,7 +13,6 @@ public class DispatcherServlet extends HttpServlet { - private static final String BASE_PACKAGE = "com.techcourse.controller"; private static final long serialVersionUID = 1L; private static final Logger log = LoggerFactory.getLogger(DispatcherServlet.class); @@ -26,9 +20,9 @@ public class DispatcherServlet extends HttpServlet { private final HandlerMappingRegistry handlerMappingRegistry; private final HandlerExceptionResolver handlerExceptionResolver; - public DispatcherServlet() { + public DispatcherServlet(String basePackage) { handlerAdapterRegistry = new HandlerAdapterRegistry(); - handlerMappingRegistry = new HandlerMappingRegistry(BASE_PACKAGE); + handlerMappingRegistry = new HandlerMappingRegistry(basePackage); handlerExceptionResolver = new ArgumentHandlerExceptionResolver(); } From 9f30cff78b4fc7e4f0290d3c09ce6f593b9c28e2 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Mon, 30 Sep 2024 11:00:36 +0900 Subject: [PATCH 19/21] refactor: remove unused method on dispatcher servlet --- .../com/interface21/webmvc/servlet/DispatcherServlet.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mvc/src/main/java/com/interface21/webmvc/servlet/DispatcherServlet.java b/mvc/src/main/java/com/interface21/webmvc/servlet/DispatcherServlet.java index 66656342a2..001c5f197a 100644 --- a/mvc/src/main/java/com/interface21/webmvc/servlet/DispatcherServlet.java +++ b/mvc/src/main/java/com/interface21/webmvc/servlet/DispatcherServlet.java @@ -68,8 +68,4 @@ private void renderViewWithModel(HttpServletRequest request, HttpServletResponse View view = modelAndView.getView(); view.render(model, request, response); } - - public void addHandlerMapping(HandlerMapping handlerMapping) { - handlerMappingRegistry.addHandlerMapping(handlerMapping); - } } From 9c7fe1903af4f50b77afb33f9ac6c0f239655006 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Mon, 30 Sep 2024 11:03:21 +0900 Subject: [PATCH 20/21] style: add eof for viewing good on github --- .../test/java/com/techcourse/controller/HomeControllerTest.java | 2 +- .../test/java/com/techcourse/controller/UserControllerTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/test/java/com/techcourse/controller/HomeControllerTest.java b/app/src/test/java/com/techcourse/controller/HomeControllerTest.java index 3b7011b827..a8d9925815 100644 --- a/app/src/test/java/com/techcourse/controller/HomeControllerTest.java +++ b/app/src/test/java/com/techcourse/controller/HomeControllerTest.java @@ -46,4 +46,4 @@ void getHome() throws Exception { // then assertThat(response.body()).contains("대시보드"); } -} \ No newline at end of file +} diff --git a/app/src/test/java/com/techcourse/controller/UserControllerTest.java b/app/src/test/java/com/techcourse/controller/UserControllerTest.java index 4439b3ad64..98224e898f 100644 --- a/app/src/test/java/com/techcourse/controller/UserControllerTest.java +++ b/app/src/test/java/com/techcourse/controller/UserControllerTest.java @@ -88,4 +88,4 @@ void getUserWithEmptyReturnBadRequest() throws Exception { () -> assertThat(response.body()).isEqualTo("Please input account as parameter") ); } -} \ No newline at end of file +} From ac51700275b657d1ed20be82f99a1eb145e6242b Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Wed, 2 Oct 2024 16:16:34 +0900 Subject: [PATCH 21/21] feat: write only value if having single entry --- .../com/interface21/webmvc/servlet/view/JsonView.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 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 8d29230dc2..8bef4005cb 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 @@ -19,9 +19,15 @@ public JsonView() { @Override public void render(final Map model, final HttpServletRequest request, HttpServletResponse response) throws IOException { - String json = jsonMapper.writeValueAsString(model); - response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); + + if (model.size() == 1) { + String singleValue = model.values().iterator().next().toString(); + response.getWriter().write(singleValue); + return; + } + + String json = jsonMapper.writeValueAsString(model); response.getWriter().write(json); } }