대략적인 과정을 보면, 키 값당 하나의 Value를 갖는 Hash맵 안에 각 URI 요청에 대한 처리를 할 클래스를 로딩하여 객체화한 뒤
HashMap< URI , 처리객체 > 의 Map 객체를 만드는 과정이다.
서블릿 구동시 작동하는 init() 메서드에 적용하고 tomcat 서블릿 구동 순서에 1 번을 주어서 1순위로 실행시키는 것 같다.
Servlet 생명 주기에 따라 init() 메서드는 단 한번 실행되고 WAS가 죽을때 같이 destroy() 되는데, 이에 따라서 init 메서드에 서문에 기재한 사항을 적용하여 FrontController를 구현하는 과정이라고 생각해본다.
-
작동 원리는, 요청이 들어오면 해당 키값이 즉 요청값이므로 , 맞는 키값의 객체를 꺼내 구현대상 클래스의 메서드를 실행시켜 서비스 로직을 실행시킨다는 것 같다.
ackage chap18;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ControllerUsingURI extends HttpServlet {
private static final long serialVersionUID = 1L;
private Map<String,CommandHandler> map = new HashMap<>();
@Override
public void init() throws ServletException {
String filePath = getInitParameter("confilgFile");
System.out.println("\n파일경로: "+filePath);
String realPath = getServletContext().getRealPath(filePath);
try (FileInputStream fis = new FileInputStream(realPath);){
Properties prop = new Properties();
prop.load(fis);
Enumeration<String> keys = (Enumeration<String>)prop.propertyNames();
while(keys.hasMoreElements()) {
String key = keys.nextElement();
System.out.println("키 : " +key);
String className = prop.getProperty(key);
System.out.println("클래스이름 : "+className);
Class<CommandHandler> clazz = (Class<CommandHandler>) Class.forName(className);
CommandHandler com = clazz.newInstance();
System.out.println(com);
map.put(key,com);
}
}catch(Exception e) {
e.printStackTrace();
}
}
public ControllerUsingURI() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
process(request,response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
process(request,response);
}
private void process(HttpServletRequest request, HttpServletResponse response) {
// 어떤 경로로 왔는지 파악, a.do b.do c.do
String requestUri = request.getRequestURI();
//localhost:8090/contextRoot/some/a.do
String contextPath = request.getContextPath();
int startIndex = requestUri.indexOf(contextPath);
String uri = requestUri.substring(startIndex+contextPath.length(),requestUri.length());
System.out.println(uri);
CommandHandler com = map.get(uri);
if(com != null) {
String res = com.process(request, response);
request.setAttribute("result", res);
}
/* request.setAttribute("result", res); */
try {
request.getRequestDispatcher("/chap18/simpleView.jsp").forward(request, response);
} catch (ServletException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Properties 파일의 내용은 키, 밸류 값으로 적용되며 메서드로 이를 Map<String, String> 으로 변환시킨다.
process1 = chap18.Process1Handler
process2 = chap18.process2Handler
같은 인터페이스를 구현하여, 하나의 타입으로 다형성을 구현시켜 같은 Process를 거치게한다. 즉 사용하려는 모든 클래스들은 전부 해당 인터페이스를 구현해야만 한다.
package chap18;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface CommandHandler {
String process(HttpServletRequest request, HttpServletResponse response);
}
@Override
public String process(HttpServletRequest request, HttpServletResponse response) {
return "프로세스1";
}
web.xml 파일, FrontServlet을 등록하고, InitParameter로 경로 문자열을 준다. 나중에 getInitParameter 메서드로 불러올 것이므로, 저장해두었고, 서문에서 작성한대로 1순위(<load-on-startup>1</load-on-startup>)로 로드 시킨다. 프론트 컨트롤러는 모든 요청처리 객체를 로드시키기 때문에, 반드시 1순위에 두어야한다.
모든 .do 확장자 요청을 받을 것이므로 FrontController를 *.do 요청 경로에 맵핑시킨다.
<!-- comments -->
<servlet>
<servlet-name>ControllerUsingUri</servlet-name>
<servlet-class>chap18.ControllerUsingURI</servlet-class>
<init-param>
<param-name>confilgFile</param-name>
<param-value>/WEB-INF/CommandHandler.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ControllerUsingUri</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
init() 메서드에 있는 경로에 따른 문자열 조작.
// 어떤 경로로 왔는지 파악, a.do b.do c.do
String requestUri = request.getRequestURI();
//localhost:8090/contextRoot/some/a.do
String contextPath = request.getContextPath();
int startIndex = requestUri.indexOf(contextPath);
String uri = requestUri.substring(startIndex+contextPath.length(),requestUri.length());
System.out.println(uri);
CommandHandler com = map.get(uri);
if(com != null) {
String res = com.process(request, response);
request.setAttribute("result", res);
'JSP & Servlet' 카테고리의 다른 글
<c:out> 태그로 뿌린 내용을 작성 시 그대로 가져오기. (0) | 2020.07.30 |
---|---|
Servlet에서의 Session (0) | 2020.07.28 |
커스텀태그에서의 복잡한 Attribute 사용. (0) | 2020.07.20 |
커스텀태그의 몸통 내용 처리방식 (0) | 2020.07.20 |
태그파일을 이용한 커스텀태그 구현 (0) | 2020.07.20 |