본문 바로가기
Dev/Java

MVC - 커맨드 패턴을 이용한 요청 URI를 명령어로 사용하기

by vellahw 2022. 10. 11.

 

https://tavi.tistory.com/51?category=1086720 

 

MVC - 커맨드 패턴을 이용한 명령어 처리 분리

https://tavi.tistory.com/50?category=1086720 MVC 패턴 정의 0. 모델 1 구조 모델 1 구조는 JSP를 이용한 단순한 모델이다. (기존에 했던 모든 것들..) JSP에서 요청 처리 및 뷰 생성을 처리해서 구현이 쉽지만..

tavi.tistory.com


 

컨트롤러가 알맞은 로직을 수행하려면 클라이언트가 어떤 기능을 요청하는 지 구분할 수 있어야 하는데

웹 브라우저를 통해 명령어를 전달하는 방법에는 두 가지가 있다.

  1. 특정 이름의 파라미터에 명령어 정보를 전달 (ex. url에 ?type=date 를 입력)
  2. 요청 URI 자체를 명령어로 사용

 

명령어 기반의 파라미터는 컨트롤러의 URL이 사용자에게 노출 된다는 단점이 있다.

예시

 

명령어를 파라미터를 통해서 전달하기 때문에 사용자는 얼마든지 명령어를 변경해서 컨트롤러에 요청을 전송할 수 있다.

URL의 일부를 명령어로 사용하면 사용자의 악의적인 명령어 입력을 예방할 수 있고 자연스러운 URL을 제공할 수 있다.

URL의 일부를 명령어로 사용하기 위해선 특정 확장자를 가진 URL을 요청한 경우 컨트롤러 서블릿으로 요청이 가도록 하고 웹 어플리케이션에 대한 URI를 명령어로 사용하도록 컨트롤러 서블릿을 작성하면 된다.

 

 

🎈.요청 URI를 명령어로 사용하기 예제

1. properties 파일 작성

/hello.hi=mvc.command.HelloHandler
  • URL에 /hello.hi가 있으면 mvc.command.HelloHandler가 처리

 

2. web.xml 파일에 서블릿 설정

<servlet>
	<servlet-name>ControllerUsingURI</servlet-name>
	<servlet-class>mvc.controller.ControllerUsingURI</servlet-class>
	<init-param>
		<param-name>configFile2</param-name>
		<param-value>/WEB-INF/commandHandlerURI.properties</param-value>
	</init-param>
</servlet>
<servlet-mapping>
	<servlet-name>ControllerUsingURI</servlet-name>
	<url-pattern>*.hi</url-pattern>
</servlet-mapping>
  • configFile2란 이름으로 /WEB-INF/commandHandler.properties 파일로부터 설정 정보를 읽어옴
  • .hi 확장자 URL을 가진 요청을 처리함

 

3. 컨트롤러 서블릿 클래스 작성

package mvc.controller;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import mvc.command.CommandHandler;
import mvc.command.NullHandler;

public class ControllerUsingURI extends HttpServlet {
	
	private Map<String, Object> commandHandlerMap = new HashMap<String, Object>();
	
	public void init(ServletConfig config) throws ServletException {
		String configFile = config.getInitParameter("configFile2"); //web.xml에 설정한 이름
		Properties prop = new Properties();
		FileInputStream fis = null;
		
		try {
			//받아온 상대경로를 절대 경로로 바꿔줌
			String configFilePath = config.getServletContext().getRealPath(configFile);
			fis = new FileInputStream(configFilePath);
			prop.load(fis); //프로퍼티스 로딩
			
		} catch (IOException e) {
			throw new ServletException(e);
		} finally {
			if(fis!=null)
				try {
					fis.close();
				} catch (IOException e2) {
				}
		}
	
		//Iterator 객체 생성
		Iterator keyIter = prop.keySet().iterator(); //키값 받아옴
		
		//반복
		while (keyIter.hasNext()) {
			String command = (String) keyIter.next();
			String handlerClassName = prop.getProperty(command);
			
			try {
				//문자열을 클래스로 변환
				Class handlerClass = Class.forName(handlerClassName);
				Object handlerInstance = handlerClass.newInstance();
				commandHandlerMap.put(command, handlerInstance);
				
			} catch (ClassNotFoundException e) {
				throw new ServletException(e);
			} catch (InstantiationException e) {
				throw new ServletException(e);
			} catch (IllegalAccessException e) {
				throw new ServletException(e);
			}
		}
	}
	
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
		process(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		process(request, response);
	}
	
	public void process(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String command = request.getRequestURI();
		
		if(command.indexOf(request.getContextPath()) == 0) {
			command = command.substring(request.getContextPath().length());
		}
		CommandHandler handler = (CommandHandler) commandHandlerMap.get(command);
		
		if(handler == null) {
			handler = new NullHandler();
		}
	
		String viewPage = null;
		try {
			viewPage = handler.process(request, response);
		} catch (Throwable e) {
			throw new ServletException(e);
		}
		
		RequestDispatcher dispatcher = request.getRequestDispatcher(viewPage);
		dispatcher.forward(request, response);
	}
}

 

실행결과 ▼

 

 

String command = request.getRequestURI();
		
if(command.indexOf(request.getContextPath()) == 0) {
	command = command.substring(request.getContextPath().length());
}

cmd 패턴을 사용한 예제와 비교하면 컨트롤러 서블릿의 process() 메소드에서 이 부분만이 달라졌다.

 

🎇 분석

🎈 request.getRequestURI(): 프로젝트 + 파일경로까지 가져온다

예)  http://localhost:9999/Project/hello.jsp
 ==>       /Project/hello.jsp  

🎈 request.getContextPath(): 프로젝트 Path만 가져온다 

==> /Project

🎈 indexOf(): 특정 문자나 문자열이 앞에서부터 처음 발견되는 인덱스를 반환하며 만약 찾지 못했을 경우 -1을 반환

==> /Project  의 인덱스: [0,1,2,3,4,5,6,7]


🎈 length(): 문자열의 길이를 알고자 할 때 사용

==> /Project = 8자

🎈 String substring : 입력 받은 인자값을 인덱스로 해당 위치에 포함하여 그 이후의 모든 문자열을 리턴

==> 8자 이후의 슬래시(/)포함 문자열을 저장

 ==> 요청 URI를 저장

 

'Dev > Java' 카테고리의 다른 글

DTO와 VO  (0) 2023.02.03
MVC 게시판 구현 메모  (0) 2022.10.05
MVC - 커맨드 패턴을 이용한 명령어 처리 분리  (0) 2022.10.04
MVC 패턴 정의  (0) 2022.10.04
Tiles를 이용한 컴포지트 뷰 구현  (1) 2022.09.30

댓글