요청한 URL에 따라 첫번째 Path로 Class를 로딩하여 객체를 생성한 후 두번째 path에 지정된 method를 자동 호출하는 방법이다.
web.xml 에 다음과 같이 servlet 지정
<?xml version= "1.0" encoding= "UTF-8" ?>
<! DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
< web-app>
< servlet>
< servlet-name> Dynamic Servlet </ servlet-name>
< servlet-class> com.example.DynamicServlet </servlet-class >
< init-param>
< param-name> controllerPackage </param-name >
< param-value> com.example.controller </param-value >
</ init-param>
< load-on-startup> 1</ load-on-startup >
</ servlet>
< servlet-mapping>
< servlet-name> Dynamic Servlet </ servlet-name>
< url-pattern> /api/* </ url-pattern>
</ servlet-mapping>
< session-config>
< session-timeout> 1</ session-timeout >
</ session-config>
</ web-app>
DynamicServlet 클래스 제작
package com.example;
import java.io.IOException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.text.WordUtils;
public class DynamicServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private String controllerPackage = "";
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doAction(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doAction(req, resp);
}
@Override
public void destroy() {
super.destroy();
}
@Override
public void init() throws ServletException {
controllerPackage = getServletConfig().getInitParameter("controllerPackage");
super.init();
}
protected void doAction(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String[] path = req.getPathInfo().split("/");
if( path.length <= 1 ) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
Class<?> controllerClass = null;
Method method = null;
try {
controllerClass = Class.forName(controllerPackage + "." + WordUtils.capitalize(path[1]) );
method = controllerClass.getMethod(path[2], new Class[] {HttpServletRequest.class, HttpServletResponse.class});
} catch (ClassNotFoundException e) {
e.printStackTrace();
resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
return;
} catch (NoSuchMethodException e) {
e.printStackTrace();
resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
return;
} catch (SecurityException e) {
e.printStackTrace();
resp.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
return;
}
Object controller = null;
try {
controller = controllerClass.newInstance();
method.invoke(controller, req, resp);
} catch (Exception e) {
e.printStackTrace();
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
}
}
}
com.example.controller.TestController 클래스를 생성하고, 인자로 (HttpServletRequest, HttpServletResponse)를 받는 testMethod 함수를 작성한다.
/dyn/testController/testMethod URL을 호출하면 com.example.controller.TestController 클래스에 대한 object를 생성한 후 testMethod 함수를 자동으로 호출한다.
동적 호출이므로 실행 시간 클래스 교체가 가능하다.