本文是《轻量级 Java Web 框架架构设计》的系列博文。
上一篇 提到了 MVC 的两种模式,目前 Smart Framework 仅提供了“反向 MVC 模式”,计划在 2.0 版本中实现“正向 MVC”。今天抽了一点时间,扩展了一下框架,详细开发过程如下:
第一步:定义一个 JavaBean 用于封装 View 与 Model,取名为 Page。
public class Page extends BaseBean { private String path; // 页面路径 private Map<String, Object> data; // 相关数据 public Page(String path) { this.path = path; data = new HashMap<String, Object>(); } public Page data(String key, Object value) { data.put(key, value); return this; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public Map<String, Object> getData() { return data; } public void setData(Map<String, Object> data) { this.data = data; } }第二步:开发一个 Action,用于接收请求。
@Bean public class FooAction extends BaseAction { @Request("get:/foo") public Page index() { String aaa = "aaa"; String bbb = "bbb"; String ccc = "ccc"; return new Page("foo.jsp") .data("aaa", aaa) .data("bbb", bbb) .data("ccc", ccc); } }
接收 /foo 请求,模拟在 Action 中处理业务逻辑,最后转发到 foo.jsp,并传递相应的数据(通过链式方法实现)。
第三步:编写一个 JSP,用户展现数据。
<%@ page pageEncoding="UTF-8" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Foo</title> </head> <body> ${aaa}, ${bbb}, ${ccc} </body> </html>
使用 JSTL 表达式获取相应的数据,即通过 key 获取 value。
第四步:扩展 DispatcherServlet,用户处理 Page 类型的 Action 返回值。
@WebServlet(urlPatterns = "/*", loadOnStartup = 0) public class DispatcherServlet extends HttpServlet { ... private void handleActionMethod(ActionBean actionBean, List<Object> paramList, HttpServletRequest request, HttpServletResponse response) { ... // 调用 Action 方法 Object actionMethodResult = ... // 判断返回值类型 if (actionMethodResult != null) { if (actionMethodResult instanceof Result) { ... } else if (actionMethodResult instanceof Page) { // 若为 Page 类型,则 转发 或 重定向 到相应的页面中 Page page = (Page) actionMethodResult; String path = page.getPath(); if (path.startsWith("/")) { // 重定向请求 redirectRequest(page, response); } else { // 转发请求 forwordRequest(page, request, response); } } } } ... private void redirectRequest(Page page, HttpServletResponse response) { try { // 获取路径 String path = page.getPath(); // 重定向请求 response.sendRedirect(path); } catch (Exception e) { logger.error("页面重定向出错!", e); throw new RuntimeException(e); } } private void forwordRequest(Page page, HttpServletRequest request, HttpServletResponse response) { try { // 获取路径 String path = "/jsp/" + page.getPath(); // 初始化 Request 属性 Map<String, Object> data = page.getData(); if (MapUtil.isNotEmpty(data)) { for (Map.Entry<String, Object> entry : data.entrySet()) { request.setAttribute(entry.getKey(), entry.getValue()); } } // 转发请求 request.getRequestDispatcher(path).forward(request, response); } catch (Exception e) { logger.error("页面转发出错!", e); throw new RuntimeException(e); } } }
以上考虑到了“转发(forword)”与“重定向(redirect)”两种模式,若返回的 path 中以“/”开头,则说明是重定向,否则即为转发。
此外,需要在 DispatchServlet 初始化的时候,将所有 JSP 请求注册到 JspServlet(由 Web 服务器提供)中:
... // 用 JspServlet 映射所有 JSP 请求 ServletRegistration jspServletRegistration = context.getServletRegistration("jsp"); jspServletRegistration.addMapping("/jsp/*"); ...
第五步:编译并启动服务器,发送请求进行测试。
发送 /foo 请求,返回如下页面:
通过简单扩展,实现了“正向 MVC”。此时,Smart Framework 可同时支持正向与反向 MVC,从此,我们的小伙伴们又多了一种选择,而且更加亲切!
期待您的点评!