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