diff --git a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java index ff88a1d087..3a5c996de1 100644 --- a/app/src/main/java/com/techcourse/DispatcherServletInitializer.java +++ b/app/src/main/java/com/techcourse/DispatcherServletInitializer.java @@ -3,6 +3,7 @@ import jakarta.servlet.ServletContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import web.org.springframework.web.DispatcherServlet; import web.org.springframework.web.WebApplicationInitializer; import webmvc.org.springframework.web.servlet.mvc.asis.CustomControllerAdapter; import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationHandlerMapper; @@ -21,7 +22,6 @@ public class DispatcherServletInitializer implements WebApplicationInitializer { @Override public void onStartup(final ServletContext servletContext) { final var dispatcherServlet = new DispatcherServlet(); - dispatcherServlet.addHandlerMapping(new LegacyHandlerMapper()); dispatcherServlet.addHandlerMapping(new AnnotationHandlerMapper("com")); dispatcherServlet.addHandlerAdapter(new CustomControllerAdapter()); dispatcherServlet.addHandlerAdapter(new HandlerExecutionHandlerAdapter()); diff --git a/app/src/main/java/com/techcourse/LegacyHandlerMapper.java b/app/src/main/java/com/techcourse/LegacyHandlerMapper.java deleted file mode 100644 index 0e1eb74522..0000000000 --- a/app/src/main/java/com/techcourse/LegacyHandlerMapper.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.techcourse; - -import com.techcourse.controller.lagacy.*; -import jakarta.servlet.http.HttpServletRequest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import webmvc.org.springframework.web.servlet.mvc.HandlerMapper; -import webmvc.org.springframework.web.servlet.mvc.asis.CustomController; -import webmvc.org.springframework.web.servlet.mvc.asis.ForwardController; - -import java.util.HashMap; -import java.util.Map; - -public class LegacyHandlerMapper implements HandlerMapper { - - private static final Logger log = LoggerFactory.getLogger(LegacyHandlerMapper.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())); - } - - public CustomController getHandler(final HttpServletRequest request) { - String requestURI = request.getRequestURI(); - log.debug("Request Mapping URI : {}", requestURI); - return controllers.get(requestURI); - } -} diff --git a/app/src/main/java/com/techcourse/controller/lagacy/LoginController.java b/app/src/main/java/com/techcourse/controller/lagacy/LoginController.java deleted file mode 100644 index d55eb2dde6..0000000000 --- a/app/src/main/java/com/techcourse/controller/lagacy/LoginController.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.techcourse.controller.lagacy; - -import com.techcourse.domain.User; -import com.techcourse.repository.InMemoryUserRepository; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import webmvc.org.springframework.web.servlet.ModelAndView; -import webmvc.org.springframework.web.servlet.mvc.asis.CustomController; -import webmvc.org.springframework.web.servlet.view.JspView; - -public class LoginController implements CustomController { - - private static final Logger log = LoggerFactory.getLogger(LoginController.class); - - public ModelAndView login(HttpServletRequest req, HttpServletResponse res) throws Exception { - return new ModelAndView(new JspView(execute(req, res))); - } - - @Override - public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { - if (UserSession.isLoggedIn(req.getSession())) { - return "redirect:/index.jsp"; - } - - return InMemoryUserRepository.findByAccount(req.getParameter("account")) - .map(user -> { - log.info("User : {}", user); - return login(req, user); - }) - .orElse("redirect:/401.jsp"); - } - - 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 "redirect:/index.jsp"; - } - return "redirect:/401.jsp"; - } - -} diff --git a/app/src/main/java/com/techcourse/controller/lagacy/LoginViewController.java b/app/src/main/java/com/techcourse/controller/lagacy/LoginViewController.java deleted file mode 100644 index 0ddbeaf5cb..0000000000 --- a/app/src/main/java/com/techcourse/controller/lagacy/LoginViewController.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.techcourse.controller.lagacy; - -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.CustomController; - -public class LoginViewController implements CustomController { - - private static final Logger log = LoggerFactory.getLogger(LoginViewController.class); - - @Override - public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { - return UserSession.getUserFrom(req.getSession()) - .map(user -> { - log.info("logged in {}", user.getAccount()); - return "redirect:/index.jsp"; - }) - .orElse("/login.jsp"); - } -} diff --git a/app/src/main/java/com/techcourse/controller/lagacy/LogoutController.java b/app/src/main/java/com/techcourse/controller/lagacy/LogoutController.java deleted file mode 100644 index cd4012c643..0000000000 --- a/app/src/main/java/com/techcourse/controller/lagacy/LogoutController.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.techcourse.controller.lagacy; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.CustomController; - -public class LogoutController implements CustomController { - - @Override - public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { - final var session = req.getSession(); - session.removeAttribute(UserSession.SESSION_KEY); - return "redirect:/"; - } -} diff --git a/app/src/main/java/com/techcourse/controller/lagacy/RegisterController.java b/app/src/main/java/com/techcourse/controller/lagacy/RegisterController.java deleted file mode 100644 index 03683ed67a..0000000000 --- a/app/src/main/java/com/techcourse/controller/lagacy/RegisterController.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.techcourse.controller.lagacy; - -import com.techcourse.domain.User; -import com.techcourse.repository.InMemoryUserRepository; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.CustomController; - -public class RegisterController implements CustomController { - - @Override - public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { - final var user = new User(2, - req.getParameter("account"), - req.getParameter("password"), - req.getParameter("email")); - InMemoryUserRepository.save(user); - - return "redirect:/index.jsp"; - } -} diff --git a/app/src/main/java/com/techcourse/controller/lagacy/RegisterViewController.java b/app/src/main/java/com/techcourse/controller/lagacy/RegisterViewController.java deleted file mode 100644 index 9f7719b714..0000000000 --- a/app/src/main/java/com/techcourse/controller/lagacy/RegisterViewController.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.techcourse.controller.lagacy; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import webmvc.org.springframework.web.servlet.mvc.asis.CustomController; - -public class RegisterViewController implements CustomController { - - @Override - public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { - return "/register.jsp"; - } -} diff --git a/app/src/main/java/com/techcourse/controller/lagacy/UserSession.java b/app/src/main/java/com/techcourse/controller/lagacy/UserSession.java deleted file mode 100644 index bd7fdf007d..0000000000 --- a/app/src/main/java/com/techcourse/controller/lagacy/UserSession.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.techcourse.controller.lagacy; - -import com.techcourse.domain.User; -import jakarta.servlet.http.HttpSession; - -import java.util.Optional; - -public class UserSession { - - public static final String SESSION_KEY = "user"; - - public static Optional getUserFrom(final HttpSession session) { - final var user = (User) session.getAttribute(SESSION_KEY); - return Optional.ofNullable(user); - } - - public static boolean isLoggedIn(final HttpSession session) { - return getUserFrom(session).isPresent(); - } - - private UserSession() {} -} diff --git a/app/src/main/java/com/techcourse/controller/mvc/MvcUserController.java b/app/src/main/java/com/techcourse/controller/mvc/MvcUserController.java new file mode 100644 index 0000000000..ded882d8f9 --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/mvc/MvcUserController.java @@ -0,0 +1,34 @@ +package com.techcourse.controller.mvc; + +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; + +import java.util.NoSuchElementException; + +@Controller +public class MvcUserController { + + private static final Logger log = LoggerFactory.getLogger(MvcUserController.class); + + @RequestMapping(value = "/api/user", method = RequestMethod.GET) + public ModelAndView show(HttpServletRequest request, HttpServletResponse response) { + String account = request.getParameter("account"); + log.debug("user id : {}", account); + User user = InMemoryUserRepository.findByAccount(account) + .orElseThrow(() -> new NoSuchElementException("user not found!")); + + ModelAndView modelAndView = new ModelAndView(new JsonView()); + modelAndView.addObject("user", user); + return modelAndView; + } + +} diff --git a/app/src/main/java/com/techcourse/DispatcherServlet.java b/mvc/src/main/java/web/org/springframework/web/DispatcherServlet.java similarity index 92% rename from app/src/main/java/com/techcourse/DispatcherServlet.java rename to mvc/src/main/java/web/org/springframework/web/DispatcherServlet.java index 131879d614..69722a1d28 100644 --- a/app/src/main/java/com/techcourse/DispatcherServlet.java +++ b/mvc/src/main/java/web/org/springframework/web/DispatcherServlet.java @@ -1,17 +1,17 @@ -package com.techcourse; +package web.org.springframework.web; -import com.techcourse.support.handler.HandlerAdapters; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import web.org.springframework.web.support.handler.HandlerAdapters; +import web.org.springframework.web.support.handler.HandlerMappers; import webmvc.org.springframework.web.servlet.ModelAndView; import webmvc.org.springframework.web.servlet.View; import webmvc.org.springframework.web.servlet.mvc.HandlerAdapter; import webmvc.org.springframework.web.servlet.mvc.HandlerMapper; -import com.techcourse.support.handler.HandlerMappers; public class DispatcherServlet extends HttpServlet { @@ -34,6 +34,7 @@ protected void service(final HttpServletRequest request, final HttpServletRespon final String requestURI = request.getRequestURI(); log.debug("Method : {}, Request URI : {}", request.getMethod(), requestURI); final Object handler = handlerMappers.getHandler(request); + final HandlerAdapter handlerAdapter = handlerAdapters.getHandlerAdapter(handler); try { diff --git a/app/src/main/java/com/techcourse/support/handler/HandlerAdapters.java b/mvc/src/main/java/web/org/springframework/web/support/handler/HandlerAdapters.java similarity index 92% rename from app/src/main/java/com/techcourse/support/handler/HandlerAdapters.java rename to mvc/src/main/java/web/org/springframework/web/support/handler/HandlerAdapters.java index 9b89be9d06..2c55c5de09 100644 --- a/app/src/main/java/com/techcourse/support/handler/HandlerAdapters.java +++ b/mvc/src/main/java/web/org/springframework/web/support/handler/HandlerAdapters.java @@ -1,4 +1,4 @@ -package com.techcourse.support.handler; +package web.org.springframework.web.support.handler; import webmvc.org.springframework.web.servlet.mvc.HandlerAdapter; diff --git a/app/src/main/java/com/techcourse/support/handler/HandlerMappers.java b/mvc/src/main/java/web/org/springframework/web/support/handler/HandlerMappers.java similarity index 92% rename from app/src/main/java/com/techcourse/support/handler/HandlerMappers.java rename to mvc/src/main/java/web/org/springframework/web/support/handler/HandlerMappers.java index e5ecb6c860..39d46c09bd 100644 --- a/app/src/main/java/com/techcourse/support/handler/HandlerMappers.java +++ b/mvc/src/main/java/web/org/springframework/web/support/handler/HandlerMappers.java @@ -1,11 +1,10 @@ -package com.techcourse.support.handler; +package web.org.springframework.web.support.handler; import jakarta.servlet.http.HttpServletRequest; import webmvc.org.springframework.web.servlet.mvc.HandlerMapper; import java.util.ArrayList; import java.util.List; -import java.util.Objects; public class HandlerMappers { diff --git a/app/src/main/java/com/techcourse/support/web/filter/CharacterEncodingFilter.java b/mvc/src/main/java/web/org/springframework/web/support/web/filter/CharacterEncodingFilter.java similarity index 92% rename from app/src/main/java/com/techcourse/support/web/filter/CharacterEncodingFilter.java rename to mvc/src/main/java/web/org/springframework/web/support/web/filter/CharacterEncodingFilter.java index 290fc83b7d..a089451b85 100644 --- a/app/src/main/java/com/techcourse/support/web/filter/CharacterEncodingFilter.java +++ b/mvc/src/main/java/web/org/springframework/web/support/web/filter/CharacterEncodingFilter.java @@ -1,4 +1,4 @@ -package com.techcourse.support.web.filter; +package web.org.springframework.web.support.web.filter; import jakarta.servlet.*; import jakarta.servlet.annotation.WebFilter; diff --git a/app/src/main/java/com/techcourse/support/web/filter/ResourceFilter.java b/mvc/src/main/java/web/org/springframework/web/support/web/filter/ResourceFilter.java similarity index 96% rename from app/src/main/java/com/techcourse/support/web/filter/ResourceFilter.java rename to mvc/src/main/java/web/org/springframework/web/support/web/filter/ResourceFilter.java index ddbddd671c..f7506f29bb 100644 --- a/app/src/main/java/com/techcourse/support/web/filter/ResourceFilter.java +++ b/mvc/src/main/java/web/org/springframework/web/support/web/filter/ResourceFilter.java @@ -1,4 +1,4 @@ -package com.techcourse.support.web.filter; +package web.org.springframework.web.support.web.filter; import jakarta.servlet.*; import jakarta.servlet.annotation.WebFilter; 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 18bfba3b56..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 CustomController { - - 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/AnnotationHandlerMapper.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapper.java index 6c182e0ba2..67b46a50e5 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapper.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapper.java @@ -2,12 +2,6 @@ import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; import org.reflections.Reflections; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,7 +9,11 @@ import web.org.springframework.web.bind.annotation.RequestMethod; import webmvc.org.springframework.web.servlet.mvc.HandlerMapper; +import java.lang.reflect.Method; +import java.util.*; + import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toSet; public class AnnotationHandlerMapper implements HandlerMapper { @@ -31,50 +29,60 @@ public AnnotationHandlerMapper(final Object... basePackage) { @Override public void initialize() { - final Reflections reflections = new Reflections(basePackage); - final Set> controllers = reflections.getTypesAnnotatedWith(Controller.class); - - controllers.forEach(controller -> { - Object handler = createHandlerByConstructor(controller); - Arrays.stream(controller.getDeclaredMethods()) - .filter(method -> method.isAnnotationPresent(RequestMapping.class)) - .forEach(method -> parseMethod(handler, method)); - }); + Reflections reflections = new Reflections(basePackage); + Set> classes = reflections.getTypesAnnotatedWith(Controller.class); + for (Class clazz : classes) { + initializeHandler(clazz); + } log.info("Initialized AnnotationHandlerMapping!"); + handlerExecutions.keySet() + .forEach(handlerKey -> log.info("Handler Key: {}", handlerKey)); } - private void parseMethod(Object handler, Method method) { - final RequestMapping annotation = method.getAnnotation(RequestMapping.class); - final RequestMethod[] httpMethods = annotation.method(); - final String path = annotation.value(); - addHandlerExecution(handler, method, httpMethods, path); - } - - private void addHandlerExecution(Object handler, Method method, RequestMethod[] httpMethods, String path) { - final List handlerKeys = Arrays.stream(httpMethods) - .map(httpMethod -> new HandlerKey(path, httpMethod)) - .collect(toList()); - final HandlerExecution handlerExecution = new HandlerExecution(handler, method); - for (HandlerKey handlerKey : handlerKeys) { - handlerExecutions.put(handlerKey, handlerExecution); + private void initializeHandler(Class clazz) { + Object instance = toInstance(clazz); + Set methods = getAnnotatedMethod(clazz); + for (Method method : methods) { + RequestMapping annotation = method.getAnnotation(RequestMapping.class); + List handlerKeys = getHandlerKeys(annotation); + HandlerExecution handlerExecution = new HandlerExecution(instance, method); + putHandlerExecution(handlerKeys, handlerExecution); } } - private static Object createHandlerByConstructor(Class controller) { + private Object toInstance(Class clazz) { try { - Object handler = controller.getConstructor().newInstance(); - return handler; + return clazz.getConstructor().newInstance(); } catch (Exception e) { - throw new IllegalArgumentException("해당 컨트롤러의 생성자로 객체를 생성할 수 없습니다." + controller.getSimpleName() + "의 생성자를 다시 확인해주세요."); + throw new IllegalArgumentException(e); } } - @Override - public Object getHandler(final HttpServletRequest request) { - final String requestURI = request.getRequestURI(); - final RequestMethod requestMethod = RequestMethod.valueOf(request.getMethod()); - final HandlerKey handlerKey = new HandlerKey(requestURI, requestMethod); - return handlerExecutions.get(handlerKey); + private Set getAnnotatedMethod(Class clazz) { + Method[] methods = clazz.getDeclaredMethods(); + return Arrays.stream(methods) + .filter(method -> method.isAnnotationPresent(RequestMapping.class)) + .collect(toSet()); } + private List getHandlerKeys(RequestMapping annotation) { + String url = annotation.value(); + RequestMethod[] httpMethods = annotation.method(); + return Arrays.stream(httpMethods) + .map(httpMethod -> new HandlerKey(url, httpMethod)) + .collect(toList()); + } + + private void putHandlerExecution(List handlerKeys, HandlerExecution handlerExecution) { + for (HandlerKey handlerKey : handlerKeys) { + handlerExecutions.put(handlerKey, handlerExecution); + } + } + + @Override + public Object getHandler(HttpServletRequest request) { + String requestURI = request.getRequestURI(); + RequestMethod requestMethod = RequestMethod.valueOf(request.getMethod()); + return handlerExecutions.get(new HandlerKey(requestURI, requestMethod)); + } } 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 8e813645c8..c2cc80b036 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 @@ -2,9 +2,10 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import java.lang.reflect.Method; import webmvc.org.springframework.web.servlet.ModelAndView; +import java.lang.reflect.Method; + public class HandlerExecution { private final Object handler; 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..6b362add6c 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 web.org.springframework.http.MediaType; import webmvc.org.springframework.web.servlet.View; +import java.io.PrintWriter; import java.util.Map; public class JsonView implements View { + private static 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 { + response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); + String value; + if (model.size() == 1) { + value = String.valueOf(model.values().toArray()[0]); + } else { + value = objectMapper.writeValueAsString(model); + } + PrintWriter writer = response.getWriter(); + writer.write(value); } }