-
Notifications
You must be signed in to change notification settings - Fork 303
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단계] 우르(김현우) 미션 제출합니다. #476
Changes from all commits
9f3b23d
f4af913
2d15844
2a51575
2f59764
151f2c1
9dde92c
68a7708
157eca1
d298d5e
3ccf269
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,24 @@ | ||
package com.techcourse.controller; | ||
|
||
import context.org.springframework.stereotype.Controller; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import webmvc.org.springframework.web.servlet.mvc.asis.Controller; | ||
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.JspView; | ||
|
||
public class RegisterViewController implements Controller { | ||
@Controller | ||
public class RegisterViewController { | ||
|
||
@Override | ||
public String execute(final HttpServletRequest req, final HttpServletResponse res) throws Exception { | ||
return "/register.jsp"; | ||
private static final Logger log = LoggerFactory.getLogger(RegisterViewController.class); | ||
|
||
@RequestMapping(value = "/register", method = RequestMethod.GET) | ||
public ModelAndView execute(final HttpServletRequest req, final HttpServletResponse res) { | ||
log.info("RegisterViewController GET method"); | ||
|
||
return new ModelAndView(new JspView("/register.jsp")); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package webmvc.org.springframework.web.servlet.mvc.tobe; | ||
|
||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
|
||
public class AnnotationHandlerAdapter implements HandlerAdapter { | ||
|
||
@Override | ||
public boolean isSupport(final Object handler) { | ||
return handler instanceof HandlerExecution; | ||
} | ||
|
||
@Override | ||
public Object handle( | ||
final HttpServletRequest request, | ||
final HttpServletResponse response, | ||
final Object handler | ||
) { | ||
return ((HandlerExecution) handler).handle(request, response); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,7 @@ | |
import web.org.springframework.web.bind.annotation.RequestMapping; | ||
import web.org.springframework.web.bind.annotation.RequestMethod; | ||
|
||
public class AnnotationHandlerMapping { | ||
public class AnnotationHandlerMapping implements HandlerMapping { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(AnnotationHandlerMapping.class); | ||
|
||
|
@@ -26,23 +26,41 @@ public AnnotationHandlerMapping(final Object... basePackages) { | |
this.handlerExecutions = new HashMap<>(); | ||
} | ||
|
||
public void initialize() | ||
throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { | ||
log.info("Initialized AnnotationHandlerMapping!"); | ||
|
||
@Override | ||
public void initialize() { | ||
final Reflections reflections = new Reflections(basePackages); | ||
|
||
final Set<Class<?>> controllerAnnotationClasses = | ||
reflections.getTypesAnnotatedWith(Controller.class); | ||
|
||
for (Class<?> controllerAnnotationClass : controllerAnnotationClasses) { | ||
final Object instance = controllerAnnotationClass.getDeclaredConstructor().newInstance(); | ||
final Object instance = getControllerInstance(controllerAnnotationClass); | ||
final Method[] methods = controllerAnnotationClass.getDeclaredMethods(); | ||
|
||
Arrays.stream(methods) | ||
.filter(method -> method.isAnnotationPresent(RequestMapping.class)) | ||
.forEach(method -> putHandlerExecutions(method, instance)); | ||
} | ||
|
||
log.info("Initialized AnnotationHandlerMapping!"); | ||
|
||
handlerExecutions.keySet() | ||
.forEach(handlerKey -> log.info("handlerKey : {}, Controller : {}", handlerKey, | ||
handlerExecutions.get(handlerKey))); | ||
} | ||
|
||
private Object getControllerInstance(final Class<?> controllerAnnotationClass) { | ||
final Object instance; | ||
try { | ||
instance = controllerAnnotationClass.getDeclaredConstructor().newInstance(); | ||
} catch (InstantiationException | ||
| IllegalAccessException | ||
| InvocationTargetException | ||
| NoSuchMethodException e | ||
) { | ||
throw new IllegalArgumentException("AnnotationHandlerMapping Reflection Exception"); | ||
} | ||
return instance; | ||
} | ||
|
||
private void putHandlerExecutions(final Method method, final Object target) { | ||
|
@@ -55,11 +73,12 @@ private void putHandlerExecutions(final Method method, final Object target) { | |
} | ||
} | ||
|
||
@Override | ||
public Object getHandler(final HttpServletRequest request) { | ||
final String requestURI = request.getRequestURI(); | ||
final String method = request.getMethod(); | ||
|
||
final HandlerKey handlerKey = new HandlerKey(requestURI, RequestMethod.find(method)); | ||
final HandlerKey handlerKey = new HandlerKey(requestURI, RequestMethod.valueOf(method)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍🏻👍🏻 |
||
|
||
return handlerExecutions.get(handlerKey); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package webmvc.org.springframework.web.servlet.mvc.tobe; | ||
|
||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
|
||
public interface HandlerAdapter { | ||
|
||
boolean isSupport(final Object handler); | ||
|
||
Object handle( | ||
final HttpServletRequest request, | ||
final HttpServletResponse response, | ||
final Object handler | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package webmvc.org.springframework.web.servlet.mvc.tobe; | ||
|
||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import java.util.List; | ||
|
||
public class HandlerAdapters implements HandlerAdapter { | ||
|
||
private final List<HandlerAdapter> handlerAdapters; | ||
|
||
public HandlerAdapters(final List<HandlerAdapter> handlerAdapters) { | ||
this.handlerAdapters = handlerAdapters; | ||
} | ||
|
||
@Override | ||
public boolean isSupport(final Object handler) { | ||
throw new UnsupportedOperationException(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 해당 메서드에서 바로 예외를 던지는 이유가 뭔가요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
총 두 번 adapters를 도는거라 불필요한 연산이라 생각이 들었어요. 그래서 해당 메서드는 지원하지 않는다고 개발자에게 명시적으로 보여주고자 작성했습니다 |
||
} | ||
|
||
@Override | ||
public Object handle( | ||
final HttpServletRequest request, | ||
final HttpServletResponse response, | ||
final Object handler | ||
) { | ||
return handlerAdapters.stream() | ||
.filter(handlerAdapter -> handlerAdapter.isSupport(handler)) | ||
.map(handlerAdapter -> handlerAdapter.handle(request, response, handler)) | ||
.findAny() | ||
.orElseThrow(() -> new IllegalArgumentException("해당 요청은 처리할 수 없습니다.")); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
일급컬렉션 사용 목적 질문과 비슷한 맥락의 질문입니다.
여기에서 직접 일급컬렉션을 갖지 않고 추상화해주신 의도가 궁금합니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
인터페이스를 가지고 있는게 더 확장성 있다고 생각했습니다!!