From b59d375f086185fd435acd29cfcd68a1b030487f Mon Sep 17 00:00:00 2001 From: JunH Date: Mon, 25 Sep 2023 01:53:43 +0900 Subject: [PATCH 1/9] =?UTF-8?q?:sparkles:=20feat=20:=20JspView=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 --- .../org/springframework/web/servlet/view/JspView.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JspView.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JspView.java index a86514497b..82e3d3dea6 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JspView.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JspView.java @@ -1,5 +1,6 @@ package webmvc.org.springframework.web.servlet.view; +import jakarta.servlet.RequestDispatcher; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; @@ -22,14 +23,18 @@ public JspView(final String viewName) { @Override public void render(final Map model, final HttpServletRequest request, final HttpServletResponse response) throws Exception { - // todo - model.keySet().forEach(key -> { log.debug("attribute name : {}, value : {}", key, model.get(key)); request.setAttribute(key, model.get(key)); }); - // todo + if (viewName.startsWith(REDIRECT_PREFIX)) { + response.sendRedirect(viewName.substring(REDIRECT_PREFIX.length())); + return; + } + + final RequestDispatcher requestDispatcher = request.getRequestDispatcher(viewName); + requestDispatcher.forward(request, response); } public String getViewName() { From fad3786fa79e94bd93094deeda23bda1e6619aee Mon Sep 17 00:00:00 2001 From: JunH Date: Mon, 25 Sep 2023 01:55:15 +0900 Subject: [PATCH 2/9] =?UTF-8?q?:sparkles:=20feat=20:=20JsonView=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 --- .../springframework/web/servlet/view/JsonView.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java index f763743304..c9fd45c3ea 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java @@ -1,5 +1,9 @@ package webmvc.org.springframework.web.servlet.view; +import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND; +import static web.org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE; + +import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import webmvc.org.springframework.web.servlet.View; @@ -10,6 +14,13 @@ public class JsonView implements View { @Override public void render(final Map model, final HttpServletRequest request, HttpServletResponse response) throws Exception { + if (model == null || model.isEmpty()) { + response.setStatus(SC_NOT_FOUND); + return; + } + response.setContentType(APPLICATION_JSON_UTF8_VALUE); + final String body = new ObjectMapper().writeValueAsString(model); + response.getWriter().write(body); } @Override From 7b16e9bf13beafe56943ad27bc73403a3617741e Mon Sep 17 00:00:00 2001 From: JunH Date: Mon, 25 Sep 2023 02:03:54 +0900 Subject: [PATCH 3/9] =?UTF-8?q?:sparkles:=20feat=20:=20JsonView=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 --- .../springframework/web/servlet/view/JsonView.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java index c9fd45c3ea..e0268ddb95 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java @@ -1,26 +1,28 @@ package webmvc.org.springframework.web.servlet.view; import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND; -import static web.org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.View; - +import java.io.PrintWriter; import java.util.Map; +import web.org.springframework.http.MediaType; +import webmvc.org.springframework.web.servlet.View; public class JsonView implements View { @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 { if (model == null || model.isEmpty()) { response.setStatus(SC_NOT_FOUND); return; } - response.setContentType(APPLICATION_JSON_UTF8_VALUE); + response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); final String body = new ObjectMapper().writeValueAsString(model); - response.getWriter().write(body); + final PrintWriter writer = response.getWriter(); + writer.write(body); } @Override From a74c45cf733a568416035d1284bc810e25773c70 Mon Sep 17 00:00:00 2001 From: JunH Date: Mon, 25 Sep 2023 14:36:10 +0900 Subject: [PATCH 4/9] =?UTF-8?q?:sparkles:=20feat=20:=20=EC=96=B4=EB=85=B8?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EC=85=98=20Controller=EB=A1=9C=20=EC=A0=84?= =?UTF-8?q?=EB=B6=80=20=EA=B0=9C=EC=84=A0=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DispatcherServletInitializer.java | 1 + .../com/techcourse/ManualHandlerAdapter.java | 42 ------------ .../com/techcourse/ManualHandlerMapping.java | 66 ------------------- .../controller/ForwardController.java | 16 +++++ .../controller/LoginController.java | 21 +++--- .../controller/LoginViewController.java | 15 +++-- .../controller/LogoutController.java | 14 ++-- .../controller/RegisterController.java | 2 +- .../controller/RegisterViewController.java | 13 ++-- .../techcourse/controller/UserController.java | 31 +++++++++ .../techcourse/ManualHandlerMappingTest.java | 50 -------------- .../controller/UserControllerTest.java | 49 ++++++++++++++ .../web/servlet}/DispatcherServlet.java | 4 +- .../web/servlet}/HandlerAdapters.java | 2 +- .../web/servlet}/HandlerAdaptersFactory.java | 4 +- .../web/servlet}/HandlerMappings.java | 2 +- .../web/servlet}/HandlerMappingsFactory.java | 4 +- .../web/servlet/mvc/asis/Controller.java | 8 --- .../servlet/mvc/asis/ForwardController.java | 20 ------ .../mvc/tobe/AnnotationHandlerMapping.java | 1 + 20 files changed, 144 insertions(+), 221 deletions(-) delete mode 100644 app/src/main/java/com/techcourse/ManualHandlerAdapter.java delete mode 100644 app/src/main/java/com/techcourse/ManualHandlerMapping.java create mode 100644 app/src/main/java/com/techcourse/controller/ForwardController.java create mode 100644 app/src/main/java/com/techcourse/controller/UserController.java delete mode 100644 app/src/test/java/com/techcourse/ManualHandlerMappingTest.java create mode 100644 app/src/test/java/com/techcourse/controller/UserControllerTest.java rename {app/src/main/java/com/techcourse => mvc/src/main/java/webmvc/org/springframework/web/servlet}/DispatcherServlet.java (94%) rename {app/src/main/java/com/techcourse => mvc/src/main/java/webmvc/org/springframework/web/servlet}/HandlerAdapters.java (95%) rename {app/src/main/java/com/techcourse => mvc/src/main/java/webmvc/org/springframework/web/servlet}/HandlerAdaptersFactory.java (75%) rename {app/src/main/java/com/techcourse => mvc/src/main/java/webmvc/org/springframework/web/servlet}/HandlerMappings.java (96%) rename {app/src/main/java/com/techcourse => mvc/src/main/java/webmvc/org/springframework/web/servlet}/HandlerMappingsFactory.java (87%) delete mode 100644 mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/Controller.java delete mode 100644 mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/ForwardController.java diff --git a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java index 6e814cdd25..0c4515d689 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 web.org.springframework.web.WebApplicationInitializer; +import webmvc.org.springframework.web.servlet.DispatcherServlet; /** * Base class for {@link WebApplicationInitializer} diff --git a/app/src/main/java/com/techcourse/ManualHandlerAdapter.java b/app/src/main/java/com/techcourse/ManualHandlerAdapter.java deleted file mode 100644 index 3d1afe2b2a..0000000000 --- a/app/src/main/java/com/techcourse/ManualHandlerAdapter.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.techcourse; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import webmvc.org.springframework.web.servlet.ModelAndView; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerAdaptor; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecution; -import webmvc.org.springframework.web.servlet.view.JspView; - -public class ManualHandlerAdapter implements HandlerAdaptor { - @Override - public boolean supports(final Object handler) { - final Method method = (Method) handler; - return Controller.class.isAssignableFrom(method.getDeclaringClass()); - } - - @Override - public ModelAndView handle( - final HandlerExecution handler, - final HttpServletRequest request, - final HttpServletResponse response - ) { - final String viewName = invokeHandler(handler, request, response); - final JspView jspView = new JspView(viewName); - return new ModelAndView(jspView); - } - - private String invokeHandler( - final HandlerExecution handler, - final HttpServletRequest request, - final HttpServletResponse response - ) { - try { - return (String) handler.handle(request, response); - } catch (InvocationTargetException | IllegalAccessException e) { - throw new CommonMethodInvokeException("메서드 실행 도중 예외가 발생했습니다.", e); - } - } -} 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 f7235a049b..0000000000 --- a/app/src/main/java/com/techcourse/ManualHandlerMapping.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.techcourse; - -import com.techcourse.controller.LoginController; -import com.techcourse.controller.LoginViewController; -import com.techcourse.controller.LogoutController; -import com.techcourse.controller.RegisterViewController; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; -import webmvc.org.springframework.web.servlet.mvc.asis.ForwardController; -import webmvc.org.springframework.web.servlet.mvc.exception.HandlerNotFoundException; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecution; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerMapping; - -public class ManualHandlerMapping implements HandlerMapping { - private static final Logger log = LoggerFactory.getLogger(ManualHandlerMapping.class); - - private static final Map controllers = new HashMap<>(); - - @Override - public void initialize() { - controllers.put("/", new ForwardController("/index.jsp")); - controllers.put("/login", new LoginController()); - controllers.put("/login/view", new LoginViewController()); - controllers.put("/logout", new LogoutController()); - controllers.put("/register/view", new RegisterViewController()); - - log.info("Initialized Handler Mapping!"); - controllers.keySet() - .forEach(path -> log.info("Path : {}, Controller : {}", path, controllers.get(path).getClass())); - } - - @Override - public boolean isMatch(final HttpServletRequest request) { - return controllers.containsKey(request.getRequestURI()); - } - - @Override - public HandlerExecution getHandler(final HttpServletRequest request) { - final String requestURI = request.getRequestURI(); - log.debug("Request Mapping Uri : {}", requestURI); - - final Controller controller = controllers.get(requestURI); - final Method handlerMethod = getExecuteMethod(controller); - - return new HandlerExecution(handlerMethod, controller); - } - - private Method getExecuteMethod(Controller controller) { - final String methodName = "execute"; - final Class[] paramTypes = {HttpServletRequest.class, HttpServletResponse.class}; - - try { - return controller.getClass().getMethod(methodName, paramTypes); - } catch (NoSuchMethodException e) { - throw new HandlerNotFoundException( - "execute handler method를 찾을 수 없습니다. controller name: " + controller.getClass().getSimpleName() - ); - } - } -} diff --git a/app/src/main/java/com/techcourse/controller/ForwardController.java b/app/src/main/java/com/techcourse/controller/ForwardController.java new file mode 100644 index 0000000000..f0b7916d8c --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/ForwardController.java @@ -0,0 +1,16 @@ +package com.techcourse.controller; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import web.org.springframework.web.bind.annotation.GetMapping; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.view.JspView; + +@context.org.springframework.stereotype.Controller +public class ForwardController { + + @GetMapping("/") + public ModelAndView execute(final HttpServletRequest request, final HttpServletResponse response) { + 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 0428fe109e..8f71f4b395 100644 --- a/app/src/main/java/com/techcourse/controller/LoginController.java +++ b/app/src/main/java/com/techcourse/controller/LoginController.java @@ -4,18 +4,21 @@ import com.techcourse.repository.InMemoryUserRepository; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import web.org.springframework.web.bind.annotation.PostMapping; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.view.JspView; -public class LoginController implements Controller { +@context.org.springframework.stereotype.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 { + @PostMapping("/login") + public ModelAndView execute(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 +26,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 index 86ec26cdce..4704096067 100644 --- a/app/src/main/java/com/techcourse/controller/LoginViewController.java +++ b/app/src/main/java/com/techcourse/controller/LoginViewController.java @@ -4,19 +4,22 @@ import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import web.org.springframework.web.bind.annotation.GetMapping; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.view.JspView; -public class LoginViewController implements Controller { +@context.org.springframework.stereotype.Controller +public class LoginViewController { private static final Logger log = LoggerFactory.getLogger(LoginViewController.class); - @Override - public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { + @GetMapping("/login/view") + public ModelAndView execute(final HttpServletRequest req, final HttpServletResponse res) { return UserSession.getUserFrom(req.getSession()) .map(user -> { log.info("logged in {}", user.getAccount()); - return "redirect:/index.jsp"; + return new ModelAndView(new JspView("redirect:/index.jsp")); }) - .orElse("/login.jsp"); + .orElse(new ModelAndView(new JspView("/login.jsp"))); } } diff --git a/app/src/main/java/com/techcourse/controller/LogoutController.java b/app/src/main/java/com/techcourse/controller/LogoutController.java index 4642fd9450..daf7150d99 100644 --- a/app/src/main/java/com/techcourse/controller/LogoutController.java +++ b/app/src/main/java/com/techcourse/controller/LogoutController.java @@ -2,14 +2,18 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import web.org.springframework.web.bind.annotation.GetMapping; +import web.org.springframework.web.bind.annotation.PostMapping; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.view.JspView; -public class LogoutController implements Controller { +@context.org.springframework.stereotype.Controller +public class LogoutController { - @Override - public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { + @GetMapping("/logout") + public ModelAndView execute(final HttpServletRequest req, final HttpServletResponse res) { final var session = req.getSession(); session.removeAttribute(UserSession.SESSION_KEY); - return "redirect:/"; + return new ModelAndView(new JspView("redirect:/")); } } diff --git a/app/src/main/java/com/techcourse/controller/RegisterController.java b/app/src/main/java/com/techcourse/controller/RegisterController.java index c30e40fb11..ebce0a110d 100644 --- a/app/src/main/java/com/techcourse/controller/RegisterController.java +++ b/app/src/main/java/com/techcourse/controller/RegisterController.java @@ -12,7 +12,7 @@ public class RegisterController { @PostMapping("/register") - public ModelAndView save(final HttpServletRequest req, final HttpServletResponse res) throws Exception { + public ModelAndView save(final HttpServletRequest req, final HttpServletResponse res) { final var user = new User(2, req.getParameter("account"), req.getParameter("password"), diff --git a/app/src/main/java/com/techcourse/controller/RegisterViewController.java b/app/src/main/java/com/techcourse/controller/RegisterViewController.java index 136962136d..e0feb9ee03 100644 --- a/app/src/main/java/com/techcourse/controller/RegisterViewController.java +++ b/app/src/main/java/com/techcourse/controller/RegisterViewController.java @@ -2,12 +2,15 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import web.org.springframework.web.bind.annotation.GetMapping; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.view.JspView; -public class RegisterViewController implements Controller { +@context.org.springframework.stereotype.Controller +public class RegisterViewController { - @Override - public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { - return "/register.jsp"; + @GetMapping("/register/view") + public ModelAndView execute(final HttpServletRequest req, final HttpServletResponse res) { + return new ModelAndView(new JspView("/register.jsp")); } } 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..a695f618b0 --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/UserController.java @@ -0,0 +1,31 @@ +package com.techcourse.controller; + +import com.techcourse.domain.User; +import com.techcourse.repository.InMemoryUserRepository; +import context.org.springframework.stereotype.Controller; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import web.org.springframework.web.bind.annotation.GetMapping; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.view.JsonView; + +@Controller +public class UserController { + + private static final Logger log = LoggerFactory.getLogger(UserController.class); + + @GetMapping(value = "/api/user") + public ModelAndView show(HttpServletRequest request, HttpServletResponse response) { + final String account = request.getParameter("account"); + log.debug("user id : {}", account); + + final ModelAndView modelAndView = new ModelAndView(new JsonView()); + final User user = InMemoryUserRepository.findByAccount(account) + .orElseThrow(); + + modelAndView.addObject("user", user); + return modelAndView; + } +} diff --git a/app/src/test/java/com/techcourse/ManualHandlerMappingTest.java b/app/src/test/java/com/techcourse/ManualHandlerMappingTest.java deleted file mode 100644 index 0d1db6f1a4..0000000000 --- a/app/src/test/java/com/techcourse/ManualHandlerMappingTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.techcourse; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.techcourse.controller.UserSession; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import webmvc.org.springframework.web.servlet.ModelAndView; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecution; - -class ManualHandlerMappingTest { - private ManualHandlerMapping handlerMapping; - - @BeforeEach - void setUp() { - handlerMapping = new ManualHandlerMapping(); - handlerMapping.initialize(); - } - - @Test - void root() throws Exception { - final var request = mock(HttpServletRequest.class); - final var response = mock(HttpServletResponse.class); - - when(request.getRequestURI()).thenReturn("/"); - - final var handlerExecution = (HandlerExecution) handlerMapping.getHandler(request); - final var view = (String) handlerExecution.handle(request, response); - - assertThat(view).isEqualTo("/index.jsp"); - } - - @Test - void register_view() throws Exception { - final var request = mock(HttpServletRequest.class); - final var response = mock(HttpServletResponse.class); - - when(request.getRequestURI()).thenReturn("/register/view"); - - final var handlerExecution = (HandlerExecution) handlerMapping.getHandler(request); - final var view = (String) handlerExecution.handle(request, response); - - assertThat(view).isEqualTo("/register.jsp"); - } -} 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..574730c808 --- /dev/null +++ b/app/src/test/java/com/techcourse/controller/UserControllerTest.java @@ -0,0 +1,49 @@ +package com.techcourse.controller; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.techcourse.domain.User; +import com.techcourse.repository.InMemoryUserRepository; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationHandlerMapping; +import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecution; + +class UserControllerTest { + private AnnotationHandlerMapping handlerMapping; + + @BeforeEach + void setUp() { + handlerMapping = new AnnotationHandlerMapping("com.techcourse", "samples"); + handlerMapping.initialize(); + } + + @Test + void show() throws Exception { + final var request = mock(HttpServletRequest.class); + final var response = mock(HttpServletResponse.class); + + final String account = "gugu"; + final String password = "password"; + + when(request.getParameter("account")).thenReturn(account); + when(request.getRequestURI()).thenReturn("/api/user"); + when(request.getMethod()).thenReturn("GET"); + + final var handlerExecution = (HandlerExecution) handlerMapping.getHandler(request); + final var modelAndView = (ModelAndView) handlerExecution.handle(request, response); + final User user = (User) modelAndView.getObject("user"); + + assertAll( + () -> assertThat(user.getAccount()).isEqualTo(account), + () -> assertThat(user.checkPassword(password)).isTrue() + ); + } +} diff --git a/app/src/main/java/com/techcourse/DispatcherServlet.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/DispatcherServlet.java similarity index 94% rename from app/src/main/java/com/techcourse/DispatcherServlet.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/DispatcherServlet.java index cbb82b9fe4..a4a18bc605 100644 --- a/app/src/main/java/com/techcourse/DispatcherServlet.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/DispatcherServlet.java @@ -1,4 +1,4 @@ -package com.techcourse; +package webmvc.org.springframework.web.servlet; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; @@ -6,8 +6,6 @@ import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import webmvc.org.springframework.web.servlet.ModelAndView; -import webmvc.org.springframework.web.servlet.View; import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerAdaptor; import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecution; import webmvc.org.springframework.web.servlet.view.JspView; diff --git a/app/src/main/java/com/techcourse/HandlerAdapters.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerAdapters.java similarity index 95% rename from app/src/main/java/com/techcourse/HandlerAdapters.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerAdapters.java index 8ac97b5810..4a2ee8aaaa 100644 --- a/app/src/main/java/com/techcourse/HandlerAdapters.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerAdapters.java @@ -1,4 +1,4 @@ -package com.techcourse; +package webmvc.org.springframework.web.servlet; import java.util.List; import java.util.NoSuchElementException; diff --git a/app/src/main/java/com/techcourse/HandlerAdaptersFactory.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerAdaptersFactory.java similarity index 75% rename from app/src/main/java/com/techcourse/HandlerAdaptersFactory.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerAdaptersFactory.java index 6f0bd12a43..9eb44f6abd 100644 --- a/app/src/main/java/com/techcourse/HandlerAdaptersFactory.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerAdaptersFactory.java @@ -1,4 +1,4 @@ -package com.techcourse; +package webmvc.org.springframework.web.servlet; import java.util.List; import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationHandlerAdapter; @@ -9,6 +9,6 @@ private HandlerAdaptersFactory() { } public static List createHandlerAdaptors() { - return List.of(new AnnotationHandlerAdapter(), new ManualHandlerAdapter()); + return List.of(new AnnotationHandlerAdapter()); } } diff --git a/app/src/main/java/com/techcourse/HandlerMappings.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerMappings.java similarity index 96% rename from app/src/main/java/com/techcourse/HandlerMappings.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerMappings.java index 1465e1503f..596346e176 100644 --- a/app/src/main/java/com/techcourse/HandlerMappings.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerMappings.java @@ -1,4 +1,4 @@ -package com.techcourse; +package webmvc.org.springframework.web.servlet; import jakarta.servlet.http.HttpServletRequest; import java.util.List; diff --git a/app/src/main/java/com/techcourse/HandlerMappingsFactory.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerMappingsFactory.java similarity index 87% rename from app/src/main/java/com/techcourse/HandlerMappingsFactory.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerMappingsFactory.java index bf8de27c7f..82b5aeb304 100644 --- a/app/src/main/java/com/techcourse/HandlerMappingsFactory.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerMappingsFactory.java @@ -1,4 +1,4 @@ -package com.techcourse; +package webmvc.org.springframework.web.servlet; import java.util.List; import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationHandlerMapping; @@ -9,6 +9,6 @@ private HandlerMappingsFactory() { } public static List createHandlerMappings(final Object... basePackagePath) { - return List.of(new AnnotationHandlerMapping(basePackagePath), new ManualHandlerMapping()); + return List.of(new AnnotationHandlerMapping(basePackagePath)); } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/Controller.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/Controller.java deleted file mode 100644 index bdd1fde780..0000000000 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/Controller.java +++ /dev/null @@ -1,8 +0,0 @@ -package webmvc.org.springframework.web.servlet.mvc.asis; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -public interface Controller { - String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception; -} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/ForwardController.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/ForwardController.java deleted file mode 100644 index cd8f1ef371..0000000000 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/asis/ForwardController.java +++ /dev/null @@ -1,20 +0,0 @@ -package webmvc.org.springframework.web.servlet.mvc.asis; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import java.util.Objects; - -public class ForwardController implements Controller { - - private final String path; - - public ForwardController(final String path) { - this.path = Objects.requireNonNull(path); - } - - @Override - public String execute(final HttpServletRequest request, final HttpServletResponse response) { - return path; - } -} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java index 23e07ffe0f..4de4beda6c 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java @@ -36,6 +36,7 @@ public AnnotationHandlerMapping(final Object... basePackage) { public void initialize() { log.info("Initialized AnnotationHandlerMapping!"); initHandlerExecutions(); + System.out.println(handlerExecutions); log.info("Initialized AnnotationHandlerMapping successfully!"); } From 2c17a09e2fda892b1bb05dde461a2dbcd1a88e62 Mon Sep 17 00:00:00 2001 From: JunH Date: Mon, 25 Sep 2023 15:22:01 +0900 Subject: [PATCH 5/9] =?UTF-8?q?:art:=20refactor=20:=20LoginController=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EA=B0=80=EB=8F=85=EC=84=B1=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/techcourse/controller/LoginController.java | 12 +++++++----- .../servlet/mvc/tobe/AnnotationHandlerMapping.java | 1 - 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/techcourse/controller/LoginController.java b/app/src/main/java/com/techcourse/controller/LoginController.java index 8f71f4b395..369786b47b 100644 --- a/app/src/main/java/com/techcourse/controller/LoginController.java +++ b/app/src/main/java/com/techcourse/controller/LoginController.java @@ -21,20 +21,22 @@ public ModelAndView execute(final HttpServletRequest req, final HttpServletRespo return new ModelAndView(new JspView("redirect:/index.jsp")); } - return InMemoryUserRepository.findByAccount(req.getParameter("account")) + final String viewName = InMemoryUserRepository.findByAccount(req.getParameter("account")) .map(user -> { log.info("User : {}", user); return login(req, user); }) - .orElse(new ModelAndView(new JspView("redirect:/401.jsp"))); + .orElse("redirect:/401.jsp"); + + return new ModelAndView(new JspView(viewName)); } - private ModelAndView login(final HttpServletRequest request, final User user) { + private String 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 new ModelAndView(new JspView("redirect:/index.jsp")); + return "redirect:/index.jsp"; } - return new ModelAndView(new JspView("redirect:/401.jsp")); + return "redirect:/401.jsp"; } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java index 4de4beda6c..23e07ffe0f 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java @@ -36,7 +36,6 @@ public AnnotationHandlerMapping(final Object... basePackage) { public void initialize() { log.info("Initialized AnnotationHandlerMapping!"); initHandlerExecutions(); - System.out.println(handlerExecutions); log.info("Initialized AnnotationHandlerMapping successfully!"); } From bbba1839dce0e4882c6646421201d02dc05ade7d Mon Sep 17 00:00:00 2001 From: JunH Date: Mon, 25 Sep 2023 15:27:32 +0900 Subject: [PATCH 6/9] =?UTF-8?q?:art:=20refactor=20:=20LoginViewController?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20=EA=B0=80=EB=8F=85=EC=84=B1=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/techcourse/controller/LoginViewController.java | 8 +++++--- .../java/com/techcourse/controller/LogoutController.java | 1 - 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/techcourse/controller/LoginViewController.java b/app/src/main/java/com/techcourse/controller/LoginViewController.java index 4704096067..a5f60ab600 100644 --- a/app/src/main/java/com/techcourse/controller/LoginViewController.java +++ b/app/src/main/java/com/techcourse/controller/LoginViewController.java @@ -15,11 +15,13 @@ public class LoginViewController { @GetMapping("/login/view") public ModelAndView execute(final HttpServletRequest req, final HttpServletResponse res) { - return UserSession.getUserFrom(req.getSession()) + final String viewName = UserSession.getUserFrom(req.getSession()) .map(user -> { log.info("logged in {}", user.getAccount()); - return new ModelAndView(new JspView("redirect:/index.jsp")); + return "redirect:/index.jsp"; }) - .orElse(new ModelAndView(new JspView("/login.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 daf7150d99..f1260e1877 100644 --- a/app/src/main/java/com/techcourse/controller/LogoutController.java +++ b/app/src/main/java/com/techcourse/controller/LogoutController.java @@ -3,7 +3,6 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import web.org.springframework.web.bind.annotation.GetMapping; -import web.org.springframework.web.bind.annotation.PostMapping; import webmvc.org.springframework.web.servlet.ModelAndView; import webmvc.org.springframework.web.servlet.view.JspView; From ac044117b61aedc7b43b08f15a926158df0d5133 Mon Sep 17 00:00:00 2001 From: JunH Date: Mon, 25 Sep 2023 21:50:49 +0900 Subject: [PATCH 7/9] =?UTF-8?q?:fix:=20bug:=20View=EA=B0=80=20=EB=A0=8C?= =?UTF-8?q?=EB=8D=94=EB=A7=81=EB=90=98=EC=A7=80=20=EC=95=8A=EC=95=98?= =?UTF-8?q?=EB=8D=98=20=EB=B2=84=EA=B7=B8=20=ED=94=BD=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/servlet/DispatcherServlet.java | 16 +--------------- .../org/springframework/web/servlet/View.java | 2 -- .../web/servlet/view/JsonView.java | 5 ----- .../web/servlet/view/JspView.java | 4 ---- 4 files changed, 1 insertion(+), 26 deletions(-) diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/DispatcherServlet.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/DispatcherServlet.java index a4a18bc605..0a4f7d9ea9 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/DispatcherServlet.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/DispatcherServlet.java @@ -48,20 +48,6 @@ private void process(final HttpServletRequest request, final HttpServletResponse final ModelAndView modelAndView = handlerAdapter.handle(handler, request, response); final View view = modelAndView.getView(); - move(view.getViewName(), request, response); - } - - private void move( - final String viewName, - final HttpServletRequest request, - final HttpServletResponse response - ) throws Exception { - if (viewName.startsWith(JspView.REDIRECT_PREFIX)) { - response.sendRedirect(viewName.substring(JspView.REDIRECT_PREFIX.length())); - return; - } - - final var requestDispatcher = request.getRequestDispatcher(viewName); - requestDispatcher.forward(request, response); + view.render(modelAndView.getModel(), request, response); } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/View.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/View.java index 0346a3dda8..4499f36866 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/View.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/View.java @@ -7,6 +7,4 @@ public interface View { void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception; - - String getViewName(); } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java index e0268ddb95..5a942b7d45 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java @@ -24,9 +24,4 @@ public void render(final Map model, final HttpServletRequest request, final PrintWriter writer = response.getWriter(); writer.write(body); } - - @Override - public String getViewName() { - return null; - } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JspView.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JspView.java index 82e3d3dea6..e3f7805093 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JspView.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JspView.java @@ -36,8 +36,4 @@ public void render(final Map model, final HttpServletRequest request, final RequestDispatcher requestDispatcher = request.getRequestDispatcher(viewName); requestDispatcher.forward(request, response); } - - public String getViewName() { - return viewName; - } } From aff7c83424983932be6a20eb846dcf095bbca27f Mon Sep 17 00:00:00 2001 From: JunH Date: Mon, 25 Sep 2023 22:02:55 +0900 Subject: [PATCH 8/9] =?UTF-8?q?:bug:=20fix=20:=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EB=B2=84=EA=B7=B8=20=ED=94=BD?= =?UTF-8?q?=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/techcourse/AnnotationHandlerMappingTest.java | 3 ++- .../webmvc/org/springframework/web/servlet/view/JsonView.java | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/test/java/com/techcourse/AnnotationHandlerMappingTest.java b/app/src/test/java/com/techcourse/AnnotationHandlerMappingTest.java index ef2e0511af..f692ff621e 100644 --- a/app/src/test/java/com/techcourse/AnnotationHandlerMappingTest.java +++ b/app/src/test/java/com/techcourse/AnnotationHandlerMappingTest.java @@ -11,6 +11,7 @@ import webmvc.org.springframework.web.servlet.ModelAndView; import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationHandlerMapping; import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecution; +import webmvc.org.springframework.web.servlet.view.JspView; class AnnotationHandlerMappingTest { @@ -36,7 +37,7 @@ void register() throws Exception { final var handlerExecution = (HandlerExecution) handlerMapping.getHandler(request); final var modelAndView = (ModelAndView) handlerExecution.handle(request, response); - assertThat(modelAndView.getView().getViewName()).isEqualTo("redirect:/index.jsp"); + assertThat(modelAndView.getView()).usingRecursiveComparison().isEqualTo(new JspView("redirect:/index.jsp")); } @Test diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java index 5a942b7d45..946de973eb 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java @@ -1,6 +1,6 @@ package webmvc.org.springframework.web.servlet.view; -import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND; +import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; @@ -16,7 +16,7 @@ public class JsonView implements View { public void render(final Map model, final HttpServletRequest request, HttpServletResponse response) throws Exception { if (model == null || model.isEmpty()) { - response.setStatus(SC_NOT_FOUND); + response.setStatus(SC_INTERNAL_SERVER_ERROR); return; } response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); From 48d58de09fc73c22c7cbfd222b9b523d853325eb Mon Sep 17 00:00:00 2001 From: JunH Date: Mon, 25 Sep 2023 22:06:21 +0900 Subject: [PATCH 9/9] =?UTF-8?q?:art:=20refactor=20:=20=EB=AA=A8=EB=8D=B8?= =?UTF-8?q?=EC=9D=98=20=EC=83=81=ED=83=9C=EC=97=90=20=EB=94=B0=EB=9D=BC=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EC=BD=94=EB=93=9C=EB=A5=BC=20=EA=B5=AC?= =?UTF-8?q?=EB=B6=84=ED=95=B4=EC=84=9C=20=EB=B3=B4=EB=82=B4=EB=8A=94=20?= =?UTF-8?q?=EA=B2=83=EC=9C=BC=EB=A1=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/springframework/web/servlet/view/JsonView.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java index 946de973eb..52e67362a7 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java @@ -1,5 +1,6 @@ package webmvc.org.springframework.web.servlet.view; +import static jakarta.servlet.http.HttpServletResponse.*; import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; import com.fasterxml.jackson.databind.ObjectMapper; @@ -15,10 +16,15 @@ public class JsonView implements View { @Override public void render(final Map model, final HttpServletRequest request, HttpServletResponse response) throws Exception { - if (model == null || model.isEmpty()) { + if (model == null) { response.setStatus(SC_INTERNAL_SERVER_ERROR); return; } + + if (model.isEmpty()) { + response.setStatus(SC_NO_CONTENT); + return; + } response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); final String body = new ObjectMapper().writeValueAsString(model); final PrintWriter writer = response.getWriter();