使用应用程序控制器集中检索和调用请求处理组件,如命令和视图。
让我们用例子来讨论应用程序控制器设计模式是如何工作的。
问题
您希望集中并模块化操作和视图管理。
在表示层中,通常在每个请求到达时要做出两个决定:
- 首先,必须将传入请求解析为服务于请求的操作。这叫做行动管理。
- 其次,找到并发送适当的视图。这称为视图管理。
动因
- 您希望重用操作和视图管理代码。
- 您希望改进请求处理的可扩展性,例如逐步向应用程序添加用例功能。
- 您希望提高代码模块性和可维护性,从而更容易扩展应用程序,并且更容易测试请求处理代码的独立部分,而不依赖于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 |
后果
- 改善模块化
- 提高可重用性
- 提高可扩展性