这篇是承接《轻量级 Java 开发框架 设计》系列Blog文的后续文章,本文将着重讲解使用 MVC 设计模式开发基于 Hasor 的应用程序。
在《查询数据库显示到页面(http://my.oschina.net/u/1166271/blog/186940)》一文中简要介绍了如何查询数据库的内容并显示到页面上,其中也用到了 MVC 开发模式。本文将提及不同形式下的 MVC 在 Hasor 中如何运用。
最传统的 MVC 分层是, M 模型层负责处理业务逻辑,V 视图层负责展现业务层输出的数据,C 控制器负责外界环境的输入,并将输入转换为模型层的输入,最终将模型层的输出派发到视图。这种工作方式如下图所示:
这种 MVC 强制要求必须通过 控制器 将请求转发到视图上才能完成页面展示。这是典型的 MVC 模型,理解起来并不困难。但是基于这种模型开发人员在开发 Web 应用程序工作中会遇到问题。
首先我们知道,开发 WEB 应用程序需要一个展示页面。页面展示技术可以是 jsp、模板等。使用上面这种方式,开发人员要记住控制器、页面。两个地址。而控制器地址和页面地址往往会出现不一致或者无法根据一个给定的规则进行互相推导。
这样一来在调试过程中,开发人员往往会无从下手,到底是哪个控制转到这个视图,又或者这个控制器最终由哪个页面来展示。当然通过跟踪代码这根本不是问题。但是不要忘记的是这回耗去开发人员大量的时间。
即使开发人员完全熟悉了对应关系,我们仍然不能确保这套页面在软件生命周期结束之前都是由一个人去维护,后来的人依然会及其痛苦。
因此有很多项目放弃了这种模式。当然如果您的项目只有一个显示页面,同时具有多个入口地址这种模式无非是最佳的选择。
-----------------------------------------------------------------
根据上面这种情况,会出现一个变版 MVC 。其中不同的是请求直接进入 View ,由 View 调用 Mode。从而省去 控制器的开发。如下图所示:
这种开发模式有点趋向于比较原始的 JSP + Bean 没错,用 JSP + Bean 很准确的描述这种模式。这种模式改良了传统 MVC 使其更加适用于 Web 应用程序开发。在 Web 开发上可以体现以下几个优点:
1.开发人员不必记住 控制器 和 视图的 映射关系。
2.可以所见即所得的方式直接访问 View 视图,通过根据视图的需要调用一个或多个 Mode。
不过这种模式下,缺乏 action 在页面展示之前的逻辑处理。
-----------------------------------------------------------------
介于上面两个 MVC 开发方式的优缺点,有很多同学就会将两种模式整合到一起,整合之后的 MVC 结构看上去是这样的:
其实不难看出,这种 MVC 只是简单的将前面两种 MVC 模式混合起来一起应用罢了。在实际开发中,一般会直接访问 控制器 地址,通过控制器做展示前的逻辑处理。而后转给视图做展示,对于视图而言又多了一个直接调用 Model 通道。通过这个通道可以减少控制器的编码量。
在实际应用中,对于一些逻辑简单的页面来说有的同学就会直接访问视图,通过视图直接调用模型展示数据。转而略去 控制器部分代码。这相当于上面图中输入有了两条线。
这种 MVC 开发方式具有很强的灵活性,有很多公司都在采用这种模式。
-----------------------------------------------------------------
第一种 MVC在 Hasor 中的体现:
那么接下来如何使用 Hasor 开发基于上面三种 MVC 模式的应用程序呢?
大家先来看第一种,第一种比较典型,需要:控制器、视图、模型。三个元素。下面是三个元素的例子代码:
// M 模型层代码,负责查询数据库中用户列表 public class UserService { @Inject private JdbcTemplate jdbcTemplate; // /*取得用户列表*/ public List<UserBean> getUserList() { List<UserBean> userList = jdbcTemplate.queryForList("select * from TB_User", UserBean.class); return userList; } }
//C 控制器 负责接受请求参数,并调用模型层,最终派发视图显示。 @Controller("/mgr/user") public class UserAction extends AbstractController { @Inject private UserService userService;//依赖输入模型层服务类 /*获取用户列表,转发到‘/mgr/user/userList.jsp’*/ @Forword public String userList() { List<UserBean> userList = userService.getUserList(); this.setAttr("userList", userList); return "/mgr/user/userList.jsp"; } }
//最后使用 JSP 作为 View 表现层,配合 JSTL 标签库展示用户列表数据。 <%@page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Demo</title> </head> <body> <table> <thead> <tr> <td width="290px;">ID</td> <td width="120px;">姓名</td> <td width="290px;">帐号</td> <td>邮箱</td> </tr> </thead> <tbody> <c:forEach var="user" items="${userList}"> <tr> <td>${user.userUUID}</td> <td>${user.name}</td> <td>${user.loginName}</td> <td>${user.email}</td> </tr> </c:forEach> </tbody> </table> </body> </html>
-----------------------------------------------------------------
第二种 MVC在 Hasor 中的体现:
修改上面这个例子,在 UserServices 上添加 @Bean 注解并给定一个名字,这样方便在 View 层页面中找到它。从而完成第二种 MVC 中 V 访问 M 的需要。修改代码如下:
@Bean("UserService") public class UserService { @Inject private JdbcTemplate jdbcTemplate; // /*取得用户列表*/ public List<UserBean> getUserList() { List<UserBean> userList = jdbcTemplate.queryForList("select * from TB_User", UserBean.class); return userList; } }
接着我们只需要 在页面中 调用这个 Services 即可,由于使用的页面展示技术为 JSP 因此需要借助 Hasor JSTL 标签库进行调用。
这部分逻辑的执行顺序应该是这个样子的:
1.取得名称为“UserService”的服务对象。
2.调用 userList 属性的 getUserList 方法取得用户列表。
3.使用 JSTL 或者其它手段在页面中展示用户数据。
<%@page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ taglib prefix="hs" uri="http://project.hasor.net/hasor/schema/jstl" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Demo</title> </head> <body> <table> <thead> <tr> <td width="290px;">ID</td> <td width="120px;">姓名</td> <td width="290px;">帐号</td> <td>邮箱</td> </tr> </thead> <tbody> <hs:defineBean bean="UserService" var="userService"/> <c:forEach var="user" items="${userService.userList}"> <tr> <td>${user.userUUID}</td> <td>${user.name}</td> <td>${user.loginName}</td> <td>${user.email}</td> </tr> </c:forEach> </tbody> </table> </body> </html>
-----------------------------------------------------------------
第三种 MVC在 Hasor 中的体现:
第三种 MVC 其实就是将前两个例子综合到一起,这里就不在展示代码是如何开发。这种方式下无外乎就是请求 控制器,控制器将数据放入 request 然后将派发给 JSP 视图做处理。 JSP 在处理过程中又再次通过 hs:defineBean 标签去访问其它 Servlet 。从而协同完成页面开发。
----------------------------------------------------------------
目前的开发代码存放于(包括Demo程序):
Github: https://github.com/zycgit/hasor
git@OSC: http://git.oschina.net/zycgit/hasor
非常感谢您百忙之中抽出时间来看这一系博文。可以通过Maven 中央仓库网站 http://search.maven.org/ 搜索 Hasor 下载 hasor 的相关代码。