使用应用程序控制器集中检索和调用请求处理组件,如命令和视图。
让我们用例子来讨论应用程序控制器设计模式是如何工作的。
问题
您希望集中并模块化操作和视图管理。
在表示层中,通常在每个请求到达时要做出两个决定:
动因
解决方案
使用应用程序控制器集中检索和调用请求处理组件,如命令和视图。
在表示层中,我们将传入的请求参数映射到特定的请求处理类,并查看处理每个请求的组件。
操作管理是指定位和调用操作来处理特定的请求,而视图管理是指导航和分派到适当的视图或视图生成机制。
结构
我们使用UML类图来表示解决方案的基本结构,本节中的UML序列图展示了解决方案的动态机制。
下面是表示Application Controller模式关系的类图。
类图
序列图
参与者和职责
客户端:调用应用程序控制器。在表示层中,前端控制器或截取过滤器(FrontController or an InterceptingFilter)通常完成此角色。
ApplicationController:使用Mapper将传入请求解析为相应的操作和视图,并将其委托或分派给相应的操作和视图。
映射器( Mapper) :使用Map将传入请求转换为适当的操作和视图。Mapper充当工厂。
map:保存对表示目标资源的句柄的引用。map可以实现为类或注册表。
目标( Target) :有助于完成特定请求的资源,包括命令、视图和样式表。
实施
让我们用一个例子来理解应用程序控制器模式。
步骤1: 让我们创建一些视图组件,如 index.jsp 和 viewstestudent.jsp 页面。
<%@ page language=<font>"java"</font><font> contentType=</font><font>"text/html; charset=ISO-8859-1"</font><font> pageEncoding=</font><font>"ISO-8859-1"</font><font>%> <!DOCTYPE html PUBLIC </font><font>"-//W3C//DTD HTML 4.01 Transitional//EN"</font><font> </font><font>"http://www.w3.org/TR/html4/loose.dtd"</font><font>> <html> <head> <meta http-equiv=</font><font>"Content-Type"</font><font> content=</font><font>"text/html; charset=ISO-8859-1"</font><font>> <title>Index Page</title> </head> <body> <a href=</font><font>"studentView.do?id=10"</font><font>>Show Student Information</a> </body> </html> </font>
步骤2: Application Controller Pattern 是J2EE设计模式,所以让我们创建部署描述符web.xml。
<web-app xmlns:xsi=<font>"http://www.w3.org/2001/XMLSchema-instance"</font><font> xmlns=</font><font>"http://java.sun.com/xml/ns/javaee"</font><font> xsi:schemaLocation=</font><font>"http:</font><font><i>//java.sun.com/xml/ns/javaee </i></font><font> http:</font><font><i>//java.sun.com/xml/ns/javaee/web-app_3_0.xsd" </i></font><font> id=</font><font>"WebApp_ID"</font><font> version=</font><font>"3.0"</font><font>> <display-name>ApplicationControllerWeb</display-name> <servlet> <servlet-name>front</servlet-name> <servlet-<b>class</b>>design.FrontController</servlet-<b>class</b>> </servlet> <servlet-mapping> <servlet-name>front</servlet-name> <url-pattern>*.<b>do</b></url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app> </font>
步骤3: 让我们像studentvo.java那样创建Value Object或DTO。
<b>public</b> <b>class</b> StudentVO {
<b>private</b> String id;
<b>private</b> String name;
<font><i>//constructor</i></font><font>
<b>public</b> StudentVO(String id, String name) {
<b>this</b>.id = id;
<b>this</b>.name = name;
}
</font><font><i>//setters and getters</i></font><font>
<b>public</b> String getId() {
<b>return</b> id;
}
<b>public</b> <b>void</b> setId(String id) {
<b>this</b>.id = id;
}
<b>public</b> String getName() {
<b>return</b> name;
}
<b>public</b> <b>void</b> setName(String name) {
<b>this</b>.name = name;
}
}
</font>
现在创建 Command 接口。
<b>public</b> <b>interface</b> Command {
String execute(RequestContext requestContext);
}
实现Command 接口的StudentViewCommand 类
<b>public</b> <b>class</b> StudentViewCommand implements Command {
@Override
<b>public</b> String execute(RequestContext requestContext) {
String id = <b>null</b>;
StudentVO studentVo = <b>null</b>;
id = requestContext.getParameter(<font>"id"</font><font>);
</font><font><i>//call delegate and dao </i></font><font>
studentVo = <b>new</b> StudentVO(id, </font><font>"Ramesh"</font><font>);
requestContext.setAttribute(</font><font>"student"</font><font>, studentVo);
<b>return</b> </font><font>"showStudent"</font><font>;
}
}
</font>
创建 ContextFactory 以处理上下文信息。
<b>import</b> java.util.Map;
<b>import</b> javax.servlet.http.HttpServletRequest;
<b>public</b> <b>class</b> ContextFactory {
<b>public</b> RequestContext getContextObject(HttpServletRequest request) {
Map < String, String[] > requestMap = <b>null</b>;
RequestContext requestContext = <b>null</b>;
HttpRequestMapper requestMapper = <b>null</b>;
requestMapper = <b>new</b> HttpRequestMapper();
requestMap = requestMapper.extract(request);
requestContext = <b>new</b> RequestContext(request.getRequestURI(), requestMap);
<b>return</b> requestContext;
}
<b>public</b> <b>void</b> bindContextObject(HttpServletRequest request, RequestContext requestContext) {
HttpRequestMapper requestMapper = <b>null</b>;
requestMapper = <b>new</b> HttpRequestMapper();
requestMapper.bind(request, requestContext.getResponseMap());
}
}
让我们创建 RequestContext 类。
<b>import</b> java.util.HashMap;
<b>import</b> java.util.Map;
<b>public</b> <b>class</b> RequestContext {
<b>private</b> String requestUri;
<b>private</b> Map < String, String[] > requestMap;
<b>private</b> Map < String, Object > responseMap;
<b>public</b> RequestContext() {
requestUri = <b>null</b>;
requestMap = <b>new</b> HashMap < String, String[] > ();
responseMap = <b>new</b> HashMap < String, Object > ();
}
<b>public</b> RequestContext(String requestUri, Map < String, String[] > requestMap) {
<b>this</b>.requestUri = requestUri;
<b>this</b>.requestMap = requestMap;
<b>this</b>.responseMap = <b>new</b> HashMap < String, Object > ();
}
<b>public</b> String getParameter(String param) {
String[] val = <b>null</b>;
<b>if</b> (param != <b>null</b>) {
val = requestMap.get(param);
}
<b>return</b> val[0];
}
<b>public</b> <b>void</b> setAttribute(String param, Object value) {
responseMap.put(param, value);
}
<b>public</b> String getRequestUri() {
<b>return</b> requestUri;
}
<b>public</b> Map < String, String[] > getRequestMap() {
<b>return</b> requestMap;
}
<b>public</b> Map < String, Object > getResponseMap() {
<b>return</b> responseMap;
}
}
步骤4: 是时候创建frontcontroller.java了。
<b>import</b> javax.servlet.ServletException;
<b>import</b> javax.servlet.http.HttpServlet;
<b>import</b> javax.servlet.http.HttpServletRequest;
<b>import</b> javax.servlet.http.HttpServletResponse;
<b>public</b> <b>class</b> FrontController <b>extends</b> HttpServlet {
<b>private</b> <b>static</b> <b>final</b> <b>long</b> serialVersionUID = 1 L;
@Override
<b>protected</b> <b>void</b> service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String page = <b>null</b>;
String view = <b>null</b>;
Dispatcher dispatcher = <b>null</b>;
RequestContext requestContext = <b>null</b>;
ContextFactory contextFactory = <b>null</b>;
ApplicationController applicationController = <b>null</b>;
<font><i>// plubbing code (security, authorization)</i></font><font>
</font><font><i>// extracting data from protocol</i></font><font>
contextFactory = <b>new</b> ContextFactory();
requestContext = contextFactory.getContextObject(request);
applicationController = <b>new</b> ApplicationController();
view = applicationController.process(requestContext);
</font><font><i>// binding data back to protocol</i></font><font>
contextFactory.bindContextObject(request, requestContext);
page = applicationController.mapViewToPage(view);
dispatcher = <b>new</b> Dispatcher();
dispatcher.dispatch(request, response, page);
}
}
</font>
步骤5: 创建 ApplicationController 类以及演示此模式所需的各个类。
<b>public</b> <b>class</b> ApplicationController {
<b>public</b> String process(RequestContext requestContext) {
String view = <b>null</b>;
Command command = <b>null</b>;
CommandHelper commandHelper = <b>null</b>;
commandHelper = <b>new</b> CommandHelper();
command = commandHelper.getCommand(requestContext.getRequestUri());
view = command.execute(requestContext);
<b>return</b> view;
}
<b>public</b> String mapViewToPage(String view) {
String page = <b>null</b>;
<b>if</b> (view != <b>null</b>) {
page = <font>"viewStudent.jsp"</font><font>;
}
<b>return</b> page;
}
}
</font>
<b>public</b> <b>class</b> CommandHelper {
<b>public</b> Command getCommand(String uri) {
Command command = <b>null</b>;
<b>if</b> (uri.contains(<font>"studentView.do"</font><font>)) {
command = <b>new</b> StudentViewCommand();
}
<b>return</b> command;
}
}
</font>
<b>public</b> <b>class</b> Dispatcher {
<b>public</b> <b>void</b> dispatch(HttpServletRequest request, HttpServletResponse response, String page) {
RequestDispatcher rd = <b>null</b>;
rd = request.getRequestDispatcher(page);
<b>try</b> {
rd.forward(request, response);
} <b>catch</b> (ServletException e) {
e.printStackTrace();
} <b>catch</b> (IOException e) {
e.printStackTrace();
}
}
}
<b>import</b> java.util.Map;
<b>import</b> java.util.Set;
<b>import</b> javax.servlet.http.HttpServletRequest;
<b>public</b> <b>class</b> HttpRequestMapper {
<b>public</b> Map < String, String[] > extract(HttpServletRequest request) {
Map < String, String[] > requestMap = <b>null</b>;
requestMap = request.getParameterMap();
<b>return</b> requestMap;
}
<b>public</b> <b>void</b> bind(HttpServletRequest request, Map < String, Object > responseMap) {
Set < String > keys = <b>null</b>;
keys = responseMap.keySet();
<b>for</b> (String param: keys) {
request.setAttribute(param, responseMap.get(param));
}
}
}
输出:
http:<font><i>//localhost:8001/javaT/</i></font><font> http:</font><font><i>//localhost:8001/javaT/studentView.do?id=10</i></font><font> browser : Student Id : 100 Student Name : Ramesh </font>
后果