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 구현하기 - 1단계] 춘식(안예장) 미션 제출합니다. #39

Merged
merged 10 commits into from
Sep 10, 2021
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
# MVC 프레임워크 구현하기
# MVC 프레임워크 구현하기

- [X] Annotation Based MVC Framework 구현
- [X] HTTP 메서드와 URL을 매핑 조건에 포함
- [X] AnnotationHandlerMapping 테스트 통과
- [X] JspView Todo (DispatcherServlet 참고)
- [X] Legacy MVC와 Annotation Based MVC 통합
bimppap marked this conversation as resolved.
Show resolved Hide resolved
17 changes: 14 additions & 3 deletions app/src/main/java/com/techcourse/AppWebApplicationInitializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,32 @@

import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletRegistration;
import nextstep.mvc.DispatcherServlet;
import nextstep.mvc.handleradapter.AnnotationHandlerAdapter;
import nextstep.mvc.handleradapter.ManualHandlerAdapter;
import nextstep.mvc.controller.tobe.AnnotationHandlerMapping;
import nextstep.mvc.servlet.DispatcherServlet;
import nextstep.mvc.servlet.HandlerAdapterRegistry;
import nextstep.mvc.servlet.HandlerMappingRegistry;
import nextstep.web.WebApplicationInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AppWebApplicationInitializer implements WebApplicationInitializer {

private static final Logger log = LoggerFactory.getLogger(AppWebApplicationInitializer.class);
private static final String BASE_PACKAGE = "com.techcourse.controller";

@Override
public void onStartup(ServletContext servletContext) {
final DispatcherServlet dispatcherServlet = new DispatcherServlet();
final DispatcherServlet dispatcherServlet = new DispatcherServlet(
new HandlerMappingRegistry(), new HandlerAdapterRegistry());
dispatcherServlet.addHandlerMapping(new ManualHandlerMapping());
dispatcherServlet.addHandlerMapping(new AnnotationHandlerMapping(BASE_PACKAGE));
dispatcherServlet.addHandlerAdapter(new AnnotationHandlerAdapter());
dispatcherServlet.addHandlerAdapter(new ManualHandlerAdapter());

final ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", dispatcherServlet);
final ServletRegistration.Dynamic dispatcher = servletContext
.addServlet("dispatcher", dispatcherServlet);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");

Expand Down
17 changes: 6 additions & 11 deletions app/src/main/java/com/techcourse/ManualHandlerMapping.java
Original file line number Diff line number Diff line change
@@ -1,33 +1,28 @@
package com.techcourse;

import com.techcourse.controller.*;
import com.techcourse.controller.LogoutController;
import jakarta.servlet.http.HttpServletRequest;
import nextstep.mvc.HandlerMapping;
import java.util.HashMap;
import java.util.Map;
import nextstep.mvc.controller.asis.Controller;
import nextstep.mvc.controller.asis.ForwardController;
import nextstep.mvc.controller.tobe.HandlerMapping;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

public class ManualHandlerMapping implements HandlerMapping {

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

private static final Map<String, Controller> 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()));
controllers.keySet().forEach(
path -> log.info("Path : {}, Controller : {}", path, controllers.get(path).getClass()));
}

@Override
Expand Down
45 changes: 30 additions & 15 deletions app/src/main/java/com/techcourse/controller/LoginController.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,50 @@
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import nextstep.mvc.controller.asis.Controller;
import nextstep.mvc.view.JspView;
import nextstep.mvc.view.ModelAndView;
import nextstep.web.annotation.Controller;
import nextstep.web.annotation.RequestMapping;
import nextstep.web.support.RequestMethod;
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(HttpServletRequest req, HttpServletResponse res) throws Exception {
if (UserSession.isLoggedIn(req.getSession())) {
return "redirect:/index.jsp";
@RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView show(HttpServletRequest request, HttpServletResponse response) {
return UserSession.getUserFrom(request.getSession())
.map(user -> {
log.info("logged in {}", user.getAccount());
return new ModelAndView(new JspView("redirect:/index.jsp"));
})
.orElse(new ModelAndView(new JspView("/login.jsp")));
}
bimppap marked this conversation as resolved.
Show resolved Hide resolved

@RequestMapping(value = "/login", method = RequestMethod.POST)
public ModelAndView login(HttpServletRequest request, HttpServletResponse response) {
if (UserSession.isLoggedIn(request.getSession())) {
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");
return InMemoryUserRepository.findByAccount(request.getParameter("account"))
.map(user -> {
log.info("User : {}", user);
return login(request, user);
})
.orElse(new ModelAndView(new JspView("redirect:/401.jsp")));
}

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

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,31 @@
import com.techcourse.repository.InMemoryUserRepository;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import nextstep.mvc.controller.asis.Controller;
import nextstep.mvc.view.JspView;
import nextstep.mvc.view.ModelAndView;
import nextstep.web.annotation.Controller;
import nextstep.web.annotation.RequestMapping;
import nextstep.web.support.RequestMethod;

public class RegisterController implements Controller {
@Controller
public class RegisterController {

@Override
public String execute(HttpServletRequest req, HttpServletResponse res) throws Exception {
final User user = new User(2,
req.getParameter("account"),
req.getParameter("password"),
req.getParameter("email"));
private static final String REGISTER_VIEW = "/register.jsp";
private static final String REDIRECT_INDEX_VIEW = "redirect:/index.jsp";

@RequestMapping(value = "/register", method = RequestMethod.GET)
public ModelAndView show(HttpServletRequest request, HttpServletResponse response) {
return new ModelAndView(new JspView(REGISTER_VIEW));
}

@RequestMapping(value = "/register", method = RequestMethod.POST)
public ModelAndView save(HttpServletRequest request, HttpServletResponse response) {
final String account = request.getParameter("account");
final String password = request.getParameter("password");
final String email = request.getParameter("email");
User user = new User(account, password, email);
InMemoryUserRepository.save(user);

return "redirect:/index.jsp";
return new ModelAndView(new JspView(REDIRECT_INDEX_VIEW));
}
}

This file was deleted.

16 changes: 14 additions & 2 deletions app/src/main/java/com/techcourse/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@

public class User {

private final long id;
private final Long id;
private final String account;
private final String password;
private final String email;

public User(long id, String account, String password, String email) {
public User(Long id, String account, String password, String email) {
this.id = id;
this.account = account;
this.password = password;
this.email = email;
}

public User(String account, String password, String email) {
this(null, account, password, email);
}

public boolean checkPassword(String password) {
return this.password.equals(password);
}
Expand All @@ -22,6 +26,14 @@ public String getAccount() {
return account;
}

public String getPassword() {
return password;
}

public String getEmail() {
return email;
}

@Override
public String toString() {
return "User{" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@
public class InMemoryUserRepository {

private static final Map<String, User> database = new ConcurrentHashMap<>();
private static Long id = 1L;

static {
final User user = new User(1, "gugu", "password", "[email protected]");
final User user = new User(id, "gugu", "password", "[email protected]");
database.put(user.getAccount(), user);
}

public static void save(User user) {
database.put(user.getAccount(), user);
User saveUser = new User(++id, user.getAccount(), user.getPassword(), user.getEmail());
bimppap marked this conversation as resolved.
Show resolved Hide resolved
database.put(user.getAccount(), saveUser);
}

public static Optional<User> findByAccount(String account) {
Expand Down
2 changes: 1 addition & 1 deletion app/webapp/index.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
</c:when>
<c:otherwise>
<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>
</c:otherwise>
</c:choose>
Expand Down
2 changes: 1 addition & 1 deletion app/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/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
1 change: 1 addition & 0 deletions learning/src/test/java/reflection/Junit3Test.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package reflection;

public class Junit3Test {

public void test1() throws Exception {
System.out.println("Running Test1");
}
Expand Down
18 changes: 16 additions & 2 deletions learning/src/test/java/reflection/Junit3TestRunner.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
package reflection;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.junit.jupiter.api.Test;

class Junit3TestRunner {

@Test
void run() throws Exception {
void run() {
Class<Junit3Test> clazz = Junit3Test.class;
Junit3Test junit3Test = new Junit3Test();
Arrays.stream(clazz.getMethods())
.filter(method -> method.getName().startsWith("test"))
.forEach(method -> invoke(junit3Test, method));
}

// TODO Junit3Test에서 test로 시작하는 메소드 실행
private Object invoke(Junit3Test test, Method method) {
try {
return method.invoke(test);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
16 changes: 15 additions & 1 deletion learning/src/test/java/reflection/Junit4TestRunner.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
package reflection;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.junit.jupiter.api.Test;

class Junit4TestRunner {

@Test
void run() throws Exception {
Class<Junit4Test> clazz = Junit4Test.class;
Junit4Test junit4Test = new Junit4Test();
Arrays.stream(clazz.getMethods())
.filter(method -> method.isAnnotationPresent(MyTest.class))
.forEach(method -> invoke(junit4Test, method));
}

// TODO Junit4Test에서 @MyTest 애노테이션이 있는 메소드 실행
private Object invoke(Junit4Test test, Method method) {
try {
return method.invoke(test);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
1 change: 1 addition & 0 deletions learning/src/test/java/reflection/MyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface MyTest {

}
Loading