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 구현 - 3단계] 로지(윤가영) 미션 제출합니다. #564

Merged
merged 12 commits into from
Sep 25, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,26 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import web.org.springframework.web.WebApplicationInitializer;
import webmvc.org.springframework.web.servlet.mvc.AnnotationHandlerMapping;
import webmvc.org.springframework.web.servlet.mvc.DispatcherServlet;
import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationHandlerMapping;

/**
* Base class for {@link WebApplicationInitializer} implementations that register a {@link DispatcherServlet} in the
* servlet context.
*/
public class DispatcherServletInitializer implements WebApplicationInitializer {
public class AppInitializer implements WebApplicationInitializer {

Choose a reason for hiding this comment

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

오홍 DispatcherServletInitializer 에서 AppInitializer 으로 이름을 바꾼 이유가 있을까유?!

Copy link
Member Author

Choose a reason for hiding this comment

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

아, 별의미는 없었습니다. 이건 저의 아쉬움이 반영된 변경사항이었어요.
DispatcherServlet이 아니라 App으로 변경하면 app 모듈에 조금 더 직관적이지 않을까? 생각했어요.
애초에 저 이름이 있었어서 계속 mvc 모듈로 옮기려고 집착한 것 같다는 이유도 있습니다.. 하하.


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

private static final String DEFAULT_SERVLET_NAME = "dispatcher";

@Override
public void onStartup(final ServletContext servletContext) {

ManualHandlerMapping manualHandlerMapping = new ManualHandlerMapping();
manualHandlerMapping.initialize();
AnnotationHandlerMapping handlerMapping = new AnnotationHandlerMapping(this.getClass().getPackage().getName());
handlerMapping.initialize();
servletContext.setAttribute("handlerMappings", List.of(handlerMapping, manualHandlerMapping));
final var dispatcherServlet = new DispatcherServlet(servletContext);
servletContext.setAttribute("handlerMappings", List.of(handlerMapping));

final DispatcherServlet dispatcherServlet = new DispatcherServlet(servletContext);
final var registration = servletContext.addServlet(DEFAULT_SERVLET_NAME, dispatcherServlet);
if (registration == null) {
throw new IllegalStateException("Failed to register servlet with name '" + DEFAULT_SERVLET_NAME + "'. " +
Expand Down
50 changes: 0 additions & 50 deletions app/src/main/java/com/techcourse/ManualHandlerMapping.java

This file was deleted.

35 changes: 35 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,35 @@
package com.techcourse.controller;

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 static java.util.Objects.requireNonNull;

@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 = requireNonNull(request.getParameter("account"), "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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@
import com.techcourse.repository.InMemoryUserRepository;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import webmvc.org.springframework.web.servlet.ModelAndView;
import webmvc.org.springframework.web.servlet.view.JspView;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static webmvc.org.springframework.web.servlet.view.JspView.REDIRECT_PREFIX;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.techcourse.controller;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class UserControllerTest {

private UserController userController = new UserController();
@Test
void account가_없으면_예외가_발생한다() {
//given
final HttpServletRequest mockRequest = mock(HttpServletRequest.class);
final HttpServletResponse mockResponse = mock(HttpServletResponse.class);
when(mockRequest.getParameter("account")).thenReturn(null);

//when
//then
assertThatThrownBy(() -> userController.show(mockRequest, mockResponse))
.isInstanceOf(NullPointerException.class)
.hasMessage("account를 입력해주세요.");
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package webmvc.org.springframework.web.servlet;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
Expand All @@ -22,6 +24,14 @@ public ModelAndView addObject(final String attributeName, final Object attribute
return this;
}

public void render(final HttpServletRequest request, final HttpServletResponse response) throws Exception {
if (view.isRedirectView()) {
response.sendRedirect(view.getViewName());
return;
}
view.render(model, request, response);
}

public Object getObject(final String attributeName) {
return model.get(attributeName);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package webmvc.org.springframework.web.servlet.mvc.tobe;
package webmvc.org.springframework.web.servlet.mvc;

import context.org.springframework.stereotype.Controller;
import jakarta.servlet.http.HttpServletRequest;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,13 @@
import org.slf4j.LoggerFactory;
import webmvc.org.springframework.web.servlet.ModelAndView;
import webmvc.org.springframework.web.servlet.View;
import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecution;
import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerMapping;
kyY00n marked this conversation as resolved.
Show resolved Hide resolved

public class DispatcherServlet extends HttpServlet {

private static final long serialVersionUID = 1L;
private static final Logger log = LoggerFactory.getLogger(DispatcherServlet.class);

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

Choose a reason for hiding this comment

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

일...급..컬랙션..?!

Copy link
Member Author

Choose a reason for hiding this comment

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

오오, 잊고있었던 일급컬렉션... 적용해보겠습니다

Copy link
Member Author

Choose a reason for hiding this comment

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

반영했습니다!

Choose a reason for hiding this comment

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

확인했습니다!


public DispatcherServlet(ServletContext servletContext) {
handlerMappings = (List<HandlerMapping>) servletContext.getAttribute("handlerMappings");
Expand All @@ -40,7 +38,7 @@ private void handle(final HttpServletRequest request, final HttpServletResponse
throws Exception {
final HandlerExecution handler = getHandler(request);
final ModelAndView modelAndView = handler.handle(request, response);
render(request, response, modelAndView);
modelAndView.render(request, response);
}

private HandlerExecution getHandler(final HttpServletRequest request) throws ServletException {
Expand All @@ -51,14 +49,4 @@ private HandlerExecution getHandler(final HttpServletRequest request) throws Ser
.orElseThrow(() -> new ServletException("핸들러를 찾을 수 없습니다."));
}

private void render(final HttpServletRequest request, final HttpServletResponse response,
final ModelAndView modelAndView) throws Exception {
final View view = modelAndView.getView();
if (view.isRedirectView()) {
response.sendRedirect(view.getViewName());
return;
}
view.render(modelAndView.getModel(), request, response);
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package webmvc.org.springframework.web.servlet.mvc.tobe;
package webmvc.org.springframework.web.servlet.mvc;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package webmvc.org.springframework.web.servlet.mvc.tobe;
package webmvc.org.springframework.web.servlet.mvc;

import web.org.springframework.web.bind.annotation.RequestMethod;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package webmvc.org.springframework.web.servlet.mvc.tobe;
package webmvc.org.springframework.web.servlet.mvc;

import jakarta.servlet.http.HttpServletRequest;
import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecution;

public interface HandlerMapping {

Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,15 +1,35 @@
package webmvc.org.springframework.web.servlet.view;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import web.org.springframework.http.MediaType;
import webmvc.org.springframework.web.servlet.View;

import java.util.Map;

public class JsonView implements View {

private final ObjectMapper objectMapper = new ObjectMapper();

@Override
public void render(final Map<String, ?> model, final HttpServletRequest request, HttpServletResponse response) throws Exception {
public void render(final Map<String, ?> model, final HttpServletRequest request, HttpServletResponse response)
throws Exception {
final PrintWriter writer = response.getWriter();
final String body = convertString(model);
writer.write(body);
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
}

private String convertString(final Map<String, ?> model) throws JsonProcessingException {
if (model.size() == 1) {
final var value = model.values().toArray()[0];
return objectMapper.writeValueAsString(value);
}
final String body = objectMapper.writeValueAsString(model);
return body;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import jakarta.servlet.http.HttpServletResponse;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import webmvc.org.springframework.web.servlet.mvc.AnnotationHandlerMapping;
import webmvc.org.springframework.web.servlet.mvc.HandlerExecution;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
Expand Down
Loading