首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

设计 REST 作派的 MVC 框架

2012-08-30 
设计 REST 风格的 MVC 框架Java 开发者对 MVC 框架一定不陌生,从 Struts 到 WebWork,Java MVC 框架层出不

设计 REST 风格的 MVC 框架

Java 开发者对 MVC 框架一定不陌生,从 Struts 到 WebWork,Java MVC 框架层出不穷。我们已经习惯了处理 *.do 或 *.action 风格的 URL,为每一个 URL 编写一个控制器,并继承一个 Action 或者 Controller 接口。然而,流行的 Web 趋势是使用更加简单,对用户和搜索引擎更加友好的 REST 风格的 URL。例如,来自豆瓣的一本书的链接是 http://www.douban.com/subject/2129650/,而非 http://www.douban.com/subject.do?id=2129650

有经验的 Java Web 开发人员会使用 URL 重写的方式来实现类似的 URL,例如,为前端 Apache 服务器配置 mod_rewrite 模块,并依次为每个需要实现 URL 重写的地址编写负责转换的正则表达式,或者,通过一个自定义的 RewriteFilter,使用 Java Web 服务器提供的 Filter 和请求转发(Forward)功能实现 URL 重写,不过,仍需要为每个地址编写正则表达式。

既然 URL 重写如此繁琐,为何不直接设计一个原生支持 REST 风格的 MVC 框架呢?

要设计并实现这样一个 MVC 框架并不困难,下面,我们从零开始,仔细研究如何实现 REST 风格的 URL 映射,并与常见的 IoC 容器如 Spring 框架集成。这个全新的 MVC 框架暂命名为 WebWind。

当扫描到标记有 @Mapping 注解的方法时,需要首先检查 URL 与方法参数是否匹配,UrlMatcher 用于将 @Mapping 中包含 $1、$2 ……的字符串变为正则表达式,进行预编译,并检查参数个数是否符合方法参数,代码见清单 5。


清单 5. 定义 UrlMatcher

?

JspTemplate 用于渲染页面,只需要传入 JSP 的路径,将 Model 绑定到 HttpServletRequest,就可以调用 Servlet 规范的 forward 方法将请求转发给指定的 JSP 页面并渲染。代码见清单 14。


清单 14. 定义 JspTemplate

?

对于正常的 Field 参数,保存在成员变量 Map<String, List<String>> formItems 中,通过覆写 getParameter()、getParameters() 等方法,就可以让客户端把 MultipartHttpServletRequest 也当作一个普通的 Request 来操作,代码见清单 29。


清单 29. 覆写 getParameter

public class MultipartHttpServletRequest extends HttpServletRequestWrapper {     ...     @Override     public String getParameter(String name) {         List<String> list = formItems.get(name);         if (list==null)             return null;         return list.get(0);     }     @Override     @SuppressWarnings("unchecked")     public Map getParameterMap() {         Map<String, String[]> map = new HashMap<String, String[]>();         Set<String> keys = formItems.keySet();         for (String key : keys) {             List<String> list = formItems.get(key);             map.put(key, list.toArray(new String[list.size()]));         }         return Collections.unmodifiableMap(map);     }     @Override     @SuppressWarnings("unchecked")     public Enumeration getParameterNames() {         return Collections.enumeration(formItems.keySet());     }     @Override     public String[] getParameterValues(String name) {         List<String> list = formItems.get(name);         if (list==null)             return null;         return list.toArray(new String[list.size()]);     } } 

?

为了简化配置,在 Web 应用程序启动的时候,自动检测当前 ClassPath 下是否有 Commons FileUpload,如果存在,文件上传功能就自动开启,如果不存在,文件上传功能就不可用,这样,客户端只需要简单地把 Commons FileUpload 的 jar 包放入 /WEB-INF/lib/,不需任何配置就可以直接使用。核心代码见清单 30。


清单 30. 检测 Commons FileUpload

class Dispatcher {     private boolean multipartSupport = false;     ...     void initAll(Config config) throws Exception {         try {             Class.forName("org.apache.commons.fileupload.servlet.ServletFileUpload");             this.multipartSupport = true;         }         catch (ClassNotFoundException e) {             log.info("CommonsFileUpload not found.");         }         ...     }     void handleExecution(Execution execution, HttpServletRequest request,             HttpServletResponse response) throws ServletException, IOException {         if (this.multipartSupport) {             if (MultipartHttpServletRequest.isMultipartRequest(request)) {                 request = new MultipartHttpServletRequest(request, maxFileSize);             }         }         ...     }     ... } 

?

小结

要从头设计并实现一个 MVC 框架其实并不困难,设计 WebWind 的目标是改善 Web 应用程序的 URL 结构,并通过自动提取和映射 URL 中的参数,简化控制器的编写。WebWind 适合那些从头构造的新的互联网应用,以便天生支持 REST 风格的 URL。但是,它不适合改造已有的企业应用程序,企业应用的页面不需要搜索引擎的索引,其用户对 URL 地址的友好程度通常也并不关心。

热点排行