论文关键词:b/s结构 计算机网络 数据库 sql语言 jsp web服务器
论文摘要:本文结合公交查询系统的实际需要,通过对b/s模式、jdk开发环境及工具、web发布服务、数据库以及sql语言的深入学习及实践,主要完成了公交查询系统的需求分析、数据库设计、应用程序设计的工作。
第一章 引 言
§1.1数据库技术
数据库技术作为数据管理技术,是计算机软件领域的一个重要分支,产生于60年代末。现已形成相当规模的理论体系和实用技术。优秀的数据库设计是应用成功的基石。万万丈高楼平地起,数据库设计如同高楼的基石,是开发高品质应用的前提。
1.1.1数据库管理系统(dbms)
数据库管理系统(dbms)是指数据库系统中管理数据的软件系统。dbms是数据库系统的核心组成部分。对数据库的一切操作,包括定义、查询、更新及各种控制,都是通过dbms进行的。
在不同的计算机系统中,由于缺乏统一的标准,即使同种数据模型的dbms,它们在用户接口、系统功能方面也常常是不相同的。
用户对数据库进行操作,是由dbms把操作从应用程序带到外部级、概念级、再导向内部级,进而操作存储器中的数据。dbms的主要目标,是使数据作为一种可管理的资源处理。
§1.2 公交查询系统
1.2.1系统功能
1、基于浏览器(b/s模式)的公交线路分类查询;
2、数据的录入、修改、添加、删除。
1.2.2系统运行环境
该系统采用browser/server模式进行设计: 在服务器上运行web发布服务器、数据库程序,服务器操作系统为windowsnt/2000/xp/2003 server,客户机操作为windows9×/ nt/2000/xp/2003,其上运行浏览器程序,服务器和客户机可为同一设备。
1.2.3系统开发工具
该系统采用jdk java环境进行开发,数据库服务器为mysql,web发布服务器为tomcat server;客户端使用浏览器运行程序,整个系统调试成功。
§1.3 本文所作工作
首先介绍了城市公交查询系统的应用背景、开发环境以及选用的开发工具与数据库的关系,阐明了计算机互联网络的概念。并对数据库的体系结构、dbms进行了介绍;介绍关系型数据库的基本概念,着重说明了几个关键概念的定义;然后对sql语言作了一个介绍说明;从特点和功能入手,介绍java、jsp;并且介绍了b/s模式的概念、特点;用软件工程的方法分析城市公交查询系统,对整个系统进行了需求分析、功能模块划分,并通过er图对数据库进行概念设计;对城市公交查询系统的具体设计,描述了查询、录入模块的实现过程。
第二章 数据库理论基础
§2.1 关系型数据库
2.1.1数据库的设计理论
关系数据库的设计理论主要包括三个方面的内容:数据依赖、范式,模式设计方法。其中数据依赖起着核心的作用。
1. 函数依赖(functional dependency , fd)的定义
设r(u)是一个关系模式,u是r的属性集合,x和y是u的子集。对于r(u)的任何一个可能的关系r,如果r中不存在两个元组,它们在x上的属性值相同,而在y上的属性值不同,则称“y函数依赖于x” ,记作x→y。如果x→y,并且对于x的任一真子集x ’,都有y 不函数依赖于x ’,则称“y完全函数依赖于x” ,记作x f y 。若x→y,但y不完全函数依赖于x,则称“y部分函数依赖于x” ,记作x p y 。如果x→y,y→z,且y≮ x, x不函数依赖于y,则称“z传递函数依赖于x”。
2. 范式
在对表的形式进行了规范化定义后,数据结构还有五种规范化定义,定名为规范化模式,称为范式。在这五种范式中,一般只用前三种,对于常用系统就足够了。而且这五种范式是“向上兼容”的,即满足第五范式的数据结构自动满足一、二、三、四范式,满足第四范式的数据结构自动满足第一、二、三范式,……,依此类推。
为防止数据库出现更新异常、插入异常、删除异常、数据冗余太大等现象,关系型数据库要尽量按关系规范化要求进行数据库设计。
3. 模式设计方法
一个好的模式设计方法应符合下列三条原则:
表达性:涉及到两个数据库模式的等价性问题,即数据等价和依赖等价,分别用无损联接和保持函数依赖来衡量。
分离性:是指属性间的“独立关系”应该用不同的关系模式表达。独立联系是我们所考虑的“基本信息单位”。实际上分离就是清除存储异常和数据冗余现象。如果能达到这个目的,就分离。分离的基准就是一系列范式,分离与依赖等价有时是不可兼容的。
最小冗余性:要求在分解后的数据库能表达原来数据库的所有信息这个前提下实现。目的就是节省存储空间,提高对关系的操作效率,清除不必要的冗余。但要注意,在实际使用中,并不一定要达到最小宙余。因为有时带点冗余对于查询处理是有好处的。
关系模式的方法基本上可以分为分解与合成两大类。分解型算法要求输入一个初始模式集和依赖集,而结果满足数据等价要求。对于合成型算法只要求输入初始依赖集,结果满足依赖等要求。但它们依据的基本思想是共同的,即独立的联系独立表示。 §2.2 sql语言介绍
sql(structured query language)即“结构式查询语言”。sql虽然名为查询语言,但实际上具有定义、查询、更新和控制等多种功能。由于它使用方便、功能丰富、语言简单易学,很快得到应用和推广。
2.2.1 sql的组成
sql主要分成四个部分:
1)数据定义:这一部分也称为“sql ddl”,用于定义sql模式、基本表、视图和索引。
2)数据操纵:这一部分也称为“sql dml”。它分为数据查询和数据更新两类。其中数据更新又分成插入、删除、和修改三种操作。
3)数据控制:这一部分包括对基本表和视图的授权,完整性规则的描述,事务控制等内容。
4)嵌入式sql的使用规定:这一部分内容涉及到sql语句嵌入在宿主语言程序中使用的规则。
2.2.2 sql的数据查询
n select语句的语法
select 目标表的列名或列表达式序列
from 基本表和(或)视图序列
[where行条件表达式]
[group by列名序列
[having组条件表达式]]
[order by列名[asc|desc]…]
句法中[]表示该成分可有,也可无。
整个语句的执行过程如下:
a) 读取from子句中基本表、视图的数据,执行笛卡尔积操作。
b) 读取满足where子句中给出的条件表达式的元组。
c) 按group子句中指定列的值分组,同时提取满足having子句中组条件表达式的那些组。
d) 按select子句中给出的列名或列表达式求值输出。
e) order子句对输出的目标表进行排序,按附加说明asc升序排列,或按desc降序排列。
select语句中,where子句称为“行条件子句”,group子句称为“分组子句”,having子句称为“组条件子句”,order子句称为“排序子句”。
2.2.3 sql的数据更新
sql的数据更新包括数据插入、删除和修改等三种操作
1)数据插入
a) 元组值的插入
insert into 基本表名(列名表)
values(元组值)
或者 insert into 基本表名(列名表)
(table(元组值),
(元组值),
……)
前一种格式只能插入一个元组,后一种格式可以插入多个元组。
2)数据删除
sql的删除操作是指从基本表删除元组,其语法如下:
delete from 基本表名
[where条件表达式]
其语义是从基本表中删除满足条件表达式的元组。
3)数据修改
当需要修改基本表中元组的某些列值时,可以用update语句实现,其句法如下:
update 基本表名
set 列名=值表达式[,列名=值表达式…]
[where条件表达式]
其语义是:修改基本表中满足条件表达式的那些元组中的列值,需修改的列值在set子句中指出。
第三章 技术介绍 §3.1 jsp技术介绍
在 sun 正式发布 jsp(javaserver pages) 之后,这种新的 web 应用开发技术很快引起了人们的关注。jsp为创建高度动态的 web 应用提供了一个独特的开发环境。按照 sun 的说法, jsp 能够适应市场上包括 apache webserver 、 iis4.0 在内的 85% 的服务器产品。
3.1.1 jsp运行环境
sun 公司的 jsp 主页上可以下载 jsp 规范,这些规范定义了供应商在创建 jsp 引擎时所必须遵从的一些规则。
在运行jsp示例页面之前,要注意安装jswdk的目录,特别是“work”子目录下的内容。执行示例页面时,可以在这里看到 jsp 页面如何被转换成 java 源文件,然后又被编译成class文件(即servlet)。jswdk软件包中的示例页面分为两类,它们或者是jsp文件,或者是包含一个表单的html文件,这些表单均由jsp代码处理。与asp一样,jsp中的java代码均在服务器端执行。因此,在浏览器中使用“查看源文件”菜单是无法看到jsp源代码的,只能看到结果html代码。所有示例的源代码均通过一个单独的“examples”页面提供。
3.1.2 jsp页面示例
下面分析一个简单的 jsp 页面。可以在 jswdk 的 examples 目录下创建另外一个目录存放此文件,文件名字可以任意,但扩展名必须为.jsp。从下面的代码清单中可以看到,jsp页面除了比普通 html 页面多一些 java 代码外,两者具有基本相同的结构。java代码是通过 < % 和 %> 符号加入到 html 代码中间的,它的主要功能是生成并显示一个从 0 到 9 的字符串。在这个字符串的前面和后面都是一些通过html代码输出的文本。
< html>
< head>< title>jsp 页面 < /title>< /head>
< body>
< %@ page language="java" %>
< %! string str="0"; %>
< % for (int i=1; i < 10; i++) {
str = str + i;
} %>
jsp 输出之前。
< p>
< %= str %>
< p>
jsp 输出之后。
< /body>
< /html>
这个 jsp 页面可以分成几个部分来分析。 首先是 jsp 指令。它描述的是页面的基本信息,如所使用的语言、是否维持会话状态、是否使用缓冲等。 jsp 指令由 < %@ 开始, %> 结束。在本例中,指令“ < %@ page language="java" %> ”只简单地定义了本例使用的是 java 语言(当前,在 jsp 规范中 java 是唯一被支持的语言)。
接下来的是 jsp 声明。 jsp 声明可以看成是定义类这一层次的变量和方法的地方。 jsp 声明由 < %! 开始, %> 结束。如本例中的“ < %! string str="0"; %> ”定义了一个字符串变量。在每一项声明的后面都必须有一个分号,就象在普通 java 类中声明成员变量一样。
位于 < % 和 %> 之间的代码块是描述 jsp 页面处理逻辑的 java 代码,如本例中的 for 循环所示。
最后,位于 < %= 和 %> 之间的代码称为 jsp 表达式,如本例中的“ < %= str %> ”所示。 jsp 表达式提供了一种将 jsp 生成的数值嵌入 html 页面的简单方法。
会话状态维持是 web 应用开发者必须面对的问题。有多种方法可以用来解决这个问题,如使用 cookies 、隐藏的表单输入域,或直接将状态信息附加到 url 中。 java servlet 提供了一个在多个请求之间持续有效的会话对象,该对象允许用户存储和提取会话状态信息。 jsp 也同样支持 servlet 中的这个概念。
在 sun 的 jsp 指南 中可以看到许多有关隐含对象的说明(隐含的含义是,这些对象可以直接引用,不需要显式地声明,也不需要专门的代码创建其实例)。例如 request 对象,它是 httpservletrequest 的一个子类。该对象包含了所有有关当前浏览器请求的信息,包括 cookies , html 表单变量等等。 session 对象也是这样一个隐含对象。这个对象在第一个 jsp 页面被装载时自动创建,并被关联到 request 对象上。与 asp 中的会话对象相似, jsp 中的 session 对象对于那些希望通过多个页面完成一个事务的应用是非常有用的。
为说明 session 对象的具体应用,接下来我们用三个页面模拟一个多页面的 web 应用。第一个页面( q1.html )仅包含一个要求输入用户名字的 html 表单,代码如下:
< html>
< body>
< form method=post action="q2.jsp">
请输入您的姓名:
< input type=text name="thename">
< input type=submit value="submit">
< /form>
< /body>
< /html>
第二个页面是一个 jsp 页面( q2.jsp ),它通过 request 对象提取 q1.html 表单中的 thename 值,将它存储为 name 变量,然后将这个 name 值保存到 session 对象中。 session 对象是一个名字 / 值对的集合,在这里,名字 / 值对中的名字为“ thename ”,值即为 name 变量的值。由于 session 对象在会话期间是一直有效的,因此这里保存的变量对后继的页面也有效。 q2.jsp 的另外一个任务是询问第二个问题。下面是它的代码:
< html>
< body>
< %@ page language="java" %>
< %! string name=""; %>
< %
name = request.getparameter("thename");
session.putvalue("thename", name);
%>
您的姓名是: < %= name %>
< p>
< form method=post action="q3.jsp">
您喜欢吃什么 ?
< input type=text name="food">
< p>
< input type=submit value="submit">
< /form>
< /body>
< /html>
第三个页面也是一个 jsp 页面( q3.jsp ),主要任务是显示问答结果。它从 session 对象提取 thename 的值并显示它,以此证明虽然该值在第一个页面输入,但通过 session 对象得以保留。 q3.jsp 的另外一个任务是提取在第二个页面中的用户输入并显示它:
< html>
< body>
< %@ page language="java" %>
< %! string food=""; %>
< %
food = request.getparameter("food");
string name = (string) session.getvalue("thename");
%>
您的姓名是: < %= name %>
< p>
您喜欢吃: < %= food %>
< /body>
< /html>
§3.2 b/s系统介绍
传统的c/s架构(客户机/服务器,client/server)方式中,业务逻辑位于客户端,每完成一项事务,都要频繁地访问数据库,使得网络上数据流量非常大,对于慢速连接的用户,甚至无法使用。
为弥补上述c/s架构的缺陷,人们发展出了三层或多层架构:客户机—中间件(应用服务器)—数据库服务器(client—middle ware—database server)。在这种架构中,业务逻辑放置于中间件服务器上,大量的数据流也位于中间件和数据库之间,而客户机只是简单地发出请求,中间件接受请求后进行事务处理并将处理的结果返回给客户机,这一类型的客户机也称之为“廋客户”。b/s架构实际上是三层架构的一种,所不同的是客户端就是目前几乎每台电脑中都有的网络浏览器,而中间件则是web应用服务器。注意到主要的业务逻辑均由位于web应用服务器上的servlet和jsp程序或ejb来处理。
3.2.1 b/s架构具备极大的优越性 1、面向电子商务时代的技术
将来所有的应用系统几乎都在互联网或企业内部广域网上运行,发展电子商务成为企业不可避免的信息化道路。b/s架构的软件正是电子商务的基石,正是这类软件使得移动办公和分布式协同工作真正成为现实。无论在世界的那个角落,只需要一台可以联网的设备(计算机、pda甚至手机)都可以方便地与客户联系和与他人协同工作。
2、软件操作、维护和升级方式的革命
软件系统的改进和升级越来越频繁,b/s架构的产品在维护和升级方面具备显著的优势。无论用户的规模有多大,有多少分支机构都不会增加任何维护升级的工作量,所有的操作只对服务器进行,通过远程连接服务器,异地的运维人员甚至于可以做到远程维护和升级,这对人力、时间、费用的节省是相当惊人的。
所有的客户端只是浏览器,所有的操作都和上网浏览网页类似,使用者接受的培训也仅限于业务逻辑而无需将大量精力浪费学习软件操作上。
3、系统整合
无论是办公自动化(oa)系统,人力资源(hr)系统,客户关系管理(crm)系统,erp等等,发展的趋势是不断融合。而采用统一的b/s结构开发的产品无论是现在还是将来都是最好的选择,它提供了真正意义上无缝地与其它系统进行整合的方案。
3.2.2采用java语言实现 1、跨越平台的限制
尽管目前windows桌面系统一统天下,但是服务器系统采用的操作系统却具有多样性,包括linux、unix、windows nt/2000server等系统都可以实现企业级应用。即便是桌面系统,中国政府出于安全和国家战略的考虑,希望有自己的操作系统,linux的出现使这种想法变成了现实。
传统的c/s架构的软件需要针对不同的操作系统开发不同版本的软件,面对众多的操作系统和软件快速的升级换代,采用这一架构开发软件,对于企业的it投资无疑是一种巨大的风险。而采用java语言实现的b/s架构的软件产品真正做到了“一次编写处处运行(write once, run anywhere)” ,对企业而言,可以规避将来更换操作系统所带来的风险。
2、健壮的系统
java语言实现的软件具有天然的健壮性。这是java语言自身的特性保证的。利用java写成的软件几乎不可能造成系统崩溃,这正是安全性要求很高的企业级应用所不可或缺的特性。
第四章 公交查询系统设计分析
根据数据库系统生存期的设计方法,从数据库应用系统和开发的全过程来考虑,将数据库应用系统设计分为以下几个阶段:
1)规划;
2)需求分析;
3)概念设计;
4)逻辑设计
5)物理设计
§4.1应用需求分析
要设计一个良好的公交查询系统,就必须首先明确该应用环境对系统的要求。公交查询系统的应用背景为:方便市民搭乘公交车出行;手动(目前)、自动(将来)、及时更新查询数据。因此,该系统需满足以下几方面需求:
1、查询功能:系统需要提供几种不同方式的查询手段,以实现灵活方便地管理整个系统。
2、数据的更新修改:
更新:系统允许管理员级别的用户对数据进行更新、修改并且存盘操作;
编辑:系统允许管理员级别的用户对数据进行编辑、删除的操作,保证现库的真实性与实时性。
3、打印输出(暂未实现):系统可以将用户查询到的内容动态地生成报表,并打印输出。
§4.2 系统功能模块划分
公交查询系统功能划分模块如下:
查询系统模块
该模块实现公交查询功能。可实现按起点-中转站-终点查询查询和按线路查询两种查询方式。
录入系统模块
该模块实现数据的录入、修改、删除功能。
§4.3 系统数据库设计
4.3.1 概念设计
概念设计的目标是产生反映城市公交查询系统需求的数据库概念结构,即概念模式。概念模式是独立于数据库逻辑结构,独立于支持数据库的dbms,不依赖于计算机系统的。 1、er模型
er模型是对现实世界的一种抽象。它的主要成分是实体、联系和属性。使
用这三种成分,我们可以建立许多应用环境的er模型。
2、 er模型的操作
在利用er模型进行数据库概念设计的过程中,常常需要对er图进行种种
变换。这些变换又称为er模型的操作,包括实体类型、联系类型和属性的分裂、合并和增删等等。
3、利用er方法的数据库概念设计
利用er方法进行数据库的概念设计,可以分成三步进行:首先设计局部er模式,然后把各局部er模式综合成一个全局er模式,最后对全局er模式进行优化,得到最终的er模式,即概念模式。
设计局部的er模式
通常,一个数据库系统都是为多个不同用户服务的。各个用户对数据的观点可能不一样,信息处理需求也可能不同。在设计数据库概念结构时,为了更好地模拟现实世界,一个有效的策略是“分而治之”,即先分别考虑各个用户的信息需求,形成局部概念结构,然后再综合成全局结构。在er方法中,局部概念结构又称为局部er模式,其图形表示称为er图。
实体和属性的定义如下:
站点(站点编号,站点名称,站点类别)
线路(线路编号,始发时间,终发时间,备注)
线路站点对应(线路编号,站点名称)
shape \* mergeformat
e/r图表示
4、联系定义
er模型的“联系”用于刻画实体之间的关联。一种完整的方式是对局部结构中任意两个实体类型,依据需求分析的结果,考察局部结构中任意两个实体类型之间是否存在联系。若有联系,进一步确定是1:n,m:n,还是1:1等。还要考察一个实体类型内部是否存在联系,两个实体类型之间是否存在联系,多个实体类型之间是否存在联系,等等。
5、设计全局er模式
所有局部er模式都设计好了后,接下来就是把它们综合成单一的全局概念结构。全局概念结构不仅要支持所有局部er模式,而且必须合理地表示一个完整、一致的数据库概念结构。
1)确定公共实体类型
为了给多个局部er模式的合并提供开始合并的基础,首先要确定各局部结构中的公共实体类型。在这一步中我们仅根据实体类型名和键枕认定公共实体类型。一般把同名实体类型作为公共实体类型的一类候选,把具有相同键的实体类型作为公共实体类型的另一类候选。
2)局部er模式的合并
合并的原则是:首先进行两两合并;先和合并那些现实世界中有联系的局部结构;合并从公共实体类型开始,最后再加入独立的局部结构。
3)消除冲突
冲突分为三类:属性冲突、结构冲突、命名冲突。
设计全局er模式的目的不在于把若干局部er模式形式上合并为一个er模式,而在于消除冲突,使之成为能够被所有用户共同理解和接受的同一的概念模型。
4)全局er模式的优化
在得到全局er模式后,为了提高数据库系统的效率,还应进一步依据处理需求对er模式进行优化。一个好的全局er模式,除能准确、全面地反映用户功能需求外,还应满足下列条件:实体类型的个数要尽可能的少;实体类型所含属性个数尽可能少;实体类型间联系无冗余。
4.3.2逻辑设计
由于概念设计的结果是er图,dbms一般采用关系型,因此数据库的逻辑设计过程就是把er图转化为关系模式的过程。由于关系模型古有的优点,逻辑设计可以充分运用关系数据库规范化理论,使设计过程形式化地进行。设计结果是一组关系模式的定义。
1)导出初始关系模式
2)关系子模式
子模式是用户所用到的那部分数据的描述。除了指出用户用到的数据外,还应指出数据与概念模式中相应数据的联系,即指出概念模式与子模式之间的对应性。
第五章 公交查询系统应用程序设计(部分) §5.1查询模块的功能实现
<%@ page contenttype="text/html; charset=iso8859_1" %>
<%@ page import="java.sql.*,java.util.*,com.lanyuer.util.*;" %>
<%
list routes = null;
connection connection;
com.lanyuer.route.route_manager route_manager = com.lanyuer.route.route_manager.getinstance();
connection = dataconnectionmanager.getinstance().getconnection();
try {
routes = route_manager.selectes(connection);
} catch (exception e) {
throw e;
} finally {
if (connection != null) {
connection.close();
connection = null;
}
}
%>