JSP & Servlet

Properties 파일을 이용한 FrontController 구현

Jungsoomin :) 2020. 7. 24. 17:18

대략적인 과정을 보면, 키 값당 하나의 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);