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단계] 오리(오현서) 미션 제출합니다. #543

Merged
merged 11 commits into from
Sep 28, 2023
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
package com.techcourse;

import com.techcourse.exception.NotFoundExceptionHandler;
import jakarta.servlet.ServletContext;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import web.org.springframework.web.WebApplicationInitializer;
import webmvc.org.springframework.web.servlet.DispatcherServlet;
import webmvc.org.springframework.web.servlet.mvc.tobe.adapter.AnnotationHandlerAdapter;
import webmvc.org.springframework.web.servlet.mvc.tobe.adapter.HandlerAdapterFinder;
import webmvc.org.springframework.web.servlet.mvc.tobe.exception.ExceptionResolver;
import webmvc.org.springframework.web.servlet.mvc.tobe.handler.AnnotationHandlerMapping;
import webmvc.org.springframework.web.servlet.mvc.tobe.handler.HandlerMapping;

/**
* Base class for {@link WebApplicationInitializer}
Expand All @@ -18,7 +25,7 @@ public class DispatcherServletInitializer implements WebApplicationInitializer {

@Override
public void onStartup(final ServletContext servletContext) {
final var dispatcherServlet = new DispatcherServlet();
final var dispatcherServlet = initDispatcherServlet();

final var registration = servletContext.addServlet(DEFAULT_SERVLET_NAME, dispatcherServlet);
if (registration == null) {
Expand All @@ -31,4 +38,12 @@ public void onStartup(final ServletContext servletContext) {

log.info("Start AppWebApplication Initializer");
}

public DispatcherServlet initDispatcherServlet() {
HandlerMapping handlerMapping = new AnnotationHandlerMapping();
handlerMapping.initialize();
HandlerAdapterFinder handlerAdapterFinder = new HandlerAdapterFinder(List.of(new AnnotationHandlerAdapter()));
ExceptionResolver exceptionResolver = new ExceptionResolver(List.of(new NotFoundExceptionHandler()));
return new DispatcherServlet(handlerMapping, handlerAdapterFinder, exceptionResolver);
}
}
4 changes: 2 additions & 2 deletions app/src/main/java/com/techcourse/TomcatStarter.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.techcourse;

import com.techcourse.exception.UncheckedServletException;
import java.io.File;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.util.scan.StandardJarScanner;

import java.io.File;

public class TomcatStarter {

public static final String WEBAPP_DIR_LOCATION = "app/src/main/webapp/";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.techcourse.exception;

import webmvc.org.springframework.web.servlet.ModelAndView;
import webmvc.org.springframework.web.servlet.mvc.tobe.exception.HandlerNotFoundException;
import webmvc.org.springframework.web.servlet.mvc.tobe.handler.ExceptionHandler;
import webmvc.org.springframework.web.servlet.view.JspView;

public class NotFoundExceptionHandler implements ExceptionHandler {

@Override
public boolean support(Throwable ex) {
return ex instanceof HandlerNotFoundException;
}

@Override
public ModelAndView handle() {
return new ModelAndView(new JspView("/404.jsp"));
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.techcourse;
package com.techcourse.exception;

public class UncheckedServletException extends RuntimeException {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,27 @@
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import webmvc.org.springframework.web.servlet.mvc.tobe.adapter.AnnotationHandlerAdapter;
import webmvc.org.springframework.web.servlet.mvc.tobe.adapter.HandlerAdapter;
import webmvc.org.springframework.web.servlet.mvc.tobe.adapter.HandlerAdapterFinder;
import webmvc.org.springframework.web.servlet.mvc.tobe.exception.ExceptionResolver;
import webmvc.org.springframework.web.servlet.mvc.tobe.handler.AnnotationHandlerMapping;
import webmvc.org.springframework.web.servlet.mvc.tobe.handler.HandlerMapping;

public class DispatcherServlet extends HttpServlet {

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

private HandlerMapping handlerMapping;
private HandlerAdapterFinder handlerAdapterFinder;
private ExceptionResolver exceptionResolver;
private final HandlerMapping handlerMapping;
private final HandlerAdapterFinder handlerAdapterFinder;
private final ExceptionResolver exceptionResolver;

public DispatcherServlet() {
}

@Override
public void init() {
handlerMapping = initHandlerMappings();
handlerAdapterFinder = initHandlerAdapterFinder();
exceptionResolver = new ExceptionResolver();
}

private HandlerMapping initHandlerMappings() {
HandlerMapping handlerMapping = new AnnotationHandlerMapping("com");
handlerMapping.initialize();
return handlerMapping;
}

private HandlerAdapterFinder initHandlerAdapterFinder() {
return new HandlerAdapterFinder(
List.of(new AnnotationHandlerAdapter()));
public DispatcherServlet(HandlerMapping handlerMapping, HandlerAdapterFinder handlerAdapterFinder,
ExceptionResolver exceptionResolver) {
this.handlerMapping = handlerMapping;
this.handlerAdapterFinder = handlerAdapterFinder;
this.exceptionResolver = exceptionResolver;
}

Choose a reason for hiding this comment

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

마땅히 남길만한 곳이 없어서 여기에 남겨요!
이번 단계를 구현하면서 고민했던 부분이 있어서요! 오리가 구현해주신 ExceptionResolver에서 예외처리를 해주기 위해 특정 jsp의 이름이 들어간 JspView를 생성하고 있는데요. 그렇다면 만약 app에 해당 이름을 가진 파일이 없다면 어떻게 되는것인가요? 구현해주신 DispatcherServlet을 사용하기 위해서는 무조건 404.jsp500.jsp를 구현해주는 것을 강제해야 할 것 같네요. 이렇게 되면 조금 빡빡한(?) 구조가 될 것 같아서 고민이네요!

Copy link
Author

@carsago carsago Sep 27, 2023

Choose a reason for hiding this comment

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

이 부분은 생각해보니 좀 마음에 들지 않는 부분이네요.
중간에 interface를 쓰는 방식으로 개선해보았어요.

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

import com.sun.jdi.InternalException;
import java.util.List;
import webmvc.org.springframework.web.servlet.mvc.tobe.exception.HandlerNotFoundException;

public class HandlerAdapterFinder {

Expand All @@ -15,6 +15,6 @@ public HandlerAdapter find(Object handler) {
return handlerAdapters.stream()
.filter(it -> it.supports(handler))
.findFirst()
.orElseThrow(InternalException::new);
.orElseThrow(HandlerNotFoundException::new);
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
package webmvc.org.springframework.web.servlet.mvc.tobe.exception;

import com.sun.jdi.InternalException;
import java.util.List;
import webmvc.org.springframework.web.servlet.ModelAndView;
import webmvc.org.springframework.web.servlet.view.JspView;
import webmvc.org.springframework.web.servlet.mvc.tobe.handler.ExceptionHandler;

public class ExceptionResolver {

public ModelAndView handle(Throwable ex) {
ModelAndView mv = null;
if (ex instanceof HandlerNotFoundException) {
mv = new ModelAndView(new JspView("/404.jsp"));
}
private final List<ExceptionHandler> handlers;

if (mv == null) {
return new ModelAndView(new JspView("/500.jsp"));
}
public ExceptionResolver(List<ExceptionHandler> handlers) {
this.handlers = handlers;
}

return mv;
public ModelAndView handle(Throwable ex) {
ExceptionHandler handler = handlers.stream()
.filter(it -> it.support(ex))
.findFirst()
.orElseThrow(() -> new InternalException());
return handler.handle();
Comment on lines +16 to +21

Choose a reason for hiding this comment

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

오 이렇게 처리해주셨군요 ㅎㅎ 너무 좋아요.
여기서 추가적으로 만약 개발자가 ExceptionHandler를 구현하지 않아서 아무것도 support하지 않을때, mvc 자체적으로 예외 화면을 보여주는 식으로 해볼수도 있겠네요!

}
}

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

import webmvc.org.springframework.web.servlet.ModelAndView;

public interface ExceptionHandler {

boolean support(Throwable ex);

ModelAndView handle();
}
Loading