Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
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.DispatcherServlet;
import jakarta.servlet.ServletContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -13,12 +14,12 @@ public class DispatcherServletInitializer implements WebApplicationInitializer {

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

private static final String SCANNING_CONTROLLER_PACKAGE = "com.techcourse.controller";
private static final String DEFAULT_SERVLET_NAME = "dispatcher";

@Override
public void onStartup(final ServletContext servletContext) {
final var dispatcherServlet = new DispatcherServlet();
dispatcherServlet.addHandlerMapping(new ManualHandlerMapping());
final var dispatcherServlet = new DispatcherServlet(SCANNING_CONTROLLER_PACKAGE);

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

This file was deleted.

17 changes: 17 additions & 0 deletions app/src/main/java/com/techcourse/controller/HomeController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
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;

@Controller
@RequestMapping
public class HomeController {

@RequestMapping(method = RequestMethod.GET)
public ModelAndView getHome() {
return new ModelAndView(new JspView("/index.jsp"));
}
}
20 changes: 13 additions & 7 deletions app/src/main/java/com/techcourse/controller/LoginController.java
Original file line number Diff line number Diff line change
@@ -1,29 +1,35 @@
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
@RequestMapping("/login")
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(method = RequestMethod.POST)
public ModelAndView postLogin(final HttpServletRequest req) {
if (UserSession.isLoggedIn(req.getSession())) {
return "redirect:/index.jsp";
return new ModelAndView(new JspView("redirect:/index.jsp"));
}

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

private String login(final HttpServletRequest request, final User user) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.interface21.webmvc.servlet.mvc.asis.Controller;

public class LoginViewController implements Controller {
@Controller
@RequestMapping("/login/view")
public class LoginViewController {

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())
@RequestMapping(method = RequestMethod.GET)
public ModelAndView getLoginView(final HttpServletRequest req) throws Exception {
String viewName = UserSession.getUserFrom(req.getSession())
.map(user -> {
log.info("logged in {}", user.getAccount());
return "redirect:/index.jsp";
})
.orElse("/login.jsp");
return new ModelAndView(new JspView(viewName));
}
}
17 changes: 11 additions & 6 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
@RequestMapping("/logout")
public class LogoutController {

@Override
public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception {
@RequestMapping(method = RequestMethod.GET)
public ModelAndView getLogout(final HttpServletRequest req) throws Exception {
final var session = req.getSession();
session.removeAttribute(UserSession.SESSION_KEY);
return "redirect:/";
return new ModelAndView(new JspView("redirect:/"));
}
}
42 changes: 42 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,42 @@
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);
private static final String PARAM_NAME_ACCOUNT = "account";

@RequestMapping(value = "/api/user", method = RequestMethod.GET)
public ModelAndView getUser(HttpServletRequest request, HttpServletResponse response) {
if (!isValidRequest(request)) {
throw new IllegalArgumentException("Please input account as parameter");
}

final String account = request.getParameter(PARAM_NAME_ACCOUNT);
log.debug("user id : {}", account);

final User user = InMemoryUserRepository.findByAccount(account)
.orElseThrow(() -> new IllegalArgumentException("User not found: " + account));

final ModelAndView modelAndView = new ModelAndView(new JsonView());
modelAndView.addObject("user", user);
return modelAndView;
}

private boolean isValidRequest(HttpServletRequest request) {
String account = request.getParameter(PARAM_NAME_ACCOUNT);
return account != null && !account.isBlank();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.techcourse.controller;

import static org.assertj.core.api.Assertions.assertThat;

import com.techcourse.TomcatStarter;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class HomeControllerTest {

private static final String URL = "http://localhost:8080";

private TomcatStarter tomcat;

@BeforeEach
void setUp() {
tomcat = new TomcatStarter("src/main/webapp/", 8080);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 익숙한 Rest assured를 사용했는데 추가 의존성을 사용하지 않고 TomcatStarter와 HttpClient를 사용해주셨네요! 💯 배워갑니다 👍

tomcat.start();
}

@AfterEach
void tearDown() {
tomcat.stop();
}

@Test
@DisplayName("홈 화면을 요청시 대시보드 페이지를 응답한다.")
void getHome() throws Exception {
// given
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(URL))
.build();

// when
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
client.close();

// then
assertThat(response.body()).contains("<title>대시보드</title>");
}
}
104 changes: 104 additions & 0 deletions app/src/test/java/com/techcourse/controller/LoginControllerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package com.techcourse.controller;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;

import com.techcourse.TomcatStarter;
import jakarta.servlet.http.HttpServletResponse;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class LoginControllerTest {

private static final String URL = "http://localhost:8080/login";
private static final String CONTENT_TYPE_URLENCODED = "application/x-www-form-urlencoded";
private static final String CONTENT_TYPE_NAME = "Content-Type";

private TomcatStarter tomcat;

@BeforeEach
void setUp() {
tomcat = new TomcatStarter("src/main/webapp/", 8080);
tomcat.start();
}

@AfterEach
void tearDown() {
tomcat.stop();
}

@Test
@DisplayName("올바른 계정 정보로 로그인 요청 시 대시보드 페이지로 리디렉션을 응답한다.")
void postLogin() throws Exception {
// given
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(URL))
.header(CONTENT_TYPE_NAME, CONTENT_TYPE_URLENCODED)
.POST(BodyPublishers.ofString("account=gugu&password=password"))
.build();

// when
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
client.close();

// then
assertAll(
() -> assertThat(response.headers().firstValue("Location")).hasValue("/index.jsp"),
() -> assertThat(response.statusCode()).isEqualTo(HttpServletResponse.SC_FOUND)
);
}

@Test
@DisplayName("존재하지 않는 계정으로 요청 시 401 페이지로 리디렉션을 응답한다.")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

역시 디테일한 테스트케이스 👍

void getLoginWithNonAccount() throws Exception {
// given
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(URL))
.header(CONTENT_TYPE_NAME, CONTENT_TYPE_URLENCODED)
.POST(BodyPublishers.ofString("account=seyang&password=password"))
.build();

// when
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
client.close();

// then
assertAll(
() -> assertThat(response.headers().firstValue("Location")).hasValue("/401.jsp"),
() -> assertThat(response.statusCode()).isEqualTo(HttpServletResponse.SC_FOUND)
);
}

@Test
@DisplayName("틀린 비밀번호로 요청 시 401 페이지로 리디렉션을 응답한다.")
void getLoginWithInvalidPassword() throws Exception {
// given
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(URL))
.header(CONTENT_TYPE_NAME, CONTENT_TYPE_URLENCODED)
.POST(BodyPublishers.ofString("account=gugu&password=pw"))
.build();

// when
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
response.sslSession();
client.close();

// then
assertAll(
() -> assertThat(response.headers().firstValue("Location")).hasValue("/401.jsp"),
() -> assertThat(response.statusCode()).isEqualTo(HttpServletResponse.SC_FOUND)
);
}
}
Loading