https://tavi.tistory.com/51?category=1086720
MVC - 커맨드 패턴을 이용한 명령어 처리 분리
https://tavi.tistory.com/50?category=1086720 MVC 패턴 정의 0. 모델 1 구조 모델 1 구조는 JSP를 이용한 단순한 모델이다. (기존에 했던 모든 것들..) JSP에서 요청 처리 및 뷰 생성을 처리해서 구현이 쉽지만..
tavi.tistory.com
컨트롤러가 알맞은 로직을 수행하려면 클라이언트가 어떤 기능을 요청하는 지 구분할 수 있어야 하는데
웹 브라우저를 통해 명령어를 전달하는 방법에는 두 가지가 있다.
- 특정 이름의 파라미터에 명령어 정보를 전달 (ex. url에 ?type=date 를 입력)
- 요청 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 |
댓글