수정된 "requestmapping.properties"처럼 "TestRootController"클래스와 "test1"메소드를 생성합니다.
/test1.do=com.home.project.test2.controller.TestRootController@test1
4. "test2" 프로젝트의 "Java Resources"에서 "src/main/java"의 "com.home.project.test2.controller"를 선택한 후 오른쪽 버튼을 클릭하여 컨텍스트 메뉴 [New > Class]를 클릭하고 "Constructors from superclass"를 선택하여 "TestRootController.java"를 생성합니다.
"TestRootController"클래스에서 "TestController"클래스가 계승(extends) 되도록 코드를 수정합니다.
public class TestRootController extends TestController {
메소드에서 "TestService1"를 "new" 생성해서 사용할 수 있습니다. 그러나 인터페이스(interface)으로 형 변환해서 사용함으로써 클래스간의 의존관계를 줄일 수 있고 인터페이스(interface)로 구현(implements)한 다양한 클래스를 사용(다양성)할 수 있습니다. 지금의 서비스 구조는 적합하지 않지만 컨트롤의 구조를 위해 사용하겠습니다.
"TestService1"의 인터페이스(interface)인 "ITestService"를 변수로 사용합니다.
/**
* ITestService 인터페이스 객체
*/
ITestService testService = null;
생성자에서 "TestService1"를 생성하고 인터페이스(interface)으로 형 변환해서 초기화합니다.
지금은 인터페이스(interface)을 사용하지 않아도 문제가 없습니다.
/**
* TestRootController 생성자
*/
public TestRootController() {
TestService1 testService1 = new TestService1();
testService = (ITestService)testService1;
}
"test1"메소드는 "TestController"클래스의 "getMethod"메소드에서 파라메타 배열(parameterTypes)로 " HttpServletRequest.class"와 "HttpServletResponse.class"를 가지 메소드를 찾게 되어 있습니다. 그래서 "test1"메소드는 파라메타로 "HttpServletRequest"와 "HttpServletResponse"를 갖게 생성합니다. 그리고 "doProcess"가 호출되도록 합니다.
/**
* TestService1의 doProcess를 실행합니다.
* @param request HTTP 요청 객체
* @param response HTTP 응답 객체
* @return RequestDispatcher 객체
*/
public RequestDispatcher test1(HttpServletRequest request, HttpServletResponse response) {
return testService.doProcess(request, response);
}
5. "TestDispatcherServlet"클래스에 컨트롤러(Controller) 클래스를 관리하는 "classMappingMap" 변수를 추가합니다.
/**
* Class-Class 맵
*/
private Map<String, Object> classMappingMap = new HashMap<String, Object>();
"TestDispatcherServlet"클래스의 "init"메소드에서 서비스 클래스로 처리된 부분을 주석처리합니다.
Iterator<Object> keyIter = serviceHandlerMapping.keySet().iterator();
while (keyIter.hasNext()) {
String url = (String) keyIter.next();
/*
String serviceClassName = serviceHandlerMapping.getProperty(url);
try
{
Class<?> serviceClass = Class.forName(serviceClassName);
Object serviceInstance = serviceClass.newInstance();
ITestService service = (ITestService) serviceInstance;
requestMappingMap.put(url, service);
System.out.println("[RequestMapping] URL:" + url + "에 " + serviceClassName + "를 생성하여 매핑함");
}
catch (Exception e)
{
System.out.println("[RequestMapping] URL:" + url + "에 " + serviceClassName + "를 생성하지 못하여 매핑하지 못함");
// InstantiationException, IllegalAccessException
throw new ServletException(e);
}
*/
}
수정된 "requestmapping.properties"처럼 "@"구분자로 컨트롤러(Controller) 클래스 명와 메소드(Method) 명을 구분합니다.
"classMappingMap"에 컨트롤러(Controller) 클래스 명으로 생성된 클래스가 있는지 확인 하고 "Class.forName"과 "newInstance"으로 컨트롤러(Controller) 클래스를 생성합니다.
생성된 컨트롤러(Controller) 클래스에 요청(Request) URL과 메소드(Method) 명을 매핑하여 추가합니다.
Iterator<Object> keyIter = serviceHandlerMapping.keySet().iterator();
while (keyIter.hasNext()) {
String url = (String) keyIter.next();
String controllerClassName = serviceHandlerMapping.getProperty(url);
String controllerInfo[] = controllerClassName.split("@");
try
{
ITestController controller = null;
if (!classMappingMap.containsKey(controllerInfo[0])) {
Class<?> controllerClass = Class.forName(controllerInfo[0]);
Object controllerInstance = controllerClass.newInstance();
controller = (ITestController) controllerInstance;
classMappingMap.put(controllerInfo[0], controller);
} else {
controller = (ITestController) classMappingMap.get(controllerInfo[0]);
}
if (controller.addRequestFunction(url, controllerInfo[1])) {
requestMappingMap.put(url, controller);
}
} catch (Exception e) {
System.out.println("[RequestMapping] URL:" + url + "에 " + controllerInfo[0] + "를 생성하지 못하여 매핑하지 못함");
// InstantiationException, IllegalAccessException
throw new ServletException(e);
}
}
"TestDispatcherServlet"클래스의 "service"메소드에서 "ITestService"로 형 변환하여 처리된 부분을 주석처리합니다.
/*
ITestService service = (ITestService) requestMappingMap.get(requestURI);
if (null != service) {
System.out.println("[RequestMapping] URL:" + requestURI + " 요청을 " + service + "로 실행함");
requestDispatcher = service.doProcess(request, response);
} else {
*/
"ITestController"로 변환하여 처리되도록 수정합니다.
ITestController controller = (ITestController) requestMappingMap.get(requestURI);
if (null != controller) {
System.out.println("[RequestMapping] URL:" + requestURI + " 요청을 " + controller + "로 실행함");
requestDispatcher = controller.doProcess(request, response);
} else {
6. "Servers"탭에서 "tomcat8"를 선택하고 "start"버튼(start the server)을 클릭합니다. 웹 브라우저에서 "http://localhost:8080/test2/test1.do"를 입력합니다.
"Console"탭을 클릭하면 프로퍼티를 읽어 맵에 추가되고 맵에서 찾아 실행한 것을 확인할 수 있습니다.
[Console]
testDispatcherServlet init 실행
/com/home/project/test2/config/requestmapping.properties을 프로퍼티로 읽음
com.home.project.test2.controller.TestRootController@66ef27c0의 test1메소드를 찾음
[RequestMapping] URL : /test1.do에 com.home.project.test2.controller.TestRootController@66ef27c0의 test1메소드를 매핑함
[RequestMapping] URL : /test1.do요청을 com.home.project.test2.controller.TestRootController@66ef27c0로 실행함
com.home.project.test2.controller.TestRootController@66ef27c0의 test1메소드를 호출함