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

πŸ“š0단계, 1단계 μ™„λ£Œ #5

Open
wants to merge 3 commits into
base: 24HwangChabin
Choose a base branch
from
Open
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
45 changes: 45 additions & 0 deletions docs/Assignment1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
### 1단계

``AnnotationHandlerMappingTest``

#### ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ„€λͺ…

```java
final var request = mock(HttpServletRequest.class);
final var response = mock(HttpServletResponse.class);
```

Servlet클래슀λ₯Ό κ°€μ Έμ˜΄

```java
when(request.getAttribute("id")).thenReturn("gugu");
when(request.getRequestURI()).thenReturn("/get-test");
when(request.getMethod()).thenReturn("GET");
```

`id`κ°€ 호좜되면 `gugu`λ°˜ν™˜, `URI`호좜되면 `/get-test`λ°˜ν™˜, `Method`호좜되면 `GET`λ°˜ν™˜ μ„€μ •

```java
final var handlerExecution = (HandlerExecution) handlerMapping.getHandler(request);
final var modelAndView = handlerExecution.handle(request, response);
```

(기쑴에 이미 μ„€μ •λœ) ν•Έλ“€λŸ¬λ₯Ό ν˜ΈμΆœν•΄μ„œ request에 λ§žλŠ” `handlerExecution` 호좜, 이λ₯Ό 톡해 `modelAndView` λ°˜ν™˜

```java
assertThat(modelAndView.getObject("id")).isEqualTo("gugu");
```

ν…ŒμŠ€νŠΈκ°€ μ›ν™œν•˜κ²Œ λ™μž‘ν•˜λŠ”μ§€ 확인

1. request λ₯Ό Servlet이 λ°›κ³ , 이λ₯Ό HandlerMapping을 톡해 μ ν•©ν•œ HandlerControllerλ₯Ό μ°Ύμ•„ μ μš©μ‹œν‚΄
2. μ—¬κΈ°μ„œλŠ” Keyλ₯Ό 톡해 μ°Ύκ³ , 이λ₯Ό Execution 을 톡해 μ‹€ν–‰μ‹œν‚€λŠ” κ·Έλ¦Όκ°™μŒ.
`HandlerExecution`클래슀 λ˜ν•œ μˆ˜μ •. `ModelAndView`νƒ€μž… λ°˜ν™˜μž„. Viewν•„λ“œλŠ” null둜 μ΄ˆκΈ°ν™”.
idλ₯Ό μ‘°νšŒμ‹œ requestμ—μ„œ id에 ν•΄λ‹Ήν•˜λŠ” attributeλ₯Ό μ°Ύμ•„μ„œ, 이λ₯Ό λ¬Άμ–΄ `ModelAndView`둜 λ°˜ν™˜ν•˜λ„λ‘μˆ˜μ •.
3. λ”°λΌμ„œ ν‚€λ₯Ό μƒμ„±ν•˜κ³ , HandlerExecution을 생성해 Map μžλ£Œν˜• `handlerExecutions`에
`handlerExecutions.put(new HandlerKey("/get-test", RequestMethod.GET), new HandlerExecution());`
4. 이후 `getHandler`에, μž…λ ₯된 νŒŒλΌλ©”ν„° ν† λŒ€λ‘œ HandlerKeyλ₯Ό 생성, `return handlerExecutions.get(handlerKey);`

#### Postν…ŒμŠ€νŠΈλ„ λΉ„μŠ·ν•œ λ°©λ²•μœΌλ‘œ ν•΄κ²°

---
1 change: 0 additions & 1 deletion docs/README.md

This file was deleted.

Copy link
Collaborator

Choose a reason for hiding this comment

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

μ•„ DispatcherServlet은 app νŒ¨ν‚€μ§€ μ•ˆμ— μžˆμŠ΅λ‹ˆλ‹€! λ‹€μ‹œ 확인해보고 μ μš©ν•΄λ³΄μ…”μ•Ό ν•  것 κ°™μŠ΅λ‹ˆλ‹€!

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.interface21.webmvc.servlet.mvc;

import com.interface21.webmvc.servlet.ModelAndView;
import com.interface21.webmvc.servlet.View;
import com.interface21.webmvc.servlet.mvc.tobe.HandlerExecution;
import com.interface21.webmvc.servlet.mvc.tobe.HandlerMapping;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.util.List;
import java.util.Map;

public class DispatcherServlet implements HandlerMapping {
private final HandlerMapping AnnotationHandlerMapping;
private final HandlerMapping ManualHandlerMapping;

public DispatcherServlet(HandlerMapping handlerMapping1, HandlerMapping handlerMapping2) {
AnnotationHandlerMapping = handlerMapping1;
ManualHandlerMapping = handlerMapping2;
}

/**
* μ›λž˜ μ•„λž˜ 두 λ©”μ„œλ“œ 쀑 ν•˜λ‚˜λ§Œ μžˆμ–΄μ•Ό ν•˜λŠ”λ°,
* Annotation κ³Ό Manual λ‘˜ λ‹€ μ‚¬μš© κ°€λŠ₯ν•˜κ²Œ ν•˜κΈ° μœ„ν•΄μ„  이 방법이..?
*/
public Map<String, Object> doDispatchWithAnnotationHandlerMapping(HttpServletRequest request, HttpServletResponse response) throws Exception {
var handlerExecution = (HandlerExecution) AnnotationHandlerMapping.getHandler(request);
var modelAndView=handlerExecution.handle(request,response);
return modelAndView.getModel();
}
public Map<String, Object> doDispatchWithManualHandlerMapping(HttpServletRequest request, HttpServletResponse response) throws Exception {
var handlerExecution = (HandlerExecution) ManualHandlerMapping.getHandler(request);
var modelAndView=handlerExecution.handle(request,response);
return modelAndView.getModel();
}

@Override
public Object getHandler(HttpServletRequest request) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.interface21.webmvc.servlet.mvc.asis;

import com.interface21.web.bind.annotation.RequestMapping;
import com.interface21.web.bind.annotation.RequestMethod;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.util.Objects;

@com.interface21.context.stereotype.Controller
public class ForwardController implements Controller {

private final String path;
Expand All @@ -13,8 +15,19 @@ public ForwardController(final String path) {
this.path = Objects.requireNonNull(path);
}

@RequestMapping(value = "/get-test", method = RequestMethod.GET)
public void AnnotationGetMapping(){

}

@RequestMapping(value = "/post-test",method = RequestMethod.POST)
public void AnnotationPostMapping(){

}

@Override
public String execute(final HttpServletRequest request, final HttpServletResponse response) {

return path;
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package com.interface21.webmvc.servlet.mvc.tobe;

import com.interface21.context.stereotype.Controller;
import com.interface21.web.bind.annotation.RequestMapping;
import com.interface21.web.bind.annotation.RequestMethod;
import jakarta.servlet.http.HttpServletRequest;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class AnnotationHandlerMapping {
public class AnnotationHandlerMapping implements HandlerMapping {

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

Expand All @@ -21,9 +27,44 @@ public AnnotationHandlerMapping(final Object... basePackage) {

public void initialize() {
log.info("Initialized AnnotationHandlerMapping!");
try {
// νŒ¨ν‚€μ§€ μŠ€μΊ”μœΌλ‘œ Controllerλ₯Ό 가진 ν΄λž˜μŠ€λ“€ λ°˜ν™˜
for (Object packageName : basePackage) {
Reflections reflections = new Reflections(packageName);
Set<Class<?>> controllerClasses = reflections.getTypesAnnotatedWith(Controller.class);

// @Controller 클래슀 처리
for (Class<?> controllerClass : controllerClasses) {
Method[] methods = controllerClass.getDeclaredMethods();

// @RequestMapping λ©”μ„œλ“œ 처리
for (Method method : methods) {
if (method.isAnnotationPresent(RequestMapping.class)) {
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);

String url = requestMapping.value();
RequestMethod[] httpMethod = requestMapping.method();
// HTTP λ©”μ„œλ“œλ³„λ‘œ λͺ¨λ‘ ν•Έλ“€λŸ¬ 등둝
for (RequestMethod requestMethod : httpMethod) {
HandlerKey handlerKey = new HandlerKey(url, requestMethod);
HandlerExecution handlerExecution = new HandlerExecution();
handlerExecutions.put(handlerKey, handlerExecution);
}
}
}
// ν•Έλ“€λŸ¬ 정상 등둝 확인 (HandlerKey에도 getter 주석 μ œκ±°ν•΄μ€˜μ•Ό 함)
// handlerExecutions.entrySet().stream().map(Map.Entry::getKey)
// .map(HandlerKey::getRequestMethod).forEach(System.out::println);
}
}
} catch (Exception e) {
log.error("Failed to initialize AnnotationHandlerMapping", e);
}

}

public Object getHandler(final HttpServletRequest request) {
return null;
HandlerKey handlerKey = new HandlerKey(request.getRequestURI(), RequestMethod.valueOf(request.getMethod()));
return handlerExecutions.get(handlerKey);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
public class HandlerExecution {

public ModelAndView handle(final HttpServletRequest request, final HttpServletResponse response) throws Exception {
return null;
ModelAndView mv=new ModelAndView(null);
mv.addObject("id", request.getAttribute("id"));
return mv;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ public HandlerKey(final String url, final RequestMethod requestMethod) {
this.requestMethod = requestMethod;
}

/**
* AnnotationHandlerMapping 클래슀 λ‚΄μ˜
* ν•Έλ“€λŸ¬ 정상 등둝 확인을 μœ„ν•œ ν™•μΈμš© λ©”μ„œλ“œ
*/
// public RequestMethod getRequestMethod() {
// return requestMethod;
// }

@Override
public String toString() {
return "HandlerKey{" +
Expand All @@ -34,4 +42,4 @@ public boolean equals(Object o) {
public int hashCode() {
return Objects.hash(url, requestMethod);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.interface21.webmvc.servlet.mvc.tobe;

import jakarta.servlet.http.HttpServletRequest;

public interface HandlerMapping {
Object getHandler(HttpServletRequest request);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.interface21.webmvc.servlet.mvc.tobe;

import com.interface21.web.bind.annotation.RequestMethod;
import jakarta.servlet.http.HttpServletRequest;
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(AnnotationHandlerMapping.class);

private final Object[] basePackage;
private final Map<HandlerKey, HandlerExecution> handlerExecutions;

public ManualHandlerMapping(final Object... basePackage) {
this.basePackage = basePackage;
this.handlerExecutions = new HashMap<>();
}

public void initialize() {
log.info("Initialized AnnotationHandlerMapping!");
handlerExecutions.put(new HandlerKey("/get-test", RequestMethod.GET), new HandlerExecution());
handlerExecutions.put(new HandlerKey("/post-test", RequestMethod.POST), new HandlerExecution());
}

public Object getHandler(final HttpServletRequest request) {
HandlerKey handlerKey = new HandlerKey(request.getRequestURI(), RequestMethod.valueOf(request.getMethod()));
return handlerExecutions.get(handlerKey);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.interface21.webmvc.servlet.mvc;

import com.interface21.webmvc.servlet.mvc.tobe.AnnotationHandlerMapping;
import com.interface21.webmvc.servlet.mvc.tobe.ManualHandlerMapping;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

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

class DispatcherServletTest {
private DispatcherServlet dispatcherServlet;

@BeforeEach
void setUp() {
AnnotationHandlerMapping annotationHandlerMapping = new AnnotationHandlerMapping("com.interface21.webmvc.servlet");
ManualHandlerMapping manualHandlerMapping = new ManualHandlerMapping();
annotationHandlerMapping.initialize();
manualHandlerMapping.initialize();
dispatcherServlet=new DispatcherServlet(annotationHandlerMapping, manualHandlerMapping);
}

@Test
void AnnotationHandlerMapping() throws Exception {
final var requestGet = mock(HttpServletRequest.class);
final var responseGet = mock(HttpServletResponse.class);

final var requestPost = mock(HttpServletRequest.class);
final var responsePOST = mock(HttpServletResponse.class);

when(requestGet.getAttribute("id")).thenReturn("gugu");
when(requestGet.getRequestURI()).thenReturn("/get-test");
when(requestGet.getMethod()).thenReturn("GET");

when(requestPost.getAttribute("id")).thenReturn("gugu");
when(requestPost.getRequestURI()).thenReturn("/post-test");
when(requestPost.getMethod()).thenReturn("POST");

final var modelGet = dispatcherServlet.doDispatchWithAnnotationHandlerMapping(requestGet, responseGet);
final var modelPost = dispatcherServlet.doDispatchWithAnnotationHandlerMapping(requestPost, responsePOST);
assertThat(modelGet.get("id")).isEqualTo("gugu");
assertThat(modelPost.get("id")).isEqualTo("gugu");
}

@Test
void ManualHandlerMapping() throws Exception {
final var requestGet = mock(HttpServletRequest.class);
final var responseGet = mock(HttpServletResponse.class);

final var requestPost = mock(HttpServletRequest.class);
final var responsePOST = mock(HttpServletResponse.class);

when(requestGet.getAttribute("id")).thenReturn("gugu");
when(requestGet.getRequestURI()).thenReturn("/get-test");
when(requestGet.getMethod()).thenReturn("GET");

when(requestPost.getAttribute("id")).thenReturn("gugu");
when(requestPost.getRequestURI()).thenReturn("/post-test");
when(requestPost.getMethod()).thenReturn("POST");

final var modelGet = dispatcherServlet.doDispatchWithManualHandlerMapping(requestGet, responseGet);
final var modelPost = dispatcherServlet.doDispatchWithManualHandlerMapping(requestPost, responsePOST);
assertThat(modelGet.get("id")).isEqualTo("gugu");
assertThat(modelPost.get("id")).isEqualTo("gugu");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class AnnotationHandlerMappingTest {

@BeforeEach
void setUp() {
handlerMapping = new AnnotationHandlerMapping("samples");
handlerMapping = new AnnotationHandlerMapping("com.interface21.webmvc.servlet");
handlerMapping.initialize();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.interface21.webmvc.servlet.mvc.tobe;

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

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

class ManaualHandlerMappingTest {

private ManualHandlerMapping handlerMapping;

@BeforeEach
void setUp() {
handlerMapping = new ManualHandlerMapping("samples");
handlerMapping.initialize();
}

@Test
void get() throws Exception {
final var request = mock(HttpServletRequest.class);
final var response = mock(HttpServletResponse.class);

when(request.getAttribute("id")).thenReturn("gugu");
when(request.getRequestURI()).thenReturn("/get-test");
when(request.getMethod()).thenReturn("GET");

final var handlerExecution = (HandlerExecution) handlerMapping.getHandler(request);
final var modelAndView = handlerExecution.handle(request, response);

assertThat(modelAndView.getObject("id")).isEqualTo("gugu");
}

@Test
void post() throws Exception {
final var request = mock(HttpServletRequest.class);
final var response = mock(HttpServletResponse.class);

when(request.getAttribute("id")).thenReturn("gugu");
when(request.getRequestURI()).thenReturn("/post-test");
when(request.getMethod()).thenReturn("POST");

final var handlerExecution = (HandlerExecution) handlerMapping.getHandler(request);
final var modelAndView = handlerExecution.handle(request, response);

assertThat(modelAndView.getObject("id")).isEqualTo("gugu");
}
}
Loading