알맞은 웹 응용 프로그램은 여러 가지 디자인 패턴으로 구성됩니다. 가장 중요한 것만 언급하겠습니다.
사용하려는 핵심 (아키텍처) 디자인 패턴은 Model-View-Controller pattern 입니다. 컨트롤러 (투입)을 직접 생성하는 서블릿에 의해 표현 될 / 특정 사용 모델 및 보기 요청에 기반. 모델은 자바 빈즈 클래스에 의해 표현 될 것입니다. 이것은 종종 행동 (행동)을 포함하는 비즈니스 모델 과 데이터 (정보)를 포함하는 데이터 모델로 더 나눌 수 있습니다. 보기 제 (에 직접 액세스 할 수있는 JSP 파일로 표현되어야하는 데이터 ) 모델 EL (표현 언어)로합니다.
그런 다음 작업 및 이벤트 처리 방법에 따라 변형이 있습니다. 인기있는 것은 :
요청 (액션) 기반 MVC : 구현이 가장 간단합니다. ( 비즈니스 ) 모델 로 직접 작동 HttpServletRequest
및 HttpServletResponse
객체. 요청 매개 변수 (대부분)를 직접 수집, 변환 및 검증해야합니다. 보기는 요청에서 일반 바닐라 HTML / CSS / JS하고 유지하지 않는 국가에 의해 표현 될 수있다. 이것이 Spring MVC , Struts and Stripes의 작동 방식입니다.
컴포넌트 기반 MVC : 구현하기가 어렵습니다. 그러나 모든 "원시"서블릿 API가 완전히 추상화 된 더 간단한 모델과보기로 끝납니다. 요청 매개 변수를 직접 수집, 변환 및 유효성 검증 할 필요가 없습니다. 컨트롤러는 이 작업과 설정합니다의 수집, 변환 및 검증 요청 매개 변수 않는 모델 . 모델 속성과 직접 작동하는 동작 방법을 정의하기 만하면됩니다. 보기는 JSP의 태그 라이브러리 또는 차례로 / JS를 HTML / CSS를 생성하는 XML 요소의 맛에서 "구성 요소"로 표시됩니다. 뷰 의 상태후속 요청은 세션에서 유지 보수됩니다. 이는 서버 측 변환, 유효성 검사 및 값 변경 이벤트에 특히 유용합니다. 이것은 JSF , Wicket 및 Play 중 다른 방법입니다 ! 공장.
참고로, 자체 개발 한 MVC 프레임 워크를 사용하여 취미 생활을하는 것은 매우 훌륭한 학습 연습이며 개인 / 개인 목적으로 유지하는 한 권장합니다. 그러나 전문가가되면 자신의 것을 재창조하기보다는 기존 프레임 워크를 선택하는 것이 좋습니다. 기존의 잘 개발 된 프레임 워크를 학습하면 강력한 프레임 워크를 직접 개발하고 유지 관리하는 것보다 시간이 덜 걸립니다.
아래의 자세한 설명에서는 구현하기가 쉽기 때문에 MVC를 요청하도록 제한합니다.
먼저 컨트롤러 부분은 전면 컨트롤러 패턴 (특수한 종류의 중재자 패턴 )을 구현해야합니다 . 모든 요청의 중앙 집중식 진입 점을 제공하는 단일 서블릿으로 만 구성되어야합니다. 요청에 의해 제공되는 정보 (예 : 경로 정보 또는 서블릿 경로, 방법 및 / 또는 특정 매개 변수)를 기반으로 모델을 작성해야합니다 . 비즈니스 모델이 라고 Action
아래에 HttpServlet
예.
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Action action = ActionFactory.getAction(request);
String view = action.execute(request, response);
if (view.equals(request.getPathInfo().substring(1)) {
request.getRequestDispatcher("/WEB-INF/" + view + ".jsp").forward(request, response);
}
else {
response.sendRedirect(view); // We'd like to fire redirect in case of a view change as result of the action (PRG pattern).
}
}
catch (Exception e) {
throw new ServletException("Executing action failed.", e);
}
}
작업을 실행하면 일부 식별자가 반환되어 뷰를 찾습니다. JSP의 파일 이름으로 사용하는 것이 가장 간단합니다. 특정에이 서블릿을지도 url-pattern
에서 web.xml
예를 들면 /pages/*
, *.do
또는 단지 *.html
.
예를 들어 접두사 패턴의 경우 http://example.com/pages/register/pages/*
와 같은 URL을 호출 할 수 있습니다 , http://example.com/pages/login 등 및 제공 /WEB-INF/register.jsp
, /WEB-INF/login.jsp
적절한 GET 및 POST 작업으로 . 부품 register
, login
등에 의해 후 가능한 request.getPathInfo()
상기 예에서와 같이.
사용중인 경우 접미사 패턴이 좋아 *.do
, *.html
등, 다음 수 다음 URL의 같은 호출 http://example.com/register.do , http://example.com/login.do 등하고 변경해야 이 답변의 코드 예제 ( 및 ActionFactory
)를 대신 하여 register
및 login
부분 을 추출하십시오 request.getServletPath()
.
은 Action
추적해야 전략 패턴을 . 전달 된 것을 기반으로 작업을 수행해야하는 추상 / 인터페이스 유형으로 정의해야합니다 .추상 메소드 인수를 명령 패턴 과의 차이점입니다) . 구현을 생성 하는 동안 전달되는 인수 ).
public interface Action {
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
Exception
과 같은 맞춤 예외 를 사용하여 더 구체적으로 만들 수 있습니다 ActionException
. 기본 킥오프 예일 뿐이며 나머지는 모두 귀하에게 달려 있습니다.
다음 LoginAction
은 이름으로 사용자가 로그인 하는 예입니다 . 그 User
자체가 데이터 모델 입니다. 보기 의 존재를 알고있다 User
.
public class LoginAction implements Action {
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userDAO.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user); // Login user.
return "home"; // Redirect to home page.
}
else {
request.setAttribute("error", "Unknown username/password. Please retry."); // Store error message in request scope.
return "login"; // Go back to redisplay login form with error.
}
}
}
은 ActionFactory
추적해야 하는 팩토리 메소드 패턴을 . 기본적으로 추상 / 인터페이스 유형의 구체적인 구현을 반환하는 생성 방법을 제공해야합니다. 이 경우 Action
요청에서 제공 한 정보를 기반으로 인터페이스 구현을 반환해야합니다 . 예를 들어, 방법 과 의 PathInfo 합니다 (의 PathInfo 쿼리 스트링 제외 요청 URL의 컨텍스트 및 서블릿 경로 후의 부분이다).
public static Action getAction(HttpServletRequest request) {
return actions.get(request.getMethod() + request.getPathInfo());
}
그만큼 actions
차례에 약간의 정적 / applicationwide해야 Map<String, Action>
알려진 모든 조치를 보유하고 있습니다. 이지도를 작성하는 방법은 귀하에게 달려 있습니다. 하드 코딩 :
actions.put("POST/register", new RegisterAction());
actions.put("POST/login", new LoginAction());
actions.put("GET/logout", new LogoutAction());
// ...
또는 클래스 경로의 속성 / XML 구성 파일을 기반으로 구성 가능 : (의사)
for (Entry entry : configuration) {
actions.put(entry.getKey(), Class.forName(entry.getValue()).newInstance());
}
또는 특정 인터페이스 및 / 또는 주석을 구현하는 클래스에 대한 클래스 경로의 스캔을 동적으로 기반으로합니다 (의사)
for (ClassFile classFile : classpath) {
if (classFile.isInstanceOf(Action.class)) {
actions.put(classFile.getAnnotation("mapping"), classFile.newInstance());
}
}
"아무것도하지 말 것"을 명심하십시오 Action
맵핑이없는 경우 을 작성하십시오. 예를 들어 request.getPathInfo().substring(1)
그때 직접 반환하자 .
다른 패턴
그것들은 지금까지 중요한 패턴이었습니다.
한 단계 더 나아가 려면 Facade 패턴 을 사용하여 Context
클래스 를 작성 하여 요청 및 응답 오브젝트를 랩핑하고 요청 및 응답 오브젝트에 위임하는 몇 가지 편리한 메소드를 제공하고 Action#execute()
대신 메소드에 인수로 전달하십시오 . 이는 원시 서블릿 API를 숨기도록 추가 추상 계층을 추가합니다. 그런 다음 기본적으로 모든 구현 에서 0 import javax.servlet.*
선언 으로 끝나야합니다 Action
. JSF 용어로 이것이 클래스 FacesContext
와 ExternalContext
클래스가하는 일입니다. 이 답변 에서 구체적인 예를 찾을 수 있습니다 .
그런 다음 요청 매개 변수 수집, 변환, 유효성 검증, 모델 값 업데이트 및 조치 실행 태스크를 분할하기 위해 추가 추상화 계층을 추가하려는 경우 의 상태 패턴 이 있습니다. JSF 용어로, 이것은LifeCycle
하는 일입니다.
그런 다음 모델에 첨부 할 수 있고 동작이 요청 기반 수명주기의 상태에 따라 달라지는 컴포넌트 기반보기를 작성하려는 경우에 대한 복합 패턴 이 있습니다. JSF 용어로, 이것은UIComponent
대표하는 것입니다.
이 방법으로 구성 요소 기반 프레임 워크를 향해 조금씩 진화 할 수 있습니다.
또한보십시오: