Skip to content
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
7 changes: 7 additions & 0 deletions src/main/java/com/diy/app/LectureConfig.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package com.diy.app;

import com.diy.framework.web.context.annotation.Bean;
import com.diy.framework.web.context.annotation.Component;
import com.diy.framework.web.mvc.ModelAndView;
import com.diy.framework.web.mvc.controller.Controller;

@Component
public class LectureConfig {
@Bean(name = "/lectures/new")
public Controller lectureFormController() {
return params -> new ModelAndView("lecture-registration");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,14 @@ public void init(final ServletConfig config) throws ServletException {

ApplicationContext applicationContext = new ApplicationContext("com.diy");

// 1) 애너테이션 매핑(METHOD + URL)
AnnotationHandlerMapping annotationHandlerMapping = new AnnotationHandlerMapping(applicationContext);
annotationHandlerMapping.initialize();
handlerMappings.add(annotationHandlerMapping);

SimpleControllerHandlerMapping simpleHandlerMapping = new SimpleControllerHandlerMapping();
// 2) 인터페이스 매핑(URL)
SimpleControllerHandlerMapping simpleHandlerMapping = new SimpleControllerHandlerMapping(applicationContext);
simpleHandlerMapping.initialize();
handlerMappings.add(simpleHandlerMapping);

handlerAdapters.add(new AnnotationHandlerAdapter());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,38 @@
package com.diy.framework.web.mvc.handler;

import com.diy.framework.web.context.ApplicationContext;
import com.diy.framework.web.mvc.controller.Controller;

import java.util.HashMap;
import java.util.Map;

public class SimpleControllerHandlerMapping implements HandlerMapping {
private final Map<String, Controller> controllers = new HashMap<>();
private final ApplicationContext applicationContext;

public SimpleControllerHandlerMapping(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}

public void initialize() {
for (Map.Entry<String, Object> entry : applicationContext.getAllBeans().entrySet()) {
Object bean = entry.getValue();
if (bean instanceof Controller) {
// 빈 이름을 그대로 매핑 키로 사용
controllers.put(entry.getKey(), (Controller) bean);
}
}
}

public void put(String key, Controller controller) {
controllers.put(key, controller);
}

@Override
public Object getHandler(String key) {
return controllers.get(key);
// DispatcherServlet 은 "GET /lectures" 처럼 "METHOD path" 로 조회하지만,
// 인터페이스 매핑은 path(URL)만 키로 가진다. HTTP Method 를 떼고 path 로만 조회한다.
String path = key.contains(" ") ? key.split(" ", 2)[1] : key;
return controllers.get(path);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import com.diy.app.LectureController;
import com.diy.app.LectureRepository;
import com.diy.framework.web.context.ApplicationContext;
import com.diy.framework.web.mvc.controller.Controller;
import com.diy.framework.web.mvc.handler.AnnotationHandlerMapping;
import com.diy.framework.web.mvc.handler.HandlerMethod;
import com.diy.framework.web.mvc.handler.SimpleControllerHandlerMapping;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -37,4 +41,37 @@ void controllerAnnotationRegistration() {

assertThat(controller).isInstanceOf(LectureController.class);
}

@Test
@DisplayName("인터페이스 기반 컨트롤러는 빈 이름(URL)으로 등록되고 HTTP Method 와 무관하게 매핑된다")
void interfaceControllerMapping() {
ApplicationContext context = new ApplicationContext("com.diy");

Object controller = context.getBean("/lectures/new");
assertThat(controller).isInstanceOf(Controller.class);

SimpleControllerHandlerMapping mapping = new SimpleControllerHandlerMapping(context);
mapping.initialize();

assertThat(mapping.getHandler("GET /lectures/new")).isSameAs(controller);
assertThat(mapping.getHandler("POST /lectures/new")).isSameAs(controller);
}

@Test
@DisplayName("애너테이션 기반 컨트롤러는 URL과 HTTP Method 조합으로 매핑된다")
void annotationControllerMapping() {
ApplicationContext context = new ApplicationContext("com.diy");

AnnotationHandlerMapping mapping = new AnnotationHandlerMapping(context);
mapping.initialize();

Object getHandler = mapping.getHandler("GET /lectures");
Object postHandler = mapping.getHandler("POST /lectures");

assertThat(getHandler).isInstanceOf(HandlerMethod.class);
assertThat(postHandler).isInstanceOf(HandlerMethod.class);

assertThat(((HandlerMethod) getHandler).getMethod().getName()).isEqualTo("list");
assertThat(((HandlerMethod) postHandler).getMethod().getName()).isEqualTo("create");
}
}