diff --git a/app/src/main/java/com/techcourse/DispatcherServlet.java b/app/src/main/java/com/techcourse/DispatcherServlet.java deleted file mode 100644 index bb7b40aa22..0000000000 --- a/app/src/main/java/com/techcourse/DispatcherServlet.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.techcourse; - -import com.techcourse.controlleradapter.ControllerHandlerAdapter; -import com.techcourse.exception.HandlerAdapterNotFoundException; -import com.techcourse.exception.HandlerNotFoundException; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServlet; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.util.List; -import java.util.Objects; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import webmvc.org.springframework.web.servlet.ExceptionHandlerMapping; -import webmvc.org.springframework.web.servlet.HandlerMapping; -import webmvc.org.springframework.web.servlet.mvc.HandlerAdapter; -import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationExceptionHandlerMapping; -import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationHandlerMapping; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecutionHandlerAdapter; -import webmvc.org.springframework.web.servlet.view.JspView; - -public class DispatcherServlet extends HttpServlet { - - private static final long serialVersionUID = 1L; - private static final Logger log = LoggerFactory.getLogger(DispatcherServlet.class); - - private List exceptionHandlerMappings = List.of( - new AnnotationExceptionHandlerMapping("com/techcourse") - ); - - private List handlerMappings = List.of( - new ManualHandlerMapping(), - new AnnotationHandlerMapping("com/techcourse") - ); - - private List handlerAdapters = List.of( - new HandlerExecutionHandlerAdapter(), - new ControllerHandlerAdapter() - ); - - public DispatcherServlet() { - } - - @Override - public void init() { - for (ExceptionHandlerMapping exceptionHandlerMapping : exceptionHandlerMappings) { - exceptionHandlerMapping.initialize(); - } - for (HandlerMapping handlerMapping : handlerMappings) { - handlerMapping.initialize(); - } - } - - @Override - protected void service(final HttpServletRequest request, final HttpServletResponse response) throws ServletException { - final String requestURI = request.getRequestURI(); - log.debug("Method : {}, Request URI : {}", request.getMethod(), requestURI); - - try { - final Object handler = findHandler(request); - - final HandlerAdapter handlerAdapter = findHandlerAdaptor(handler); - final String viewPath = handlerAdapter.invoke(handler, request, response); - move(viewPath, request, response); - } catch (Throwable e) { - handleException(request, response, e); - } - } - - private Object findHandler(final HttpServletRequest request) { - for (HandlerMapping handlerMapping : handlerMappings) { - final Object handler = handlerMapping.getHandler(request); - if (Objects.nonNull(handler)) { - return handler; - } - } - throw new HandlerNotFoundException("Handler Not found"); - } - - private HandlerAdapter findHandlerAdaptor(final Object handler) { - for (HandlerAdapter handlerAdapter : handlerAdapters) { - if (handlerAdapter.support(handler)) { - return handlerAdapter; - } - } - throw new HandlerAdapterNotFoundException("Handler Adaptor Not found"); - } - - 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); - } - - private void handleException(final HttpServletRequest request, final HttpServletResponse response, final Throwable e) { - try { - Object handler = null; - for (ExceptionHandlerMapping exceptionHandlerMapping : exceptionHandlerMappings) { - final Object foundHandler = findExceptionHandler(e, exceptionHandlerMapping); - if (Objects.nonNull(foundHandler)) { - handler = foundHandler; - break; - } - } - - if (Objects.isNull(handler)) { - throw new ServletException("ExceptionHandler Not Found."); - } - final HandlerAdapter handlerAdapter = findHandlerAdaptor(handler); - final String viewPath = handlerAdapter.invoke(handler, request, response); - move(viewPath, request, response); - } catch (Exception exception) { - log.error("Exception caused in ExceptionHandler"); - throw new RuntimeException(e); - } - } - - private static Object findExceptionHandler(final Throwable e, final ExceptionHandlerMapping exceptionHandlerMapping) { - return exceptionHandlerMapping.getHandler(e.getClass()); - } -} diff --git a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java index 6e814cdd25..41f6bde847 100644 --- a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java +++ b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java @@ -4,6 +4,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import web.org.springframework.web.WebApplicationInitializer; +import webmvc.org.springframework.web.servlet.DispatcherServlet; +import webmvc.org.springframework.web.servlet.HandlerAdapterRegistry; +import webmvc.org.springframework.web.servlet.HandlerMappingRegistry; +import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationHandlerMapping; +import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecutionHandlerAdapter; /** * Base class for {@link WebApplicationInitializer} @@ -17,7 +22,13 @@ public class DispatcherServletInitializer implements WebApplicationInitializer { @Override public void onStartup(final ServletContext servletContext) { - final var dispatcherServlet = new DispatcherServlet(); + final HandlerMappingRegistry handlerMappingRegistry = new HandlerMappingRegistry(); + handlerMappingRegistry.addHandlerMapping(new AnnotationHandlerMapping("com/techcourse")); + + final HandlerAdapterRegistry handlerAdapterRegistry = new HandlerAdapterRegistry(); + handlerAdapterRegistry.addHandlerAdapter(new HandlerExecutionHandlerAdapter()); + + final var dispatcherServlet = new DispatcherServlet(handlerAdapterRegistry, handlerMappingRegistry); 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 cd841f3f1c..0000000000 --- a/app/src/main/java/com/techcourse/ManualHandlerMapping.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.techcourse; - -import com.techcourse.controller.*; -import jakarta.servlet.http.HttpServletRequest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import webmvc.org.springframework.web.servlet.HandlerMapping; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; -import webmvc.org.springframework.web.servlet.mvc.asis.ForwardController; - -import java.util.HashMap; -import java.util.Map; - -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()); - controllers.put("/register", new RegisterController()); - - log.info("Initialized Handler Mapping!"); - controllers.keySet() - .forEach(path -> log.info("Path : {}, Controller : {}", path, controllers.get(path).getClass())); - } - - @Override - public Controller getHandler(final HttpServletRequest request) { - log.debug("Request Mapping Uri : {}", request.getRequestURI()); - return controllers.get(request.getRequestURI()); - } -} diff --git a/app/src/main/java/com/techcourse/controller/IndexViewController.java b/app/src/main/java/com/techcourse/controller/IndexViewController.java new file mode 100644 index 0000000000..7e4fcb1a71 --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/IndexViewController.java @@ -0,0 +1,16 @@ +package com.techcourse.controller; + +import context.org.springframework.stereotype.Controller; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; + +@Controller +public class IndexViewController { + + @RequestMapping(value = "/", method = RequestMethod.GET) + public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { + return "/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..9e625ba9bd 100644 --- a/app/src/main/java/com/techcourse/controller/LoginController.java +++ b/app/src/main/java/com/techcourse/controller/LoginController.java @@ -2,28 +2,34 @@ import com.techcourse.domain.User; import com.techcourse.repository.InMemoryUserRepository; +import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.view.JspView; -public class LoginController implements Controller { + +@Controller +public class LoginController { private static final Logger log = LoggerFactory.getLogger(LoginController.class); - @Override - public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { + @RequestMapping(value = "/login", method = RequestMethod.POST) + public ModelAndView execute(final HttpServletRequest req, final HttpServletResponse res) 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")) .map(user -> { log.info("User : {}", user); - return login(req, user); + return new ModelAndView(new JspView(login(req, user))); }) - .orElse("redirect:/401.jsp"); + .orElse(new ModelAndView(new JspView("redirect:/401.jsp"))); } 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 86ec26cdce..611a36c479 100644 --- a/app/src/main/java/com/techcourse/controller/LoginViewController.java +++ b/app/src/main/java/com/techcourse/controller/LoginViewController.java @@ -1,16 +1,19 @@ package com.techcourse.controller; +import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; -public class LoginViewController implements Controller { +@Controller +public class LoginViewController { private static final Logger log = LoggerFactory.getLogger(LoginViewController.class); - @Override + @RequestMapping(value = "/login/view", method = RequestMethod.GET) public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { return UserSession.getUserFrom(req.getSession()) .map(user -> { diff --git a/app/src/main/java/com/techcourse/controller/LogoutController.java b/app/src/main/java/com/techcourse/controller/LogoutController.java index 4642fd9450..00fe3933e8 100644 --- a/app/src/main/java/com/techcourse/controller/LogoutController.java +++ b/app/src/main/java/com/techcourse/controller/LogoutController.java @@ -1,12 +1,15 @@ package com.techcourse.controller; +import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; -public class LogoutController implements Controller { +@Controller +public class LogoutController { - @Override + @RequestMapping(value = "/logout", method = RequestMethod.GET) public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { final var session = req.getSession(); session.removeAttribute(UserSession.SESSION_KEY); diff --git a/app/src/main/java/com/techcourse/controller/RegisterController.java b/app/src/main/java/com/techcourse/controller/RegisterController.java index da62e5e8e9..62d3cadde2 100644 --- a/app/src/main/java/com/techcourse/controller/RegisterController.java +++ b/app/src/main/java/com/techcourse/controller/RegisterController.java @@ -2,13 +2,16 @@ import com.techcourse.domain.User; import com.techcourse.repository.InMemoryUserRepository; +import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; -public class RegisterController implements Controller { +@Controller +public class RegisterController { - @Override + @RequestMapping(value = "/register", method = RequestMethod.POST) public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { final var user = new User(2, req.getParameter("account"), diff --git a/app/src/main/java/com/techcourse/controller/RegisterViewController.java b/app/src/main/java/com/techcourse/controller/RegisterViewController.java index 136962136d..95f288158d 100644 --- a/app/src/main/java/com/techcourse/controller/RegisterViewController.java +++ b/app/src/main/java/com/techcourse/controller/RegisterViewController.java @@ -1,12 +1,15 @@ package com.techcourse.controller; +import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; -public class RegisterViewController implements Controller { +@Controller +public class RegisterViewController { - @Override + @RequestMapping(value = "/register/view", method = RequestMethod.GET) public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { return "/register.jsp"; } diff --git a/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..4f8914d9d1 --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/UserController.java @@ -0,0 +1,33 @@ +package com.techcourse.controller; + +import com.techcourse.domain.User; +import com.techcourse.repository.InMemoryUserRepository; +import context.org.springframework.stereotype.Controller; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.view.JsonView; + +@Controller +public class UserController { + + private static final Logger log = LoggerFactory.getLogger(UserController.class); + + @RequestMapping(value = "/api/user", method = RequestMethod.GET) + public ModelAndView show(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/main/java/com/techcourse/controlleradapter/ControllerHandlerAdapter.java b/app/src/main/java/com/techcourse/controlleradapter/ControllerHandlerAdapter.java deleted file mode 100644 index 4d3616ba61..0000000000 --- a/app/src/main/java/com/techcourse/controlleradapter/ControllerHandlerAdapter.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.techcourse.controlleradapter; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.HandlerAdapter; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; - -public class ControllerHandlerAdapter implements HandlerAdapter { - - @Override - public boolean support(final Object handler) { - return handler instanceof Controller; - } - - @Override - public String invoke(final Object handler, final HttpServletRequest request, - final HttpServletResponse response) throws Exception { - return ((Controller) handler).execute(request, response); - } -} diff --git a/app/src/main/java/com/techcourse/controlleradvisor/DispatcherServletAdvisor.java b/app/src/main/java/com/techcourse/controlleradvisor/DispatcherServletAdvisor.java index 534db60583..8dfa29b6e4 100644 --- a/app/src/main/java/com/techcourse/controlleradvisor/DispatcherServletAdvisor.java +++ b/app/src/main/java/com/techcourse/controlleradvisor/DispatcherServletAdvisor.java @@ -1,7 +1,7 @@ package com.techcourse.controlleradvisor; -import com.techcourse.exception.HandlerAdapterNotFoundException; -import com.techcourse.exception.HandlerNotFoundException; +import webmvc.org.springframework.web.servlet.exception.HandlerAdapterNotFoundException; +import webmvc.org.springframework.web.servlet.exception.HandlerNotFoundException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; diff --git a/mvc/src/main/java/web/org/springframework/http/MediaType.java b/mvc/src/main/java/web/org/springframework/http/MediaType.java index 3a31f51d33..e22dc38f89 100644 --- a/mvc/src/main/java/web/org/springframework/http/MediaType.java +++ b/mvc/src/main/java/web/org/springframework/http/MediaType.java @@ -1,5 +1,6 @@ package web.org.springframework.http; public class MediaType { + public static final String TEXT_PLAIN_UTF8_VALUE = "text/plain;charset=UTF-8"; public static final String APPLICATION_JSON_UTF8_VALUE = "application/json;charset=UTF-8"; } 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 new file mode 100644 index 0000000000..2de0098cef --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/DispatcherServlet.java @@ -0,0 +1,87 @@ +package webmvc.org.springframework.web.servlet; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.util.List; +import java.util.Objects; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import webmvc.org.springframework.web.servlet.exception.HandlerAdapterNotFoundException; +import webmvc.org.springframework.web.servlet.exception.HandlerNotFoundException; +import webmvc.org.springframework.web.servlet.mvc.HandlerAdapter; +import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationExceptionHandlerMapping; + +public class DispatcherServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + private static final Logger log = LoggerFactory.getLogger(DispatcherServlet.class); + + private final List exceptionHandlerMappings = List.of( + new AnnotationExceptionHandlerMapping("com/techcourse") + ); + + private final HandlerAdapterRegistry handlerAdapterRegistry; + + private final HandlerMappingRegistry handlerMappingRegistry; + + public DispatcherServlet(final HandlerAdapterRegistry handlerAdapterRegistry, + final HandlerMappingRegistry handlerMappingRegistry) { + this.handlerAdapterRegistry = handlerAdapterRegistry; + this.handlerMappingRegistry = handlerMappingRegistry; + } + + @Override + public void init() { + for (ExceptionHandlerMapping exceptionHandlerMapping : exceptionHandlerMappings) { + exceptionHandlerMapping.initialize(); + } + } + + @Override + protected void service(final HttpServletRequest request, final HttpServletResponse response) throws ServletException { + final String requestURI = request.getRequestURI(); + log.debug("Method : {}, Request URI : {}", request.getMethod(), requestURI); + + try { + final Object handler = handlerMappingRegistry.getHandler(request) + .orElseThrow(() -> new HandlerNotFoundException("핸들러못찾았썹")); + final HandlerAdapter handlerAdapter = handlerAdapterRegistry.getHandlerAdapter(handler) + .orElseThrow(() -> new HandlerAdapterNotFoundException("Handler Adaptor Not found")); + + final ModelAndView modelAndView = handlerAdapter.invoke(handler, request, response); + modelAndView.render(modelAndView.getModel(), request, response); + } catch (Throwable e) { + handleException(request, response, e); + } + } + + private void handleException(final HttpServletRequest request, final HttpServletResponse response, final Throwable e) { + try {Object handler = null; + for (ExceptionHandlerMapping exceptionHandlerMapping : exceptionHandlerMappings) { + final Object foundHandler = findExceptionHandler(e, exceptionHandlerMapping); + if (Objects.nonNull(foundHandler)) { + handler = foundHandler; + break; + } + } + + if (Objects.isNull(handler)) { + throw new ServletException("ExceptionHandler Not Found."); + } + final HandlerAdapter handlerAdapter = handlerAdapterRegistry.getHandlerAdapter(handler) + .orElseThrow(() -> new HandlerAdapterNotFoundException("Handler Adaptor Not found")); + + final ModelAndView modelAndView = handlerAdapter.invoke(handler, request, response); + modelAndView.render(modelAndView.getModel(), request, response); + } catch (Exception exception) { + log.error("Exception caused in ExceptionHandler"); + throw new RuntimeException(e); + } + } + + private static Object findExceptionHandler(final Throwable e, final ExceptionHandlerMapping exceptionHandlerMapping) { + return exceptionHandlerMapping.getHandler(e.getClass()); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerAdapterRegistry.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerAdapterRegistry.java new file mode 100644 index 0000000000..d1155c9d91 --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerAdapterRegistry.java @@ -0,0 +1,24 @@ +package webmvc.org.springframework.web.servlet; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import webmvc.org.springframework.web.servlet.mvc.HandlerAdapter; + +public class HandlerAdapterRegistry { + + private final List handlerAdapters = new ArrayList<>(); + + public void addHandlerAdapter(HandlerAdapter handlerAdapter) { + handlerAdapters.add(handlerAdapter); + } + + public Optional getHandlerAdapter(Object handler) { + for (HandlerAdapter handlerAdapter : handlerAdapters) { + if (handlerAdapter.support(handler)) { + return Optional.of(handlerAdapter); + } + } + return Optional.empty(); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerMappingRegistry.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerMappingRegistry.java new file mode 100644 index 0000000000..08647cd1ef --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/HandlerMappingRegistry.java @@ -0,0 +1,28 @@ +package webmvc.org.springframework.web.servlet; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +public class HandlerMappingRegistry { + + private final List handlerMappings = new ArrayList<>(); + + public void addHandlerMapping(HandlerMapping handlerMapping) { + handlerMapping.initialize(); + handlerMappings.add(handlerMapping); + } + + public Optional getHandler(HttpServletRequest request) { + for (HandlerMapping handlerMapping : handlerMappings) { + final Object handler = handlerMapping.getHandler(request); + + if (Objects.nonNull(handler)) { + return Optional.of(handler); + } + } + return Optional.empty(); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java index ff8e24553f..91b782c6d3 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java @@ -1,5 +1,7 @@ package webmvc.org.springframework.web.servlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -27,7 +29,8 @@ public Map getModel() { return Collections.unmodifiableMap(model); } - public View getView() { - return view; + public void render(Map model, HttpServletRequest request, HttpServletResponse response) + throws Exception { + this.view.render(model, request, response); } } diff --git a/app/src/main/java/com/techcourse/exception/DispatcherServletException.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/exception/DispatcherServletException.java similarity index 73% rename from app/src/main/java/com/techcourse/exception/DispatcherServletException.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/exception/DispatcherServletException.java index 678ed0e1b4..d1bdfdacb1 100644 --- a/app/src/main/java/com/techcourse/exception/DispatcherServletException.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/exception/DispatcherServletException.java @@ -1,4 +1,4 @@ -package com.techcourse.exception; +package webmvc.org.springframework.web.servlet.exception; public class DispatcherServletException extends RuntimeException { public DispatcherServletException(final String message) { diff --git a/app/src/main/java/com/techcourse/exception/HandlerAdapterNotFoundException.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/exception/HandlerAdapterNotFoundException.java similarity index 75% rename from app/src/main/java/com/techcourse/exception/HandlerAdapterNotFoundException.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/exception/HandlerAdapterNotFoundException.java index a6301a25bf..7aea9b2e3a 100644 --- a/app/src/main/java/com/techcourse/exception/HandlerAdapterNotFoundException.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/exception/HandlerAdapterNotFoundException.java @@ -1,4 +1,4 @@ -package com.techcourse.exception; +package webmvc.org.springframework.web.servlet.exception; public class HandlerAdapterNotFoundException extends DispatcherServletException { public HandlerAdapterNotFoundException(final String message) { diff --git a/app/src/main/java/com/techcourse/exception/HandlerNotFoundException.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/exception/HandlerNotFoundException.java similarity index 74% rename from app/src/main/java/com/techcourse/exception/HandlerNotFoundException.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/exception/HandlerNotFoundException.java index e319d9d967..4b94cdde8e 100644 --- a/app/src/main/java/com/techcourse/exception/HandlerNotFoundException.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/exception/HandlerNotFoundException.java @@ -1,4 +1,4 @@ -package com.techcourse.exception; +package webmvc.org.springframework.web.servlet.exception; public class HandlerNotFoundException extends DispatcherServletException { public HandlerNotFoundException(final String message) { diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/HandlerAdapter.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/HandlerAdapter.java index 86c11b27b1..ead7f6528b 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/HandlerAdapter.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/HandlerAdapter.java @@ -2,10 +2,11 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import webmvc.org.springframework.web.servlet.ModelAndView; public interface HandlerAdapter { boolean support(Object handler); - String invoke(Object handler, HttpServletRequest request, HttpServletResponse response) throws Exception; + ModelAndView invoke(Object handler, HttpServletRequest request, HttpServletResponse response) throws Exception; } 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/HandlerExecution.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java index c6d984d146..2d3d475080 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java @@ -3,6 +3,8 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.lang.reflect.Method; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.view.JspView; public class HandlerExecution { @@ -12,7 +14,15 @@ public HandlerExecution(final Method method) { this.method = method; } - public Object handle(final HttpServletRequest request, final HttpServletResponse response) throws Exception { - return method.invoke(method.getDeclaringClass().getDeclaredConstructor().newInstance(), request, response); + public ModelAndView handle(final HttpServletRequest request, final HttpServletResponse response) throws Exception { + final Object returnValue = method + .invoke(method.getDeclaringClass().getDeclaredConstructor().newInstance(), request, response); + if (returnValue instanceof String) { + return new ModelAndView(new JspView((String) returnValue)); + } + if (returnValue instanceof ModelAndView) { + return (ModelAndView) returnValue; + } + throw new IllegalArgumentException("리턴타입이이상해욥"); } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecutionHandlerAdapter.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecutionHandlerAdapter.java index 7a7457d883..ab20e65fd7 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecutionHandlerAdapter.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecutionHandlerAdapter.java @@ -2,6 +2,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import webmvc.org.springframework.web.servlet.ModelAndView; import webmvc.org.springframework.web.servlet.mvc.HandlerAdapter; public class HandlerExecutionHandlerAdapter implements HandlerAdapter { @@ -12,8 +13,8 @@ public boolean support(final Object handler) { } @Override - public String invoke(final Object handler, final HttpServletRequest request, + public ModelAndView invoke(final Object handler, final HttpServletRequest request, final HttpServletResponse response) throws Exception { - return (String) ((HandlerExecution) handler).handle(request, response); + return ((HandlerExecution) handler).handle(request, response); } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java index b42c3466f0..61aef494de 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java @@ -1,14 +1,29 @@ package webmvc.org.springframework.web.servlet.view; +import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import java.io.PrintWriter; +import web.org.springframework.http.MediaType; import webmvc.org.springframework.web.servlet.View; import java.util.Map; public class JsonView implements View { + private final ObjectMapper objectMapper = new ObjectMapper(); + @Override - public void render(final Map model, final HttpServletRequest request, HttpServletResponse response) throws Exception { + public void render(final Map model, final HttpServletRequest request, HttpServletResponse response) + throws Exception { + if (model.size() == 1) { + response.setContentType(MediaType.TEXT_PLAIN_UTF8_VALUE); + final PrintWriter writer = response.getWriter(); + writer.write(objectMapper.writeValueAsString(model.values().toArray()[0])); + return; + } + response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); + final PrintWriter writer = response.getWriter(); + writer.write(objectMapper.writeValueAsString(model)); } } 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 3f4cc906ff..18f654d28d 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 @@ -14,18 +14,25 @@ public class JspView implements View { public static final String REDIRECT_PREFIX = "redirect:"; + private final String viewName; + public JspView(final String viewName) { + this.viewName = 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(JspView.REDIRECT_PREFIX)) { + response.sendRedirect(viewName.substring(JspView.REDIRECT_PREFIX.length())); + return; + } + + final var requestDispatcher = request.getRequestDispatcher(viewName); + requestDispatcher.forward(request, response); } }