当ASP.NET撞上JSF之构建应用程序的异同

简介:
理想情况下,ASP.NET和JSF web页面应该包含很少的代码而且只是包含必要的HTML和标签来生成页面的组件,一个页面的事件逻辑驻留于代码文件中。在ASP.NET中,每个web 页面与一个相应的子类化页面ASP.NET类的.NET类文件相关联。有时,这些文件被引用为"code-behind"文件。在JSF中,每个web页 面都有一个相关联的支持JavaBean类。ASP.NET的code-behind文件和JSF支持bean都包含页面属性(例如标签和输入域)。 JSF bean是用Java编写的,而ASP.NET code-behind文件可以使用任何.NET语言(例如VB.NET或C#)编写。ASP.NET code-behind类负责处理相关联的页面事件。这个处理一个组件事件的Java类不必是页面的支持JavaBean。过一会我们再讨论它。值得注意 的是,在ASP.NET中分离的code-behind文件可能是不必要的-有可能在页面本身的代码中实现事件处理。然而,一般来说,这被认为是一种不好 的编码实践,因为这样以来将会导致混淆HTML和代码问题。

  下面是我们的示例ASP.NET和JSF应用程序的两幅快照。由于两种组件的内在特性以及我也没有对之应用匹配的视觉式样,所以它们看起来略微有些不同。在两个页面中,显示一个会议房间表格,还有进一步了解相应房间的View按钮和预订该房间的Reserve按钮。

按此在新窗口浏览图片
ASP.NET程序快照
按此在新窗口浏览图片
JSF程序快照
  上面这些组件都是通过拖动添加的,然后通过修改一个属性面板定制它们的外观和行为。当然,我还可以通过编辑它们在HTML源码中的标签来定制这些组件。在此不赘述。下面,我们重点分析一下在这些web页面背后的代码文件,从而进一步分析事件代码。

我认为,以表格形式显示数据是不错的开始,因为这种情况在应用程序是常见的。为此,ASP.NET和JSF也都没有忽略这种实现,两类被显示的组件都提 供了内置功能来实现诸如排序和分页显示等效果。在ASP.NET 2.0之前,ASP.NET就已经提供了许多数据显示组件,其中DataGrid组件是使用最广泛的。另外,ASP.NET 2.0发行中引入了一个新的GridView组件。在本例中,我使用了这种组件,因为它添加了一些新的有用的特性。ASP.NET组件利用ADO.NET 技术,这也是整个.NET框架的数据存取技术-ADO.NET提供了一种健壮的对象模型来操作各种类型的数据源。例如,Dataset对象允许你以一种断 开的方式来使用数据。这意味着,为了使用数据,你的应用程序并不需要连续地连接到数据库上。一个Dataset还允许你隐蔽在它的接口后面的数据库细节, 从而使你以对应用程序的其它部分极小的影响来切换数据库。我在本例中所使用的JSF组件是一个与Java Studio Creator一同发行的表格组件。它使用一个DataProvider对象-它允许你利用JDBC Rowset技术。JDBC Rowset还能使你在断开的情况下以一种易于使用的方式使用数据库。
  每个这些启动页面都各自包含一个单一的标签组件实现页面头部。在一个页面的事件处理器中可以存取和修改该页面组件。通过在可视化编辑器中简单地 双击该组件,你可以把大多数的事件挂接到一个组件上。而且,这将会把你导向代码文件中,在此你可以添加代码。如我们前面已经注意到的,与web页面相关联 的ASP.NET页面类正是你的事件代码将驻留的地方。在JSF中,并不象这样简单。JSF事件遵循Observer设计模式。需要被通知某些事件的对象 都要把它们自己注册为该事件相应的听者(listener)。在JSF中共有两种类型的事件:Value Changed事件和Action事件。典型地,Value Changed事件发生在例如列表框选择这样的行为中,而Action事件将产生例如按钮点击这样的用户行为。任何Java类都能够响应于一个web表单 的事件。然而,JSF页面的支持bean是实现事件方法的很方便的位置,例如Sun Java Studio Creator就假定你把相应的实现放置于此。

当启动一个ASP.NET应用程序时,位于一个文件web.config中的配置信息 被分析和应用。每个ASP.NET应用程序都有一个web.config。我通过把连接串存储到Mysql数据库中来利用这个文件。web.config 经常用来存储数据库连接串以达到在代码外保持这个连接。下面展示了web.config文件的一部分代码片断:

<connectionStrings>
<add name="MyConnectionString"
connectionString="Driver={MySQL ODBC 3.51 Driver};server=localhost;database=test;uid=testuser;pwd=testpassword"
providerName="System.Data.Odbc"/>
</connectionStrings>

   JSF应用程序依赖于典型的基于Servlet的Java应用程序架构。一个'WEB-INF'文件夹下带有一些子文件夹和一个包含应用程序设置(很类 于ASP.NET的web.config)信息的文件web.xml。注意,这里的Mysql连接串并不保存在这个JSF应用程序的web.xml文件 中。而是,Studio Creator自动地把该连接添加到服务器的配置文件中,而我们的应用程序通过JNDI(Java命名和目录接口)来存取它-这是一种搜索J2EE服务的 常用方式。每一个JSF应用程序的web.xml文件都指定一个FacesServlet类型的Java Servlet。这个FacesServlet负责配置应用程序的相应于它的JSF使用的设置。在一个JSF应用程序中,所有的请求都要"流经 "FacesServlet。这个控件Servlet控制基于组件事件结果的应用程序页面之间的流程。这被称作"Front Controller"设计模式。在ASP.NET中没有使用这种级别的间接方式,则是由页面本身控制页面流,称作"Page Controller"设计模式。通过参考存储在一个配置文件faces-config.xml中的页面到页面映射,这个FacesServlet知道如 何路由请求。这个配置文件也包含一些我们将要强调的JSF配置信息。

  另外,ASP.NET和JSF页面拥有非常相似的生命周期。在前 面,我们已经讨论了组件是如何基于用户行为生成事件的,而事件仅是这种生命周期的一部分。从一种高级视图角度来观察一个页面的生命周期,其大致流程为:用 户发出一个请求并初始化页面,然后,页面的整个组件树被读入并且组件的状态被恢复,根据用户行为处理事件并更新组件值,最后结果页面被生成到用户端。当 然,实际情形可能比这更为复杂些,而且还有一些重要阶段(例如数据校验)掺杂在这些步骤中。在JSF和ASP.NET之间的一个关键区别在于,组件如何被 生成到用户。ASP.NET组件在页面上生成自己;而在JSF中,组件能够自我生成,但是更为经常的是,它们把生成代理到特定的Renderer对象(可 用于一个RenderKit中)。针对每一种不同类型的描述媒体提供一种不同的RenderKit。每一个JSF实现都会提供一个缺省的HTML RenderKit。这意味着,同一个JSF组件可能被以不同形式生成到一种web浏览器或无线设备上-通过简单地加入一个不同的Render对象,这是 一种相当强的生成能力。

  一个很方便的添加代码而又不依赖于任何特定类型的用户请求的时机是当页面对象被初始化时。ASP.NET提供 了一个Page_Load事件-它当用户作任何类型的页面请求时被调用。在JSF页面中,你可以使用类构造器方法来实现同样的页面初始化逻辑。下面是两种 应用程序的相应于用户在数据显示组件上所做动作的事件处理代码。

//ConferenceRooms.Java事件代码:
public String btnViewReservations_action() {
//把选定行的相应的房间的id和name保存起来...
Object id = getValue("#{currentRow.value['conference_rooms.room_id']}");
Object name = getValue("#{currentRow.value['conference_rooms.room_name']}");
ReservationsSessionBean resBean =(ReservationsSessionBean)this.getBean("ReservationsSessionBean");
resBean.setRoomId(id.toString());
resBean.setRoomName(name.toString());
return "view";
}
public String btnMakeReservation_action() {
Object id = getValue("#{currentRow.value['conference_rooms.room_id']}");
ReservationsSessionBean resBean = (ReservationsSessionBean)this.getBean("ReservationsSessionBean");
resBean.setRoomId(id.toString());
return "reserve";
}
//ConferenceRooms.cs事件代码
protected void GrdVwRooms_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName.Equals("Sort")) {
SortDirection sd;
if (((SortDirection)Session["sortRooms"]).Equals(SortDirection.Ascending)) {
sd = SortDirection.Descending;
}
else {
sd = SortDirection.Ascending;
}
Session.Add("sortRooms", sd);
this.GrdVwRooms.Sort(e.CommandArgument.ToString(), sd);
}
else
{
DataKey data = GrdVwRooms.DataKeys[Convert.ToInt32(e.CommandArgument)];
Session.Add("roomId", data.Values["room_id"].ToString());
Session.Add("roomName", data.Values["room_name"].ToString());
if (e.CommandName.Equals("Reserve")) {
Server.Transfer("Reserve.aspx");
}
else
{
if (e.CommandName.Equals("View")) {
Server.Transfer("RoomReservations.aspx");
}
}
}
}

   这里的代码有一点不同,Java类被分成了两个方法。这两个Java事件都是Action事件。我把这个ASP.NET应用程序中的所有的事件逻辑都纳 入到一个单一的RowCommand事件中并且查问该事件的参数来决定哪一个用户事件发生。在这个特殊的事件处理器中,我实现了view和reserve 按钮点击相应事件,还有针对于ASP.NET组件情况的排序请求。两种应用程序都保存roomId和roomName属性以便于应用程序的后面使用。具体 请参考本文相应源码中的ConferenceRooms.java和ConferenceRooms.cs文件。记住,这些类文件中的大多数代码都是工具 生成的,你可以使用编辑器提供的代码重叠功能来使代码更具可读性。在这些事件方法中,你可以立即存取这个页面组件的值以实现读取和修改。ASP.NET和 JSF保存视图状态-通过把它写到隐藏的HTML域中并把它从一个请求传递到另一个请求。当然,使用相同的方法来存储状态的传统型ASP和JSP应用程序 仍然是可用的。例如,在ASP.NET和JSF页面中,房间id和name都被放置到用户的Session中,这样它就可以在后面被检索。
  注意,在上面的事件代码中,ASP.NET文件调用一个方法"Server.Transfer"实现把控制传递给另一个页面。然而,在JSF事 件代码中,你不会找到这样的到另一个页面的直接的参考,而仅有返回串"view"和"reserve"。这是因为,JSF中经由我们更早讨论的faces -config配置文件处理页面流问题,任何使用过开源框架Struts的Java开发者应该对此很熟悉。在ConferenceRooms.jsp文件 的faces-config.xml文件中共有两个入口-字符串"view"和"reserve"。在运行时刻,应用程序使用这些字符串查询页面地址。下 面是在ConferenceRooms.jsp页面的faces-config文件中发现的XML形式的导航规则。我是使用Java Studio Creator中的一个可视化设计器创建的这些映射。

<navigation-rule>
<from-view-id>/ConferenceRooms.jsp</from-view-id>
<navigation-case>
<from-outcome>view</from-outcome>
<to-view-id>/RoomReservations.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>reserve</from-outcome>
<to-view-id>/ReserveRoom.jsp</to-view-id>
</navigation-case>
</navigation-rule>

   按此在新窗口浏览图片
  可视化设计器展示了在Java Studio Creator中的导航规则

   这个faces-config文件也是你列举与你的JSP页面文件相关联的所有Java Bean的地方。事实上,你可以通过这个文件配置任何你的应用程序需要参考的Java对象-这些Java对象被参考为'managed beans'。所有的JSF支持bean都将在这个配置文件中被列举为托管bean,但是任何你需要的其它对象也都可以在这里找到。一个托管bean包含 完全限定的类名、该bean(是把它存储在应用程序的Request,Session还是应用程序级)的使用范围以及当参考这个bean时要使用的名字。 在下面的XML中,列举出了初启web页面的支持bean,还有一个名为ReservationsSessionBean(我们使用它来共享应用程序中的 数据)的EJB的入口:

<managed-bean>
<managed-bean-name>ReservationsSessionBean</managed-bean-name>
<managed-bean-class>webreservations.ReservationsSessionBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>ConferenceRooms</managed-bean-name>
<managed-bean-class>webreservations.ConferenceRooms</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>

   让我们再回到前面的应用程序中来,我们的查看预订信息的请求把我们引向ASP.NET版本的RoomReservations.cs.aspx(相应于 JSF版本的RoomReservations.jsp)。在相关的代码文件(RoomReservations.cs和 RoomReservations.java)中,该事件代码检索存储于前一个页面中的房间id并且使用它来过滤第二个表格(它列举有关该房间的预订情 况)。在数据表格上面的标签被修改以引用相应房间的名字。

按此在新窗口浏览图片
ASP.NET

按此在新窗口浏览图片>
JSF


   一个delete按钮相应于删除每一行数据,这两个组件都允许你轻松地修改表中的数据。最后,每一个表单都包含一个按钮-它把你导向另一个表单以添加对 该房间的新的预订。这些表单显示于下面图中。注意,在图中由Java Studio Creator和Visual Studio实现的日历组件在显示上有所不同,但是实现相同的目的。
按此在新窗口浏览图片
ASP.NET

按此在新窗口浏览图片
JSF















本文转自朱先忠老师51CTO博客,原文链接:http://blog.51cto.com/zhuxianzhong/59805 ,如需转载请自行联系原作者


相关文章
|
3月前
|
存储 Shell Linux
快速上手基于 BaGet 的脚本自动化构建 .net 应用打包
本文介绍了如何使用脚本自动化构建 `.net` 应用的 `nuget` 包并推送到指定服务仓库。首先概述了 `BaGet`——一个开源、轻量级且高性能的 `NuGet` 服务器,支持多种存储后端及配置选项。接着详细描述了 `BaGet` 的安装、配置及使用方法,并提供了 `PowerShell` 和 `Bash` 脚本实例,用于自动化推送 `.nupkg` 文件。最后总结了 `BaGet` 的优势及其在实际部署中的便捷性。
181 10
|
14天前
|
弹性计算 开发框架 安全
基于云效 Windows 构建环境和 Nuget 制品仓库进行 .Net 应用开发
本文将基于云效 Flow 流水线 Windows 构建环境和云效 Packages Nuget 制品仓库手把手教你如何开发并部署一个 .NET 应用,从环境搭建到实战应用发布的详细教程,帮助你掌握 .NET 开发的核心技能。
|
1月前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
|
1月前
|
Kubernetes Cloud Native Ubuntu
庆祝 .NET 9 正式版发布与 Dapr 从 CNCF 毕业:构建高效云原生应用的最佳实践
2024年11月13日,.NET 9 正式版发布,Dapr 从 CNCF 毕业,标志着云原生技术的成熟。本文介绍如何使用 .NET 9 Aspire、Dapr 1.14.4、Kubernetes 1.31.0/Containerd 1.7.14、Ubuntu Server 24.04 LTS 和 Podman 5.3.0-rc3 构建高效、可靠的云原生应用。涵盖环境准备、应用开发、Dapr 集成、容器化和 Kubernetes 部署等内容。
57 5
|
1月前
|
JSON 算法 安全
JWT Bearer 认证在 .NET Core 中的应用
【10月更文挑战第30天】JWT(JSON Web Token)是一种开放标准,用于在各方之间安全传输信息。它由头部、载荷和签名三部分组成,用于在用户和服务器之间传递声明。JWT Bearer 认证是一种基于令牌的认证方式,客户端在请求头中包含 JWT 令牌,服务器验证令牌的有效性后授权用户访问资源。在 .NET Core 中,通过安装 `Microsoft.AspNetCore.Authentication.JwtBearer` 包并配置认证服务,可以实现 JWT Bearer 认证。具体步骤包括安装 NuGet 包、配置认证服务、启用认证中间件、生成 JWT 令牌以及在控制器中使用认证信息
102 2
|
2月前
|
SQL XML 关系型数据库
入门指南:利用NHibernate简化.NET应用程序的数据访问
【10月更文挑战第13天】NHibernate是一个面向.NET的开源对象关系映射(ORM)工具,它提供了从数据库表到应用程序中的对象之间的映射。通过使用NHibernate,开发者可以专注于业务逻辑和领域模型的设计,而无需直接编写复杂的SQL语句来处理数据持久化问题。NHibernate支持多种数据库,并且具有高度的灵活性和可扩展性。
47 2
|
2月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
109 9
|
3月前
|
数据采集 JSON API
.NET 3.5 中 HttpWebRequest 的核心用法及应用
【9月更文挑战第7天】在.NET 3.5环境下,HttpWebRequest 类是处理HTTP请求的一个核心组件,它封装了HTTP协议的细节,使得开发者可以方便地发送HTTP请求并接收响应。本文将详细介绍HttpWebRequest的核心用法及其实战应用。
164 6
|
4月前
|
数据库 C# 开发者
WPF开发者必读:揭秘ADO.NET与Entity Framework数据库交互秘籍,轻松实现企业级应用!
【8月更文挑战第31天】在现代软件开发中,WPF 与数据库的交互对于构建企业级应用至关重要。本文介绍了如何利用 ADO.NET 和 Entity Framework 在 WPF 应用中访问和操作数据库。ADO.NET 是 .NET Framework 中用于访问各类数据库(如 SQL Server、MySQL 等)的类库;Entity Framework 则是一种 ORM 框架,支持面向对象的数据操作。文章通过示例展示了如何在 WPF 应用中集成这两种技术,提高开发效率。
72 0
|
4月前
|
C# Windows 开发者
超越选择焦虑:深入解析WinForms、WPF与UWP——谁才是打造顶级.NET桌面应用的终极利器?从开发效率到视觉享受,全面解读三大框架优劣,助你精准匹配项目需求,构建完美桌面应用生态系统
【8月更文挑战第31天】.NET框架为开发者提供了多种桌面应用开发选项,包括WinForms、WPF和UWP。WinForms简单易用,适合快速开发基本应用;WPF提供强大的UI设计工具和丰富的视觉体验,支持XAML,易于实现复杂布局;UWP专为Windows 10设计,支持多设备,充分利用现代硬件特性。本文通过示例代码详细介绍这三种框架的特点,帮助读者根据项目需求做出明智选择。以下是各框架的简单示例代码,便于理解其基本用法。
237 0