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 82a4f9791a..0000000000 --- a/app/src/main/java/com/techcourse/DispatcherServlet.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.techcourse; - -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServlet; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import 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.AnnotationHandlerAdapter; -import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationHandlerMapping; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerAdapter; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerAdapterException; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerMapping; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerMappingException; -import webmvc.org.springframework.web.servlet.mvc.tobe.ManualHandlerAdapter; - -public class DispatcherServlet extends HttpServlet { - - private static final long serialVersionUID = 1L; - private static final Logger log = LoggerFactory.getLogger(DispatcherServlet.class); - - private final List handlerMappings = new ArrayList<>(); - private final List handlerAdapters = new ArrayList<>(); - - public DispatcherServlet() { - } - - @Override - public void init() { - initHandlerMappings(); - initHandlerAdapters(); - } - - private void initHandlerMappings() { - handlerMappings.add(new WrappedManualHandlerMapping()); - handlerMappings.add(new AnnotationHandlerMapping(getClass().getPackageName())); - for (final HandlerMapping handlerMapping : handlerMappings) { - handlerMapping.initialize(); - } - } - - private void initHandlerAdapters() { - handlerAdapters.add(new ManualHandlerAdapter()); - handlerAdapters.add(new AnnotationHandlerAdapter()); - } - - @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 = getHandler(request); - final HandlerAdapter handlerAdapter = getHandlerAdapter(handler); - final ModelAndView modelAndView = handlerAdapter.handle(handler, request, response); - final View view = modelAndView.getView(); - final Map model = modelAndView.getModel(); - view.render(model, request, response); - } catch (final Throwable e) { - log.error("Exception : {}", e.getMessage(), e); - throw new ServletException(e.getMessage()); - } - } - - private Object getHandler(final HttpServletRequest request) { - for (final HandlerMapping handlerMapping : handlerMappings) { - final Object handler = handlerMapping.getHandler(request); - if (handler != null) { - return handler; - } - } - throw new HandlerMappingException("해당 요청에 대한 핸들러가 없습니다."); - } - - private HandlerAdapter getHandlerAdapter(final Object handler) { - for (final HandlerAdapter handlerAdapter : handlerAdapters) { - if (handlerAdapter.supports(handler)) { - return handlerAdapter; - } - } - throw new HandlerAdapterException("해당 요청에 대한 핸들러 어댑터가 없습니다."); - } -} diff --git a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java index 6e814cdd25..c9040e0c76 100644 --- a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java +++ b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java @@ -4,10 +4,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import web.org.springframework.web.WebApplicationInitializer; +import webmvc.org.springframework.web.servlet.mvc.DispatcherServlet; /** - * Base class for {@link WebApplicationInitializer} - * implementations that register a {@link DispatcherServlet} in the servlet context. + * Base class for {@link WebApplicationInitializer} implementations that register a {@link DispatcherServlet} in the + * servlet context. */ public class DispatcherServletInitializer implements WebApplicationInitializer { diff --git a/app/src/main/java/com/techcourse/ManualHandlerMapping.java b/app/src/main/java/com/techcourse/ManualHandlerMapping.java deleted file mode 100644 index 55189ce45a..0000000000 --- a/app/src/main/java/com/techcourse/ManualHandlerMapping.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.techcourse; - -import com.techcourse.controller.LoginController; -import com.techcourse.controller.LoginViewController; -import com.techcourse.controller.LogoutController; -import com.techcourse.controller.RegisterController; -import com.techcourse.controller.RegisterViewController; -import java.util.HashMap; -import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; -import webmvc.org.springframework.web.servlet.mvc.asis.ForwardController; - -public class ManualHandlerMapping { - - private static final Logger log = LoggerFactory.getLogger(ManualHandlerMapping.class); - - private static final Map controllers = new HashMap<>(); - - public void initialize() { - controllers.put("/", new ForwardController("/index.jsp")); - controllers.put("/login", new LoginController()); - controllers.put("/login/view", new LoginViewController()); - controllers.put("/logout", new LogoutController()); - controllers.put("/register/view", new RegisterViewController()); - controllers.put("/register", new RegisterController()); - - log.info("Initialized Handler Mapping!"); - controllers.keySet() - .forEach(path -> log.info("Path : {}, Controller : {}", path, controllers.get(path).getClass())); - } - - public Controller getHandler(final String requestURI) { - log.debug("Request Mapping Uri : {}", requestURI); - return controllers.get(requestURI); - } -} diff --git a/app/src/main/java/com/techcourse/WrappedManualHandlerMapping.java b/app/src/main/java/com/techcourse/WrappedManualHandlerMapping.java deleted file mode 100644 index cf08592136..0000000000 --- a/app/src/main/java/com/techcourse/WrappedManualHandlerMapping.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.techcourse; - -import jakarta.servlet.http.HttpServletRequest; -import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerMapping; - -public class WrappedManualHandlerMapping implements HandlerMapping { - - private final ManualHandlerMapping handlerMapping = new ManualHandlerMapping(); - - @Override - public void initialize() { - handlerMapping.initialize(); - } - - @Override - public Object getHandler(final HttpServletRequest request) { - return handlerMapping.getHandler(request.getRequestURI()); - } -} diff --git a/app/src/main/java/com/techcourse/controller/ForwardController.java b/app/src/main/java/com/techcourse/controller/ForwardController.java new file mode 100644 index 0000000000..aa0af0112f --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/ForwardController.java @@ -0,0 +1,18 @@ +package com.techcourse.controller; + +import context.org.springframework.stereotype.Controller; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; + +@Controller +public class ForwardController { + + private static final String PATH = "/index.jsp"; + + @RequestMapping(value = "/", method = RequestMethod.GET) + public String execute(final HttpServletRequest request, final HttpServletResponse response) { + return PATH; + } +} diff --git a/app/src/main/java/com/techcourse/controller/LoginController.java b/app/src/main/java/com/techcourse/controller/LoginController.java index 0428fe109e..d08dd9da15 100644 --- a/app/src/main/java/com/techcourse/controller/LoginController.java +++ b/app/src/main/java/com/techcourse/controller/LoginController.java @@ -2,17 +2,20 @@ import com.techcourse.domain.User; import com.techcourse.repository.InMemoryUserRepository; +import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; -public class LoginController implements Controller { +@Controller +public class LoginController { private static final Logger log = LoggerFactory.getLogger(LoginController.class); - @Override + @RequestMapping(value = "/login", method = RequestMethod.POST) public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { if (UserSession.isLoggedIn(req.getSession())) { return "redirect:/index.jsp"; diff --git a/app/src/main/java/com/techcourse/controller/LoginViewController.java b/app/src/main/java/com/techcourse/controller/LoginViewController.java index 86ec26cdce..611a36c479 100644 --- a/app/src/main/java/com/techcourse/controller/LoginViewController.java +++ b/app/src/main/java/com/techcourse/controller/LoginViewController.java @@ -1,16 +1,19 @@ package com.techcourse.controller; +import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; -public class LoginViewController implements Controller { +@Controller +public class LoginViewController { private static final Logger log = LoggerFactory.getLogger(LoginViewController.class); - @Override + @RequestMapping(value = "/login/view", method = RequestMethod.GET) public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { return UserSession.getUserFrom(req.getSession()) .map(user -> { diff --git a/app/src/main/java/com/techcourse/controller/LogoutController.java b/app/src/main/java/com/techcourse/controller/LogoutController.java index 4642fd9450..00fe3933e8 100644 --- a/app/src/main/java/com/techcourse/controller/LogoutController.java +++ b/app/src/main/java/com/techcourse/controller/LogoutController.java @@ -1,12 +1,15 @@ package com.techcourse.controller; +import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; -public class LogoutController implements Controller { +@Controller +public class LogoutController { - @Override + @RequestMapping(value = "/logout", method = RequestMethod.GET) public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { final var session = req.getSession(); session.removeAttribute(UserSession.SESSION_KEY); diff --git a/app/src/main/java/com/techcourse/controller/RegisterController.java b/app/src/main/java/com/techcourse/controller/RegisterController.java index da62e5e8e9..bd0a56384b 100644 --- a/app/src/main/java/com/techcourse/controller/RegisterController.java +++ b/app/src/main/java/com/techcourse/controller/RegisterController.java @@ -2,13 +2,16 @@ import com.techcourse.domain.User; import com.techcourse.repository.InMemoryUserRepository; +import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; -public class RegisterController implements Controller { +@Controller +public class RegisterController { - @Override + @RequestMapping(value = "/register", method = RequestMethod.GET) public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { final var user = new User(2, req.getParameter("account"), diff --git a/app/src/main/java/com/techcourse/controller/RegisterViewController.java b/app/src/main/java/com/techcourse/controller/RegisterViewController.java index 136962136d..95f288158d 100644 --- a/app/src/main/java/com/techcourse/controller/RegisterViewController.java +++ b/app/src/main/java/com/techcourse/controller/RegisterViewController.java @@ -1,12 +1,15 @@ package com.techcourse.controller; +import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; -public class RegisterViewController implements Controller { +@Controller +public class RegisterViewController { - @Override + @RequestMapping(value = "/register/view", method = RequestMethod.GET) public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { return "/register.jsp"; } diff --git a/app/src/main/java/com/techcourse/controller/UserController.java b/app/src/main/java/com/techcourse/controller/UserController.java new file mode 100644 index 0000000000..fded092b32 --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/UserController.java @@ -0,0 +1,32 @@ +package com.techcourse.controller; + +import com.techcourse.domain.User; +import com.techcourse.repository.InMemoryUserRepository; +import context.org.springframework.stereotype.Controller; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.view.JsonView; + +@Controller +public class UserController { + + private static final Logger log = LoggerFactory.getLogger(UserController.class); + + @RequestMapping(value = "/api/user", method = RequestMethod.GET) + public ModelAndView show(final HttpServletRequest request, final HttpServletResponse response) { + final String account = request.getParameter("account"); + log.debug("user id : {}", account); + + final ModelAndView modelAndView = new ModelAndView(new JsonView()); + final User user = InMemoryUserRepository.findByAccount(account) + .orElseThrow(); + + modelAndView.addObject("user", user); + return modelAndView; + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java index ff8e24553f..ec371d84cc 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java @@ -6,10 +6,10 @@ public class ModelAndView { - private final View view; + private final Object view; private final Map model; - public ModelAndView(final View view) { + public ModelAndView(final Object view) { this.view = view; this.model = new HashMap<>(); } @@ -27,7 +27,7 @@ public Map getModel() { return Collections.unmodifiableMap(model); } - public View getView() { + public Object getView() { return view; } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java new file mode 100644 index 0000000000..61eb775adf --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/DispatcherServlet.java @@ -0,0 +1,91 @@ +package webmvc.org.springframework.web.servlet.mvc; + +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.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.View; +import webmvc.org.springframework.web.servlet.mvc.adapter.AnnotationHandlerAdapter; +import webmvc.org.springframework.web.servlet.mvc.adapter.HandlerAdapter; +import webmvc.org.springframework.web.servlet.mvc.adapter.HandlerAdapters; +import webmvc.org.springframework.web.servlet.mvc.handler.AnnotationHandlerMapping; +import webmvc.org.springframework.web.servlet.mvc.handler.HandlerMappingException; +import webmvc.org.springframework.web.servlet.mvc.handler.HandlerMappings; +import webmvc.org.springframework.web.servlet.mvc.viewresolver.JsonViewResolver; +import webmvc.org.springframework.web.servlet.mvc.viewresolver.JspViewResolver; +import webmvc.org.springframework.web.servlet.mvc.viewresolver.ViewResolverException; +import webmvc.org.springframework.web.servlet.mvc.viewresolver.ViewResolvers; + +public class DispatcherServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + private static final Logger log = LoggerFactory.getLogger(DispatcherServlet.class); + + private HandlerMappings handlerMappings; + private HandlerAdapters handlerAdapters; + private ViewResolvers viewResolvers; + + @Override + public void init() { + initHandlerMappings(); + initHandlerAdapters(); + initViewResolvers(); + } + + private void initHandlerMappings() { + handlerMappings = new HandlerMappings( + List.of(new AnnotationHandlerMapping()) + ); + handlerMappings.initialize(); + } + + private void initHandlerAdapters() { + handlerAdapters = new HandlerAdapters( + List.of(new AnnotationHandlerAdapter()) + ); + } + + private void initViewResolvers() { + viewResolvers = new ViewResolvers( + List.of(new JspViewResolver(), new JsonViewResolver()) + ); + } + + @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 = getHandler(request); + final HandlerAdapter handlerAdapter = getHandlerAdapter(handler); + final ModelAndView modelAndView = handlerAdapter.handle(handler, request, response); + final View view = getView(modelAndView); + final Map model = modelAndView.getModel(); + view.render(model, request, response); + } catch (final HandlerMappingException | ViewResolverException e) { + throw e; + } catch (final Throwable e) { + log.error("Exception : {}", e.getMessage(), e); + throw new ServletException(e.getMessage()); + } + } + + private Object getHandler(final HttpServletRequest request) { + return handlerMappings.getHandler(request); + } + + private HandlerAdapter getHandlerAdapter(final Object handler) { + return handlerAdapters.getHandlerAdapter(handler); + } + + private View getView(final ModelAndView modelAndView) { + return viewResolvers.getView(modelAndView); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapter.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/AnnotationHandlerAdapter.java similarity index 84% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapter.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/AnnotationHandlerAdapter.java index 5baec6cef6..712fe38291 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapter.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/AnnotationHandlerAdapter.java @@ -1,8 +1,9 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.adapter; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.mvc.handler.HandlerExecution; public class AnnotationHandlerAdapter implements HandlerAdapter { diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerAdapter.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapter.java similarity index 85% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerAdapter.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapter.java index 1b62b24042..546e4a90cf 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerAdapter.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapter.java @@ -1,4 +1,4 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.adapter; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerAdapterException.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapterException.java similarity index 72% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerAdapterException.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapterException.java index 86fba1051c..a4bda20de1 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerAdapterException.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapterException.java @@ -1,4 +1,4 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.adapter; public class HandlerAdapterException extends RuntimeException { diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapters.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapters.java new file mode 100644 index 0000000000..a6a2f680ab --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/adapter/HandlerAdapters.java @@ -0,0 +1,20 @@ +package webmvc.org.springframework.web.servlet.mvc.adapter; + +import java.util.ArrayList; +import java.util.List; + +public class HandlerAdapters { + + private final List handlerAdapters; + + public HandlerAdapters(final List handlerAdapters) { + this.handlerAdapters = new ArrayList<>(handlerAdapters); + } + + public HandlerAdapter getHandlerAdapter(final Object handler) { + return handlerAdapters.stream() + .filter(handlerAdapter -> handlerAdapter.supports(handler)) + .findFirst() + .orElseThrow(() -> new HandlerAdapterException("해당 요청에 대한 핸들러 어댑터가 없습니다.")); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/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/handler/AnnotationHandlerMapping.java similarity index 84% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/AnnotationHandlerMapping.java index 75284972db..cb0d9908df 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/AnnotationHandlerMapping.java @@ -1,5 +1,6 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.handler; +import com.sun.jdi.InternalException; import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; import java.lang.annotation.Annotation; @@ -9,6 +10,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import org.reflections.Reflections; @@ -32,14 +34,12 @@ public AnnotationHandlerMapping(final Object... basePackage) { @Override public void initialize() { - for (final Object basePackage : basePackages) { - initHandlerExecution(basePackage); - } + registerHandlerWithAnnotation(basePackages); log.info("Initialized AnnotationHandlerMapping!"); } - private void initHandlerExecution(final Object basePackage) { - final Set> classes = getClassesByAnnotation(basePackage, Controller.class); + private void registerHandlerWithAnnotation(final Object... basePackages) { + final Set> classes = getClassesByAnnotation(basePackages, Controller.class); for (final Class clazz : classes) { final List methods = getMethodsByAnnotation(clazz, RequestMapping.class); for (final Method method : methods) { @@ -50,9 +50,9 @@ private void initHandlerExecution(final Object basePackage) { } } - private Set> getClassesByAnnotation(final Object basePackage, + private Set> getClassesByAnnotation(final Object[] basePackages, final Class annotation) { - final Reflections reflections = new Reflections(basePackage); + final Reflections reflections = new Reflections(basePackages); return reflections.getTypesAnnotatedWith(annotation); } @@ -85,16 +85,20 @@ private Object makeHandlerInstance(final Class clazz) { return clazz.getDeclaredConstructor().newInstance(); } catch (final NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new HandlerMappingException("handler 인스턴스 생성에 실패했습니다."); + throw new InternalException("handler 인스턴스 생성에 실패했습니다."); } } @Override - public Object getHandler(final HttpServletRequest request) { + public Optional getHandler(final HttpServletRequest request) { final HandlerKey handlerKey = new HandlerKey( request.getRequestURI(), RequestMethod.valueOf(request.getMethod()) ); - return handlerExecutions.get(handlerKey); + final HandlerExecution handler = handlerExecutions.get(handlerKey); + if (handler == null) { + return Optional.empty(); + } + return Optional.of(handler); } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerException.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerException.java new file mode 100644 index 0000000000..e55afbc6e1 --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerException.java @@ -0,0 +1,8 @@ +package webmvc.org.springframework.web.servlet.mvc.handler; + +public class HandlerException extends RuntimeException { + + public HandlerException(final String message) { + super(message); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerExecution.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerExecution.java new file mode 100644 index 0000000000..99771893f1 --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerExecution.java @@ -0,0 +1,32 @@ +package webmvc.org.springframework.web.servlet.mvc.handler; + +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.JsonView; + +public class HandlerExecution { + + private final Object handler; + private final Method method; + + public HandlerExecution(final Object handler, final Method method) { + this.handler = handler; + this.method = method; + } + + public ModelAndView handle(final HttpServletRequest request, final HttpServletResponse response) throws Exception { + final Object result = method.invoke(handler, request, response); + if (result instanceof ModelAndView) { + return (ModelAndView) result; + } + if (result == null) { + return new ModelAndView(new JsonView()); + } + if (result instanceof String) { + return new ModelAndView(result); + } + throw new HandlerException("해당 핸들러의 반환타입이 올바르지 않습니다."); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerKey.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerKey.java similarity index 72% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerKey.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerKey.java index 30d3c780ff..7439edf401 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerKey.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerKey.java @@ -1,8 +1,7 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; - -import web.org.springframework.web.bind.annotation.RequestMethod; +package webmvc.org.springframework.web.servlet.mvc.handler; import java.util.Objects; +import web.org.springframework.web.bind.annotation.RequestMethod; public class HandlerKey { @@ -23,10 +22,14 @@ public String toString() { } @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof HandlerKey)) return false; - HandlerKey that = (HandlerKey) o; + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof HandlerKey)) { + return false; + } + final HandlerKey that = (HandlerKey) o; return Objects.equals(url, that.url) && requestMethod == that.requestMethod; } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMapping.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMapping.java new file mode 100644 index 0000000000..1bb184acfd --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMapping.java @@ -0,0 +1,11 @@ +package webmvc.org.springframework.web.servlet.mvc.handler; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.Optional; + +public interface HandlerMapping { + + void initialize(); + + Optional getHandler(HttpServletRequest request); +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMappingException.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMappingException.java similarity index 72% rename from mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMappingException.java rename to mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMappingException.java index 896dad5f4c..85b7215813 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMappingException.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMappingException.java @@ -1,4 +1,4 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; +package webmvc.org.springframework.web.servlet.mvc.handler; public class HandlerMappingException extends RuntimeException { diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMappings.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMappings.java new file mode 100644 index 0000000000..9f7edb40db --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/handler/HandlerMappings.java @@ -0,0 +1,28 @@ +package webmvc.org.springframework.web.servlet.mvc.handler; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class HandlerMappings { + + private final List handlerMappings; + + public HandlerMappings(final List handlerMappings) { + this.handlerMappings = new ArrayList<>(handlerMappings); + } + + public void initialize() { + handlerMappings.forEach(HandlerMapping::initialize); + } + + public Object getHandler(final HttpServletRequest request) { + return handlerMappings.stream() + .map(handlerMapping -> handlerMapping.getHandler(request)) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst() + .orElseThrow(() -> new HandlerMappingException("해당 요청에 대한 핸들러가 없습니다.")); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java deleted file mode 100644 index 52ce9aba7d..0000000000 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java +++ /dev/null @@ -1,21 +0,0 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.lang.reflect.Method; -import webmvc.org.springframework.web.servlet.ModelAndView; - -public class HandlerExecution { - - private final Object handler; - private final Method method; - - public HandlerExecution(final Object handler, final Method method) { - this.handler = handler; - this.method = method; - } - - public ModelAndView handle(final HttpServletRequest request, final HttpServletResponse response) throws Exception { - return (ModelAndView) method.invoke(handler, request, response); - } -} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMapping.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMapping.java deleted file mode 100644 index 2fd9df144a..0000000000 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMapping.java +++ /dev/null @@ -1,10 +0,0 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; - -import jakarta.servlet.http.HttpServletRequest; - -public interface HandlerMapping { - - void initialize(); - - Object getHandler(HttpServletRequest request); -} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapter.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapter.java deleted file mode 100644 index 2f968bccc0..0000000000 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapter.java +++ /dev/null @@ -1,24 +0,0 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.ModelAndView; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; -import webmvc.org.springframework.web.servlet.view.JspView; - -public class ManualHandlerAdapter implements HandlerAdapter { - - @Override - public boolean supports(final Object handler) { - return handler instanceof Controller; - } - - @Override - public ModelAndView handle(final Object handler, - final HttpServletRequest request, - final HttpServletResponse response) throws Exception { - final Controller controller = (Controller) handler; - final String viewName = controller.execute(request, response); - return new ModelAndView(new JspView(viewName)); - } -} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/JsonViewResolver.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/JsonViewResolver.java new file mode 100644 index 0000000000..bfce519139 --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/JsonViewResolver.java @@ -0,0 +1,17 @@ +package webmvc.org.springframework.web.servlet.mvc.viewresolver; + +import webmvc.org.springframework.web.servlet.View; +import webmvc.org.springframework.web.servlet.view.JsonView; + +public class JsonViewResolver implements ViewResolver { + + @Override + public boolean supports(final Object view) { + return view == null || view instanceof JsonView; + } + + @Override + public View resolve(final Object view) { + return new JsonView(); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/JspViewResolver.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/JspViewResolver.java new file mode 100644 index 0000000000..bcdc5ecc09 --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/JspViewResolver.java @@ -0,0 +1,22 @@ +package webmvc.org.springframework.web.servlet.mvc.viewresolver; + +import webmvc.org.springframework.web.servlet.View; +import webmvc.org.springframework.web.servlet.view.JspView; + +public class JspViewResolver implements ViewResolver { + + private static final String JSP_SUFFIX = ".jsp"; + + @Override + public boolean supports(final Object view) { + if (view instanceof String) { + return ((String) view).endsWith(JSP_SUFFIX); + } + return false; + } + + @Override + public View resolve(final Object view) { + return new JspView((String) view); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolver.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolver.java new file mode 100644 index 0000000000..2aae82a68f --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolver.java @@ -0,0 +1,10 @@ +package webmvc.org.springframework.web.servlet.mvc.viewresolver; + +import webmvc.org.springframework.web.servlet.View; + +public interface ViewResolver { + + boolean supports(Object view); + + View resolve(Object view); +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolverException.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolverException.java new file mode 100644 index 0000000000..1a7d1426b2 --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolverException.java @@ -0,0 +1,8 @@ +package webmvc.org.springframework.web.servlet.mvc.viewresolver; + +public class ViewResolverException extends RuntimeException { + + public ViewResolverException(final String message) { + super(message); + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolvers.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolvers.java new file mode 100644 index 0000000000..5ba5f83a6c --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/viewresolver/ViewResolvers.java @@ -0,0 +1,24 @@ +package webmvc.org.springframework.web.servlet.mvc.viewresolver; + +import java.util.ArrayList; +import java.util.List; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.View; + +public class ViewResolvers { + + private final List viewResolvers; + + public ViewResolvers(final List viewResolvers) { + this.viewResolvers = new ArrayList<>(viewResolvers); + } + + public View getView(final ModelAndView modelAndView) { + final Object view = modelAndView.getView(); + return viewResolvers.stream() + .filter(viewResolver -> viewResolver.supports(view)) + .findFirst() + .map(viewResolver -> viewResolver.resolve(view)) + .orElseThrow(() -> new ViewResolverException("해당 요청에 대한 view를 처리할 수 없습니다.")); + } +} 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..01c4cbc5d6 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/view/JsonView.java @@ -1,14 +1,31 @@ package webmvc.org.springframework.web.servlet.view; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.View; - +import java.io.PrintWriter; import java.util.Map; +import web.org.springframework.http.MediaType; +import webmvc.org.springframework.web.servlet.View; public class JsonView implements View { + private final ObjectMapper mapper = new ObjectMapper(); + @Override - public void render(final Map model, final HttpServletRequest request, HttpServletResponse response) throws Exception { + public void render(final Map model, final HttpServletRequest request, final HttpServletResponse response) + throws Exception { + response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); + final PrintWriter writer = response.getWriter(); + final String jsonResponse = jsonToString(model); + writer.write(jsonResponse); + } + + private String jsonToString(final Map model) throws JsonProcessingException { + if (model.size() == 1) { + return mapper.writeValueAsString(model.values().toArray()[0]); + } + return mapper.writeValueAsString(model); } } diff --git a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapterTest.java b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapterTest.java index 1806c63e84..b6e9a2eeaf 100644 --- a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapterTest.java +++ b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerAdapterTest.java @@ -7,9 +7,13 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.lang.reflect.Method; +import java.util.Optional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.mvc.adapter.AnnotationHandlerAdapter; +import webmvc.org.springframework.web.servlet.mvc.handler.HandlerExecution; +import webmvc.org.springframework.web.servlet.mvc.handler.HandlerMapping; import webmvc.org.springframework.web.servlet.view.JspView; class AnnotationHandlerAdapterTest { @@ -56,7 +60,7 @@ void setUp() { HttpServletResponse.class); final HandlerExecution handler = new HandlerExecution(getClass().getDeclaredConstructor().newInstance(), handlerMethod); - when(handlerMapping.getHandler(request)).thenReturn(handler); + when(handlerMapping.getHandler(request)).thenReturn(Optional.of(handler)); // when final ModelAndView modelAndView = handlerAdapter.handle(handler, request, response); diff --git a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMappingTest.java b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMappingTest.java index dcec215a3f..1cc03355c2 100644 --- a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMappingTest.java +++ b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMappingTest.java @@ -1,13 +1,15 @@ package webmvc.org.springframework.web.servlet.mvc.tobe; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import webmvc.org.springframework.web.servlet.mvc.handler.AnnotationHandlerMapping; +import webmvc.org.springframework.web.servlet.mvc.handler.HandlerExecution; class AnnotationHandlerMappingTest { @@ -28,7 +30,7 @@ void get() throws Exception { when(request.getRequestURI()).thenReturn("/get-test"); when(request.getMethod()).thenReturn("GET"); - final var handlerExecution = (HandlerExecution) handlerMapping.getHandler(request); + final var handlerExecution = (HandlerExecution) handlerMapping.getHandler(request).get(); final var modelAndView = handlerExecution.handle(request, response); assertThat(modelAndView.getObject("id")).isEqualTo("gugu"); @@ -43,7 +45,7 @@ void post() throws Exception { when(request.getRequestURI()).thenReturn("/post-test"); when(request.getMethod()).thenReturn("POST"); - final var handlerExecution = (HandlerExecution) handlerMapping.getHandler(request); + final var handlerExecution = (HandlerExecution) handlerMapping.getHandler(request).get(); final var modelAndView = handlerExecution.handle(request, response); assertThat(modelAndView.getObject("id")).isEqualTo("gugu"); diff --git a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapterTest.java b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapterTest.java deleted file mode 100644 index 53d2b4b7df..0000000000 --- a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/ManualHandlerAdapterTest.java +++ /dev/null @@ -1,72 +0,0 @@ -package webmvc.org.springframework.web.servlet.mvc.tobe; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import webmvc.org.springframework.web.servlet.ModelAndView; -import webmvc.org.springframework.web.servlet.mvc.asis.Controller; -import webmvc.org.springframework.web.servlet.view.JspView; - -class ManualHandlerAdapterTest { - - private ManualHandlerAdapter handlerAdapter; - - @BeforeEach - void setUp() { - handlerAdapter = new ManualHandlerAdapter(); - } - - @Test - void 핸들러가_Controller_타입이면_true를_반환한다() { - // given - final Controller controller = mock(Controller.class); - - // when - final boolean result = handlerAdapter.supports(controller); - - // thend - assertThat(result).isTrue(); - } - - @Test - void 핸들러가_Controller_타입이_아니면_false를_반환한다() { - // given - final String controller = "Controller"; - - // when - final boolean result = handlerAdapter.supports(controller); - - // then - assertThat(result).isFalse(); - } - - @Test - void 인자로_들어온_핸들러의_메소드를_어댑터를_통해_실행한다() throws Exception { - // given - final var request = mock(HttpServletRequest.class); - final var response = mock(HttpServletResponse.class); - final var handlerMapping = mock(HandlerMapping.class); - - final TestController handler = new TestController(); - when(handlerMapping.getHandler(request)).thenReturn(handler); - - // when - final ModelAndView modelAndView = handlerAdapter.handle(handler, request, response); - - // then - assertThat(modelAndView.getView().getClass()).isEqualTo(JspView.class); - } - - static class TestController implements Controller { - - @Override - public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { - return "test.jsp"; - } - } -}