第13章 层次式架构设计理论与实践

层次式架构的核心思想是将系统组成为一种层次结构,每一层为上层服务,并作为下层客户。其实不管是分层还是其他的架构都是为了解耦,更好的复用,只要秉承着这种思想去理解一切都迎刃而解了。

13.1 层次上体系结构概述

回顾一下软件体系结构的相关概念:

软件体系结构可定义为(其中一种):软件体系结构为软件系统提供了结构、行为和属性的高级抽象,由构成系统的元素描述、这些元素的相互作用、指导元素集成的模式以及这些模式的约束组
成。
软件体系结构不仅指定了系统的组织结构拓扑结构,并且显示了系统需求和构成系统的元素之间的对应关系,提供了一些设计决策的基本原理,是构建于软件系统之上的系统级复用
软件体系结构贯穿于软件研发的整个生命周期内,具有重要的影响。这主要从以下三个方
面来进行考察。
(1)利益相关人员之间的交流。
(2)系统设计的前期决策。
(3)可传递的系统级抽象。
层次式体系结构设计是将系统组成一个层次结构,每一层为上层服务,并作为下层客户。

在一些层次系统中,除了一些精心挑选的输出函数外,内部的层接口只对相邻的层可见。

连接件通过决定层间如何交互的协议来定义,拓扑约束包括对相邻层间交互的约束。由于每一层最
多只影响两层,同时只要给相邻层提供相同的接口,允许每层用不同的方法实现,同样为软件重用提供了强大的支持。
软件层次式体系结构是最通用的架构,也被叫作N层架构模式(n-tier architecture pattern)。
大部分的应用会分成表现层(或称为展示层)中间层(或称为业务层)数据访问层(或称为持久层)数据层
分层架构的一个特性就是关注分离(separation of concerns)。该层中的组件只负责本层的逻
辑,组件的划分很容易明确组件的角色和职责,也比较容易开发、测试、管理和维护。

层次式体系结构是一个可靠的通用的架构,设计时要注意以下两点:

(1)要注意的是污水池反模式。

所谓污水池反模式(architecture sinkhole anti-pattern),就是请求流简单地穿过几个层,每层里面基本没有做任何业务逻辑,或者做了很少的业务逻辑。比如一些Java EE例子,业务逻辑层只是简单的调用了持久层的接口,本身没有什么业务逻辑。
二八原则可以帮助你决定是否正在遇到污水池反模式。如果请求超过20则应该考虑让一些层变
成开放的。

(2)需要考虑的是分层架构可能会让你的应用变得庞大。

即使你的表现层和中间层可以独立发布,但它的确会带来一些潜在的问题,比如:分布模
式复杂、健壮性下降、可靠性和性能的不足,以及代码规模的膨胀等。

13.2 表现层框架设计

13.2.1 表现层设计模式

1.MVC模式

MVC强制性地把一个应用的输入、处理、输出流程按照视图、控制、模型的方式进行分离,形成了控制器、模型、视图三个核心模块。
(1)控制器(Controller):
接受用户的输入并调用模型和视图去完成用户的需求。该部分是用户界面与Model的接口。
一方面它解释来自于视图的输入,将其解释成为系统能够理解的对象,同时它也识别用户动作,并将其解释为对模型特定方法的调用
例:用户注册输入信息后,把这些信息转换成要Model好存入表中,如输入出生日期,自动计算出年龄,然后把值赋给Model中年龄字段;识别用户动作,点击查询按钮调用查询方法,点击保存按钮调用保存方法。
另一方面,它处理来自于模型的事件和模型逻辑执行的结果,调用适当的视图为用户提供反馈。
例:model返回查询的数据,controller根据结果返回给对应的view
(2)模型(Model):

应用程序的主体部分。模型表示业务数据和业务逻辑。一个模型能为多个视图提供数据。由于同一个模型可以被多个视图重用,所以提高了应用的可重用性。
1:多的例子:员工表可给员工查询view提供数据,也可给员工产量查询、部门下员工信息等等view提供数据;

(3)视图(View):
视图向用户显示相关的数据,并能接收用户输入的数据,但是它并不进行任何实际的业务处理。视图可以向模型查询业务状态,但不能改变模型。视图还能接受模型发出的数据更新事件,从而对用户界面进行同步更新。
首先,控制器接收用户的请求,并决定应该调用哪个模型来处理;
然后,模型根据用户请求进行相应的业务逻辑处理,并返回数据;
最后,控制器调用相应的视图来格式化模型返回的数据,并通过视图呈现给用户。
MVC优点:
(1)允许多种用户界面的扩展。(2)易于维护。(3)功能强大的用户界面。

2. MVP模式

MVP是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。区别:MVC中V和M可直接通信,MVP中不允许。

使用MVP模式来设计表现层,可以有以下的优点
(1)模型与视图完全分离,可以修改视图而不影响模型。
(2)可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部。
(3)可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的
有用,因为视图的变化总是比模型的变化频繁。
(4)如果把逻辑放在Presenter中,就可以脱离用户接口来测试这些逻辑(单元测试)。

目前,MVP模式被更多地用在Android开发当中。

3. MVVM模式

MVVM模式全称是模型-视图-视图模型(Model-View-ViewModel),它和MVC、MVP类似,主要目的都是为了实现视图和模型的分离,不同的是MVVM中,View与Model的交互通过ViewModel来实现。ViewModel是MVVM的核心,它通过DataBinding实现View与Model之间的双向绑定,其内容包括数据状态处理、数据绑定及数据转换。例如,View中某处的状态和Model中某部分数据绑定在一起,这部分数据一旦变更将会反映到View层。而这个机制通过ViewModel来实现。
数据的双向绑定,这使得MVVM更适用于数据驱动的场景,尤其是数据操作特别频繁的场景。
但也正是由于数据和视图的双向绑定,导致出现问题时不太好定位来源,有可能由数据问题导致、也有可能由业务逻辑中对视图属性的修改导致

13.2.2 使用XML设计表现层,统一Web Form与Windows Form的外观

这么一段XML很清晰地表示一个控件容器位置是(16,22,78,200),包含了一个不可视按钮。
总结:XML和HTML都是标记语言,而且各有千秋。

13.2.3 表现层中UIP设计思想

  • 导航和工作流控制:这些将不会出现的Ul中,但是经常因为要基于业务逻辑决定哪一个视图将被显示。这导致代码的不雅和难于管理。
  • 导航和工作流改变:用传统的UI技术改变应用程序的界面(改变页面的顺序或者添加删除页面)是非常痛苦的。
  • 状态管理:不管是在windows form还是在web form中,在视图间维护状态都是比较困难的。
  • 保存当前交互的快照:你可能想保存一个交互的快照并且在别的地方(不同的时间,不同的地点)重新开始它。
使用UIP框架的应用程序把表现层分为了以下几层。
● User Interface Components:这个组件就是原来的表现层,用户看到的和进行交互都是这
个组件,它负责获取用户的数据并且返回结果。
● User Interface Process Components:这个组件用于协调用户界面的各部分,使其配合后
台的活动,例如导航和工作流控制,以及状态和视图的管理。用户看不到这一组件,但
是这些组件为User Interface Components提供了重要的支持功能。

                        

UIP的组件主要负责的功能是:管理经过User Interface Components的信息流;管理UIP中各个事件之间的事务;修改用户过程的流程以响应异常;将概念上的用户交互流程从实现或者涉及的设备上分离出来;保持内部的事务关联状态,通常是持有一个或者多个的与用户交互的事务实体。因此,这些组件也能从UI组件收集数据,执行服务器的成组的升级或是跟踪UIP中的任务过程的管理。

13.2.4 表现层动态生成设计思想

基于XML的界面管理技术可实现灵活的界面配置、界面动态生成和界面定制。其思路是
用XML生成配置文件及界面所需的元数据,按不同需求生成界面元素及软件界面。
基于XML界面管理技术,包括界面配置、界面动态生成和界面定制三部分。

简单理解:用XML把页面需要的元素(如按钮、文本框、图标等等)及元素的位置、属性等保存起来,然后通过DOM API读取这个XML,动态的生成网页。

一些现有的框架思想也是这样,比如权限具体到页面的按钮上。

13.3 中间层架构设计

13.3.1业务逻辑层组件设计

业务逻辑组件分为接口和实现类两个部分。
接口用于定义业务逻辑组件,定义业务逻辑组件必须实现的方法是整个系统运行的核心。
通常按模块来设计业务逻辑组件,每个模块设计一个业务逻辑组件,并且每个业务逻辑组件以
多个DAO(Data Access Object)组件作为基础,从而实现对外提供系统的业务逻辑服务。增加
业务逻辑组件的接口,是为了提供更好的解耦,控制器无须与具体的业务逻辑组件耦合,而是
面向接口编程。

1.业务逻辑组件的实现类

业务逻辑组件以DAO组件为基础,必须接收Spring容器注入的DAO组件,因此必须为业
务逻辑组件的实现类提供对应的setter方法。业务逻辑组件的实现类将DAO组件接口实例作为
属性(面向接口编程),而对于复杂的业务逻辑,可能需要访问多个对象的数据,那么只需在这
个方法里调用多个DAO接口,将具体实现委派给DAO完成。

2.业务逻辑组件的配置

配置信息。

13.3.2业务逻辑层工作流设计

工作流定义为:业务流程的全部或部分自动化,在此过程中,文档、信息或任务按照一定的过程规则流转,实现组织成员间的协调工作以达到业务的整体目标。
它解决的主要问题是:使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行,从而实现某个预期的业务目标,或者是促使此目标的实现。
用工作流的思想组织业务逻辑,优点是:将应用逻辑与过程逻辑分离,在不修改具体功能
的情况下,通过修改过程模型改变系统功能,完成对生产经营部分过程或全过程的集成管理,
可有效地把人、信息和应用工具合理地组织在一起,发挥系统的最大效能。
例如:

13.3.3业务逻辑层实体设计

业务逻辑层实体具有以下特点:

  • 业务逻辑层实体提供对业务数据及相关功能(在某些设计中)的状态编程访问。
  • 业务逻辑层实体可以使用具有复杂架构的数据来构建,这种数据通常来自数据库中的多个相关表。业务逻辑层实体数据可以作为业务过程的部分I/O参数传递。
  • 业务逻辑层实体可以是可序列化的,以保持它们的当前状态。例如,应用程序可能需要在本地磁盘、桌面数据库(如果应用程序脱机工作)或消息队列消息中存储实体数据。
  • 业务逻辑层实体不直接访问数据库,全部数据库访问都是由相关联的数据访问逻辑组件提供的。
  • 业务逻辑层实体不启动任何类型的事务处理,事务处理由使用业务逻辑层实体的应用程序或业务过程来启动。
将业务逻辑层实体表示为XML的优点如下。
(1)标准支持。XML是World Wide Web Consortium(W3C)的标准数据表示格式。
(2)灵活性。XML能够表示信息的层次结构和集合。
(3)互操作性。在所有平台上,XML都是与外部各方及贸易伙伴交换信息的理想选择。
举例:

将业务逻辑层实体表示为通用DataSet的优点如下。

  • (1)灵活性。DataSet可以包含数据的集合,能够表示复杂的数据关系。
  • (2)序列化。在层间传递时,DataSet本身支持序列化。
  • (3)数据绑定。可以把DataSet绑定到ASP.NET应用程序和Windows窗体应用程序的任意用户界面控件。
  • (4)排序与过滤。可以使用DataView对象排序和过滤DataSet。应用程序可以为同一个DataSet创建多个DataView对象,以便用不同方式查看数据。
  • (5)与XML的互换性。可以用XML格式读写DataSet。
  • (6)开放式并发。在更新数据时,可以配合使用数据适配器与DataSet方便地执行开放式并发检查。
  • (7)可扩展性。如果修改了数据库架构,则适当情况下数据访问逻辑组件中的方法可以创建包含修改后的DataTable和DataRelation对象的DataSet。

将业务逻辑层实体表示为有类型的DataSet。有类型的DataSet是包含具有严格类型的方法、属性和类型定义以公开DataSet中的数据和元数据的类。 将业务逻辑层实体表示为有类型的DataSet的优点如下。

  • (1)代码易读。要访问有类型的DataSet中的表和列,可以使用有类型的方法和属性。
  • (2)有类型的方法和属性的提供使得使用有类型的DataSet比使用通用DataSet更方便。使
  • 用有类型的DataSet时,IntelliSense将可用。
  • (3)编译时类型检查,无效的表名称和列名称将在编译时而不是在运行时检测。

13.3.4业务逻辑层框架

业务框架位于系统架构的中间层,是实现系统功能的核心组件。采用容器的形式,便于系统功能的开发、代码重用和管理。
例如:
从图13-10中可以看到,业务层采用业务容器(Business Container)的方式存在于整个系统当中,采用此方式可以大大降低业务层和相邻各层的耦合,表示层代码只需要将业务参数传递给业务容器,而不需要业务层多余的干预。如此一来,可以有效地防止业务层代码渗透到表示层。
在业务容器中,业务逻辑是按照Domain Model—Service—Control思想来实现的。
(1)Domain Model是领域层业务对象,它仅仅包含业务相关的属性。
(2)Service是业务过程实现的组成部分,是应用程序的不同功能单元,通过在这些服务之间定义良好的接口和契约联系起来。接口是采用中立的方式进行定义的,这使得构建在各种这样的系统中的服务可以以一种统一和通用的方式进行交互。这种具有中立的接口定义(没有强制绑定到特定的实现上)的特征称为服务之间的松耦合。松耦合系统的好处有两点,一是它的灵活性,二是当组成整个应用程序的每个服务的内部结构和实现逐渐地发生改变时,它能够继续存在。
(3)Control服务控制器,是服务之间的纽带,不同服务之间的切换就是通过它来实现的。
通过服务控制器控制服务切换可以将服务的实现和服务的转向控制分离,提高了服务实现的灵
活性和重用性。
以下是Domain Model—Service—Control三者的互动关系。
(1)Service的运行会依赖于Domain Model的状态,反之,Service也会根据业务规则改变
Domain Model的状态。
(2)Control作为服务控制器,根据Domain Model的状态和相关参数决定Service之间的执
行顺序及相互关系。
Domain Model—Service—Control的互动关系,是吸取了Model—View—Control的优点,在
“控制和显示的分离”的基础之上演变而来的,通过将服务和服务控制隔离,使程序具备高度的
可重用性和灵活性。

13.4 数据访问层设计

13.4.1 5种数据访问模式

1.在线访问

在线访问是最基本的数据访问模式,也是在实际开发过程中最常采用的。这种数据访问模式会占用一个数据库连接,读取数据,每个数据库操作都会通过这个连接不断地与后台的数据源进行交互。

2.DataAccess Object

DAO模式是标准J2EE设计模式之一,开发人员常常用这种模式将底层数据访问操作与高层业务逻辑分离开。
一个典型的DAO实现通常有以下组件。
(1)一个DAO工厂类。
(2)一个DAO接口。
(3)一个实现了DAO接口的具体类。
(4)数据传输对象。
这当中具体的DAO类包含访问特定数据源的数据的逻辑。

3.Data Transfer Object

Data Transfer Object是经典EJB设计模式之一。DTO本身是这样一组对象或是数据的容器,它需要跨不同的进程或是网络的边界来传输数据。这类对象本身应该不包含具体的业务逻辑,并且通常这些对象内部只能进行一些诸如内部一致性检查和基本验证之类的方法,而且这些方法最好不要再调用其他的对象行为。
在具体设计这类对象(DTO)时,通常可以有如下两种选择。
(1)使用编程语言内置的集合对象,它通常只需要一个类,就可以在整个应用程序中满足
任何数据传输目的;而且几乎所有的编程语言都内置了集合类型,不需要再另外编写实现代码。
同时,使用内置的集合对象来实现DTO对象的时候,客户端必须按位置序号(在简单数组的
情况下)或元素名称(在键控集合的情况下)访问集合内的字段。不过,集合存储的是同一类
型(通常是最基本的Object类型)的对象,这有时会导致在编译时碰到一些无法检测到的编码
错误。
(2)通过创建自定义类来实现DTO对象,通过定义显示的get或是set方法来访问数据。
这种方式能够提供与任何其他对象完全一样的、客户端应用程序可访问的强类型对象。这种对
象可以提供编译时的类型检查,但是增加了编码的工作量,若应用程序发出许多远程调用的话,
需要编写大量的调用代码。
具体实现中有许多方法试图将上述这两种方法的优点结合在一起.

4.离线数据模式

离线数据模式是以数据为中心,数据从数据源获取之后,将按照某种预定义的结构(这种结构可以是SDO中的Data图表结构,也同样可以是ADO.NET中的关系结构)存放在系统中,成为应用的中心。离线,对数据的各种操作独立于各种与后台数据源之间的连接或是事务;与XML集成,数据可以方便地与XML格式的文档之间互相转换;独立于数据源,离线数据模式的不同实现定义了数据的各异的存放结构和规则,这些都是独立于具体的某种数据源的。

5.对象/关系映射(Object/Relation Mapping,O/R Mapping)

在最近几年,采用OR映射的指导思想来进行数据持久层的设计似乎已经成了一种潮流。
对象/关系映射的基本思想来源于这样一种现实:大多数应用中的数据都是依据关系模型存储
在关系型数据库中;而很多应用程序中的数据在开发或是运行时则是以对象的形式组织起来的。
那么,对象/关系映射就提供了这样一种工具或是平台,能够帮助将应用程序中的数据转换成
关系型数据库中的记录;或是将关系数据库中的记录转换成应用程序中代码便于操作的对象。

13.4.2 工厂模式在数据访问层应用

数据库有很多种,相应的每种数据库访问类也不同,可是实际开发中,同一个功能,遇到不同的数据库就要写一个专门的访问类,或者复杂点的系统需要抽取不同种类的数据库的时候,就比较尴尬,每种数据库都得配上个访问类,而且后期的维护也不好。

那怎么办呢?搞一个专门根据不同数据库访问的一个类或者一个组件,让它来代替我们对每个数据库写一个对应的访问类,而我们直接调用它不就好了。

这时候,利用工厂思想就可以实现。

工厂模式定义一个数据库访问接口,这个接口只包含要干啥而且是通用的工作,比如所有的数据库都有类型吧(oracle、sqlserver、mysql...)需要连接吧,都需要打开连接吧,都需要执行相应的语句吧,最后还得关闭连接吧等等这些。

用子类继承这个接口,在子类里具体实现要实例化的哪种数据库。

参考代码:

// 访问接口
public interface DataAccess
{
DatabaseType DatabaseTypelget;) //数据库类型
IDbConnection DbConnection{get;} //得到数据库连接
void Open(); //打开数库连接
void Close(); //关闭数据库连接
IDbTransaction BeginTransaction(); //开始一个事务
int ExecuteNonQuery(string commandText); //执行Sq1语句
DataSet ExecuteDataset(string commandText); //执行Sq1,返回DataSet
}
//子类实现代码
public sealed class MSSqlDataAccess :AbstractDataAccess
{
…//具体实现代码
}
public class oleDbDataAccess :AbstractDataAccess
{
…//具体实现代码
}
public class OracleDataAccess ;AbstractDataAccess
{
…//具体实现代码
}

再省点事偷个懒的,把这个自动切换功能给它加上

public sealed class DataAccessFactory
{
private DataAccessFactory(){}
private static PersistenceProperty defaultPersistenceProperty;
public static PersistenceProperty DefaultPersistenceProperty
{
get{return defaultPersistenceProperty;}
set{defaultPersistenceProperty=value;}
}
public static DataAccess CreateDataAccess(PersistenceProperty pp)
{
DataAccess dataAccess;
switch(pp.DatabaseType)
{
case(DatabaseType.MSSQLServer):
dataAccess = new MSSqIDataAccess(pp.ConnectionString);
break;
case(DatabaseType.Oracle):
dataAccess = new OracleDataAccess(pp.ConnectionString);
break;
case(DatabaseType.OleDBSupported):
dataAccess = new OleDbDataAccess(pp.Connectionstring);
break;
default:
dataAccesswnew MSSqlDataAccess(pp.Connectionstring);
break;
}
return dataAccess;
}public static DataAccess CreateDataAccess()
{
return CreateDataAccess(defaultPersistenceProperty);
}
}
现在一切都完成了,客户端在代码调用的时候,可能就是采用如下形式。
PersistenceProperty pp = new PersistenceProperty();
pp.Connectionstring -"server=127.0.0.1;uid=sa;pwd=;database-Northwind;”;
pp.DatabaseType = DatabaseType.MSSQLServer;
pp.UserID =“sa”;
pp.Password -"”;
DataAccess db= DataAccessFactory.CreateDataAccess(pp)
db.Open();
…//db.需要的操作
db.Close();

切换数据库只要改变红色类型就行了。

13.4.3 ORM、Hibernate与CMP2.0设计思想

运用sql语句是需要一定的数据库知识门槛的,但是很多的开发人员并不具备这方面的知识储备,比如同样是取数据,有的人写的语句就0.01秒出结果,有的人写的需要1秒钟才出结果,如果不具备数据库方面的知识或者不够了解,那么还要花费大量的时间和精力来搞明白这些,这时候ROM思想诞生了,它们的作用就是让你像写代码一样操作数据库的语句,你只关心你的业务逻辑,至于与数据库打交道的(生成sql然后执行)让ORM来干。

ORM也是有缺点的,毕竟封装了一层比直接写语句效率低,但是随着ORM技术的发展,以及配合Cache技术等等,效率也是不错的。

13.4.4 灵活运用XML Schema

XML Schema用来描述XML文档合法结构、内容和限制。
XML Schema充分地改造了并且极大地扩展了DTDs(传统描述XML文档结构和内容限制的机制)的能力,将逐步替代DTDs。
XML Schema同XML规范、Namespace规范一起成为XML体系的坚实基础。
XML Schema规范由如下三部分组成。
(1)XML Schema Part0:Primer。一个非标准化的文档,提供了XML Schema的一个简单可
读的描述,目的是快速地理解如何利用XML Schema语言创建一个Schema(框架)。
(2)XMLSchema Partl:Structures。这一部分详细说明了XML Schema定义语言,这个语言
为描述XML1.0文档的结构和内容限制提供了便利,包括开发了XML Namespace(命名空间)
的使用。
(3)XML Schema Part2:Datatypes。这一部分定义了可用于XML Schema和其他XML规范
中的定义数据类型的方法。这个数据类型语言,本身由XML 1.0自描述,提供了说明元素和属
性数据类型的XML1.0文档类型定义(DTDs)的一个超集。这部分提出了标准的数据类型内容
集合,其中讲述了目的、需求、范围和术语。XML Schema与DTD相比,有其独特的特点,提
供了丰富的数据类型,实现了继承和复用,与命名空间紧密联系,易于使用。
特征:
ML Schema规范提供了丰富的数据类型。
XML Schema支持继承是它的另一特点。
XML Schema与XML Namespace紧密联系,使得在一个命名空间中创建元素和属性非常容易。

13.4.5 事务处理设计

ACID原则是原子性 (Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)的缩写。

13.4.6 连接对象管理设计

共享资源---连接池。

连接池简单理解:

建立、关闭数据库连接非常的消耗资源的,但是我们的应用访问数据库是很频繁的,这样不停的建立、关闭造成大量的资源损耗和浪费,

那怎么办呢?

搞一个共享的连接可以吧,连接一直开着不关闭,你用完了,我再用,我用完了它再用,这样共享连接就会减少很多的资源消耗。访问量上来了,那么一个连接共享就不够了,好吧,那么给这个应用100个连接足够了,那就系统初始化就自动建立了100个连接,这100个连接就组成了连接池(当然不代表连接池哈,连接池还得管理哪些连接用完了释放,哪些正在连接打标记等等),这个应用的所有对数据库的操作都从连接池里取连接用。

13.5 数据架构规划与设计

13.5.1数据库设计与类的设计融合

对类和类之间关系的正确识别是数据模型的关键所在。
好模型的目标是将工程项目整个生存期内的花费减至最小,同时也会考虑到随时间的推移系统将可能发生的变化,因而设计时也要考虑能适应这些变化。因此,将目光集中在最大限度地降低开发费用上是一个错误。

13.5.2数据库设计与XML设计融合

目前Web数据发展的多样化和复杂化,传统的数据库技术很难存储和管理所有的web数据了,而且XML有代替HTML趋势。

鉴于以上情况,存储数据开始考虑用XML与现有的数据库结合的方式。

XML文档分为两类:
一类是以数据为中心的文档,这种文档在结构上是规则的,在内容上是同构的,具有较少的混合内容和嵌套层次,人们只关心文档中的数据而并不关心数据元素的存放顺序,这种文档简称为数据文档,它常用来存储和传输Web数据。
另一类是以文档为中心的文档,这种文档的结构不规则,内容比较零散,具有较多的混合内容,并且元素之间的顺序是有关的,这种文档常用来在网页上发布描述性信息、产品性能介绍和E-mail信
息等。
已经提出的XML文档的存储方式有两种:基于文件的存储方式和数据库存储方式。
(1)基于文件的存储方式。基于文件的存储方式是指将XML文档按其原始文本形式存
储,主要存储技术包括操作系统文件库、通用文档管理系统和传统数据库的列(作为二进制
大对象BLOB或字符大对象CLOB)。这种存储方式需维护某种类型的附加索引,以建立文
件之间的层次结构。基于文件的存储方式的特点:无法获取XML文档中的结构化数据;通
过附加索引可以定位具有某些关键字的XML文档,一旦关键字不确定,将很难定位;查询
时,只能以原始文档的形式返回,即不能获取文档内部信息;文件管理存在容量大、管理难
的缺点。
(2)数据库存储方式。数据库在数据管理方面具有管理方便、存储占用空间小、检索速度
快、修改效率高和安全性好等优点。一种比较自然的想法是采用数据库对XML文档进行存取
和操作,这样可以利用相对成熟的数据库技术处理XML文档内部的数据。数据库存储方式的
特点:能够管理结构化和半结构化数据;具有管理和控制整个文档集合本身的能力;可以对文
档内部的数据进行操作;具有数据库技术的特性,如多用户、并发控制和一致性约束等;管理
方便,易于操作。
在某种程度上,XML及其一系列相关技术就是一个数据库系统。它提供了传统数据库所具有的特点,如存储(以XML文档形式)、数据库的模式(DTD或XMLSchema)、查询语言(XQuery、XPath、XQL和XML-QL等)和编程接口(如SAX、DOM)等。但与传统数据库相比,它在存储、索引、安全、多用户访问和事务管理等方面还存在不足之处。
在一定的环境下,例如当数据量和操作用户较少并且性能要求不高的情况下,XML文档能够作为数据库在应用程序中使用。如果应用程序有许多操作用户,并且要求严格的数据完整性和性能要求,则不宜采用XML文档。

13.6 物联网层次架构设计

物联网可以分为三个层次,
底层是用来感知数据的感知层,即利用传感器、二维码、RFID等设备随时随地获取物体的信息。第二层是数据传输处理的网络层,即通过各种传感网络与互联网的融合,将对象当前的信息实时准确地传递出去。
第三层则是与行业需求结合的应用层,即通过智能计算、云计算等将对象进行智能化控制。
网络层中的感知数据管理与处理技术是实现以数据为中心的物联网的核心技术,包括传
感网数据的存储、查询、分析、挖掘和理解,以及基于感知数据决策的理论与技术。云计算
平台作为海量感知数据的存储、分析平台,将是物联网网络层的重要组成部分,也是应用层
众多应用的基础。在产业链中,通信网络运营商和云计算平台提供商将在物联网网络层占据重要的地位。

13.7 层次式架构案例分析---看看即可

13.7.1电子商务网站(网上商店PetShop)

13.7.2基于物联网架构的电子小票服务系统

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/17734.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【uniapp】uniapp页面介绍

目录 开发工具:HBuilderX介绍特点和功能 页面简介页面管理新建页面删除页面页面改名pages.json 设置应用首页 页面内容构成template模板区script 脚本区export default 外的代码export default 里的代码 style样式区 页面生命周期Vue2 页面及组件生命周期流程图Vue3…

重生奇迹MU剑士两把单手剑

重生奇迹mu觉醒剑士在武器的选择上非常广泛,可以单手操作也可以双手,那么许多玩家觉得单手剑特别帅气,能否装备两个单手剑,感兴趣的玩家一起来看看详情介绍。 单手剑是一个单手武器,你可以选择装备一个单手剑&#xf…

13.Redis之数据库管理redis客户端JAVA客户端

1.数据库管理 mysql 中有一个重要的概念,database 1个 mysql 服务器上可以有很多个 database1个 database 上可以有很多个 表mysql 上可以随心所欲的 创建/删除 数据库~~ Redis 提供了⼏个⾯向 Redis 数据库的操作,分别是 dbsize、select、flushdb、flushall 命令…

在 GPT-4o 释放完整能力前,听听实时多模态 AI 创业者的一手经验 | 编码人声

「编码人声」是由「RTE开发者社区」策划的一档播客节目,关注行业发展变革、开发者职涯发展、技术突破以及创业创新,由开发者来分享开发者眼中的工作与生活。 5 月中旬 GPT-4o 的发布,让人与 AI 的交互,从对话框的文本交流加速推进…

去除uni微信小程序button的边框

想要去除button的边框,如下未去除边框时,非常影响观感。 解决方法 使用伪元素::after,简单但是易忘,正常情况下,我直接是给button上加上一个类名直接设置border:none,但是这样是无效的,应该如下…

前端canvas实现图片涂鸦(Vue2、Vue3都支持)

先看一下效果图吧 代码组成&#xff1a;画笔大小、颜色、工具按钮都是组件&#xff0c;通俗易懂&#xff0c;可以按照自己的需求调整。 主要代码App.vue <template><div class"page"><div class"main"><div id"canvas_panel&qu…

动态规划part01 Day41

动态规划算法解题步骤 确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 LC509斐波那契数 LC70爬楼梯 LC746使用最小花费爬楼梯 dp[]含义&#xff1a;爬到第i层楼梯的最小花费

B站尚硅谷git学习记录

文章目录 一、Git概述1.何为版本控制2.为什么需要版本控制3.版本控制工具 二、Git常用命令1.设置用户签名1.1 基本语法1.2 案例实操 2.初始化本地库2.1 基本语法2.2 案例实操 3.查看本地库状态3.1基本语法3.2 案例实操&#xff08;1&#xff09;首次查看&#xff08;工作区没有…

TinyEngine 低代码引擎:带你5分钟高效构建游戏登录界面

本文由体验技术团队 TinyEngine 项目成员李旭宏创作&#xff0c;欢迎大家实操体验&#xff0c;本体验项目基于 TinyEngine 低代码引擎提供的环境&#xff0c;通过体验简单拖、拉、拽的形式帮助开发者快速了解低代码引擎的使用流程&#xff0c;达到快速开发游戏登录界面的效果。…

143.栈和队列:用队列实现栈(力扣)

题目描述 代码解决 class MyStack { public:queue<int> que; // 定义一个队列用于实现栈// 构造函数&#xff0c;初始化队列MyStack() {}// 向栈中推入元素 xvoid push(int x) {que.push(x); // 使用队列的 push 方法将元素 x 添加到队列尾部}// 从栈中弹出并返回栈顶元…

【MIT 6.5840(6.824)学习笔记】GFS

1 分布式存储系统难点 在设计大型分布式系统或存储系统时&#xff0c;初衷通常是为了获得显著的性能提升&#xff0c;通过数百台计算机的资源来并行完成大量工作。因此&#xff0c;性能问题成为最初的关注点。一个自然的想法是将数据分片&#xff08;Sharding&#xff09;&…

《数字图像处理》笔记/期末复习资料

目录 1 简述二值图像、灰度图像与彩色图像间的区别。 2 图像量化时&#xff0c;如果量化级比较小会出现什么现象&#xff1f;为什么&#xff1f; 3 图像增强的目的是什么&#xff1f; 4 什么是中值滤波&#xff0c;有何特点&#xff1f; 5 叙述高通滤波、低通滤波、带通滤…

区块链技术引领:Web3时代的新网络革命

随着区块链技术的快速发展和不断成熟&#xff0c;人们已经开始意识到它所带来的潜在影响&#xff0c;尤其是在构建一个更加去中心化、安全和透明的互联网时。这个新的互联网时代被称为Web3&#xff0c;它将不再受制于传统的中心化平台&#xff0c;而是更多地依赖于去中心化的网…

Rust最新版安装(v1.78.0+)

系统&#xff1a;Windows 11 专业版 23H2rustc&#xff1a;1.78.0 配置环境变量和设置配置文件 新建文件夹“C:\Rust\Rustup”和“C:\Rust\Cargo”。【以管理员身份运行】打开CMD 设置系统环境变量&#xff0c;如下设置RUSTUP_DIST_SERVER&#xff0c;其余同理 C:\Windows\S…

Golang | Leetcode Golang题解之第103题二叉树的锯齿形层序遍历

题目&#xff1a; 题解&#xff1a; func zigzagLevelOrder(root *TreeNode) (ans [][]int) {if root nil {return}queue : []*TreeNode{root}for level : 0; len(queue) > 0; level {vals : []int{}q : queuequeue nilfor _, node : range q {vals append(vals, node.V…

物联网架构实例—Ubuntu 安装MySQL

1.ubuntu安装mysql apt-get upgrade apt-get update 安装mysql apt-get install mysql-server Y执行安装后&#xff0c;会来到软件包设置界面. 再次确认设置的密码. 开启mysql的服务 service mysql start 确认是否成功开启mysql service mysql status 确认是否启动成功&a…

Java Object类方法介绍

Object作为顶级类&#xff0c;所有的类都实现了该类的方法&#xff0c;包括数组。 查询Java文档&#xff1a; 1、object.eauqls(): 其作用与 有些类似。 &#xff1a; 是一个比较运算符&#xff0c;而不是一个方法。 ①可以判断基本类型&#xff0c;也可以判断引用类型。 ②若…

gitLab 使用tortoiseGit 克隆新项目 一直提示tortoiseGitPlink输入密码 输完也不生效

问题描述&#xff1a;准备用TortoiseGit拉取gitlab上一个新项目代码&#xff0c;出现tortoiseGitPlink提示让输入密码&#xff0c;输入后又弹出&#xff0c;反复几次&#xff0c;无法down下来代码。 解决方案&#xff1a; 1.找到PuTTYgen工具&#xff0c;打开 2. 点击load 按钮…

山脉数组的峰顶索引 ---- 二分查找

题目链接 题目: 分析: 我们很明显, 可以从峰值位置将数组分成两段, 具有"二段性", 所以可以用二分查找因为arr是山峰数组, 不存在相等的情况如果arr[mid] > arr[mid 1], 说明mid的位置可能是峰值, 移动right mid如果arr[mid] < arr[mid 1], 说明mid的位置…

神奇的一万

在代码界&#xff0c;有个神奇的存在&#xff0c;它叫一万&#xff1a;eval&#xff08;&#xff09;。 这个神奇的一万&#xff0c;在python和JavaScript中都存在&#xff0c;作用也是基本相同的。 Python中的eval函数能将字符串str当成有效的表达式来求值并返回计算结果。 …