Skip to content

Commit

Permalink
[MVC 구현하기 - 3단계] 페드로(류형욱) 미션 제출합니다. (#804)
Browse files Browse the repository at this point in the history
* feat(JsonView): JSON으로 응답할 수 있는 JsonView 구현

* test(JsonViewTest): 단일 엔트리, 다중 엔트리, 직렬화 예외 테스트 케이스 추가

* feat(UserController): JSON을 응답하는 컨트롤러 구현

* refactor: app 모듈에 있는 모든 컨트롤러를 어노테이션 기반 MVC로 변경

* refactor(DispatcherServlet): 패키지 위치 변경

* refactor(HandlerMapping): HandlerMapping의 지연 초기화 제거

* refactor: tobe 패키지 이름 변경

* test: DI 학습 테스트 완료

* fix(ClassPathScanner): 스트림 생성 대상 오류 수정

* style(LoginController): 메서드 인자에서 final 키워드 제거

* refactor(DispatcherServlet): 컨트롤러 스캔 basePackage를 생성자가 아닌 `ServletContext`를 통해 전달받도록 변경

* refactor(DispatcherServletInitializer): 현재 패키지 경로를 동적으로 계산하도록 변경
  • Loading branch information
hw0603 authored Oct 1, 2024
1 parent f450148 commit 16c69f6
Show file tree
Hide file tree
Showing 36 changed files with 364 additions and 171 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.techcourse;

import com.interface21.web.WebApplicationInitializer;
import com.interface21.webmvc.servlet.mvc.DispatcherServlet;
import jakarta.servlet.ServletContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -12,13 +13,14 @@
public class DispatcherServletInitializer implements WebApplicationInitializer {

private static final Logger log = LoggerFactory.getLogger(DispatcherServletInitializer.class);

private static final String DEFAULT_SERVLET_NAME = "dispatcher";
private static final String CONTROLLER_SCAN_BASE = "controller";

@Override
public void onStartup(final ServletContext servletContext) {
final var dispatcherServlet = new DispatcherServlet();
dispatcherServlet.addHandlerMapping(new ManualHandlerMapping());
public void onStartup(ServletContext servletContext) {
String currentPackage = getClass().getPackageName();
servletContext.setAttribute("basePackage", String.join(".", currentPackage, CONTROLLER_SCAN_BASE));
final var dispatcherServlet = new DispatcherServlet(servletContext);

final var registration = servletContext.addServlet(DEFAULT_SERVLET_NAME, dispatcherServlet);
if (registration == null) {
Expand Down
38 changes: 0 additions & 38 deletions app/src/main/java/com/techcourse/ManualHandlerMapping.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.techcourse.controller;

import com.interface21.context.stereotype.Controller;
import com.interface21.web.bind.annotation.RequestMapping;
import com.interface21.web.bind.annotation.RequestMethod;
import com.interface21.webmvc.servlet.ModelAndView;
import com.interface21.webmvc.servlet.view.JspView;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@Controller
public class GreetingController {

@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView index(HttpServletRequest req, HttpServletResponse res) {
return new ModelAndView(new JspView("redirect:/index.jsp"));
}
}
29 changes: 19 additions & 10 deletions app/src/main/java/com/techcourse/controller/LoginController.java
Original file line number Diff line number Diff line change
@@ -1,37 +1,46 @@
package com.techcourse.controller;

import com.interface21.context.stereotype.Controller;
import com.interface21.web.bind.annotation.RequestMapping;
import com.interface21.web.bind.annotation.RequestMethod;
import com.interface21.webmvc.servlet.ModelAndView;
import com.interface21.webmvc.servlet.view.JspView;
import com.techcourse.domain.User;
import com.techcourse.repository.InMemoryUserRepository;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import com.interface21.webmvc.servlet.mvc.asis.Controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoginController implements Controller {
@Controller
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.GET)
public ModelAndView show(HttpServletRequest req, HttpServletResponse res) {
return new ModelAndView(new JspView("/login.jsp"));
}

@RequestMapping(value = "/login", method = RequestMethod.POST)
public ModelAndView login(HttpServletRequest req, HttpServletResponse res) {
if (UserSession.isLoggedIn(req.getSession())) {
return "redirect:/index.jsp";
return new ModelAndView(new JspView("redirect:/index.jsp"));
}

return InMemoryUserRepository.findByAccount(req.getParameter("account"))
.map(user -> {
log.info("User : {}", user);
return login(req, user);
})
.orElse("redirect:/401.jsp");
.orElse(new ModelAndView(new JspView("redirect:/401.jsp")));
}

private String login(final HttpServletRequest request, final User user) {
private ModelAndView login(HttpServletRequest request, User user) {
if (user.checkPassword(request.getParameter("password"))) {
final var session = request.getSession();
session.setAttribute(UserSession.SESSION_KEY, user);
return "redirect:/index.jsp";
return new ModelAndView(new JspView("redirect:/index.jsp"));
}
return "redirect:/401.jsp";
return new ModelAndView(new JspView("redirect:/401.jsp"));
}
}

This file was deleted.

15 changes: 10 additions & 5 deletions app/src/main/java/com/techcourse/controller/LogoutController.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package com.techcourse.controller;

import com.interface21.context.stereotype.Controller;
import com.interface21.web.bind.annotation.RequestMapping;
import com.interface21.web.bind.annotation.RequestMethod;
import com.interface21.webmvc.servlet.ModelAndView;
import com.interface21.webmvc.servlet.view.JspView;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import com.interface21.webmvc.servlet.mvc.asis.Controller;

public class LogoutController implements Controller {
@Controller
public class LogoutController {

@Override
public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception {
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public ModelAndView logout(HttpServletRequest req, HttpServletResponse res) throws Exception {
final var session = req.getSession();
session.removeAttribute(UserSession.SESSION_KEY);
return "redirect:/";
return new ModelAndView(new JspView("redirect:/"));
}
}
32 changes: 32 additions & 0 deletions app/src/main/java/com/techcourse/controller/UserController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.techcourse.controller;

import com.interface21.context.stereotype.Controller;
import com.interface21.web.bind.annotation.RequestMapping;
import com.interface21.web.bind.annotation.RequestMethod;
import com.interface21.webmvc.servlet.ModelAndView;
import com.interface21.webmvc.servlet.view.JsonView;
import com.techcourse.domain.User;
import com.techcourse.repository.InMemoryUserRepository;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Controller
public class UserController {

private static final Logger log = LoggerFactory.getLogger(UserController.class);

@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;
}
}
4 changes: 4 additions & 0 deletions app/src/main/java/com/techcourse/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ public String getAccount() {
return account;
}

public String getEmail() {
return email;
}

@Override
public String toString() {
return "User{" +
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/webapp/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

<!-- before login -->
<div class="navbar-nav d-none d-md-inline-block ms-auto me-0 me-md-3 my-2 my-md-0">
<a class="nav-link" href="/login/view" role="button"><i class="fas fa-user fa-fw"></i>&nbsp;로그인</a>
<a class="nav-link" href="/login" role="button"><i class="fas fa-user fa-fw"></i>&nbsp;로그인</a>
</div>
<!-- before login -->

Expand Down
2 changes: 1 addition & 1 deletion app/src/main/webapp/index.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
</div>
<% } else { %>
<div class="navbar-nav d-none d-md-inline-block ms-auto me-0 me-md-3 my-2 my-md-0">
<a class="nav-link" href="/login/view" role="button"><i class="fas fa-user fa-fw"></i>&nbsp;로그인</a>
<a class="nav-link" href="/login" role="button"><i class="fas fa-user fa-fw"></i>&nbsp;로그인</a>
</div>
<% } %>
</nav>
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/webapp/login.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
</form>
</div>
<div class="card-footer text-center py-3">
<div class="small"><a href="/register/view">아이디가 없나요? 회원가입 하러가기</a></div>
<div class="small"><a href="/register">아이디가 없나요? 회원가입 하러가기</a></div>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/webapp/register.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
</form>
</div>
<div class="card-footer text-center py-3">
<div class="small"><a href="/login/view">이미 가입하셨나요? 로그인 하러가기</a></div>
<div class="small"><a href="/login">이미 가입하셨나요? 로그인 하러가기</a></div>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package com.techcourse;
package com.interface21.webmvc.servlet.mvc;

import com.interface21.webmvc.servlet.ModelAndView;
import com.interface21.webmvc.servlet.mvc.HandlerAdapter;
import com.interface21.webmvc.servlet.mvc.HandlerAdapterRegistry;
import com.interface21.webmvc.servlet.mvc.HandlerMapping;
import com.interface21.webmvc.servlet.mvc.HandlerMappingRegistry;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
Expand All @@ -18,12 +15,14 @@ public class DispatcherServlet extends HttpServlet {
@Serial
private static final long serialVersionUID = 1L;
private static final Logger log = LoggerFactory.getLogger(DispatcherServlet.class);
private static final String BASE_PACKAGE_ATTRIB_NAME = "basePackage";

private final HandlerMappingRegistry handlerMappingRegistry;
private final HandlerAdapterRegistry handlerAdapterRegistry;

public DispatcherServlet() {
handlerMappingRegistry = new HandlerMappingRegistry();
public DispatcherServlet(ServletContext context) {
String basePackage = (String) context.getAttribute(BASE_PACKAGE_ATTRIB_NAME);
handlerMappingRegistry = new HandlerMappingRegistry(basePackage);
handlerAdapterRegistry = new HandlerAdapterRegistry();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.interface21.webmvc.servlet.mvc;

import com.interface21.webmvc.servlet.mvc.tobe.ControllerHandlerAdapter;
import com.interface21.webmvc.servlet.mvc.tobe.HandlerExecutionHandlerAdapter;
import com.interface21.webmvc.servlet.mvc.mapping.HandlerExecutionHandlerAdapter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
Expand All @@ -15,7 +14,6 @@ public HandlerAdapterRegistry() {
}

public void initialize() {
handlerAdapters.add(new ControllerHandlerAdapter());
handlerAdapters.add(new HandlerExecutionHandlerAdapter());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

import jakarta.servlet.http.HttpServletRequest;

@FunctionalInterface
public interface HandlerMapping {

void initialize();

Object getHandler(HttpServletRequest request);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.interface21.webmvc.servlet.mvc;

import com.interface21.webmvc.servlet.mvc.tobe.AnnotationHandlerMapping;
import com.interface21.webmvc.servlet.mvc.mapping.AnnotationHandlerMapping;
import jakarta.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -9,17 +9,16 @@

public class HandlerMappingRegistry {

private static final String ANNOTATION_BASED_CONTROLLER_BASE = "com.techcourse.controller";

private final String controllerScanBase;
private final List<HandlerMapping> handlerMappings;

public HandlerMappingRegistry() {
public HandlerMappingRegistry(String basePackage) {
this.controllerScanBase = Objects.requireNonNull(basePackage);
handlerMappings = new ArrayList<>();
}

public void initialize() {
handlerMappings.add(new AnnotationHandlerMapping(ANNOTATION_BASED_CONTROLLER_BASE));
handlerMappings.forEach(HandlerMapping::initialize);
handlerMappings.add(new AnnotationHandlerMapping(controllerScanBase));
}

public void addHandlerMapping(HandlerMapping mapping) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.interface21.webmvc.servlet.mvc.asis;
package com.interface21.webmvc.servlet.mvc.legacy;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@Deprecated(since = "step3", forRemoval = true)
public interface Controller {
String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception;
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.interface21.webmvc.servlet.mvc.tobe;
package com.interface21.webmvc.servlet.mvc.legacy;

import com.interface21.webmvc.servlet.ModelAndView;
import com.interface21.webmvc.servlet.mvc.HandlerAdapter;
import com.interface21.webmvc.servlet.mvc.asis.Controller;
import com.interface21.webmvc.servlet.view.JspView;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@Deprecated(since = "step3", forRemoval = true)
public class ControllerHandlerAdapter implements HandlerAdapter {

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.interface21.webmvc.servlet.mvc.asis;
package com.interface21.webmvc.servlet.mvc.legacy;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.util.Objects;

@Deprecated(since = "step3", forRemoval = true)
public class ForwardController implements Controller {

private final String path;
Expand Down
Loading

0 comments on commit 16c69f6

Please sign in to comment.