Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MVC 구현하기 - 2, 3단계] 다니(이다은) 미션 제출합니다. #85

Merged
merged 22 commits into from
Sep 20, 2021
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,51 @@ public class RegisterController {
}
}
```

<br/>

## 리팩터링
### AnnotationHandlerMapping
- [x] `HandlerScanner` 추가 for 역할/책임 분리
- @Controller 어노테이션이 붙은 클래스를 찾고, 해당 클래스의 인스턴스 생성

### DispatcherServlet
- [x] `HandlerAdapter` 추가 for 다른 Handler 타입
- Request URI에 따라 ManualHandlerMapping -> Controller, AnnoationHandlerMapping -> HandlerExecution 반환

<br/>

## View 구현하기
- [x] JSP를 지원하는 JspView 구현
- [x] REST API를 지원하는 JsonView 구현
- e.g. `UserController`를 추가했을 때, 정상 동작
```java
@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;
}
}
```

- [x] JSON <-> Java Object 변환할 때, Jackson 라이브러리 사용 -> 공식 문서 참고
- [x] JSON으로 응답할 때, Content-Type은 `MediaType.APPLICATION_JSON_UTF8_VALUE`로 반환
- [x] Model에 데이터가 1개면 값을 그대로 반환, 2개 이상이면 값을 JSON으로 변환해서 반환

<br/>

## Legacy MVC 제거하기
- [x] 모든 컨트롤러 -> 어노테이션 기반 컨트롤러 변경
- [x] `asis` 패키지에 있는 레거시 코드를 삭제해도 정상 동작
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void onStartup(ServletContext servletContext) {
final DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.addHandlerMappings(
new ManualHandlerMapping(),
new AnnotationHandlerMapping("com.techcourse")
new AnnotationHandlerMapping("com.techcourse.controller")
);
dispatcherServlet.addHandlerAdapters(
new ManualHandlerAdapter(),
Expand Down
26 changes: 13 additions & 13 deletions app/src/main/java/com/techcourse/ManualHandlerMapping.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package com.techcourse;

import com.techcourse.controller.manual.LoginController;
import com.techcourse.controller.manual.LoginViewController;
import com.techcourse.controller.manual.LogoutController;
import com.techcourse.controller.manual.RegisterController;
import com.techcourse.controller.manual.RegisterViewController;
import com.techcourse.controller.manual.ManualLoginController;
import com.techcourse.controller.manual.ManualLoginViewController;
import com.techcourse.controller.manual.ManualLogoutController;
import com.techcourse.controller.manual.ManualRegisterController;
import com.techcourse.controller.manual.ManualRegisterViewController;
import jakarta.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import nextstep.mvc.controller.asis.Controller;
import nextstep.mvc.controller.asis.ForwardController;
import nextstep.mvc.controller.asis.ManualHomeController;
import nextstep.mvc.handler.mapping.HandlerMapping;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -21,12 +21,12 @@ public class ManualHandlerMapping implements HandlerMapping {

@Override
public void initialize() {
controllers.put("/", new ForwardController("/index.jsp"));
controllers.put("/manual/login", new LoginController());
controllers.put("/manual/login/view", new LoginViewController());
controllers.put("/manual/logout", new LogoutController());
controllers.put("/manual/register/view", new RegisterViewController());
controllers.put("/manual/register", new RegisterController());
controllers.put("/manual", new ManualHomeController("/index.jsp"));
controllers.put("/manual/login", new ManualLoginController());
controllers.put("/manual/login/view", new ManualLoginViewController());
controllers.put("/manual/logout", new ManualLogoutController());
controllers.put("/manual/register/view", new ManualRegisterViewController());
controllers.put("/manual/register", new ManualRegisterController());

LOG.info("Initialize ManualHandlerMapping!");

Expand All @@ -39,7 +39,7 @@ public void initialize() {
public Controller getHandler(HttpServletRequest request) {
final String requestURI = request.getRequestURI();

LOG.debug("Request Mapping Uri : {}", requestURI);
LOG.debug("Request Mapping URI : {}", requestURI);

return controllers.get(requestURI);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.techcourse.controller.annotation;

import static nextstep.web.support.RequestMethod.GET;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import nextstep.mvc.view.JspView;
import nextstep.mvc.view.ModelAndView;
import nextstep.web.annotation.Controller;
import nextstep.web.annotation.RequestMapping;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Controller
public class HomeController {

private static final Logger LOG = LoggerFactory.getLogger(HomeController.class);
private static final String HOME_PATH = "/index";

@RequestMapping(value = "/", method = GET)
public ModelAndView getHome(HttpServletRequest request, HttpServletResponse response) {
LOG.info("Welcome to Home!");

return new ModelAndView(new JspView(HOME_PATH));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,27 @@
import org.slf4j.LoggerFactory;

@Controller
public class AnnotationLoginController {
public class LoginController {

private static final Logger LOG = LoggerFactory.getLogger(AnnotationLoginController.class);
private static final Logger LOG = LoggerFactory.getLogger(LoginController.class);
private static final String REDIRECT_PREFIX = "redirect:";
private static final String HOME_PATH = "/index";
private static final String UNAUTHORIZED_PATH = "/401";

@RequestMapping(value = "/login", method = GET)
public ModelAndView getLogin(HttpServletRequest request, HttpServletResponse response) {
return UserSession.getUserFrom(request.getSession())
.map(user -> {
LOG.info("logged in {}", user.getAccount());
return new ModelAndView(new JspView(HOME_PATH));
LOG.info("Login: {}", user.getAccount());
return new ModelAndView(new JspView(REDIRECT_PREFIX + HOME_PATH));
})
.orElse(new ModelAndView(new JspView(request.getRequestURI())));
}

@RequestMapping(value = "/login", method = POST)
public ModelAndView postLogin(HttpServletRequest request, HttpServletResponse response) {
if (UserSession.isLoggedIn(request.getSession())) {
return new ModelAndView(new JspView(HOME_PATH));
return new ModelAndView(new JspView(REDIRECT_PREFIX + HOME_PATH));
}
return InMemoryUserRepository.findByAccount(request.getParameter("account"))
.map(user -> {
Expand All @@ -51,7 +52,7 @@ private ModelAndView login(HttpServletRequest request, User user) {
final HttpSession session = request.getSession();
session.setAttribute(UserSession.SESSION_KEY, user);

return new ModelAndView(new JspView(HOME_PATH));
return new ModelAndView(new JspView(REDIRECT_PREFIX + HOME_PATH));
}
return new ModelAndView(new JspView(UNAUTHORIZED_PATH));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.techcourse.controller.annotation;

import static nextstep.web.support.RequestMethod.POST;

import com.techcourse.controller.UserSession;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import nextstep.mvc.view.JspView;
import nextstep.mvc.view.ModelAndView;
import nextstep.web.annotation.Controller;
import nextstep.web.annotation.RequestMapping;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Controller
public class LogoutController {

private static final Logger LOG = LoggerFactory.getLogger(LogoutController.class);
private static final String REDIRECT_PREFIX = "redirect:";
private static final String HOME_PATH = "/index";

@RequestMapping(value = "/logout", method = POST)
public ModelAndView postLogout(HttpServletRequest request, HttpServletResponse response) {
HttpSession session = request.getSession();
session.removeAttribute(UserSession.SESSION_KEY);

LOG.info("Logout Success!");

return new ModelAndView(new JspView(REDIRECT_PREFIX + HOME_PATH));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
import org.slf4j.LoggerFactory;

@Controller
public class AnnotationRegisterController {
public class RegisterController {

private static final Logger LOG = LoggerFactory.getLogger(AnnotationRegisterController.class);
private static final Logger LOG = LoggerFactory.getLogger(RegisterController.class);
private static final String REDIRECT_PREFIX = "redirect:";
private static final String HOME_PATH = "/index";

@RequestMapping(value = "/register", method = GET)
Expand All @@ -31,13 +32,15 @@ public ModelAndView postRegister(HttpServletRequest request, HttpServletResponse
LOG.info("Annotation Register Controller - POST Method");

User user = new User(
2L,
null,
request.getParameter("account"),
request.getParameter("password"),
request.getParameter("email")
);
InMemoryUserRepository.save(user);

return new ModelAndView(new JspView(HOME_PATH));
LOG.info("User id: {}, account: {}", user.getId(), user.getAccount());

return new ModelAndView(new JspView(REDIRECT_PREFIX + HOME_PATH));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.techcourse.controller.annotation;

import static nextstep.web.support.RequestMethod.GET;

import com.techcourse.domain.User;
import com.techcourse.exception.NoSuchUserException;
import com.techcourse.repository.InMemoryUserRepository;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import nextstep.mvc.view.JsonView;
import nextstep.mvc.view.ModelAndView;
import nextstep.web.annotation.Controller;
import nextstep.web.annotation.RequestMapping;
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 = GET)
public ModelAndView show(HttpServletRequest request, HttpServletResponse response) {
final String account = request.getParameter("account");

LOG.info("user id: {}", account);

final ModelAndView modelAndView = new ModelAndView(new JsonView());
final User user = InMemoryUserRepository.findByAccount(account)
.orElseThrow(NoSuchUserException::new);

modelAndView.addObject("user", user);

return modelAndView;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoginController implements Controller {
public class ManualLoginController implements Controller {

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

@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoginViewController implements Controller {
public class ManualLoginViewController implements Controller {

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

@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import jakarta.servlet.http.HttpSession;
import nextstep.mvc.controller.asis.Controller;

public class LogoutController implements Controller {
public class ManualLogoutController implements Controller {

@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
import jakarta.servlet.http.HttpServletResponse;
import nextstep.mvc.controller.asis.Controller;

public class RegisterController implements Controller {
public class ManualRegisterController implements Controller {

@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
final User user = new User(
2L,
null,
request.getParameter("account"),
request.getParameter("password"),
request.getParameter("email")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import jakarta.servlet.http.HttpServletResponse;
import nextstep.mvc.controller.asis.Controller;

public class RegisterViewController implements Controller {
public class ManualRegisterViewController implements Controller {

@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
Expand Down
22 changes: 17 additions & 5 deletions app/src/main/java/com/techcourse/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,29 @@ public boolean checkPassword(String password) {
return this.password.equals(password);
}

public Long getId() {
return id;
}

public String getAccount() {
return account;
}

public String getPassword() {
return password;
}

public String getEmail() {
return email;
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", account='" + account + '\'' +
", email='" + email + '\'' +
", password='" + password + '\'' +
'}';
"id=" + id +
", account='" + account + '\'' +
", email='" + email + '\'' +
", password='" + password + '\'' +
'}';
}
}
15 changes: 15 additions & 0 deletions app/src/main/java/com/techcourse/exception/AppException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.techcourse.exception;

public class AppException extends RuntimeException {

private final Integer httpStatus;

public AppException(String message, Integer httpStatus) {
super(message);
this.httpStatus = httpStatus;
}

public Integer getHttpStatus() {
return httpStatus;
}
}
Loading