扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
设计 JSP 的目的是将 Web 开发人员的任务与设计动态页面 UI 的非开发人员的任务分离开来。遗憾的是,JSP 对于许多设计人员来说太复杂了,为解决各种动态内容问题添加的软件层让他们觉得非常棘手。(例如,国际化要求将文本存储在其他地方并通过键来引用。)所以对于大多数项目,Java 开发人员只好自己处理 JSP 代码,这常常会包含本属于设计人员的工作,使他们的精力消耗在标记库和其他东西上,无法集中于 Java 代码。
与正统的方式不同,可以使用简单的 helper 对象,根据常规 servlet 构建简洁优美的 Web 界面。本文讲解如何以标准的 Java 形式编写动态 Web 页面的视图输出。我将解释这种方法的好处,并用一个计分应用程序演示这种方法,这个程序管理一个 NCAA 三月狂热 奖金池。
HTML 是动态的
这种纯 servlet 方法非常简单。它涉及一个 servlet 基类和一个定制的写出器对象,servlet 子类使用这个对象产生输出。代码很简洁,因为大多数 HTML 封装在 helper 对象的方法中,都可以按需重写。代码重用总是令人愉快,而且大多数 Web 站点的页面共享许多 HTML,所以重用应该是个重要的考虑因素。HTML 输出方法产生直观紧凑的 servlet 代码,因此可维护性很高,这使代码的维护成本差不多直接与代码规模成正比。通过将 JSP 界面重写成纯 servlet,可以将代码缩减三分之二。
例如,要根据用户权限输出一个链接,就需要下面这样冗长的构造代码:
<c:if test="${user.permission[ sessionScope.ConstantMap[ EDIT_WIDGET ] ] != 0}">
<c:url var="editUrl" value="/EditWidget.jsp"/>
<div class="navigation"><a href="<c:out value="${editUrl}"/>">Edit
this widget</a></div>
</c:if>
通过使用 Java 语法,代码就简洁多了:
if (user.getPermission(Constants.EDIT_WIDGET) != 0) out.printNavlinkDIV("/EditWidget.jsp", "Edit this widget"); |
另外,在同一个地方获取和输出业务对象,而不是通过请求对象传递它们,这也会节省大量代码。简洁是美。
使用 JSP 和其他视图技术可能是 Web 开发中最让人头疼的部分。JSP 页面不是 HTML 或 XML、Java 代码、JavaServer Pages Standard Tag Library(JSTL)代码或表达式语言(EL),而是这些东西的大杂烩。JSP 代码不但是奇怪的组合体,而且每个抽象层都给开发带来新的障碍。例如,对 JSP 页面进行调试简直就像探矿那样困难。您知道某个地方出了毛病,但是无法找到出问题的位置;神秘难懂的错误消息虽然指出了行号,但这个行号往往不是问题的真正所在。
JSP 技术不能扩展基类,所以代码重用只能通过 bean、include 文件和定制的标记库来进行。标记库太麻烦,不适合进行有效的重用。为您所做的每处 API 修改维护一个 XML 是非常麻烦的,而且 “标记设计就是语言设计”。结果是在本已分了很多层的接口上又加了一层。
我们正面对着全新的 World Wide Web。无论 Ajax 能否引领 Web 开发的方向,Web 站点都会继续向着更加智能化的方向发展。另外,尽管 HTML 本身总是声明性的,但是产生它的代码却不一定如此。JSP 技术和其他模板化系统必然过分复杂,因为它们试图以声明式的方式表达本质上动态的输出。这正是开发人员无法容忍在 JSP 源代码中添加 scriptlet 的原因:我们试图表达的逻辑 具有各种各样的形式。
通过将 HTML 封装成 Java 代码,可以简洁地表达输出逻辑。if 语句和 for 循环可以采用大家熟悉的形式。页面元素可以重构成方法,这样就很容易理解和维护它们。(对较大的 JSP 页面进行维护是非常麻烦的,非常容易出现错误,尤其是在缺少良好的注释的情况下。)通过使用纯 servlet,可以尽可能增加代码重用,因为不需要为每个页面的构造编写新的类。
狂热的设计
为了演示纯 servlet 的概念,我为一个 NCAA March Madness 锦标赛奖金池构建了一个计分界面。用户可以从参加锦标赛的 64 支球队中选择他们认为最出色的 20 支球队,并给每个球队分配一个加权的分数。比赛开始之后,他们的选择就变成只读的;当比赛结束时,管理员输入获胜球队的名称。根据用户选择的球队,自动地计算用户的累积分数并显示分数的排名。
这个项目大约花费了我三周的业余时间,大部分时间花在样式和图像上(毕竟我不是画家)。除了一个 HTML 文件和其他静态资源之外,UI 层由 21 个 Java 类组成,根据 JavaNCSS 的度量标准,一共有 1,334 个 Java 语句。
逃离 MVC
这里演示的纯 servlet 设计在客户机和业务逻辑之间建立一个视图层。Model-View-Controller(MVC,或者说 Model 2)实际上不是万能的,而且支持它的 Web 框架往往比较难以处理。Spring MVC 和 JavaServer Faces(JSF)太过复杂,我可以断言,Struts 的麻烦程度不亚于此,每次调整控制逻辑时都必须调整臃肿复杂的配置文件。N. Alex Rupp(参见 参考资料)甚至将 MVC 称为反模式,一种 “看似聪明其实非常愚蠢的” Web 技术。
例如,开发人员常常误解 Struts 中 Action 模块的用途。业务逻辑常常被放在这里(如果不是都放在 JSP 中的话)。将视图和控制器实现为 servlet 可以促使业务逻辑放入恰当位置,因为 servlet 明确关注与浏览器的接口。
对于这个项目,我使用了几个来自我自己的 elseforif-servlet 库的类。这是 设计的关键,因为它为生成 HTML 提供了一个方便的接口。但是,本文的重点不是这个库,而是证明我的方法的优点。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者