分类

课内:
不限
类型:
不限 毕业设计 课程设计 小学期 大作业
汇编语言 C语言 C++ JAVA C# JSP PYTHON PHP
数据结构与算法 操作系统 编译原理 数据库 计算机网络 软件工程 VC++程序设计
游戏 PC程序 APP 网站 其他
评分:
不限 10 9 8 7 6 5 4 3 2 1
年份:
不限 2018 2019 2020

资源列表

  • 基于JSP的SSM框架和MYSQL数据库实现的租车管理系统

    一、实验目的需求分析是分析客户提出的初步需求的基础上,确定系统完整、准确、清晰、具体的功能要求,并且分析形成客户业务处理的数据流图和数据字典。此次实验主要是分析酒店预定管理系统的需求分析。
    二、实验原理进行需求分析首先是调查清楚用户的实际要求,与客户达成共识,然后分析与表达这些需求。
    调查客户需求的具体步骤是:

    调查组织机构情况。包括两节该组织的部门组成情况、各部门的职责等,为分析信息流程做准备
    调查各部门的业务活动情况。包括了解各部门输入和使用什么数据,如何加工处理这些数据,输出什么信息,输出到什么部门,输出结果的格式是什么等,这是调查的重点
    在熟悉业务活动的基础上,协助用户明确对新系统的各种要求,包括信息要求、处理要求、安全性与完整性要求,这是调查的又一个重点
    确定新系统的边界。对前面调查的结果进行初步分析,确定哪些功能由计算机完成或将来准备让计算机完成,哪些活动由人工完成

    三、实验内容3.1 功能要求
    客户

    注册/登录租车系统基本信息更新车辆信息浏览车辆预订预订订单信息更新(查看、增加、修改、删除)
    工作人员

    注册/登录租车系统客户基本信息更新车辆信息更新(查看、增加、修改、删除)订单信息更新(查看、增加、修改、删除)门店信息更新(查看、增加、修改、删除)续租信息更新(查看、增加、修改、删除)违章事务处理费用计算
    信息统计功能

    财务信息统计功能里程信息统计功能客户使用信息统计

    3.2 信息要求客户可以查看车辆基本信息、生成订单、查看订单、修改订单、删除订单、修改个人资料等。
    工作人员可以查询所有车辆基本信息以及所有客户基本信息、查询订单情况、删除订单、生成订单、记录订单信息、记录租车人的违约信息、车辆事故信息。
    3.3 处理要求当有订单生成或者删除的时候,系统需要及时更新系统中的车辆信息和订单信息,维护系统的信息的统一性。
    3.4 安全性与完整性要求系统应设置访问用户的标识以鉴别是否是合法用户,并要求合法用户设置其密码,保证用户身份不被盗用。
    3.5 总结从上述的功能分析可以得出,租车系统中需要有工作人员和客户两种模式,需要满足工作人员和客户的功能需求;工作人员功能有:注册/登录、信心更新、续租处理、违章处理等功能,其中信息更新包括对车辆基本信息进行更新、客户基本信息更新和订单信息更新等;用户功能需求有注册/登录、租车、还车和信息更新,其中信息更新包括对用户基本信息的更新和订单信息的更新。
    租车系统中的车辆租赁的基本规则如下:

    客户可以通过网上预订、电话预订、门店预订的方式预订租车服务
    网上预订租车服务时,系统需要检查用户的信息是否合法对租车的权限进行限制
    每位客户每次限租1辆,即在所租车辆未归还前,不能租用其他车辆
    每辆车在同一时间端内只允许被一个用户租赁
    每位客户在租赁时需要向租车公司缴一定的租车押金
    客户在还车时,工作人员需要对车辆进行检查,若在租车期间车辆发生一定的损坏需要交付一定赔偿金,同时返回租车押金
    客户在还车过程中,还需要缴一定的违章押金,如果在一个月之内发生违章,则需要根据交警违章处理结果进行一定的押金抵扣和其他形式赔偿,若一个月之内,没有查询到交警的违章处理,则返还违章押金
    租车费用根据租车时间和租赁价格进行计算,可能包含超时费用、超公里费用,及优惠金额,其中费用可能包含发生的违章保证金及其他未结清的费用押金

    3.6 程序流程图
    3.7 数据库表设计车型基本信息(ModelInfo)



    字段
    类型

    约束
    注释




    ID
    Char(32)
    NotNull
    PrimaryKey
    全局统一标识符


    Model_type
    Char(10)
    Not Null

    车辆类型


    Model_name
    Char(10)


    车辆名称


    Model_retailer
    Char(8)


    销售商


    Model_seatNum
    smallInt
    NotNull

    座位数


    Model_fuel_tank
    smallInt
    NotNull

    油箱容量


    Model__status
    Boolean


    车型状态


    Model_creator
    Char(10)
    NotNull
    ForeignKey
    记录创建人


    Model_createtime
    Date
    NotNull

    记录创建时间



    车辆基本信息(CarInfo)



    字段
    类型

    约束
    注释




    ID
    Char(32)
    NotNull
    PrimaryKey
    全局统一标识符


    ModelInfoID
    Char(32)
    NotNull
    ForeignKey
    参考ModelInfo的UUID


    Car_no
    Char(8)
    Not Null
    Unique
    车牌号


    Car_color
    Char(4)
    Not Null

    车辆颜色


    Car_purchaseD
    Date


    购买日期


    Car_engineN
    Char(8)
    Not Null

    发动机号


    Car_frameN
    Char(8)
    Not Null

    车架编号


    Car_fuelN
    Char(8)
    Not Null

    燃油编号


    Car_status
    Boolean


    车辆状态


    Store_UUID_Ref
    Char(32)
    NotNull
    ForeignKey
    车辆所在门店


    Car_creator
    Char(10)
    NotNull
    ForeignKey
    记录创建人


    Car_createtime
    Date
    NotNull

    记录创建时间



    租赁价格信息(RentpriceInfo)



    字段
    类型

    约束
    注释




    ID
    Char(32)
    NotNull
    PrimaryKey
    全局统一标识符


    ModeInfoID
    Char(32)
    NotNull
    ForeignKey
    参考ModelInfo的UUID


    Ullage_deposit
    Float
    Not Null

    车损押金


    Price_dailyM
    Float
    Not Null

    日租金


    Price_daily
    Float


    日公里限制


    Price_overtime
    Float

    15人民币/小时
    超时费用


    Price_overkm
    Float

    5人民币/千米
    超公里费用


    Price_status
    Boolean


    租赁状态


    Price_creator
    Char(10)
    NotNull
    ForeignKey
    记录创建人


    Price_createtime
    Date
    NotNull

    记录创建时间



    门店信息(StoreInfo)



    字段
    类型

    约束
    注释




    ID
    Char(32)
    NotNull
    PrimaryKey
    全局统一标识符


    Store_no
    Char(10)
    Not Null
    Unique
    门店编号


    Store_address
    Char(20)
    Not Null

    门店地址


    Store_Tel
    Char(20)
    Not Null

    门店联系方式


    Store_Openhours
    Char(10)
    Not Null

    门店营业时间


    Store_status
    Boolean


    门店状态


    Store_creator
    Char(10)
    NotNull
    ForeignKey
    记录创建人


    Store_createtime
    Date
    NotNull

    记录创建时间



    基本信息(CustomerInfo)



    字段
    类型

    约束
    注释




    ID
    Char(32)
    NotNull
    PrimaryKey
    全局统一标识符


    Customer_no
    Char(10)

    Unique
    用户编号


    Customer_password
    Char(10)


    密码


    Customer_name
    Char(10)


    姓名


    Customer_sex
    Char(2)


    性别


    Customer_age
    Char(4)


    年龄


    Customer_ID
    Char(18)
    Not Null

    身份证号


    Customer_Tel
    Char(15)


    电话


    Customer_workplace
    Char(15)


    工作单位


    Customer_address
    Char(20)


    地址


    Customer_post
    Char(6)


    邮编


    Customer_eMail
    Char(15)
    Not Null

    eMail


    Customer_status
    boolean


    客户状态


    Customer_creator
    Char(10)
    NotNull
    ForeignKey
    记录创建人


    Customer_createtime
    Date
    NotNull

    记录创建时间



    基本信息(CustomerInfo)



    字段
    类型

    约束
    注释




    ID
    Char(32)
    NotNull
    PrimaryKey
    全局统一标识符


    License_no
    Char(10)
    Not Null
    Unique
    驾驶证号


    License_type
    Char(10)
    Not Null

    驾照类型


    License_years
    Int
    Not Null

    驾龄


    License_start
    Date
    Not Null

    发证日期


    License_end
    Date
    Not Null

    失效日期


    License_status
    Boolean


    状态


    License_creator
    Char(10)
    NotNull
    ForeignKey
    记录创建人


    License_createtime
    Date
    NotNull

    记录创建时间



    驾驶证信息(LicenceInfo)



    字段
    类型

    约束
    注释




    ID
    Char(32)
    NotNull
    PrimaryKey
    全局统一标识符


    License_no
    Char(10)
    Not Null
    Unique
    驾驶证号


    License_type
    Char(10)
    Not Null

    驾照类型


    License_years
    Int
    Not Null

    驾龄


    License_start
    Date
    Not Null

    发证日期


    License_end
    Date
    Not Null

    失效日期


    License_status
    Boolean


    状态


    License_creator
    Char(10)
    NotNull
    ForeignKey
    记录创建人


    License_createtime
    Date
    NotNull

    记录创建时间



    订单信息(OrderInfo)



    字段
    类型

    约束
    注释




    ID
    Char(32)
    NotNull
    PrimaryKey
    全局统一标识符


    Order_no
    Char(8)
    Not Null
    Unique
    订单号


    Car_no
    Char(8)
    Not Null

    车牌号


    Car_type
    Char(10)
    Not Null

    车辆类型


    License_no
    Char(10)
    Not Null

    驾驶证号


    Customer_no
    Char(10)
    Not Null

    客户编号


    Order_startD
    Date


    开始时间


    Order_P_endID
    Date


    计划还车时间


    Order_A_endD
    Date


    实际还车时间


    Order_startM
    Float


    开始里程


    Order_endM
    Float


    结束里程


    Order_useM
    Float


    使用里程


    Order_basicF
    Float


    基本消费


    Order_timeoutF
    Float


    超时金额


    Order_mileoutF
    Float


    超里程金额


    Order_discountF
    Float


    优惠金额


    Order_deposit
    Float


    租车押金


    Violate_deposit
    Float


    违章押金


    Ullage_deposit
    Float


    车损押金


    Order_violateF
    Float


    违章罚款


    Order_ullageF
    Float


    车损扣款


    Order_sumF
    Float


    消费金额


    Order_status
    Char(8)


    订单状态


    Order_creator
    Char(10)
    NotNull
    ForeignKey
    记录创建人


    Order_createtime
    Date
    NotNull

    记录创建时间



    续租订单信息(PostOrderInfo)



    字段
    类型

    约束
    注释




    ID
    Char(32)
    NotNull
    PrimaryKey
    全局统一标识符


    OrderInfoID
    Char(32)
    NotNull
    ForeignKey
    续租的主订单号


    Order_no
    Char(8)
    Not Null
    Unqiue
    续租订单号


    PostOrder_startD
    Date


    开始时间


    PostOrder_endD
    Date


    结束时间


    PostOrder_deposit
    Float


    租车押金


    PostOrder_status
    Boolean


    续租状态


    PostOrder_creator
    Char(10)
    NotNull
    ForeignKey
    记录创建人


    PostOrder_createtime
    Date
    NotNull

    记录创建时间



    违章信息(ViolateInfo)



    字段
    类型

    约束
    注释




    ID
    Char(32)
    NotNull
    PrimaryKey
    全局统一标识符


    CarInfoID
    Char(32)
    NotNull
    ForeignKey
    违章车辆标志号


    Violate_date
    Date
    Not Null

    违章时间


    Violate_event
    Char(8)


    违章事件


    Violate_marks
    Float


    扣分


    Violate_fee
    Float


    违章罚款


    Violate_status
    Boolean


    状态


    Violate_creator
    Char(10)
    NotNull
    ForeignKey
    记录创建人


    Violate_createtime
    Date
    NotNull

    记录创建时间



    四、总结与建议本次实验主要是依据神州租车网设计一个简易的租车网站系统,在现有系统提供的一部分功能的基础上进行简化。采用B/S模式,通过客户与工作人员对租车系统功能的实现,客户主要是通过前端系统对产生预订订单,工作人员主要是通过后端对数据库中数据的操作,所以整个系统的主体部分实现在于工作人员模块功能的完善。
    在小组讨论中,我们队租车管理系统有了更加深入的了解,为后续的系统开发做出了充分的准备。同时在与老师交谈过程中发现整个系统设计的过程中主体部分的偏离,并及时做了改正。
    5 评论 269 下载 2018-11-06 14:32:31 下载需要8点积分
  • 基于JSP SSM框架的城市公交查询系统的设计与实现

    摘 要公交查询系统是为了方便人们查询公交的信息,并且能够及时的做到信息更新,其主要是要做到方便人们的使用,信息的可维护性和程序的稳定性 。本系统采用了JAVA编程语言,数据库使用Mysql。计算机技术不断发展,逐渐适应用于各领域,给人们的学习工作生活带来了便利,在公交查询系统也是这样。纸质的公交指南或繁杂的网络版公交指南,都在不同程度上限制了市民出行的方便性。本论文介绍的是一个城市的公交查询系统,方便市民用最简约的方式,查询到最实用的公交信息。本论文是在此系统经过测试并且所有功能都实现的基础上完成的,主要涉及软件,数据库与网络技术等。
    关键词:城市公交查询系统;数据库;JAVA;SSM
    AbstractThis city buses inquiry system aims to make the resident inquire city buses information more convenient and must achieve the information not too lag, but its main idea is the system administrate user-friendly, the data processes reliability, the maintainability, as well as procedure toughness. The system uses the JAVA programming language and MYSQL as database. Along with computer technology’s unceasing development, the computer applies in each big domain, and has brought the enormous convenience to people’s life, the city buses referral system is also. The departed paper city buses guide or the numerous and diverse online edition city buses guide, has limited the conveniences which in the different procedure when a resident goes on a journey. This thesis introduces a city buses referral system, by facilitates the resident with the briefest way and inquires the most useful city buses information. This thesis that is based on the system has been tested and functions all come true mainly involves software, database and networking and so on.
    Key words: City Buses inquiry system; Databases; JAVA; SSM
    1 概述1.1 项目开发背景和现状的研究1.1.1 开发背景随着城市建设的飞速发展,生活节奏的加快,公交系统对城市来说越来越重要。而政府在这方面的投入也是加大了力度,城市中的公交系统也是日益完善,公交系统的不断更新,却又导致了市民无法从原来的公交指南上看到现如今的信息,从而产生了很多不必要的麻烦。所以需要提供一个高效的公交查询系统,才是问题的根本所在。
    现在,随着计算机技术和通信技术的发展,与网络相结合是现如今的重要发展方向,特别是在网络普及,上网极为方便的网络信息时代,通过上网来查询公交信息是公交查询系统的发展方向。
    1.1.2 研究现状公交查询系统是为了方便人们查询公交的一些信息,并且能够做到信息的及时更新,主要是要方便人们的使用,信息的可维护性和程序的稳定性 。本系统采用JAVA,数据库使用的是Mysql。计算机技术的不断发展,逐渐适应用于各领域,给人们的学习工作生活带来了便利,在公交查询系统也是这样。纸质的公交指南或繁杂的网络版公交指南,都在不同程度上限制了市民出行的方便性。本论文介绍的是一个城市的公交查询系统,方便市民用最简约的方式,查询到最实用的公交信息。
    1.2 项目开发目的与意义1.2.1 系统开发的目标本系统是基于J2EE的公交查询系统,其中包括了公交查询系统的基本功能,并提供了用户留言的功能,方便根据用户提供的留言信息或是提出的建议对系统进行修改和完善,并提供了管理员用户后台维护公交信息的功能,做到能够实时添加和删除公交车次站点。除主要功能以外本系统还附带发布寻物启示与失物招领模块,方便用户。 本系统目标是方便市民进行公交信息查询,并且要做到信息不滞后,其主要思想是做到系统管理的人性化,数据处理的可靠性,可维护性,以及程序的健壮性[2]。系统提供了用户留言的功能,根据用户提供的留言信息或提出的建议提高公交公司的服务质量。基于J2EE的城市公交查询系统,它采用B/S模式。该系统不仅可以用于公交公司管理系统中,也可以单独作为公交管理系统的一个模块存在,并可以制作成城市公交信息系统查询网,放置于城市的主要场所[3]。这样不仅可以体现出一个城市的智能公交系统的水平,更显示出城市的数字化,信息化水平。
    1.2.2 系统开发的意义Internet 是城市公交信息查询系统得以实现的基础。在当今社会,网络大为普及,上网极为方便,通过网络查询公交信息更是城市公交信息查询系统的发展方向,与网络相结合是大势所趋[4]。城市公交信息查询系统旨在应用现代的信息网络化为广大乘客提供一种方便快捷的乘车线路服务,让网络惠及更多的人。提高市民的出行效率,促进社会的和谐。
    本论文主要涉及软件,数据库与网络技术等。涵盖知识面广,可有效地提高学生综合运用所学知识分析解决问题的能力,增强学生对事物的理解与掌握能力,培养学生掌握科学的研究方法,正确的设计思想,独立思考,勇于进取,探索创新,为今后进一步学习与工作奠定了良好的基础。
    1.3 本论文研究的主要内容本论文采用软件工程思想来进行城市公交信息查询系统的设计与实现。
    首先,介绍当前形势下大多数城市公交路线查询系统存在的诸多问题。在此基础上提出本系统的现实意义以及必要性。对城市公交信息查询系统进行了可行性分析,确定了本系统的功能、性能、界面等。
    其次,对城市公交信息查询系统进行模块分解,确定软件结构,模块功能和模块间的接口,以及数据库的设计。及根据需求分析中提出的思路来设计系统,对各个模块的设计进行了描述。然后给出了城市公交信息查询系统的整体结构图以及各个模块的实现流程图以及数据库设计时需要的表结构。
    再次,对本系统进行详细设计,在此基础上对各个模块的实现进行了介绍,给出了本系统的效果图,并且对重要功能给出了主要代码。
    最后,对系统进行了测试及分析。本文对软件测试的概念和方法进行了概要说明,并对系统的设计和实现进行了总结,提出了对城市公交信息查询系统的展望和具体的改进建议。
    2 需求分析2.1 需求分析2.1.1 系统需求由于本系统面向广大市民和公交公司管理本系统等非计算机专业人士的需求,因此要求硬件配置不能太高,任何一个普通的计算机用户都能很快的熟悉整个软件的使用。本系统要做到所耗费的资源常小,任何用户只需要在一般的电脑上面,就能够通过浏览器使用这个软件。公交公司管理人员能够简单、方便、快捷、远程的实现对系统实时维护和管理。
    2.1.2 技术需求本系统是以互联网为基础,采用SSM框架MySQL数据库开发模式,服务器采用Tomcat 6.0。服务器由数据库服务器、Web服务器等服务器组成,通过客户端网络连接进行系统的管理和维护,数据库服务器中的数据要实现实时更新,数据库要可靠稳定。
    2.1.3 安全需求本系统面向社会,因此对系统的安全性有较高的要求。对数据库要设置不同的用户权限,数据的操作需要用户身份验证,只有取得合法的身份才能进行操作,还应避免数据并发现象,防止数据库无法响应操作。
    2.2 系统可行性分析2.2.1 技术可行性现在,随着计算机技术和通信技术的发展,与网络相结合是以后的重要发展方向,特别是在网络大为普及,上网极为方便的网络信息时代,通过网络查询公交信息更是公交查询系统的发展方向。特别是在网络大为普及,上网极为方便的网络信息时代,通过网络查询公交信息更是查询系统的发展方向。基于Web的新型公交信息查询系统,数据信息更新更为准确、及时,用户可以利用计算机、手机等平台通过有限或无线的网络连接方式对系统进行访问,得到快捷的服务[5]。SSM(Spring + Springmvc +Mybatis)框架中Mybatis提供了多种常用的数据库应用程序,通过少量代码的编写,就能够实现数据库的访问[6]。系统采用MYSQL作为开发数据库。MYSQL是一种客户机/服务器结构的关系数据库管理系统[7]。在技术难度方面,有指导老师的指导、周围同学的热心帮助,加上对很多相关文献的参考,能够解决开发过程中所遇到的困难。因此,技术是可行的。
    2.2.2 经济可行性如今,随着计算机的大量普及,各种软件的开发成本越来越低,价格也越来越底。本系统也是这样,开发成本较低,只是需要一台配置一般的计算机,该系统运行时占计算机的资源也不多,但并不会因为开发成本低而造成系统功能性能的下降。相反,随着计算机技术的发展,各种实用软件的性能日渐提高。任务管理系统廉价的开发成本,却能够为用户带来相当大的实惠和方便。主要表现在:

    本系统可以说是一个拥有多种实用功能的系统,它集成了多种功能,具有较强的实用性和方便性
    本系统的运行可以大大提高查询信息的效率,减少不必要的人力和物力

    2.3 功能分析要设计一个良好的公交查询系统,就必须首先明确该应用环境对系统的要求。公交查询系统的应用背景为:方便市民搭乘公交车出行;手动(目前)、自动(将来)、及时更新查询数据。
    2.3.1 查询功能分析系统需要提供几种不同方式的查询手段,以实现灵活方便地管理整个系统。其中包括:

    线路查询:可以获得要查询公交所通过的所有站点
    站点查询:通过输入指定站点查询经过该站点的公交车
    公交换乘模块:主要体现那些不可直达需要转车的线路的所有换发

    2.3.2 数据的更新以及修改分析
    更新:系统允许管理员级别的用户对数据进行更新、修改并且存盘操作
    编辑:系统允许管理员级别的用户对数据进行编辑、删除的操作,保证数据的真实性与实时性

    系统采用采用B/S(Browser/Server)结构。整个系统最关键的就是数据库系统,一个强大的数据库可以支持完善一个优秀的软件设计,通过软件系统与数据库系统的连接来实现通过软件界面观察和处理操作数据[8]。通过软件系统与数据库系统的连接来实现通过软件界面观察和处理操作数据,如图2-1所示。

    系统采用三层结构,在客户端用户通过浏览器完成数据下载与模拟操作,浏览器端的表现逻辑通过JAVA网页完成[9]。而系统内部复杂的业务逻辑主要通过JavaBean的组件(Component)实现,JavaBean组件在WWW服务器上运行,通过JAVA返回到客户浏览器。通过表现逻辑与业务逻辑的分离,使网页内容简洁,系统的可维护性和可扩充性增强。在服务器端,系统使用JDBC中间件访问数据库,数据库服务器定义了本系统所需要的事务逻辑和数据逻辑。本系统使用JAVA技术作为表现手段,服务器采用Tomcat6.0作为JAVA引擎,系统业务逻辑由JavaBean 组件完成,使用JDBC 3.0 驱动程序访问数据库[10]。由于系统测试需要成熟的数据库支持,因此系统采用MySQL数据库作为数据库服务器。
    3 系统关键技术3.1 JAVA技术JAVA是由Sun微系统公司于1999年6月推出的一项技术,是基于JavaServlet以及整个Java体系的Web开发技术,利用这一技术可以建立先进、安全和跨平台的动态网页技术[11]。JAVA技术在多个方面加速了动态Web页面的开发。
    与微软公司的ASP技术相比,JAVA具有如下优点:

    开放的技术:JAVA技术基于平台和服务器的相互独立,技术支持来自广泛的、专门的、各种工具包,有服务器的组件和数据库产品开发商提供。相比之下,JAVA技术主要依赖MICROSOFT支持
    平台和服务器的独立性:JAVA编写的代码可运行在任何符合JAVA语法结构的环境中。这样JAVA就能够运行在多种WEB服务器上并支持来自多家开发商提供的各种工具包
    开放的开发过程,开放的源码:自1995年以来,SUN用开放过程方法同国际JAVA组织合作开发和修改JAVA技术和规范
    JAVA标记可扩充性:JAVA技术能够为开发者扩展JAVA标记,充分利用与XML兼容的标记技术强大的功能,大大减少对脚本语言的依赖
    JAVA跨平台的可重用性:JAVA组件(EJB,JavaBean或定制的JAVA标记)都是跨平台可重用的

    3.2 Java Bean技术JAVA作为一个很好的动态网站开发语言得到了越来越广泛的应用,在各类JAVA应用程序中,JAVA + JavaBean的组合成为了一种事实上最常见的JAVA程序的标准[12]。JavaBean是描述Java的软件组件模型,有点类似于Microsoft的COM组件概念。在Java模型中,通过JavaBean可以无限扩充Java程序的功能,通过JavaBean的组合可以快速的生成新的应用程序。对于程序员来说,最好的一点就是JavaBean可以实现代码的重复利用,另外对于程序的易维护性等等也有很重大的意义。JavaBean通过Java虚拟机(Java Virtual Machine)可以得到正确的执行,具有平台无关性[13]。一个JavaBean有三个部分组成:
    属性(Property)
    Bean的属性就是对象的属性,但提供了属性读取和设置的接口支持。例如一个时钟Bean可以有时区和镇铃属性,日历Bean可以有年份和月份属性。每个属性通常遵守简单的方法命名规则。这样可以很方便的找出Bean提供的属性,然后查询属性值或改变属性值,对Bean进行操作。
    方法(Method)
    由于Bean本身是Java对象,调用这个对象的方法是与其交互作用的唯一途径。JavaBean严格遵守面向对象的类设计逻辑,不让外界访问其任何实例字段(没有Public字段)。这样,方法调用的是接触Bean的唯一途径。
    事件(Event)
    Bean与其他软件组件交流信息的主要方式是发送和接收事件。这与对象之间通过消息通信类似。JavaBean传统的应用在于可视化的领域,如AWT下的应用。自从JAVA诞生后,JavaBean更多的应用在非可视化领域,在服务器端应用方面表现出来了越来越强的生命力。利用非可视化JavaBean, 来封装事务逻辑、数据库操作等等,可以很好地实现业务逻辑和前台程序(如JAVA)的分离,使得系统具有更好的健壮性和灵活性。
    3.3 JDBC技术JDBC是Java的开发者——Sun的Java Soft公司制定的Java数据库连接Java Data Base Connectivity技术的简称,是为各种常用数据库提供无缝联接的技术[14]。JDBC在Web和Internet应用程序中的作用和ODBC在Windows系列平台应用程序中的作用类似。JDBC有一个非常独特的动态连接结构,它使得系统模块化。使用JDBC来完成对数据库的访问包括以下四个主要组件:Java的应用程序、JDBC驱动器管理器、驱动器和数据源。简单地说,JDBC能完成下列三件事:

    同一个数据库建立连接
    向数据库发送SQL语句
    处理数据库返回的结果

    JDBC是一种可用于执行SQL语句的Java API(Application Programming Interface,应用程序设计接口)。它由一些Java语言写的类、界面组成。JDBC给数据库应用开发人员、数据库前台工具开发人员提供了一种标准的应用程序设计接口,使开发人员可以用纯Java语言编写完整的数据库应用程序。
    通过使用JDBC,开发人员可以很方便地将SQL语句传送给几乎任何一种数据库。也就是说,开发人员可以不必写一个程序访问MySQL,写另一个程序访问Oracle,再写一个程序访问Microsoft的SQLServer。用JDBC写的程序能够自动地将SQL语句传送给相应的数据库管理系统(DBMS)。不但如此,使用Java编写的应用程序可以在任何支持Java的平台上运行,不必在不同的平台上编写不同的应用。Java和JDBC的结合可以让开发人员在开发数据库应用时真正实现“Write Once,Run Everywhere![15]”。
    Java 具有健壮、安全、易用等特性,而且支持自动网上下载,是一种很好的与数据库线连接而使用的编程语言。它所需要的是Java应用如何同各种各样的数据库连接,JDBC正是实现这种连接的关键。
    JDBC扩展了Java的能力,如使用Java和JDBC API就可以公布一个Web页,页中带有能访问远端数据库的Applet。或者企业可以通过JDBC让全部的职工(他们可以使用不同的操作系统,如Windows, UNIX)在Internet上连接到几个全球数据库上,而这几个全球数据库可以是不相同的。
    3.4 Springmvc技术Springmvc虽然是在Struts1的基础上发展起来的,但它实质上是以WebWork为核心的,其次它为传统的Struts1注入了WebWork的先进设计理念,是在Struts和WebWork的技术基础上进行合并后的一种全新框架。它全新的体系结构与Struts1的体系结构差别很大,Springmvc以WebWork为核心,在Springmvc中大量使用拦截器机制来处理用户请求,采用这种设计的优势表现在:业务逻辑控制器能够与Servlet API 完全分离,避免了Struts1与Servlet API的严重耦合。
    Springmvc对Struts1进行了巨大的改进,主要表现在以下几个方面:

    线程模型方面:Springmvc的Action是一个请求对应一个实例,而Struts1用一个Action的实例处理所有的请求,它的Action工作在单例模式,存在线程安全问题
    Action实现方面:Struts1要求统一扩展自Action类,而Springmvc中可以是一个普通的POJO(Plain Old Java Objects)。POJO指简单的Java对象,实际就是普通Java Beans
    Servlet依赖方面:Struts1的Action依赖于Servlet API,例如Action的execute方法的参数包括request和response对象,使得程序难以测试,而Springmvc的Action不再依赖于Servlet API,便于测试
    封装请求参数:在Struts1中强制使用ActionForm对象封装请求参数而在Springmvc中可以直接使用Action的属性或者选择使用JavaBean来封装要请求的参数
    在数据校验方面: Struts1中支持覆盖validate方法或者使用Validator框架,而在Springmvc中支持重写validate方法或者使用XWork的验证框架
    在Action执行控制方面:Struts1支持每一个模块对应一个请求处理,但是模块中的所有Action必须共享相同的生命周期,而Springmvc支持通过拦截器堆栈为每一个Action创建不同的生命周期

    3.5 Mybatis技术Mybatis是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得开发人员可以随意的使用对象编程思想来操纵数据库,最具特色的是它可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任[16]。
    Mybatis 核心接口有Session、SessionFactory、Transaction、Query、Criteria和Configuration等6个。通过这六个核心接口,不仅可以对持久化对象进行存取,还能够进行事物控制。以下是对这6个核心接口的介绍:

    Session接口:该接口负责执行持久化对象的CRUD(Create Read Update Delete)操作,需要特别指出的是Session对象时非线程安全的
    SessionFactory接口:该接口负责初始化Mybatis。它的职能是负责创建Session对象,并充当数据存储的代理。这里用到了工厂模式,需要注意的是SessionFactory 并不是轻量级的,因为一般情况下,一个项目通常只需要一个SessionFactory 就够了,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory
    Transaction接口:该接口负责事物相关的操作。它是可选的,开发人员可以根据自己的需要来编写自己的底层事物处理代码
    Query和Criteria接口:Query和Criteria接口负责各种数据库查询。它们可以使用SQL语句和HQL语言两种方式,本系统采用SQL语句

    3.6 JavaScript技术JavaScript是适应动态网页制作的需要而诞生的一种脚本语言。它具有交互性,能够包含更多活跃的元素,如今已经广泛地应用于Internet网页制作[17]。JavaScript是由Netscape公司开发的一种脚本语言(Scripting Language)。在HTML基础上,使用JavaScript可以开发交互式网页。它的出现使得网页和用户之间实现了一种实时性的、动态的、交互性的关系,使网页包含更多活跃的元素和更精彩的内容。
    JavaScript可以嵌入到HTML文件中,它的出现增强了网页的互动性,JavaScript简化了HTML文段中的有规律重复的部分,缩短了网页加载时间。
    3.7 MVC设计模式MVC模式是目前广泛流行的设计模式,包括三类对象。它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器[18]。
    3.7.1 模型(Model)模型就是业务流程、状态的处理以及业务规则的制定,业务流程的处理过程对其它层来说就是黑箱操作,模型接受视图请求的数据,并返回最终的处理结果。业务模型的设计可以说是MVC最主要的核心。目前流行的EJB模型就是一个典型的应用,它从应用技术实现的角度对模型做了进一步的划分,以便充分利用现有的组件。在MVC的三个部件中,模型处理的任务最多。模型的好处在于代码可以被多个视图重用,因此简化了代码。
    3.7.2 试图(View)视图代表用户交互界面,对于Web应用来说,可以概括为HTML界面。由于一个应用可能有很多不同的视图,MVC设计模式对于视图的处理仅限于视图上数据的采集和处理,以及用户的请求,而不包括在视图上业务流程的处理。业务流程的处理交予模型处理。
    3.7.3 控制器(Controller)控制器可以理解为从用户接收请求,将模型与视图匹配在一起,共同完成用户的请求。所以当单击Web页面中的超链接和发送HTML表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后用确定用哪个视图来显示模型处理返回的数据。
    3.8 系统运行环境服务器端的最低配置是由建立站点所需要的软件来决定的,在最底配置的情况下,服务器的性能往往不进人意,现在硬件性能已经相当出色,而且价格也很便宜,因此通常应给服务器端配置高性能硬件。
    本系统的配置要求如下:

    处理器:1.5GHZ以上
    内存:512MB
    硬件空间:160GB

    题目主要采用的开发环境及技术:

    开发环境

    Windows XP Professional(以上版本)Internet Explorer6.0(以上版本)
    开发工具包:JDK Version1.6
    脚本语言:JavaScript
    数据库工具:MYSQL
    JAVA开发工具:MyEclipse8.5

    4 系统总体设计4.1 系统总体设计概述本系统设计使用了面向对象技术和模块化技术。面向对象技术是一种软件开发和程序设计技术,其所开发的程序是面向对象程序,直接描述客观世界的对象及其相互关系。对象是封装了数据和操作的程序块。所谓封装是为这个程序块建立显示的界面,其它对象只能向这个界面发消息,不能访问内部的私有数据和操作。因此,内部的数据和实现操作的算法若有改动,对其它程序对象没有任何影响。封装使程序局部化、易修改、好维护,但许多对象有相同的功能时免不了重复,所以面向对象技术有继承的机制。此外,由于对象自己操作自己的数据,对同一消息不同的对象均以自己的方式响应使得一种消息可有多种响应方式,这就是多态性。封装、继承、多态是面向对象程序的主要特征[19]。正是这些特征使程序安全、可靠、可重用、易维护。因而面向对象技术也成为当今计算机的新兴技术。
    4.2 系统功能结构图根据上述设计思想进行分析,确定了系统的基本框架,如图4-1所示。

    可以看出城市公交信息查询系统的相关功能,这为系统开发及功能模块化提供了清晰地设计思路与方向,基于系统需求分析,以下为该系统的详细功能:
    登录模块
    普通登陆成功后进入用户个人主界面并选择各种操作,否则会返回到登录界面重新进行登录。管理员登录成功进入管理员主界面选择相应操作。
    公交系统查询模块
    无需登录,进入系统首页根据自己需要进行公交查询。有包括车次查询、站点查询和查询公交换乘方案等。车次查询即为根据车次号查询车次经过的站点,该车次开收车时间,等基本信息;站点查询为经过该站点的车次信息;公交换乘方案查询即分别输入起始站点和目的站点并查询公交乘车方案。
    公告管理模块
    普通用户登录系统后,进入公告管理模块,用户可以提出自己的一些看法意见和对本公交系统的建议,能查看以前的留言。除此之外系统还提供事物认领模块。
    用户个人信息管理模块
    用户登录成功后即可进入到用户的个人主界面,在个人主界面中,用户可以查看个人详细信息,包括用户名账号,保护邮箱等信息,并可以自行修改密码等个人信息,最后注销登录返回到系统登录界面。
    站点信息管理模块
    管理员登录系统后进入相应管理员主界面,在管理员主界面中,可对公交站点信息进行添加和删除,实时更新公交变动信息。
    车次信息管理模块
    管理员登录系统后进入相应管理主界面,在管理员主界面中,可对公交车次信息进行添加和删除,实时更新公交变动信息。
    4.3 系统流程图4.3.1 系统操作流程系统操作流程图详细阐述了该系统的整体操作流程,如图4-2所示。

    用户进行登录,选择登录身份是普通用户或者管理员,如果用户名和密码正确则进入到相应的用户个人主界面,否则返回登录界面重新进行登录。在用户个人主界面,用户可以进行各自需要的操作。若用户为普通用户,则可以进行查询公交信息,留言,注销和更改个人信息等操作;用户为管理员,可添加删除公交信息。最后,用户操作完毕,即可退出本系统,整个系统操作流程到此结束。
    4.3.2 数据增加流程添加信息时,编号字段由系统自动生成,且不能修改,其他信息由用户输入,之后对数据进行合法判断, 合法则写入保存至数据库,不合法则重新输入数据。数据增加流程图如图4-3所示。

    4.3.3 数据修改流程在修改信息时,先选中一条待修改的记录,然后直接输入数据,判断合法性,合法则保存至数据库,不合法重新输入。数据修改流程图如图4-4所示。

    4.3.4 数据删除流程当用户选定一条记录时,单击删除按钮,会提示用户是否确定删除,然后删除数据库相关内容。数据删除流程图如图4-5所示。

    4.4 数据流分析管理员登录系统后,可进行车次管理、站点管理、线路管理、删除用户等操作。普通用户注册登录后,进入查询界面通过系统数据库,可进行公交信息查询、留言版留言。如图4-6所示。

    4.5 业务流分析城市公交信息查询系统工作流程为:输入首页网址进入首页界面,游客只能查询公交信息,游客可以通过注册成为普通用户。普通用户除了具备游客权限外还可以管理个人资料以及发布信息。管理员拥有最高权限,可以对系统信息增删改查,以及对普通管理员的管理,系统业务流程图如图4-7所示。

    5 系统详细设计5.1 后台数据库设计数据库技术是信息资源管理最有效的手段。数据库设计是指对于一个给定的应用环境,构造最优的数据库模式,建立数据库及其应用系统,有效存储数据,满足用户信息要求和处理要求[20]。
    毕业设计城市公交信息查询系统需要对大量的数据完成搜集、分析、整理、存储、交换等工作,这就需要设计一个较为强大的数据库来对这些数据进行管理。在这里本着实用、方便、安全、可靠的原则,采用MySQL作为本系统数据库的支持。本系统主要数据表有:普通用户表、管理员表、车次信息表、站点信息表、中间站点关联表、留言信息表等。
    为了满足系统存储数据需要,方便进行插入,更新,统计分析等操作,数据一共设计为两个部分,第一部分为满足插入,更新,删除较多的数据存储。第二部分为满足查询和统计分析。
    管理员信息表:该表主要保存管理员信息,包含管理员编号、管理员姓名、账户名、密码。



    列名
    数据类型
    字段大小
    可否为空
    说明




    id
    int


    管理员编号(主键)


    adminName
    varchar
    50

    管理员姓名


    loginName
    varchar
    50

    账户名


    passWord
    Varchar
    50

    密码



    公交线路信息表:该表主要保存公交线路信息,包含线路编号、正向途经站点、反向途经站点、公交线路名称、始发时间与末班时间。



    列名
    数据类型
    字段大小
    可否为空
    说明




    id
    int


    线路编号(主键)


    content
    varchar
    255

    正向途径站点


    content2
    varchar
    255

    反向途径站点


    name
    varchar
    50

    线路名称


    title
    varchar
    255

    始末发车时间



    失物信息表:该表主要保存用户发布的信息,包括启示编号、启示内容、发布时间、启示标题、启示类别。



    列名
    数据类型
    字段大小
    可否为空
    说明




    id
    int


    启示编号(主键)


    contents
    varchar
    20

    启示内容


    inputTime
    varchar
    255

    发布时间


    title
    varchar
    255

    启示标题


    type
    int


    启示类型



    找回密码表:该表主要保存找回密码所需信息,包括编号、问题答案内容、问题类型。



    列名
    数据类型
    字段大小
    可否为空
    说明




    id
    int


    编号(主键)


    content
    varchar
    255

    答案内容


    title
    int


    问题类型



    公告表:该表主要保存发布的公告信息,包括公告编号、公告内容、发布时间、公告标题。



    列名
    数据类型
    字段大小
    可否为空
    说明




    id
    int


    公告编号(主键)


    contents
    varchar
    20

    公告内容


    inputTime
    varchar
    255

    发布时间


    title
    varchar
    255

    公告标题



    用户信息表:该表主要保存用户注册信息,包括编号、用户地址、用户邮箱、用户姓名、登录密码、用户名、用户电话、附加信息。



    列名
    数据类型
    字段大小
    可否为空
    说明




    id
    int


    用户编号(主键)


    address
    varchar
    255

    用户地址


    contents
    varchar
    255

    附加信息


    email
    varchar
    50

    邮箱


    loginName
    varchar
    255

    用户名


    passWord
    varchar
    50

    密码


    userName
    varchar
    50

    用户姓名


    tel
    varchar
    20

    用户电话



    5.2 系统模块设计5.2.1 注册与登录用户注册界面,要求用户必须输入姓名、用户名、密码、联系电话以及邮箱等必填信息以及联系地址等选填信息。当信息填完后点击保存按钮完成注册工作,进入用户登录界面,点击返回按钮返回到首页,如图5-1所示。

    登录界面,分为普通用户登录和管理员登录。普通用户或系统管理员在用户对应的文本框中输入用户名,在密码对应的文本框中输入密码,然后选择相应的用户类型。如果用户名和密码同时与数据库中的用户名和密码相对应,点击确定后进入系统主界面,如果输入的信息不正确,则给出提示。
    用户要登录本系统需要提供用户名和密码,在这里就是要检验用户是否满足输入的要求,即检验用户名和密码文本框是否为空,若为空,则提示用户输入用户名和密码。检验用户名是否存在或密码是否正确,即是否存在用户输入的用户名,并且密码是否正确,如图5-2所示。

    输出:登录成功,进入用户的系统使用资源页面,不成功则显示错误信息页面,管理界面如图5-3所示。

    5.2.2 公交信息查询用户根据自己的实际情况选择按站点查询、按线路查询也可以根据其实位置和终点位置进行查询,在相应的位置进行输入,然后提交给系统,系统会自动查找线路表所有相匹配的信息,并返回给用户要查询的公交信息,如图5-4所示。

    查询公交信息数据库相关操作代码:
    public String zz() throws Exception { String cd = request.getParameter("textfield3").trim(); String zd = request.getParameter("textfield4").trim(); ArrayList al = (ArrayList) indexDao.checkCDZD(cd, zd); System.out.println("al.size=" + al.size()); HttpSession session = request.getSession(); if (al.size() > 0 && al != null) { //如果有直达的车辆(也就是不用转车) session.setAttribute("zzMore", al); //直达的车辆的信息 session.setAttribute("zzMorecd", cd); //您输入的起点名 session.setAttribute("zzMorezd", zd); //您输入的终点名 return "zzone"; } else { ArrayList arrMiddleAll = indexDao.checkMiddle(cd, zd); if (arrMiddleAll.size() > 0 && arrMiddleAll != null) {//查询一个中转站可以到达目的地的方法 session.setAttribute("zzMoreMiddleAll", arrMiddleAll); //得到一个中转站可以到达目的地的所有信息 session.setAttribute("zzMorecd", cd); //您输入的起点名 session.setAttribute("zzMorezd", zd); //您输入的终点名 System.out.println("=======================zztwo"); return "zztwo"; } else { //也就是要倒两次以上车 ArrayList arrTwoMiddleAll=indexDao.checkTwoMiddle(cd,zd); if (arrTwoMiddleAll.size() > 0 && arrTwoMiddleAll != null) { session.setAttribute("zzMorecd", cd); //您输入的起点名 session.setAttribute("zzMorezd", zd); //您输入的终点名 session.setAttribute("zzMoreTwoMiddleAll", arrTwoMiddleAll); //得到二个中转站可以到达目的地的所有信息 System.out.println("=======================zzthree"); return "zzthree"; }else{ System.out.println("======================= - zzerror - "); return "zzerror";}
    5.2.3 寻物启事和失物招领普通用户进入该模块可以发布寻物启示以及失物招领信息,如图5-5所示。

    数据库操作相关代码:
    public String noteSSMow() throws Exception { if (request.getSession().getAttribute("loginmessage") == null) return "noLogin";//判断是否登录 NotesEntity pe = indexDao.noteSSMow(request); request.setAttribute("NotesEntity", pe); return "noteSSMow"; } // 公告管理:修改信息 public String notesUpdList() throws Exception { if (request.getSession().getAttribute("loginmessage") == null) return "noLogin";//判断是否登录 List list = indexDao.notesList(request); request.setAttribute("notesUpdList", list); return "notesUpdList"; } // 公告管理:修改单个信息 public String notesUpd() throws Exception { if (request.getSession().getAttribute("loginmessage") == null) return "noLogin";//判断是否登录 NotesEntity notesEntity = indexDao.noteSSMow(request); request.setAttribute("getNotesView", notesEntity); return "notesUpd"; } // 公告管理:修改保存到数据库 public String notesUpdDB() throws Exception { if (request.getSession().getAttribute("loginmessage") == null) return "noLogin";//判断是否登录 indexDao.notesUpdDB(request); return "notesUpdList"; } // 公告管理:删除信息 public String notesDelList() throws Exception { if (request.getSession().getAttribute("loginmessage") == null) return "noLogin";//判断是否登录 List list = indexDao.notesList(request); request.setAttribute("notesDelList", list); return "notesDelList"; } // 公告管理:删除单个信息 public String notesDel() throws Exception { if (request.getSession().getAttribute("loginmessage") == null) return "noLogin";//判断是否登录 indexDao.notesDel(Long.valueOf(request.getParameter("id"))); return "notesDelList"; }
    5.2.4 用户个人信息管理普通用户登录成功后可以进入到个人主界面,该界面实现的功能为:查看个人详细信息、修改个人信息,如图5-6所示。

    5.2.5 公交线路管理此模块需要系统管理员权限,在管理员主界面中,可对公交线路进行添加、删除以及对公交变动信息实时更新。如图5-7所示。

    5.3 连接池配置在城市公交信息查询系统中采用数据库连接处技术提高访问数据库的效率。在数据源中建立了多个数据库连接,这些连接保存在数据库连接池中。Java程序访问数据库时,只需要从连接池中取出空闲的数据库连接,程序访问数据库完毕之后,再将数据库连接池放回连接池,具体实现是在applicationContext.xml中加入:
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://127.0.0.1:3306/buscity</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value></value> </property></bean>
    5.4 SSM框架的整合为实现Spring 整合Mybatis和Springmvc,需要配置applicationContext.xml文件,配置完成后系统就可以通过Springmvc的action直接调用了。Mybatis访问数据库的操作都在Spring中实现了,而Spring的调用是在Springmvc的action中实现。SSM框架整合具体如下:
    首先在web.xml文件中添加Spring配置、新增一个监听器(Linstener)。监听器的作用是启动 Web 容器时,自动装配 ApplicationContext 的配置信息。因为它实现了ServletContextListener这个接口,在Web.xml完成这个监听器的配置后,启动容器时,就会默认执行它实现它的方法。实现代码如下:
    <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:/applicationContext.xml </param-value> </context-param><listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>
    配置数据源、SessionFactory。连接池的数据源和分配 sessionFactory 对象是通过Spring 管理的。Spring 通过建立一个LocalSessionFactory对象来完成对Mybatis 的配置,这是一个工厂 bean 的实现。然后就可以通过继承 Spring 为 我们提供MybatisDaoSupport(MybatisDao层都需要继承extends它)来对数据库的 DAO 模式管理。代码如下:
    <!-- 配置数据源 DBCP 提供的BasicDataSource --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://127.0.0.1:3306/buscity</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value></value> </property> </bean> <!-- Mybatis配置 --> <bean id="sessionFactory" class="org.springframework.orm.Mybatis3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="MybatisProperties"> <props> <prop key="Mybatis.dialect">org.Mybatis.dialect.MySQL5Dialect</prop> <prop key="Mybatis.show_sql">true</prop> <prop key="Mybatis.format_sql">true</prop> <prop key="Mybatis.hbm2ddl.auto">update</prop> </props> </property> <property name="packagesToScan" value="com.Mybatis" /> </bean>
    将sessionFactory 对象作为属性注入到这个服务类中去。代码如下:
    <bean id="indexDao" class="com.struts.dao.IndexDao"> <property name="sessionFactory" ref="sessionFactory"></property></bean>
    装配事务管理器,使用annotation定义事物、自动注册bean。代码如下:
    <!-- 事务管理器配置,单数据源事务 --> <bean id="transactionManager" class="org.springframework.orm.Mybatis3.MybatisTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 使用annotation定义事务 --> <tx:annotation-driven transaction-manager="transactionManager" /> <context:annotation-config /> <!-- 使用annotation 自动注册bean,并保证@Required,@Autowired的属性被注入 --> <context:component-scan base-package="com.*"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/> </context:component-scan>
    配置struts.xml的Action。
    6 系统调试与测试6.1 程序调试在设计系统的过程中,存在一些错误是必然的。对于语句的语法错误,在程序运行时自动提示,并请求立即纠正,因此,这类错误比较容易发现和纠正。但另一类错误是在程序执行时由于不正确的操作或对某些数据的计算公式的逻辑错误导致的错误结果。这类错误隐蔽性强,有时会出现,有时又不出现,因此,对这一类动态发生的错误的排查是耗时费力的。
    6.2 程序的测试6.2.1 测试的重要性及目的测试的重要性
    软件的测试在软件生命周期中占据重要的地位,在传统的瀑布模型中,软件测试学仅处于运行维护阶段之前,是软件产品交付用户使用之前保证软件质量的重要手段。近来,软件工程界趋向于一种新的观点,即认为软件生命周期每一阶段中都应包含测试,从而检验本阶段的成果是否接近预期的目标,尽可能早的发现错误并加以修正,如果不在早期阶段进行测试,错误的延时扩散常常会导致最后成品测试的巨大困难。
    测试是所有工程学科的基本组成单元,是软件开发的重要部分。自有程序设计的那天起测试就一直伴随着。统计表明,在典型的软件开发项目中,软件测试工作量往往占软件开发总工作量的40%以上。而在软件开发的总成本中,用在测试上的开销要占30%到50%。如果把维护阶段也考虑在内,讨论整个软件生存期时,测试的成本比例也许会有所降低,但实际上维护工作相当于二次开发,乃至多次开发,其中必定还包含有许多测试工作。
    在实践中,软件测试的困难常常使人望而却步或敷衍了事,这是由于对测试仍然存在一些不正确的看法和错误的态度,这包括:
    认为测试工作不如设计和编码那样容易取得进展难以给测试人员某种成就感;
    以发现软件错误为目标的测试是非建设性的,甚至是破坏性的,测试中发现错位是对责任者工作的一种否定;
    测试工作枯燥无味,不能引起人们的兴趣;
    测试工作是艰苦而细致的工作;
    对自己编写的程序盲目自信,在发现错误后,顾虑别人对自己的开发能力的看法。
    这些观点对软件测试工作是极为不利的,必须澄清认识、端正态度,才可能提高软件产品的质量。
    测试的目的
    如果测试的目的是为了尽可能多地找出错误,那么测试就应该直接针对软件比较复杂的部分或是以前出错比较多的位置。
    软件测试是为了发现错误而执行程序的过程,测试是为了证明程序有错,而不是证明程序无错误,一个好的测试用例是在于它能发现至今未发现的错误,一个成功的测试是发现了至今未发现的错误的测试。
    这种观点可以提醒人们测试要以查找错误为中心,而不是为了演示软件的正确功能。但是仅凭字面意思理解这一观点可能会产生误导,认为发现错误是软件测试的唯一目,查找不出错误的测试就是没有价值的,事实并非如此。
    首先,测试并不仅仅是为了要找出错误。通过分析错误产生的原因和错误的分布特征,可以帮助项目管理者发现当前所采用的软件过程的缺陷,以便改进。同时,这种分析也能帮助我们设计出有针对性地检测方法,改善测试的有效性。其次,没有发现错误的测试也是有价值的,完整的测试是评定测试质量的一种方法。
    6.2.2 测试的步骤与内容与开发过程类似,测试过程也必须分步骤进行,每个步骤在逻辑上是前一个步骤的继续。大型软件系统通常由若干个子系统组成,每个子系统又由若干个模块组成。因此,大型软件系统的测试基本上由下述几个步骤组成:

    模块测试:在这个测试步骤中所发现的往往是编码和详细设计的错误
    系统测试:在这个测试步骤中发现的往往是软件设计中的错误,也可能发现需求说明中的错误
    验收测试: 在这个测试步骤中发现的往往是系统需求说明书中的错误

    测试的主要内容:
    为了保证测试的质量,将测试过程分成几个阶段,即:代码审查、单元测试、集成测试、确认测试和系统测试[21]。
    单元测试
    单元测试集中在检查软件设计的最小单位—模块上,通过测试发现实现该模块的实际功能与定义该模块的功能说明不符合的情况,以及编码的错误。
    集成测试
    集成测试是将模块按照设计要求组装起来同时进行测试,主要目标是发现与接口有关的问题。如一个模块与另一个模块可能有由于疏忽的问题而造成有害影响;把子功能组合起来可能不产生预期的主功能;个别看起来是可以接受的误差可能积累到不能接受的程度;全程数据结构可能有错误等。
    确认测试
    确认测试的目的是向未来的用户表明系统能够像预定要求那样工作。经集成测试后,已经按照设计把所有的模块组装成一个完整的软件系统,接口错误也已经基本排除了,接着就应该进一步验证软件的有效性,这就是确认测试的任务,即软件的功能和性能如同用户合理期待的那样。
    系统测试
    软件开发完成以后,最终还要与系统中其他部分配套运行,进行系统测试。包括恢复测试、安全测试、强度测试和性能测试等。
    6.2.3 单独对系统的测试单独对系统的测试主要从以下几个方面入手:

    功能测试:测试是否满足开发要求,是否提供设计所描述的功能,是否用户的需求都得到满足。功能测试是系统测试最常用和必须的测试,通常还会以正式的软件说明书为测试标准
    强度测试及性能测试:测试系统能力最高实际限度,即软件在一些超负荷情况下功能实现的情况
    安全测试:验证安装在系统内的保护机构确实能够对系统进行保护,使之不受各种非常的干扰。针对本系统主要是对权限系统的测试和对无效数据、错数据、和非法数据干扰的能力的测试

    6.3 测试分析本系统主要实现了公交查询功能,并附有用户留言的功能,同时具有管理员后台维护公交信息等功能。但由于本人能力不足以及所学知识的缺乏,再加上时间有限,该系统还不够健全。该系统虽然基本实现了所要求的功能,但是还存在很多不足,有待于进一步的完善和改进。经过上述的测试过程对软件进行测试后,软件基本满足开发的要求,测试宣告结束。
    结束语本文通过本系统设计与开发感触颇深,总结如下:
    学习一门新技术,最重要的是实践,只有多动手才能尽快掌握它。一个系统的开发,经验是最重要的,经验不足,就难免会有许多考虑不周之处。要想吸引更多的用户,系统的界面必须要美观、有特色、友好,功能要健全。不过由于经验不足,我设计的图形界面比较简单。只是对基本功能进行了开发。
    本次开发,我参考了很多本系统的例子,吸取了一些别的本系统的长处,对自己的毕业设计进行了完善,但是还有很多的不足之处,有待以后进一步学习。实践证明,本系统有着很好的发展前景,经测试运行。本文所制作的系统界面友好、使用灵活、操作简单、功能齐全、表现方式独特,已基本具备了成熟的技术理论。
    由于时间仓促,本次设计由我完成本系统的制作,对我这样一个JAVA新手而言所制作的模块还有不完善的地方。数据库的设计也比较简单。还有很多毕业设计中用到JAVA语言的知识也不够全面,还有很多地方不能够作到完全的理解和掌握。通过这次毕业论文的设计制作使本人受益匪浅。由于是毕业设计是独立完成的,因此在毕业设计的过程遇到了很多的困难,我求教了不少老师和同学,在这个过程中让我体会到了,一个团队的重要性。
    参考文献[1] BruceEckel. JAVA编程思想[M].北京:机械工业出版社,2003
    [2] 赛奎春. JAVA工程应用与项目实践[M]. 北京:机械工业出版社, 2002
    [3] 陈守学、刘电霆.中小城市公交线路查询系统设计方法研究[M]. 桂林航天工业高等专科学校学报,2007.12
    [4] 刘晓妍. 基于J2EE公交查询系统的研究[D].上海:华东师范大学软件学院,2010.4
    [5] 吴永军、蔡永香、郭庆胜. 城市公交查询系统的设计与实现[D].武汉:武汉大学资源与环境科学学院,2006.5
    [6] 周继芳. 基于J2EE的公交线路查询系统的设计与实现[D].西昌:西昌卫星发射基地,2009.5
    [7] 孙一林,彭波. JAVA数据库编程实例[M]. 北京:清华大学出版社,2002
    [8] 萨师煊,王珊. 数据库系统概论[D].高等教育出版社,2002
    [9] 耿祥义,张跃平. JAVA实用教程[M]. 北京:清华大学出版社,2003
    [10] 蔡剑,景楠. Java Web应用开发J2EE和Tomcat[M]. 北京:清华大学出版社, 2005
    [11] Brown等. JAVA编程指南(第二版)[M]. 北京:电子工业出版社 ,2003
    [12] 沈雄. 基于SSM的分布式公交运营管理系统设计与实现[EB/OL].http://wenku.baidu.com/view/c49946293169a4517723a3cc.html,2011-05-09/2012-03-28
    [13] JAVA 程序设计论坛http://techbbs.zol.com.cn/subcate_list_8.html,2010-11-04/2012-03-29
    [14] 徐国志,汪孝宜等. SQL Server数据库开发实例精粹[M].北京:电子工业出版社,2006
    [15] 岳昆、王晓玲、周傲英. Web服务核心支撑技术[J]:研究综述.软件学报,2004,18(1):16-20
    [16] 冯锐. SSM权威指南[M].北京:中国电力出版社,2003
    [17] 月影. JavaScript王者归来[M].北京:清华大学出版社,2008
    [18] 孙卫琴. 精通Struts:基于MVC的Java Web设计与开发[M]. 北京:电子工业出版社,2004
    [19] 张存保等. 基于WebGIs的城市公交问路系统.武汉理工大学学报,2004,23(1):20-24
    [20] Paul Simith. Database Appliction[J]. 北京:电子工业出版社,2001
    [21] 王水,张晓民.软件工程素质导论[M].河南:河南科学技术出版社,2011
    5 评论 103 下载 2019-05-14 11:17:31 下载需要16点积分
  • 基于javaEE实现的在线音乐系统

    1、概述
    开发环境

    Windows10EclipseTomcat 9.0Mysql 8JDK 10
    运行环境

    Tomcat 9.0Mysql 8Chrome 71

    2、系统的需求分析2.1 系统可行性分析本系统是采用Java Web技术的B-S架构的网站,用到的技术有Java EE 、CSS、JavaScript、Ajax。为了使用的效果以及开发的简便,在前端使用了CSS的Bootstrap及其UI组件框架,JS的Jquery库以及Ajax技术。在线音乐是获取的外部站点的API提供查询服务,并且每一次播放在线音乐会将其数据保存到本地数据库。本地音乐是从本地数据库中获取数据展现到用户界面。
    2.2 系统功能描述2.2.1 用户管理
    用户注册:用户可以点击注册按钮进入注册界面,注册属于自己的账号
    用户登录:用户使用自己的账号登录系统
    用户设置:可点击个人设置,修改个人信息,例如昵称,头像等

    2.2.2 播放界面
    音乐播放[播放与暂停]:对在播放器中的音乐进行播放和暂停
    音量调节:对正在播放器中的音乐的音量大小进行调节

    2.2.3 歌单与音乐管理
    歌单管理:对歌单的增删查改
    音乐管理:将音乐添加进歌单,将音乐从歌单中删除

    2.2.4 音乐搜索
    在线搜索:在网络上搜索获取音乐资源
    系统乐库:获取系统所在服务器上的音乐资源

    2.3 系统的数据流图
    2.4 系统UML建模设计
    2.5 系统的状态图登陆模块状态图

    登陆模块状态图

    2.6 系统的UML类图本系统后台总共使用了四个包,其功能与关系如下。

    utils:封装了连接数据库和关闭数据库的操作
    dto:包含封装了某个对象的所有信息的类
    dao**:封装了对数据库的操作
    servlets:包含处理前端发送的各种信息的servlet

    以上四个包都位于cn.edu.whpu.music包下,它们的关系如下图所示。

    3、系统总体设计3.1 系统结构方框图
    3.2 各模块功能用户信息模块
    包含功能有用户的注册,用户的登录,用户个人信息的修改和用户个人信息的展示。
    搜索音乐模块
    包含功能有在线音乐搜索,本地乐库搜索。
    歌单管理模块
    包含功能有添加新的歌单,修改歌单信息,删除歌单。
    收藏歌曲模块
    包括添加音乐到指定歌单,从歌单中删除音乐。
    3.3 详细的UML类图用户信息模块


    DBManager:封装了连接数据库和关闭数据库的操作
    UserDTO:封装了用户个人信息的类
    UserDAO:封装了操作用户个人信息的类
    UserRegistServlet:用户注册的servlet
    UserLoginServlet:用户登录的servlet
    EditUserInfoServlet:修改用户个人信息的servlet

    搜索音乐模块(本地乐库)


    DBManager:封装了连接数据库和关闭数据库的操作
    MusicDTO:封装了音乐信息的类
    MusicDAO:封装了操作音乐信息的类
    LocalMusicServlet:处理点击本地乐库按钮后的请求并返回数据的servlet

    注:在线音乐搜索是用ajax请求的网络上的API接口获取数据并渲染到主页面,与该处的servlet无关。
    歌单管理模块


    DBManager:封装了连接数据库和关闭数据库的操作
    MusicListDTO:封装了歌单信息的类
    MusicListDAO:封装了操作歌单信息的类
    AddMusicListServlet:添加歌单信息的servlet
    InitMusicListServlet:通过用户ID查询并返回其对应的歌单的servlet
    DeleteMusicListServlet:删除歌单的servlet
    UpdateMusicListServlet:更新歌单的servlet
    ShowMusicsFromListServlet:通过用户ID和歌单ID查询并返回其对应的歌单的servlet

    收藏歌曲模块


    DBManager:封装了连接数据库和关闭数据库的操作
    MusicDTO:封装了音乐信息的类
    MusicDAO:封装了操作音乐信息的类
    ListMusicRelationDTO:封装了音乐与歌单对应关系信息的类
    ListMusicRelationDAO:封装了操作音乐与歌单对应关系信息的类
    CollectionMusicServlet:收藏音乐进入指定歌单的servlet
    CancelCollectMusicServlet:从歌单取消某音乐收藏的servlet

    3.4 设计数据管理子系统因为使用java编写的并发量不是特别大的后台程序,所以使用了更为轻量级的mysql 8。其好处有如下几点:

    普及性:MySQL在过去两年已经获得了25%的市场份额。相比其他的开源数据库和闭源数据库,越来越多的开发者将继续选择MySQL。MySQL在业界的流行所带来的另一个好处是,人们总可以很轻松地发现本行业的解决方案
    简单性:对于MySQL数据库,无论是在开发方面,还是支持方面,现在有大量强大的工具可以选择。每一个新手开发者可以轻松地使用MySQL数据库进行开发。甚至一个有经验的Windows管理者也可以轻松部署并开始学习它,不需投入一分钱来了解这个数据库
    低成本:MySQL数据库归MySQL AB公司所有,但是这个软件是开源的,有一个社区版可以免费下载。稍俱常识的新入门者都可以轻松实现在一个常见硬件上安装和配置MySQL。MySQL对硬件的较低要求是其最大的优势之一,不过需要注意的是:内存越多越好,因为所有的重要数据存储都在内存中完成。一个免费的数据库意味着,更多珍贵的资金可以用于其他业务的启动,诸如市场、广告或调研和开发等

    3.5 系统E-R图
    系统E-R图如上图所示。主要逻辑有:

    一个用户在某一时刻只能播放一首歌曲
    一个用户可以创建n个歌单
    一个音乐可以被n个歌单收藏,一个歌单也能收藏n首音乐

    3.6 数据库表
    本系统该次设计了四张表:

    tb_users表记录用户信息
    tb_musiclists表
    tb_list_music表
    tb_musics表

    3.7 数据库表之间的关系关系1
    tb_users表和tb_musiclists表是一对多的关系。其中tb_musiclists中表的list_uid字段必须遵照tb_users表中的user_id。即一个用户可以有多个歌单,而一个歌单只能由一个用户。

    关系2
    tb_musiclists表和tb_musics表是多对多的关系,并且tb_list_music表记录了它们之间的对应关系。tb_list_music表中lid参照tb_musiclists中的list_id字段,tb_list_music表中mid参照tb_musics中的music_id字段。并且lid与mid作为该表的联合主键。即一个歌单可以收藏多首音乐,一个音乐也能被多个歌单收藏。

    3.8 数据库表结构tb_users表

    tb_musics表

    tb_musiclists表

    tb_list_music表

    3.9 设计人机交互子系统3.9.1 登陆界面登录界面引用了jquery.video库,将登录的背景设置为一个动态的循环播放的视频,极具科技感和新鲜感。
    3.9.2 注册界面注册界面沿袭登陆界面的大体设计,并在注册信息上使用了jquery.validate库对于用户输入注册所需要的信息进行了初步的判断,避免录入冗余、错误的信息。
    规则有:

    用户名:必须输入,长度为6-20个字符
    密码:必须输入,长度为8-16个字符
    重复密码:必须输入,必须与密码一致
    用户昵称:必须输入,长度为20字符以内
    性别:必须选择
    头像:必须上传

    3.9.3 主界面整体布局
    使用一个界面避免用户进行跳转。采用bootstrap框架的栅栏式布局。大致布局如下图所示。

    顶部导航栏
    整体采用bootstrap的导航栏样式,如下图所示。左侧依次为Logo区,在线搜索区和本地乐库区。当在在线搜索的输入框中输入内容,并点击搜索按钮后,会在主界面呈现出搜索内容。当点击本地乐库按钮后,会在主界面呈现出系统自带的音乐列表。

    右侧为用户栏,点击歌单按钮会弹出“添加歌单”、“管理歌单”功能按钮。点击“添加歌单”按钮会弹出模态框。点击管理歌单会在歌单栏出现编辑和删除按钮。点击消息按钮会弹出“查看消息”功能按钮。点击用户按钮会弹出“修改信息”和“退出”功能按钮。点击修改信息会弹出修改用户信息的模态框。详情在模态框中介绍。
    主区域

    主界面大致分为左、中、右三个区域。按照1:2:1的分配区域。在点击导航栏中的“管理歌单按钮后”,歌单区域进入编辑模式。点击主区域的播放按钮和收藏按钮,歌单区的编辑和删除,用户区的头像均会弹出模态框。详情在模态框中介绍。
    唱片CD会在歌曲播放的时候旋转如下图所示。

    播放器区域
    播放器方面我们开发小组认为原生的AUDIO标签还有市面上找到的播放器插件不契合我们的样式,于是从5sing音乐网站的播放器部分借鉴了样式,并为静态的样式添加了拖动歌曲进度,实时显示已经播放时间,和调节音量大小的动态效果。其主要布局和功能如下图所示。

    模态框
    为了使界面不发生跳转,我们将主界面中所有的操作运用了bootstrap的模态框UI组件。在点击“歌单➡添加歌单”,“用户➡修改信息”,“歌曲➡收藏按钮”,“用户➡头像”,“歌单列表➡修改”,“歌单列表➡删除”时均会弹出相应的模态框组件。


    整体效果

    4、详细设计4.1 登陆注册模块流程图
    4.2 在线搜索模块流程图
    4.3 本地乐库模块流程图
    4.4 歌单管理模块流程图
    5、总结通过为期五天的课设,我收获颇多。最直观的感受就是在这次在线音乐网站的开发中能够系统性的运用从大一到现在所学到的知识。新学习到的Servlet的知识更是让我明白了为何之前写过的html只能叫做静态页面,还有一个网站的前端是如何与后台进行数据交互。同时这次也让我从平时的文件级别的代码编写上升到了工程级别的项目开发。在其中更好了理解了这个学期学过的关于软件开发的步骤。认识到了文档编写在软件项目开发中不可替代的重要性。我觉得收获最深的地方就是以前只觉得写代码才是最重要的部分,现在明白了项目管理、需求分析、文档编写才是项目开发中更重要的部分。让我把眼界从代码拓宽到了更高的层次。同时还深刻认识到自己在项目开发领域还存在着诸多的不足,明白了以后要学习的地方还有许多。
    当然,在项目开发期间也遇到过许多问题:
    老师教授的是用后台修改动态数据,而我们想将前端和后台完全分离,这就存在了一个如何将后台数据打包成JSON发送到前端的问题。
    解决方案:在老师的指导下使用了阿里巴巴公司的fastjson这个jar包来打包数据。同时在前端使用了axios来实现通信和局部页面刷新。
    因为一开始没有编写规范的文档,导致在开发途中想要增加功能的时候会发现不知道更改项目的哪个地方。他人接手编写的时候还要重新看一遍代码,效率低下。
    解决方案:停下开发工作,转头编写规范的文档,统一了数据库和测试数据。并且集中到一起开发,使得遇到什么问题小组成员之间可以很快的交流并解决。
    每个人有自己的代码编写风格,而为了赶时间没有在文件中书写规范的注释。结果在互相测试小组成员单元时发现看不懂对方的代码,导致浪费极多时间。
    解决方案:就算再赶时间也要书写规范的注释,写明类的用途,写明方法的用途以及接受参数和返回参数的类型、作用,这样在测试或者修改的时候会节省大量时间。
    在开发过程中想要对功能进行增加、删除、修改或者是想要复用一段代码时发现代码编写冗余没有规范。导致代码难以维护、复用程度低,重构成本极高。
    解决方案:在将来的项目开发中一定要灵活运用设计模式,设计模式是前辈留给我们的解耦、复用代码的成功经验,虽然使用设计模式在编写的时候可能会造成困难,但是在维护、更新的时候会体现出设计模式的优越性。
    7 评论 138 下载 2019-04-16 15:00:02 下载需要14点积分
  • C语言实现huffman编解码与压缩文本

    1 原理哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。
    在计算机数据处理中,霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。
    例如,在英文中,e的出现机率最高,而z的出现概率则最低。当利用霍夫曼编码对一篇英文进行压缩时,e极有可能用一个比特来表示,而z则可能花去25个比特(不是26)。用普通的表示方法时,每个英文字母均占用一个字节(byte),即8个比特。二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。倘若我们能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。
    2 流程图
    3 评论 76 下载 2018-11-09 21:16:44 下载需要3点积分
  • C语言实现的基于Huffman哈夫曼编码的数据压缩与解压缩

    一、实验题目用哈夫曼编码实现文件压缩
    二、实验目的
    了解文件的概念
    掌握线性链表的插入、删除等算法
    掌握Huffman树的概念及构造方法
    掌握二叉树的存储结构及遍历算法
    利用Huffman树及Huffman编码,掌握实现文件压缩的一般原理

    三、实验设备与环境微型计算机、Windows 系列操作系统 、Visual C++6.0软件
    四、实验内容根据ASCII码文件中各ASCII字符出现的频率情况创建Haffman树,再将各字符对应的哈夫曼编码写入文件中,实现文件压缩。
    五、概要设计5.1 数据结构类型定义/*****Huffman结构定义**********/typedef struct node { long w;//w为权值 short p,l,r; //p为parent,l为左孩子,r为右孩子}htnode,*htnp;//动态分配数组存储哈夫曼树/*****Huffman编码表结构定义*****/typedef struct huffman_code { unsigned char len;//长度 unsigned char *codestr; }hufcode;typedef char **huffmancode;//动态分配数组存储哈夫曼编码表
    5.2 程序构成本程序的构成,共有 14 个函数,1 个菜单函数。
    // 1.初始化文件名int initial_files(char *source_filename,FILE **inp,char *obj_filename,FILE **outp);// 2.创建文件名char *create_filename(char *source_filename,char* obj_filename);// 3.压缩文件int compress(char *source_filename,char *obj_filename);// 4.频率数据long frequency_data(FILE *in,long fre[]);// 5.选取结点权值最小的树int search_set(htnp ht,int n,int *s1, int *s2);// 6.创建哈夫曼树int create_hftree(long w[],int n,htnode ht[]);// 7.编码哈夫曼树int encode_hftree(htnp htp,int n,hufcode hc[]);// 8.把字符串用二进制数字表示:运用位运算的知识unsigned char chars_to_bits(const unsigned char chars[8]);// 9.写入压缩文件int write_compress_file(FILE *in,FILE *out,htnp ht,hufcode hc[],char* source_filename,long source_filesize);// 10.解压缩int decompress(char *source_filename,char *obj_filename);// 11.构造微型哈夫曼树void get_mini_huffmantree(FILE* in,short mini_ht[][2]);// 12.写入解压缩int write_decompress_file(FILE *in,FILE* out,short mini_ht[][2],long bits_pos,long obj_filesize);// 13.重新变成原始文件int d_initial_files(char *source_filename,FILE **inp,char *obj_filename,FILE **outp);// 14.菜单函数void main()
    5.3 写文件压缩的基本思路文件压缩的基本思路:

    打开需压缩文件
    创建Haffman树
    将需压缩文件中的每个ascii码对应的haffman编码按bit单位输出(此过程需要运用位运算的知识点)
    文件压缩结束

    最后,通过解压缩来验证是否失真现象。
    六、详细设计6.1 文件的初始化及其创建创建文件是使用了字符串的知识,构造临时文件夹temp,运用字符串的复制strncpy,连接strcat函数来实现对文件名的创建,我把文件压缩的格式定义为”.zip”。

    6.2 构造Huffman树的方法——Huffman算法6.2.1 构造Huffman树步骤
    根据给定的n个权值{w1,w2,……wn},构造n棵只有根结点的二叉树,令起始权值为wj
    在森林中选取两棵根结点权值最小的树作左右子树,构造一棵新的二叉树,置新二叉树根结点权值为其左右子树根结点权值之和
    在森林中删除这两棵树,同时将新得到的二叉树加入森林中
    重复上述两步,直到只含一棵树为止,这棵树即哈夫曼树。

    下面给出中实现的Haffman树的结构及创建算法,有两点说明:

    这里的Haffman树采用的是基于数组的带左右儿子结点及父结点下标作为存储结点的二叉树形式,这种空间上的消耗带来了算法实现上的便捷
    由于对于最后生成的Haffman树,其所有叶子结点均为从一个内部树扩充出去的,所以,当外部叶子结点数为m个时,内部结点数为m-1,整个Haffman树的需要的结点数为2m-1
    初始化Haffman树分两步进行,先将所有结点赋值,再将前m个叶子结点赋初值
    在查找权值最小并且父结点为空的两个结点时,通过逐个比较,将两结点的位置下标与权值分别保存。方便在与其父节点建立联系时调用


    6.2.2 Huffman编码:数据通信用的二进制编码
    思想:根据字符出现频率编码,使电文总长最短
    编码:根据字符出现频率构造Huffman树,然后将树中结点引向其左孩子的分支标“0”,引向其右孩子的分支标“1”;每个字符的编码即为从根到每个叶子的路径上得到的0、1序列

    6.3 压缩过程的实现压缩过程的流程

    打开需压缩文件
    创建Haffman树
    将需压缩文件中的每个ascii码对应的haffman编码按bit单位输出
    文件压缩结束

    在实际编码中,压缩函数是通过多次函数调用实现的。
    我的代码中,位运算的小函数:把字符串用二进制表示。在写入压缩函数中起到压缩的功能。
    七、测试结果及分析压缩后的程序运行结果截图

    解压缩后的运行结果截图

    压缩后的结果截图

    解压缩后的结果截图

    请注意修改时间的比较,文件wangyun.doc确实完成了从压缩到解压缩的过程,而且初步看,解压后的doc文件大小是一样的。
    接下来进一步说明:
    下图是被压缩文件和压缩文件的属性比较,原本有28.5KB的文件压缩成了9.79KB的文件


    下面两幅图是压缩前的文本文件wangyun和解压后的文本文件wangyun的比较,两图的内容都相同说明没有失真。
    压缩前的源文件

    压缩后的源文件

    八、总结这次实验确实是让自己特别头疼,代码中有关于C程序语言中文件知识如打开,关闭等的操作,这些知识点是我上个学期学习的薄弱环节,因为没有怎么运用,所以也没怎么看文件的知识点。我通过翻阅图书馆书籍和上个学期C程序设计书,还有同学的解释,看懂了基本的文件操作。
    值得高兴的是,我知道了一些小知识,怎样把调试框变颜色的的函数,感觉非常有趣。
    代码中的使用字符串处理函数:strcat,strcpy,strcmp等也是我忘记的知识点,翻阅书籍之后,就记起它们的具体操作和运用实现了。
    还有一个大的问题,就是位运算的使用,通过运行,明显出现压缩的比率不高,而且还出现了越压越大的问题,询问老师发现,是自己没有用位运算的知识,知道问题的所在,老师说这不是重点。在我的代码中,老师还是耐心的帮我找到了我的位运算的小程序。也知道了,为什么有时候压缩程序出现错误,有可能是压缩的文件越界了,可能是统计频率出现小问题,不同的程序有不同的限定范围。同时,我也发现,不同的文件扩展名有着不同的压缩比例,这有可能和自己代码里频率函数有错误。在我的压缩程序中,小文件txt文件是不适用的,该比例是越压越大的,doc文件是适用的,且文件越小,压缩比例越小,该压缩程度越好,且解压缩后程序是不失真。
    当然,我的不足是很多的,但是比起刚开始着手的迷茫,现在是大致了解了。所以,平时要注意知识的积累,能举一反三。
    2 评论 246 下载 2018-10-31 11:34:38 下载需要6点积分
  • 基于JSP实现的医院住院管理系统

    一、课程设计介绍1.1 目的软件综合课程设计是学生在学习完数据库系统概论后必须进行的一项重要的实践环节。通过该课程设计,学习数据库设计工具的使用,掌握数据库设计的基本方法、步骤和数据库设计各阶段的任务,完成对某一小型数据库应用系统的基本流程进行分析,数据库设计和相应文档的编写工作。加深对课堂理论学习的理解,增强动手能力,使学生更加深入地掌握数据库系统分析与设计的基本概念和基本方法,以培养学生合作的能力,为毕业设计作好实践环节上的准备。
    1.2 内容课程设计的题目与设计要求由指导老师指定,每组学生最终需要实现一个功能完整、可运行的 MIS 系统。
    课程设计报告中应包括需求分析、概要设计、数据库设计、详细设计、编码实现、总结等,具体地:

    设计报告中应首先包括设计题目、学号、姓名、专业、班级、指导教师、完成日期
    概要设计中应包括设计思想、实现方法、系统中主要模块及各模块间的关系的描述
    设计包括根据需求分析所得到的信息,用 E-R 图完成系统的概念结构设计,并对 E-R 图进行优化。将系统 E-R 图转换为选定的 DBMS 所支持的关系模型,并按关系规范化理论对关系模型进行优化
    详细设计中应对各模块,各功能进一步细化,写各功能的算法等
    编程实现中应包括对主要模块、主要功能、关键功能的代码说明,代码中应有适当的注释
    总结里主要写该系统用何种开发语言,开发了何种系统,主要实现了哪些功能,系统性能如何,有何不足等

    2 系统需求通过简单的需求分析,完成的医院住院管理系统,能够实现辅助医院医 护人员工作,提高医院医护人员的工作效率。通过本系统,能够实现对住院 部门的病人和病房两大信息的管理包括增、删、改、查,减轻医护人员的工 作负担。本系统提供强大的查询功能,可以让系统用户根据各种不同的查询 条件查询出相应的数据。出入院操作能够简单的实现病人的出入院操作,方 便医院医护人员的操作,系统应该界面美观,操作简单,功能明确、完善。 系统操作,应该有很高的效率,数据库操作方面应该提高效率,不能反应缓 慢,这在系统搭建上要求合理、完善。
    通过建立该医院住院管理系统,采用计算机对医院病房和病人进行管理 和查询,进一步提高医院住院管理效益和现代化水平,帮助提高医院住院管 理工作人员工作效率,实现医院住院管理工作流程的系统化、规范化和自动 化。系统应该具有很好的扩展性,这就要求系统架构合理、可扩展,充分考 虑到以后的需求变化。设计良好的代码允许更多的功能在必要时可以被插入 到适当的位置中。这样做的好处是为了应对未来可能需要进行的修改,这就 需要系统设计时能够有一个良好的软件框架。系统的安全性,也是本次系统 设计的一个重要目标,设计中要考虑到用户的非法访问,通过拒绝用户的非 法访问来保证用户数据的安全和系统的安全。
    2.1 系统总体目标
    加快办理病人入院、出院的速度,实现病人的资料在住院的全过程中实现信息化管理
    准确记录病人和床位的各项信息,并提供全方位的查询功能,让病人、医生、护士,能够及时准确的掌握病人和床位的各种信息,从而有效提高工作效率,缩短工作时间
    系统具有一定的安全性和运行稳定性、可扩展性。系统需要医院员 工输入账号和密码才能操作,可以避免其它人员的恶意操作给医院信息带来的损失
    系统能够提供一个界面友好、功能完善的信息管理系统,方面医护 人员学习和操作,尽可能的简化医院操作,减少医护人员学习和掌握系统的时间

    2.2 功能需求本系统主要实现与病人相关的各种信息的系统化、规范化和自动化,本 住院管理系统主要完成的功能有:

    出入院管理模块:包括入院登记、病人出院操作
    病房管理模块:包括对病房的增删改查(CRUD)操作,支持多种查询条件
    病人管理模块:包括对病人信息的维护,增删改查操作,支持多种查询条件
    系统管理模块:包括对修改用户、添加用户、删除用户、退出系统
    系统功能模块:包括首页、前进、后退、刷新等操作和显示当前时间

    功能分析得到数据流图如下所示:

    3 概要设计3.1 医生功能模块图
    3.2 管理员功能模块图
    3.3 总体联系3.3.1 医护人员
    3.3.2 管理
    4 详细设计4.1 总体流程图
    4.2 实体及其属性
    病人:住院编号,病人姓名,病人性别,入住病房编号,病人入院时间, 病人出生地
    病房:病房编号,病房类型,病房租金,病房状态,病房所属科室,病房 医生,病房医生号码
    医生:医生姓名,医生性别,电话号码,医生地址

    各个实体间有如下关系:一个病人只能入住一个病房,而一个病房可以住多名病人。
    4.3 E-R 图实体与实体间的对应关系是一对一,“m”、“ n”表示实体与实体间的关系是一对多。

    4.4 数据库设计数据库设计是整个程序设计的最关键部分。数据库的设计是否合理,将 对数据库的大小、代码的优化起到至关重要的作用。因此,在设计程序前必 须对数据库进行设计,而在设计数据库前必须对所要完成的功能进行认真的研究分析。
    根据系统的要求,需要建立存放系统使用过程中所用到的各种信息表: 医生信息表、病人信息表、病房信息表、管理员信息表。
    用户信息表:用来存放使用此系统的用户的信息。

    管理员信息表:存放病人信息。

    病房信息表:存放病房信息。

    病人信息表:存放病人信息。

    5 系统实现5.1 数据库代码部分医生信息表
    create table doc_info ( user_id int PRIMARY KEY auto_increment, user_num varchar(12), -- 12 user_name varchar(10), user_pwd char(32), sex char(4), tel char(11), addr varchar(50))
    管理员信息表
    create table admin_info ( user_id int PRIMARY KEY auto_increment, user_num varchar(12), -- 12 user_name varchar(10), user_pwd char(32), sex char(4), tel char(11), addr varchar(50))
    病人信息表
    CREATE TABLE pati_info( pati_id int primary key auto_increment, pati_num char(5), -- P0000 pati_name varchar(10), pati_sex char(4), pati_ward_num char(5), -- 病房编号 pati_birthday char(12), -- 流水号处理日期 pati_birthplace varchar(50) );
    病人信息表的触发器
    create trigger trig_pati before INSERT on pati_info for each ROW begin declare p char(5); declare n int; DECLARE num int; DECLARE type char(4); set new.pati_birthday=date_format(sysdate(),'%Y%m%d%H%i'); set p=(select MAX(pati_num) from pati_info); if p is null then set p='P1000'; end if; set n=substring(p,2)+1; set new.pati_num=concat('P',n); set num =(select COUNT(*) from pati_info group by new.pati_ward_num); set type=(select ward_type from ward_info where new.pati_ward_num=ward_info.ward_num); if (type='单人') then if(num=0) then update ward_info set ward_status=1 where ward_info.ward_num = new.pati_ward_num; end if; ELSEIF (type='双人') then if(num=1) then update ward_info set ward_status=1 where ward_info.ward_num=new.pati_ward_num ; end if; ELSE if (num=3) then update ward_info set ward_status=1 where ward_info.ward_num=new.pati_ward_num; end if; end if;end; create TRIGGER trig_pati_delete AFTER DELETEon pati_info for each ROW BEGIN DECLARE num int; DECLARE type char(4); set num =(select COUNT(*) from pati_info group by old.pati_ward_num); set type=(select ward_type from ward_info where old.pati_ward_num=ward_info.ward_num); if (type='单人') then if(num=0) then update ward_info set ward_status=0 where ward_info.ward_num=old.pati_ward_num ; end if; ELSEIF (type='双人') then if(num<2) then update ward_info set ward_status=0 where ward_info.ward_num=old.pati_ward_num ; end if; ELSE if (num<4) then update ward_info set ward_status=0 where ward_info.ward_num=old.pati_ward_num ; end if; end if;end;
    病房信息表
    create table ward_info ( ward_id int PRIMARY KEY auto_increment, ward_num char(5), /*W0000*/ ward_type char(4), -- 病房类型 -- ward_depart varchar(10), -- 所属科室 -- ward_doc varchar(10), -- 管理医生 -- ward_doc_tel char(11), -- 医生电话 -- ward_rent DECIMAL(5,1), -- 租金 -- ward_status int DEFAULT 0 -- 1 满)
    病房信息表的触发器
    create TRIGGER trig_ward_num before insert on ward_infofor each row begin DECLARE w char(5); DECLARE n int; set w=(select max(ward_num) from ward_info); if w is null then set w='W1000'; end if; set n=SUBSTRING(w,2)+1; set new.ward_num=CONCAT('W',n); end;
    病人住院信息视图
    Create view v_pati_ward (pw_ward_num, pw_pati_num, pw_pati_name, pw_pati_sex, pw_ward_depart, pw_ward_doc, pw_ward_doc_tel, pw_ward_rent) as SELECT ward_num, pati_num, pati_name, pati_sex, ward_depart, ward_doc, ward_doc_tel, ward_rent from pati_info, ward_info where pati_info.pati_ward_num=ward_info.ward_num;
    5.2 JSP 前端页面代码<script> function show(f) { var chs=document.getElementsByName("pati_id"); for(var i=0;i<chs.length;i++) { chs[i].checked=f; } } function batdelete(){ var flag=0; var pati_id=document.getElementsByName("pati_id"); for(var j=0;j<pati_id.length;j++){ if(pati_id[j].checked==true){ flag=1; } } if( flag==1 ){ for(var i=0;i<pati_id.length;i++){ if(pati_id[i].checked==true){ //window.location.href="DeletePatiServlet?pati_id="+pati_id[i].value; }else{ pati_id[i].value=""; } } } else{ $("form").attr("action",""); alert(" 请选中要删除的病人信息!"); } } // 单个删除 function del(id){ window.location.href='javascript:doDelete('+id+')'; } var doDelete=function(n){ var f=confirm("确定删除吗?"); if(f) { window.location.href="DeletePatiServlet?pati_id="+n; } }; </script>
    医生界面左侧导航页面 JSP 代码
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel="stylesheet" type="text/css" href="bootstrap/css/bootstrap.min.css"> <style> *{ margin:0px; padding:0px; } body{ background-color: #E0E0E0; } #left{ height:300px; padding-top:150px; margin-left:27px; } .navi{ font-size:17px; } a{ color: black; } </style> </head> <body> <div id="left"> <ul class="nav nav-stacked"> <li class="active"> <a class="navi" href="Welcome.jsp" target="main">首页</a> </li> <li> <a class="navi" href="ToUpdateDocServlet?user_id=${sessionScope.doc.user_id }" target="main">个人信息</a> </li> <li class="dropdown"> <a class="dropdown-toggle navi" data-toggle="dropdown">病人管理<span class="caret"></span></a> <ul class="dropdown-menu"> <li onmouseover="activ(this);" onmouseout="defau(this);"> <a href="addpati.jsp" target="main">添加病人信息</a></li> <li class="nav-divider"></li> <li onmouseover="activ(this);" onmouseout="defau(this);"> <a href="SearchPatiServlet" target="main"> 病人信息查询 </a></li> </ul> </li> <li class="dropdown"> <a class="dropdown-toggle navi" data-toggle="dropdown">病房管理<span class="caret"></span></a> <ul class="dropdown-menu"> <li onmouseover="activ(this);" onmouseout="defau(this);"> <a href="SearchWardServlet" target="main"> 病房信息查询</a></li> </ul> </li> <li class="dropdown"> <a class="dropdown-toggle navi" data-toggle="dropdown">综合信息查询<span class="caret"></span></a> <ul class="dropdown-menu"> <li onmouseover="activ(this);" onmouseout="defau(this);"> <a href="SearchPwServlet" target="main"> 住 院 信 息 查 询</a></li> </ul> </li> <li> <a href="aboutus.jsp" target="main" class="navi">关于我们</a> </li> </ul> </div> </body> <script src="jquery-3.2.1.min.js"></script> <script src="bootstrap/js/bootstrap.min.js"></script> <script> function activ(obj){ if(obj.className!=null) obj.className+=" active"; else obj.className="active"; } function defau(obj){ if(obj.className=="active") obj.className-="active"; else obj.className-=" active"; } </script> </html>
    管理员界面左侧导航页面 JSP 代码
    <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>欢迎使用</title> <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <link rel="stylesheet" type="text/css" href="lib/bootstrap/css/bootstrap.css"> <link rel="stylesheet" type="text/css" href="stylesheets/theme.css"> <link rel="stylesheet" href="lib/font-awesome/css/font-awesome.css"> <script src="lib/jquery-1.7.2.min.js" type="text/javascript"></script> <!-- Demo page code --> <style type="text/css"> #line-chart { height:300px; width:800px; margin: 0px auto; margin-top: 1em; } .brand { font-family: georgia, serif; } .brand .first { color: #ccc; font-style: italic; } .brand .second { color: #fff; font-weight: bold; } </style> <link rel="shortcut icon" href="../assets/ico/favicon.ico"> <link rel="apple-touch-icon-precomposed" href="../assets/ico/appletouch-icon-57-precomposed.png"> <style type="text/css"> <!-- .STYLE2 {color: #FFFFFF} --> </style> </head> <body class=""> <div class="sidebar-nav"> <a href="Welcome.jsp" target="Newmain" class="nav-header" ><i class="icon-dashboard"></i>欢迎</a> <a href="#dashboard-menu" data-toggle="collapse" class="nav-header" ><i class="icon-dashboard"></i>医生操作</a> <ul id="dashboard-menu" class="nav nav-list collapse in"> <li ><a href="DelDoc.jsp" target="Newmain"> 删除医生账户</a></li> <li ><a href="SearchDocServlet" target="Newmain">查询医生账户</a></li> </ul> <a href="#accounts-menu" class="nav-header" data-toggle="collapse"><i class="icon-briefcase"></i>病房操作</a> <ul id="accounts-menu" class="nav nav-list collapse"> <li ><a href="NewAddRoom.jsp" target="Newmain"> 添 置 病 房</a></li> <li ><a href="NewDelRoom.jsp" target="Newmain"> 删 除 病 房</a></li> <li ><a href="NewSearchNullBedServlet" target="Newmain"> 病房查询</a></li> </ul> <a href="ToEditAdminServlet?user_num=${sessionScope.map.user_num }" class="nav-header" target="Newmain"><i class="icon-question-sign"></i>个人信息维护</a></div> <script src="lib/bootstrap/js/bootstrap.js"></script> <script type="text/javascript"> $("[rel=tooltip]").tooltip(); $(function() { $('.demo-cancel-click').click(function(){return false;}); }); </script> <body> </body> </html>
    5.3 后端代码package com.neu.service; import java.util.List; import java.util.Map; import java.util.HashMap; import com.neu.dao.AdminInfoDao; import com.neu.util.ConvertUtil; public class AdminInfoService { private AdminInfoDao adminInfoDao; public AdminInfoService(){ this.adminInfoDao=new AdminInfoDao(); } public boolean doReg(Map<String,String[]> params){ boolean flag=false; Map<String,String> map=ConvertUtil.convertMap(params); int row=adminInfoDao.insert(map); if(row>0){ flag=true; } return flag; } public List<Map<String,String>> findByParams(Map<String,String[]> params){ List<Map<String,String>> list=null; Map<String,String> map=ConvertUtil.convertMap(params); list=adminInfoDao.search(map); return list; } public boolean doDelete(Map<String,String[]> params){ boolean flag=false; Map<String,String> map=ConvertUtil.convertMap(params); int row=adminInfoDao.delete(map); if(row>0){ flag=true; } return flag; } public Map<String, String> checkLogin(Map<String,String[]> params){ Map<String, String> item=null; Map<String,String> map=ConvertUtil.convertMap(params); List<Map<String, String>> list=adminInfoDao.search(map); if(list.size()>0){ item=list.get(0); } return item; } public boolean doUpdate(Map<String, String[]> params){ boolean flag=false; Map<String, String> map=ConvertUtil.convertMap(params); // 存放 修改语句的条件 Map<String,String> where=new HashMap<String, String>(); where.put("user_num", map.get("user_num")); // 必须把作为条件的列从map中移除 map.remove("user_num"); int row=adminInfoDao.update(map, where); if(row>0){ flag=true; } return flag; } public Map<String,String> findById(Map<String,String[]> params){ Map<String,String> item=null; Map<String,String> map=ConvertUtil.convertMap(params); List<Map<String,String>> list=adminInfoDao.search(map); if(list.size()>0){ item=list.get(0); } return item; } }
    5.4 功能截图删除病房

    修改病房信息

    病床查询

    添置病床

    删除医生账户

    管理员主界面

    查询医生账户

    修改个人信息

    医生账户操作面板

    6 用户说明书第一步:登录界面,分为管理员和用户两种身份,登录不同的账号跳转到不同的页面如图 7-1:

    第二步:根据你的身份登录完成后,如果你的身份是医生,那么你可以 进行病人信息的增删改查以及查询空病房,添加病房等操作。如果你是管理 员,那么你可以进行对医生的查询和删除操作,病房的增删改查操作,以及 对自己个人信息的修改操作。

    第三步:根据你的身份你可以在页面上进行你想进行的操作了,例如:我 是一名管理员,我想知道某某某医生的信息,那么经过如下页面操作即可完成:


    参考文献[1] 林来兴. 空间控制技术. 宇航出版社, 1992:34-36
    [2] J.R.McDonnell,D.Wagen. Evolving Recurrent Perceptions for Time-Seeies Modeling. IEEE Trans. on Neural Networks. 1994,5(1):24-38
    [3] 洪炳熔. 自由浮游空间机器人捕捉目标的运动规划研究. 中国第五届机 器人学术会议论文集. 哈尔滨, 1997:75-80
    8 评论 205 下载 2018-11-05 22:18:09 下载需要4点积分
  • 基于Face++的人脸融合及换脸系统

    1.项目介绍在本项目中,我们实现了对人脸图片数据的三种处理:人脸互换(face swap)、人脸融合(face morph)以及基于特征向量的人脸处理(eigen face)。
    1.1 人脸互换(face swap)人脸互换部分主要实现的功能是,给定任意两张人脸图片,通过一系列操作,使两个人的脸部交换,这部分需要的问题有:

    不同的人的脸部结构千差万别,同一个人也会因为角度、面部表情的不同而导致差别,即如何实现不同图片的人脸对齐
    不同人脸的肤色、光照不同,即不同图片的面部亮度不同,在换脸后如何与整体亮度统一
    不同人脸的纹理不同,比如老人的皱纹等,如何实现换脸后纹理的统一

    1.2 人脸融合(face morph)在人脸融合部分,我们需要实现给定任意两张人脸图片和融合度α,通过一系列操 作,实现两个人脸的融合。这一部分的困难在于:

    人脸结构的检测与分割。对于给定的人脸图片,人脸的结构差异很大
    人脸融合度的构建。对于给定的融合度 α,如何对两张图片的人脸取样与映射

    1.3 本征脸(eigen face)在这一部分,需要对较大的数据集(几百张,几千张人脸图片)进行处理,通过主成分分析的方法,得到一定数量的人脸主成分。这一部分的主要困难在于数据集的预处理,我们需要将不同图片中的人脸对齐,才能进行后续的处理。
    2.算法结构与处理过程2.1 人脸变换2.1.1 人脸关键点检测实现人脸变换的第一步,便是人脸关键点的检测,得到图片中的人脸的结构。在这 里,我们利用旷视face++的API来定位人脸关键的集合{V1,V2,…,Vn},其中关键点的数量可 以选择 83 或者 106。
    左:人脸关键点与凸包;右:德劳内三角集。

    2.1.2 计算凸包在获取人脸关键点集合后,我们需要计算这些关键点的凸包(convex hull)(凸包是一个计算几何(图形学)中的概念:在一个实数向量空间 V 中,对于给定集合 X,所有包含 X 的凸集的交集 S 被称为 X 的凸包。X 的凸包可以用 X 内所有点(X1,…Xn)的凸组合来构造.)在这里,我们计算凸包是为了获取这些人脸关键点组成的一个人脸区域。
    2.1.3 德劳内(Delaunay)三角划分在获得凸包以后,我们对凸包内的人脸关键点进行德劳内三角的划分。德劳内三角划分能将我们的凸包区域进行分割,并且更易于保留人脸的细节部分,并且因为获取仿射变换需要原图片和目标图片的各三个点,正好对应于原图和目标图的对应的德劳内三角。
    2.1.4 进行仿射变换在获得原图片和目标图图片的德劳内三角以后,我们需要寻找两张图对应的三角形对,对这样的每一对三角形,我们可以计算得到一个仿射函数。这个仿射函数将被用于三角形对之间的仿射变换。重复这个操作,直到所有区域都操作完毕,我们得到了人脸的位置变换。
    2.1.5 无缝融合在上述人脸仿射变换后,我们得到人脸结构和位置的变换,但我们没有对人脸区域亮度进行调整,这样会造成人脸区域和其他区域的颜色协调的问题。所以最后我们用 opencv 的无缝融合函数 seamlessClone()来实现无缝融合操作。
    2.2 人脸融合2.2.1 人脸关键点检测和 2.1.1 部分一样,我们首先需要确定给定图片的人脸的结构,所以需要检测人脸的关键点。在这里我们仍然使用旷视 face++的人脸关键点识别 API,选择 108 点检测。
    2.2.2 定义融合度要实现两张人脸的融合,我们还要定义融合度 α(0=<α<=1):

    M 是融合后的图像,I,J 是两张待融合图像。我们定义 α,使 α 趋于 0 使,越来越接近图 像 I;α 趋于 1 时,越来越接近图像 J;α 等于 0.5 时,相当于两张图像的平均。
    2.2.3 采样点加权在获得两张人脸的关键点后,我们再对两张人脸进行加权平均:

    通过这个式子,我们计算加权后的人脸关键点的位置。
    左:采样点加权后的人脸结构;右:德劳内三角划分。

    2.2.4 德劳内三角划分如同 1.1.3,我们对获取的人脸关键点进行德劳内三角划分,不同的是,我们为了获取人脸框架结构在整张图中的位置,需要手动添加图片四个角以及四边中心点作为辅助点,再进行德劳内三角划分。这样,我们就得到非常详细的人脸结构。
    2.2.5 图像融合在经过以上步骤后,我们进行人脸融合。首先,我们对源图像的人脸关键点对我们在 2.2.3 中得到的加权后的人脸关键点进行仿射变换。由对应的德劳内三角形确定的三个点,我们可以确定一个仿射变换;对所有的三角形进行这样的操作,我们就得到了仿射后的人脸图片。对两张源图进行这样的操作,我们就得到两个仿射后的人脸图片,再运用我们定义的融合度 α 进行加权平均,最终得到我们的目标图片。

    2.3 本征脸2.3.1 数据预处理此次我们用于测试的数据集有两个,一个是 NBA 现役球员,另一个是女外女明星。对于我们的人脸图片数据集,我们首先要做的是将它们的大小固定为统一的大小。然后,我们需要将每张人脸配准定位,一个方法是将每张图片的人的眼睛定位于同一水平线上,并且使每张图片的两眼中心点在相同的位置。
    2.3.2 主成分分析在预处理图片后,我们对图片的数据进行主成分分析。首先,对于每张 NxN 大小的图片,我们将其转化成一个(NxNx3)x 1 的向量。当有 M 张图片时,我们便有一个(NxNx3)x M 的矩阵。
    在计算主成分之前,我们先来对我们的图片矩阵数据求平均值向量,这是为了后面的方差和协方差准备的。在获取了平均值向量之后,我们来计算主成分。在数数学上,我们通过线性代数中的矩阵特征值分解,可以找到矩阵的特征值和相应的特征向量,我们将这些特征值按从大到小排列,越大的特征值说明数据在这个特征值对应的特征向量的方向上 的方差越大,这就是我们要找的主成分。在这里,我们可以设置参数,来选择主成分的数量。例如,我们选择前十大的特征值和对应的特征向量。
    2.3.3 获得本征脸在获得主成分之后,我们将选取的主成分矩阵,按原来图片矩阵转化为向量的逆操 作,将矩阵变成图片矩阵。
    3.代码结构3.1 人脸互换相关文件:faceswap.py

    get_points 函数。用于封装好 Face++的 API,得到图片的 83 个人脸特征点,并存储在一个列表当中,方便后续处理
    AffineTransform 函数。该函数输入源图、源图的德劳内三角、目标图的德劳内三角和给定的大小。通过计算获取仿射变换函数,并且进行仿射变换,输出变换后的图片
    DelaunayTriangles函数。用于计算我们人脸关键点的德劳内三角。我们应用openCV的Subdiv2D 函数,可以得到我们的德劳内三角
    warpTriangle 函数。通过德劳内三角的划分,我们定义这个函数,用来实现对德劳内三角的仿射变换,并且最终将左右变换后的三角形区域合并,得到我们的目标脸
    最后是主函数,调用这些定义好的函数,读取我们的图片进行处理

    3.2 人脸融合有关文件:morph.py

    detect 函数。用于封装好 Face++的 API,得到图片的 108 个人脸特征点,并存储在一个字典当中,方便后续处理
    addBorderPoints 函数。该函数功能是给处理图片准备要划分三角形的时候,把图片四个顶点和四条边的中点的坐标添加到带划分的点中,这让得劳内三角形能完整的划分 整张图片
    delaunaryTriangles 函数。由特征点的坐标生成其用来划分这些特征点的得劳内三角形
    affineTransform 函数。根据划分好的三角形,我们可以用来计算一张图的三角形到另外一张图所对应的三角形的仿射变换,该函数在 morphingTriangle 函数中使用
    morphingTriangle 函数。对两个仿射后的人脸图片,运用我们定义的融合度 α 进行加权平均,最终得到我们的目标图片


    morphing 函数。总的融合函数的接口,得到融合图片的脸部特征点的坐标,与新图片的脸部划分三角形坐标,调用 morphingTriangle 函数得到新的融合图片
    getPic 函数。用于实现 GUI 中根据 alpha 生成一张图片的功能
    get20Pics,create,sortKey,createGIF 函数。用于实现 GUI 生成一张 gif 图片的功能

    3.3 本征脸人脸相关文件:eigenface_origin.py

    readImages 函数。从指定的文件夹中读取图片文件,将其转化成 numpy 矩阵,放到一个 list 中。在此过程中,每张图片翻转后又保存了一次
    createdatamatrix 函数。将保存图片的 numpy 矩阵压平。(每张图片压平)
    createnewface 函数。产生特征脸并且用 opencv 可视化界面展示
    resetslidervalues 函数。在 opencv 可视化界面中,点击一下图片,就重置所有 bar
    总体思路:从文件夹中读取图片,变成矩阵,每张图片 flatten,用求平均向量,特征向量,再计算出 eigenface。

    3.4 GUI 部分有关文件:

    mainPage.py 主界面 GUI
    morphGUI.py 融合脸功能界面 GUI
    swapGUI.py 换脸功能界面 GUI
    eigenGUI.py 特征脸界面 GUI

    4.开发环境在本次项目中,算法几接口 API 都是由 pyhton3.5(python3.6)完成的,其中还使用了openCV 库。GUI 使用 pyqt 完成。API 使用 face++人脸关键点接口。
    5.可执行文件及使用的数据集5.1 数据集我们有 2 个数据集,其中一个 image_swap 是用于测试换脸操作的;另外一个 image_eigen 数据集是用来测试本征脸的,是 NBA 现役球员的图片。人脸融合测试图片,一定要是放在与该py文件夹中相同的文件夹,所以没有专门的数据集,可以从其他地方复制一些图片,进行测试。
    5.2 可执行文件及运行方式在 windows 下,我们有可执行文件 face#.exe。执行方式:双击打开,会看到我们 GUI 的初始界面。在界面中我们会看到三个按钮,这是我们 GUI 实现的三个功能,及人脸互换、人脸融合和本征脸。点击其中一个按钮,会进入下一层界面,具体的操作可以参考我们附加提交的操作演示视频。




    在 macOS 系统下,可以通过 python 文件名.py 命令运行我们的 python 文件。
    6.项目成果与反思6.1 项目成果6.1.1 人脸互换
    从测试结果图中,我们可以看到,我们的人脸互换效果还是非常好的:从前景图上截取的脸部,能够非常好地与背景图融合;在边缘部分,没有明显的边界;在人脸的姿势上,也根据背景的姿势得到了调整,能够与背景姿势相一致。当然我们也可以看到,在第二个结果中,由于前景脸和背景脸的脸部颜色相差太大,导致结果图中的脸部与额头等地方有明显的不一致,这是因为我们在做人脸互换的时候,只根据人脸关键点确定的凸包进行变换,而人脸关键点是没有包含额头及脖子部分的。这是我们人脸互换做的不好的地方
    6.1.2 人脸融合
    同样,对于我们人脸融合的结果,也非常好。在它融合度为 0.5 的情况下,包含了两张源图中一样多的特征,让我们能在结果图中能找到明显的属于两张源图的特征。但是同样存在一些问题,比如在上面一张结果中,我们可以看到头发部分有重影。这是因为两张源图片的头发差异部分存在白色的背景,当进行融合时,由于有两部分的特征,所以会造成重影;但是第二张结果图中,我们没有看到这个现象,这是因为两张源图的差异部分没有很白的背景颜色。
    6.1.3 本征脸
    对于我们的本征脸,我们在此解释一下左侧拖条的含义:首先我们这部分是对人脸数据集进行主成分分析,所谓的主成分就是数据中方差最大的一些方向,对应到人脸数据中,便是影响数据集中人脸的形态的最大的方向,或者说数据集中人脸变化最大的一些特征。比如,NBA 球员数据集中,球员的肤色有黑有白,这是变化非常大的特征,所以应该会有一个主成分只指向球员肤色的黑白的。而之所以右侧的结果会很模糊,正是因为我们计算出的主成分代表了人脸数据集中变化最大的特征,所以这些特征组成的图片必定是非常模糊非常不整齐的。
    6.2 项目思考与改进6.1.1 人脸互换我们的人脸互换算法依赖于人脸关键点锁定的区域,基本上限定于眉毛-两侧脸颊-下巴组成的区域,当两张源图的脸部颜色差别很大时,会出现结果图中脸部与额头差别很大的问题。所以,我们设想后续的优化是,将脸部的区域扩大到额头,乃至整个脖子,但是由于一般人脸检测的算法只限于原先的区域,如何检测这些扩展的区域,是一个较难解决的问题。
    6.1.1 人脸融合对于人脸融合中出现的结果图中脸部区域以外的重影问题,我们设想的优化是,将脸部以外的区域,全部设置成其中一张源图的背景区域。
    6.2.3 本征脸对于主成分分析得出来的若干个对人脸变化影响最大的特征,其中一些我们能够直观地看出来,例如肤色的黑白等,但有一些特征并不能很容易地得知与什么相关,需要我们进一步测试、观察与分析。
    8 评论 55 下载 2019-05-24 10:28:03 下载需要11点积分
  • 基于Android的手机音乐播放器的设计与实现

    摘 要随着Android系统和移动互联网的快速崛起,手机已经成为人们生活不可缺的一部分,在现代人的生活中,人们生活节奏的加快,生活压力越来越大,碎片化的时间越来越多,那么一个可以在碎片化的时间内调节自己心情的产品,无疑将拥有一个巨大的市场,而且随着移动设备硬件越来越先进,人们对移动设备的软件要求也越要越高,而基于Android系统的手机音乐播放器就能很好地满足这个需求。
    Android是一个开源的基于Linux的系统,本论文将基于Android开源系统技术,使用java语言和Android Studio开发工具实现基于Android系统的音乐播放器。相对于传统的卡带式音乐播放器,MP3播放器,MP4播放器,Android系统的手机音乐播放器有着反应速度快,在线听音乐,分享心情感受,收藏歌曲等无法比拟的优势,Android系统的手机音乐播放器逐渐成为人们生活不可或缺的一部分,所以一个基于Android的音乐播放器无疑将拥有一个巨大的市场。
    本文将会详细地从需求分析开始,认真分析用户需求,然后进行界面,数据库等的设计工作。进而使用java实现需求,开发出一个高效的贴近用户的操作简单的音乐APP。最后通过系统化的测试,检验系统的稳定性。同时也要总结整个过程并指出播放器的不足之处,并提出修改的思路。
    关键词:Android,音乐播放器,高效
    AbstractWith the rapid rise of the Android system and mobile Internet, mobile phones have become an indispensable part of people’s lives. In modern people’s lives, people’s life pace is accelerated, life pressure is increasing, and fragmentation takes more and more time. Then a product that can adjust its mood in a fragmented time will undoubtedly have a huge market, and as the hardware of mobile devices becomes more and more advanced, people’s software requirements for mobile devices will also be higher, based on Android. The system’s mobile music player will be able to meet this demand.
    Android is an open source Linux-based system. This article will be based on Android open source system technology, using java language and Android Studio development tools to achieve Android-based music player. Compared to traditional cassette music players, MP3 players, MP4 players, Android mobile music players have a fast response, listen to music online, share feelings, collect songs and other incomparable advantages, Android system Mobile music players have gradually become an integral part of people’s lives, so an Android-based music player will undoubtedly have a huge market.
    This article will start from the requirements analysis in detail, carefully analyze the user requirements, and then proceed with the design of the interface and database. Then use java to realize the demand and develop an efficient and simple music APP that is close to the user. Finally, through systematic testing, the stability of the system is checked. At the same time, we must also sum up the entire process and point out the inadequacies of the player and propose revised ideas.
    Key words: Android, MusicPlayer, Efficient
    1 前言1.1 研究目的与意义现今社会生活节奏越来越快,而听音乐是舒缓压力的有效方式之一,本文的主要目的是开发一个方便快捷地为大众提供服务的音乐播放器,它可以支持多种格式播放,比如MP3,Wav等多种格式,并且能够控制音乐的播放暂停,停止,上一首,下一首等功能,界面简洁,操作简单。
    在现代生活中,能在空闲的时间里听一下音乐,无疑是一大乐趣,而随着科技的进步,人们听音乐的方式也在悄悄地改变,从传统的MP3转到了智能手机,这时候一个好的音乐APP就可以满足你要求的一切,所以本系统选择移动手机作为开发平台。
    目前,移动互联网已经超越传统PC,成为最大的互联网市场,在庞大的手机市场中,主流的手机操作系统包括Android,IOS,Windows mobile,相对于Windows mobile的一蹶不振,IOS的封闭,Android系统由于它的开放性,吸引了越来越多的开发者投身于Android开发社区中,Android成为现今最受欢迎的系统,所以本文选择Android作为开发的目的系统。
    综上,本文选择为基于Android系统的手机音乐播放器,传统的手机音乐播放器一味地追求功能强大而忽略了CPU和内存占用率过大,对低端智能手机用户不友好,所以该APP追求的是一个更加简洁,通用性广的音乐播发器,同时本系统也会在这基础上追求为用户提供更多音乐资源,致力于打造一个最适合大部分用户的APP,同时本人也可以借助这个机会学习Android移动平台的开发技能。
    1.2 研究概况首先简单介绍一下Android系统,Android开始的时候是Rubin Andy团队开发的一个独立的手机系统,他是基于Linux内核,后来(2005年)该系统被Google公司收购,2007年11月Google宣布退出基于Linux的Android开源系统,而这时正值Apple发布革命性产品iPhone。发展到现在,Android已经更新的8.0,Android也经历了11个年头,也成为了市场占有率最高的系统。根据最新市场调查,在中国市场,Android市场份额上升7.2%,达到79.9%,iOS用户则下滑5.4%,Windows几乎面临“绝迹”,而且还具有上升的趋势。
    在Android系统中主流的音乐播放器有百度音乐,酷狗音乐、QQ音乐、天天动听、网易云音乐。
    百度音乐的前身为“千千静听”,二者进行整合之后更是发挥了自身优势,为用户带来了更加完美的视听享受。且百度音乐重视原创和正版,在应用中还专门设立了原创歌曲榜单。百度音乐独有场景电台功能,可根据当前的时间为您推荐不同种类的歌曲,相当的智能化,比如午后会为您推荐一些慵懒又温暖的音乐,而在下班的路上则会推荐一些较为轻快的乐曲。除此之外,百度音乐还有K歌台服务,这里有大量歌曲供您选择,且提供伴奏曲,您尽可以举着手机高歌一曲,保存后还可分享给好友们收听,或请他们也来PK一下,不只是听歌,百度音乐还能满足您唱歌的需求。
    酷狗算是老牌的音乐播放器了,出色的交互设计和良好的使用体验让它积累了不少忠实用户,酷狗音乐拥有海量乐曲库,并且都是正版,这是因为酷狗与多家媒体或唱片公司都是合作伙伴关系,不但在质量上有所保证,更新速度也能保持同步。酷狗音乐中有个功能叫做“演艺直播”,这里聚集着大量的草根明星,用自己的歌喉为用户们献上一首首精心录制的歌曲,用户可为她送礼物和她交流,也能自己点歌,和舞台上的明星不同,这里多了一丝亲切的味道。
    QQ音乐,但它的优势在于,结合着QQ自身的优势,让用户可以享受到更多的服务。听歌识曲应该是音乐客户端的标准配置了,可QQ音乐却将识曲与摇一摇相结合,无需任何点击,晃动一下即可启动,不仅方便还增添了不少乐趣。QQ音乐为用户们准备了明星部落,这里汇聚了明星们的一手消息,和大量的话题,保证能满足用户追星的需求。
    天天动听是上海水渡石旗下的一款音乐播放器,以其绚丽的可视化效果赢得了用户的喜爱,在播放时封面还会随着音乐一起变换,在视觉和听觉上都是一种享受。它功能丰富实用,支持多种格式的歌曲,操作简单流畅,听歌也能变得如此简单,它功能丰富实用,支持多种格式的歌曲,操作简单流畅,听歌也能变得如此简单,天天动听提供了摇一摇切歌功能,且摇的力度也不尽相同。用户可自己设置首页显示内容,个性化做的非常出众。
    网易云音乐上线仅有几年的时间,但是它却迅速成为了用户们追捧的对象,不止是因为其出众的界面设计,在操作体验上也令人印象深刻,网易云音乐在功能上也有创新,它融入了流行的社交元素,让用户在听歌之外,还能实现分享交流的目的。网易云音乐的与众不同之处,是社交,评论、分享让大家因为对音乐的共同品味而走到了一起,除此之外就是主播电台栏目,音乐故事、情感调频、娱乐八卦,还有热度极高的明星做主播,与听CD的感觉完全不同,偶像与粉丝之间消除了隔阂感,距离更近一些。当然其它的功能在网易云音乐中也能找到,比如听歌识曲、定时停止播放,还可以更换主题皮肤。
    1.3 论文的主要工作本文主要针对播放器的基本功能进行实现,主要研究内容分为:对播放界面的优化,美观的播放界面会给用户带来更好的体验,文中主要提到对图片毛玻璃效果的实现,基于百度音乐API的接口实现访问,跨进进程调度音乐播放器,最后还使用高德地图API实现实时的天气预报功能。
    1.4 论文的结构本论文各章内容安排如下:

    第一章:前言,介绍了国内的Android手机音乐播放器发展现状,并进一步分析了这些软件对于用户使用的一些不足
    第二章:开发技术及工具的介绍,这里主要阐述Android系统的发展和架构,Retrofit和Rxjava作为Android客户端访问网络的的框架,和使用MVP的设计模式,使用Android Studio 开发Android端,Idea作为后台的开发工具,JavaEE技术,MySQL数据库,Spring-Boot框架
    第三章:需求分析。通过对该系统实现的可行性做了分析,在了解需求的基础上,对系统的功能需求做了阐述,采用了用例图、用例简介、活动图、包图等对系统的流程进行了分析
    第四章:系统总体设计。概括分析说明了音乐播放器的主要功能,在了解需求的基础上,设计了系统的总体功能模块。从概念结构设计、物理结构设计及数据库设计三方面对系统的设计进行介绍
    第五章:系统详细设计。分别通过时序图、界面、核心代码(内附界面截图及精髓技术的代码)。阐述播放器播放音乐流程。并介绍了本文实践项目的一些亮点与独到之处
    第六章:系统测试。对目前常用的测试技术进行了介绍并介绍了测试该系统的方法
    第七章:结束语。总结整个设计,并说明不足及进一步改善的方向

    2 开发技术及工具的介绍在本章中,本系统主要采用Retrofit和Rxjava作为Android客户端访问网络的的框架,使用MVP的设计模式,使用Android Studio 开发Android端,Idea作为后台的开发工具,使用JavaEE技术,使用MySQL作为后台数据库,Spring-Boot框架。
    2.1 Android系统简介Android是一个基于Linux内核的开放源代码移动操作系统,由Google成立的Open Handset Alliance(OHA,开放手持设备联盟)持续领导与开发,主要设计用于触屏移动设备如智能手机和平板电脑与其他便携式设备。
    Android系统最初并不是由Google公司研发的,Android最初由安迪•鲁宾(Andy Rubin)的团队开发制作,最初开发这个系统的目的是创建一个数码相机的先进操作系统;但是后来发现市场需求不够大,加上智能手机市场快速成长,于是Android成为一款面向智能手机的操作系统。于2005年7月11日被美国科技企业Google收购。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商成立开放手持设备联盟来共同研发改良Android,随后,Google以Apache免费开放源代码许可证的授权方式,发布了Android的源代码,开放源代码加速了Android普及,让生产商推出搭载Android的智能手机,Android后来更逐渐拓展到平板电脑及其他领域上。随着时间的推移,Android系统逐渐强大起来,现在Android已经成为了全球最大的移动操作系统,Android从面世以来已经有二十多个版本了在这几年的发展过程中,谷歌为Android建立了一个完整的生态系统[5]。Android系统的主要厂商有SAMSUNG,华为,HTC,OPPO,VIVO,小米等。目前最新的额Android版本是Android 8.1(更智能、更迅捷、更强大。广受世人喜爱的不仅仅是曲奇饼干,更是为您打造的全新 Android 系统[1]) 。
    Android系统由高到低分为Application层、Application Framework层、Libraries层、AndroidRuntime层,和 Linux 内核层。蓝色的代表java程序,黄色的代码为运行JAVA程序而实现的虚拟机,绿色部分为C/C和和语言编写的程序库,红色的代码内核(linux内核和driver)。在Application Framework之下,由C/C和和的程序库组成,通过JNI完成从JAVA到C的调用。

    2.1.1 Application所有的应用程序都是使用JAVA语言编写的,每一个应用程序由一个或者多个活动组成,活动必须以Activity类为超类,活动类似于操作系统上的进程,但是活动比操作系统的进程要更为灵活,与进程类似的是,活动在多种状态之间进行切换。利用JAVA的跨平台性质,基于Android框架开发的应用程序可以不用编译运行于任何一台安装有android系统的平台,这点正是Android的精髓所在[6]。
    2.1.2 Application Framework应用程序的架构设计简化了组件的重用;任何一个应用程序都可以发布它的功能块并且任何其它的应用程序都可以使用其所发布的功能块(不过得遵循框架的安全性限制)。帮助程序员快速的开发程序,并且该应用程序重用机制也使用户可以方便的替换程序组件[11]。
    2.1.3 LibrariesAndroid包含一个C/C和和库的集合,供Android系统的各个组件使用。这些功能通过Android的应用程序框架(application framework)暴露给开发者。下面列出一些核心库。
    2.1.4 Android Runtime层Android包含一个核心库的集合,提供大部分在Java编程语言核心类库中可用的功能。每一个Android应用程序是Dalvik虚拟机中的实例,运行在他们自己的进程中。Dalvik虚拟机设计成,在一个设备可以高效地运行多个虚拟机。Dalvik虚拟机可执行文件格式是.dex,dex格式是专为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统。
    2.1.5 Linux内核Android 的核心系统服务依赖于 Linux 2.6 内核 ,如安全性,内存管理,进程管理, 网络协议栈和驱动模型。 Linux 内核也同时作为硬件和软件栈之间的抽象层。
    2.2 Retrofit技术框架A type-safe HTTP client for Android and Java[2],这是Retrofit官网对Retrofit的定义。Retrofit 是 Square公司旗下的类型安全的 HTTP 客户端,支持 Android 和 Java 等,它能将你的 HTTP API 转换为 Java 接口。Retrofit其实就是对okhttp做了进一步一层封装优化。用户只需要通过简单的配置就能使用Retrofit来进行网络请求了。
    Retrofit能够直接返回Bean对象,例如如果用户进行一个网络接口的请求,返回来一串json字符串。那么这个时候一般用户都要拿到这个json字符串后进行解析得到对应的Bean对象,Retrofit只要依赖一下Gson的转换库然后进行简单的配置就能够直接拿到Bean对象了,不需要用户自己去解析。
    2.3 Rxjava技术框架RxJava is a Java VM implementation of Reactive Extensions: a library for composing asynchronous and event-based programs by using observable sequences[3]。Rxjava和Retrofit都是由Square公司开发的开源框架,Rxjava一般配合Retrofit一起使用,RxJava是JVM的响应式编程扩展是一个为Java虚拟机编写的使用可观察序列的构建异步的基于事件的程序的类库。它基于观察者模式实现对数据/事件的序列的支持,并添加了一些操作符,允许你以声明式构建序列, 使得开发者无需关心底层的线程、同步、线程安全和并发数据结构。
    2.4 MVP框架技术简介对于一个应用而言用户需要对它抽象出各个层面,而在MVP架构中它将UI界面和数据进行隔离,所以用户的应用也就分为三个层次。

    View:对于View层也是视图层,在View层中只负责对数据的展示,提供友好的界面与用户进行交互。在Android开发中通常将Activity或者Fragment作为View层
    Model:对于Model层也是数据层。它区别于MVC架构中的Model,在这里不仅仅只是数据模型。在MVP架构中Model它负责对数据的存取操作,例如对数据库的读写,网络的数据的请求等
    Presenter:对于Presenter层他是连接View层与Model层的桥梁并对业务逻辑进行处理。在MVP架构中Model与View无法直接进行交互。所以在Presenter层它会从Model层获得所需要的数据,进行一些适当的处理后交由View层进行显示。这样通过Presenter将View与Model进行隔离,使得View和Model之间不存在耦合,同时也将业务逻辑从View中抽离。更好的使得单元测试得以实现[14]

    下图很好的展示了MVP各个组件间的关系:

    2.5 Android studio开发工具简介Android Studio是一个为Android平台开发程序的集成开发环境。2013年5月16日在Google I/O上发布,可供开发者免费使用。2013年5月发布早期预览版本,版本号为0.1。2014年6月发布0.8版本,至此进入beta阶段。第一个稳定版本1.0于2014年12月8日发布。Android Studio基于JetBrains IntelliJ IDEA,为Android开发特殊定制,并在Windows、OS X和Linux平台上均可运行。
    Android Studio 是基于 IntelliJ IDEA 的官方 Android 应用开发集成开发环境 (IDE)。 除了 IntelliJ 强大的代码编辑器和开发者工具,Android Studio 提供了更多可提高 Android 应用构建效率的功能,例如:

    基于 Gradle 的灵活构建系统
    快速且功能丰富的模拟器
    可针对所有 Android 设备进行开发的统一环境
    Instant Run,可将变更推送到正在运行的应用,无需构建新的 APK
    可帮助您构建常用应用功能和导入示例代码的代码模板和 GitHub 集成
    丰富的测试工具和框架
    可捕捉性能、易用性、版本兼容性以及其他问题的 Lint 工具
    C和和 和 NDK 支持
    内置对 Google 云端平台的支持,可轻松集成 Google Cloud Messaging 和 App 引擎
    对最新的Google主推的开发语言Kotlin进行支持

    目前Android Studio的最新版本时3.1。
    2.6 IntelliJ IDEA开发工具简介IntelliJ IDEA是一种商业化销售的Java集成开发环境(Integrated Development Environment,IDE)工具软件,由捷克软件公司JetBrains在2001年1月时推出最初版。
    IntelliJ IDEA是用于开发计算机软件的Java集成开发环境(IDE)。 它由JetBrains(以前称为IntelliJ)开发,可作为Apache 2许可社区版本和专有商业版本提供。 两者均可用于商业开发。
    IntelliJ IDEA能尽可能地促进程序员的编程速度。它包括了很多辅助的功能,并且与Java结合得相当好。不同的工具窗口围绕在主编程窗口周围,当鼠标点到时即可 打开,无用时也可轻松关闭,使用户得到了最大化的有效屏幕范围。以技术为导向的IDEA集成了调试器,支持本地和远程的调试,即使用户需要修改一些设置上 的东西使用户的工作顺利进展。另外,它还提供了通常的监视,分步调试以及手动设置断点功能,在这种断点模式下,用户可以自动地在断点之外设置现场访问,甚 至可以浏览不同的变量的值。IDE支持多重的JVM设置,几个编译程序和Ant建造系统,并且,它使得设置多重的自定义的类途径变得简单。
    IntelliJ IDEA是一个相对较新的Java IDE。它是Java开发环境中最为有用的一个。高度优化的IntelleJ Idea使普通任务变得相当容易,Idea支持很多整合功能,更重要的使它们设计的好容易使用。Idea支持XML中的代码实现,Idea同时还会校正 XML,Idea支持JSP的结构。作用于普通Java代码的众多功能同样适用于JSP(比如整合功能),同时支持JSP调试;支持EJB,尽管它不包括 对个别应用服务器的特殊支持。Idea支持Ant建立工具,不仅是运行目标它还支持编译与运行程序前后运行目标,另外也支持绑定键盘快捷键。在编辑一个 Ant建立XML文件时,Idea还对组成Ant工程的XML部分提供支持。IntelliJ IDEA 被称为是最好的JAVA IDE开发平台,这套软件就是以其聪明的即时分析和方便的 refactoring 功能深获大家所喜爱。缺点是较复杂,对初学者来说,理解起来比较困难。
    2.7 PowerDesign工具介绍Power Designer 是Sybase公司的CASE工具集,使用它可以方便地对管理信息系统进行分析设计,他几乎包括了数据库模型设计的全过程。利用Power Designer可以制作数据流程图、概念数据模型、物理数据模型,还可以为数据仓库制作结构模型,也能对团队设计模型进行控制。他可以与许多流行的数据库设计软件,例如PowberBuilder,Delphi,VB等相配合使来缩短开发时间和使系统设计更优化。
    2.8 Rotation Rose简介由于本系统使用RUP设计模式,需要建立可视化建模。可视化建模(VISUAL MODELING)是利用围绕现实想法组织模型的一种思考问题的方法。模型对于了解问题、与项目相关的每个人(客户、行业专家、分析师、设计者等)沟通、模仿企业流程、准备文档、设计程序和数据库来说都是有用的。建模促进了对需求的更好的理解、更清晰的设计、更加容易维护的系统。
    Rational Rose是Rational公司出品的一种面向对象的统一建模语言的可视化建模工具。用于可视化建模和公司级水平软件应用的组件构造。
    Rational Rose 是一个完全的,具有能满足所有建模环境(Web开发,数据建模,Visual Studio和 C和和 )需求能力和灵活性的一套解决方案。Rose 允许开发人员,项目经理,系统工程师和分析人员在软件开发周期内在将需求和系统的体系架构转换成代码,消除浪费的消耗,对需求和系统的体系架构进行可视化,理解和精练。通过在软件开发周期内使用同一种建模工具可以确保更快更好的创建满足客户需求的可扩展的、灵活的并且可靠的应用系统。
    2.9 Spring-boot技术简介Spring Boot favors convention over configuration and is designed to get you up and running as quickly as possible[4]。Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。
    从最根本上来讲,Spring Boot就是一些库的集合,它能够被任意项目的构建系统所使用。简便起见,该框架也提供了命令行界面,它可以用来运行和测试Boot应用。框架的发布版本,包括集成的CLI(命令行界面),可以在Spring仓库中手动下载和安装。
    要进行打包和分发的工程会依赖于像Maven或Gradle这样的构建系统。为了简化依赖图,Boot的功能是模块化的,通过导入Boot所谓的“starter”模块,可以将许多的依赖添加到工程之中。为了更容易地管理依赖版本和使用默认配置,框架提供了一个parent POM,工程可以继承它。
    2.10 Mysql数据库简介MySQL Enterprise Edition includes the most comprehensive set of advanced features, management tools and technical support to achieve the highest levels of MySQL scalability, security, reliability, and uptime。 MySQL是一种开放源代码的关系型数据库管理系统(RDBMS),MySQL数据库系统使用最常用的数据库管理语言—结构化查询语言(SQL)进行数据库管理。由于MySQL是开放源代码的,因此任何人都可以在General Public License的许可下下载并根据个性化的需要对其进行修改。MySQL因为其速度、可靠性和适应性而备受关注。大多数人都认为在不需要事务化处理的情况下,MySQL是管理内容最好的选择。
    MySQL的海豚标志的名字叫“sakila”,它是由MySQL AB的创始人从用户在“海豚命名”的竞赛中建议的大量的名字表中选出的。获胜的名字是由来自非洲斯威士兰的开源软件开发者Ambrose Twebaze提供。根据Ambrose所说,Sakila来自一种叫SiSwati的斯威士兰方言,也是在Ambrose的家乡乌干达附近的坦桑尼亚的Arusha的一个小镇的名字。
    MySQL,虽然功能未必很强大,但因为它的开源、广泛传播,导致很多人都了解到这个数据库。它的历史也富有传奇性。
    2.11 Glide框架Glide is a fast and efficient open source media management and image loading framework for Android that wraps media decoding, memory and disk caching, and resource pooling into a simple and easy to use interface。[7]在泰国举行的谷歌开发者论坛上,谷歌为开发者介绍了一个名叫 Glide 的图片加载库,作者是bumptech。这个库被广泛的运用在google的开源项目中,包括2014年google I/O大会上发布的官方app。
    Glide中有一部分单词,用英文单词可能在行文中更加合适,还有一些词在Glide中有特别的含义,这里简要说明一下:

    View:一般情况下,指Android中的View及其子类控件(包括自定义的),尤其指ImageView。这些控件可在上面绘制Drawable
    Target:Glide中重要的概念,目标。它即可以指封装了一个View的Target(ViewTarget),也可以不包含View(SimpleTarget)
    Drawable:指Android中的Drawable类或者它的子类,如BitmapDrawable等。或者Glide中继承Drawable实现的自定义Drawable(如GifDrawable等)。Request - 加载请求,可以是网络请求或者其他任何下载图片的请求,也是Glide中的一个类
    Model:数据源的提供者,如Url,文件路径等,可以从model中获取InputStream
    Signature:签名,可以唯一地标识一个对象
    recycle():Glide中Resource类有此方法,表示该资源不被引用,可以放入池中(此时并没有释放空间)。Android中Bitmap也有此方法,表示释放Bitmap占用的内存

    2.12 MybatisMyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。[9]MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

    3 需求分析3.1 系统概述本系统主要的用户为广大的Android手机用户提供音乐播放,歌曲下载,歌迷互动三大模块功能。
    3.2 系统分析3.2.1 系统需求分析随着Android系统和移动互联网的快速崛起,手机已经成为人们生活不可缺的一部分,在现代人的生活中,人们生活节奏的加快,生活压力越来越大,碎片化的时间越来越多,那么一个可以在碎片化的时间内调节自己心情的产品,无疑将拥有一个巨大的市场,而基于Android系统的手机音乐播放器就能很好地满足这个需求。
    通过调查分析,本系统的用户为广大的Android手机用户,用户可以通过本系统实现音乐播放的基本功能包括播放,暂停,上一首,下一首等。用户还可以分享歌曲,对歌曲进行评论或者点赞别人的评论,下载歌曲,具体需求如下:

    音乐播放,音乐播放包括了音乐播放的基本功能:开始,暂停,上一首,下一首,同时还可以滑动唱片来实现切换上下首,通过拖动进度条来切换到音乐的不同位置
    歌曲下载,首先用户需要搜索所需要的歌曲,然后点击下载。同时用户可以搜索不同平台的歌曲,这样就可以不会因为不同版权而听不到音乐
    乐迷互动,用户可以通过在播放页面的评论按钮评论歌曲,进入评论界面后还可以对自己喜欢的评论进行点赞或者评论,同时歌迷也可以通过分享到第三方平台一起享受音乐带来的乐趣

    3.2.2 系统可行性分析
    经济可行性:本系统作为一个毕业设计,并不需要任何的开发经费,而且本人也可以通过这次机会提升本人的Android开发技术和后台技术。并且本系统由于其简介的界面设计和丰富的资源平台将在这个巨大的市场有很大的发展空间
    技术可行性: 为了保证系统开发成功,必须采用RUP的系统开发方法。并且采取主流的MVP设计框架,运用成熟的技术比如Rxjava和Retrofit,还有Glide等。后台也采用了目前主流的MySQL作为数据库,数据安全得到了很好的保障,Tomcat 8.5作为服务器,使用Spring-Boot简易开发

    就本人而言,本人有系统地学习Android开发基础同时也有不错的Android开发技术,和Retrofit和Rxjava的开发经验,也有Spring-Boot的开发技术,所以技术可行性上是没有问题的。
    3.2.3 系统用力模型分析3.2.3.1 包图
    3.2.3.2 用例图及其用例简介用例图定义:由参与者(Actor)、用例(Use Case)以及它们之间的关系构成的用于描述系统功能的动态视图称为用例图。
    音乐播放用例:本用例可以通过通过播放器进行对音乐播放的基本操作,包括上一首,下一首,播放,暂停,还有拖动到某一时间点的功能。

    歌曲下载,首先用户需要搜索所需要的歌曲,然后点击下载。同时用户可以搜索不同平台的歌曲,这样就可以不会因为不同版权而听不到音乐。

    乐迷互动,用户可以通过在播放页面的评论按钮评论歌曲,进入评论界面后还可以对自己喜欢的评论进行点赞或者评论,同时歌迷也可以通过分享到第三方平台一起享受音乐带来的乐趣。

    3.3 系统用例分析本文将采用活动图来阐述系统的业务用例实现的工作流程,通过业务工作流程说明业务为向所服务的业务主角提供其所需的价值而必须完成的工作。业务用例由一系列活动组成,它们共同为业务主角生成某些工件。工作流程通常包括一个基本工作流程和一个或多个备选工作流程。工作流程的结构使用活动图来进行说明。
    3.3.1 用例阐述3.3.1.1 播放音乐
    基本流

    用户启动应用并进入播放界面后播放界面有播放,上一首,下一首三个按钮,用户点击播放按钮系统监听到用户点击播放按钮的回调后,系统查找播放列表,判断播列表是否有歌曲。系统找到歌曲,系统将歌曲信息发送给MediaPalyer,MediaPlayer根据歌曲信息找到播放源进行播放
    备选流

    系统在监听到用户点击播放按钮的回调后,系统查找播放列表,判断播放列表是否有歌曲。系统没有找到歌曲,系统提示用户播放列表为空

    3.3.1.2 暂停播放
    基本流

    用户处于播放界面,用户点击暂停按钮系统监听到用户点击暂停按钮的回调后,系统判断现在是否处于播放状态,系统处于播放状态。系统通知MediaPlayer暂停播放音乐,MediaPalyer暂停播放音乐
    备选流

    系统监听到用户点击暂停按钮的回调后,系统判断现在是否处于播放状态,系统并没有处于播放状态。提示用户现在是暂停状态

    3.3.1.3 播放上一首
    基本流

    用户启动应用并进入播放界面后播放界面有播放,上一首,下一首三个按钮,用户点击上一首按钮系统监听到用户点击播放按钮的回调后,系统查找播放列表,判断播列表是否有上一首歌曲。系统找到歌曲,系统将歌曲信息发送给MediaPalyer,MediaPlayer根据歌曲信息找到播放源进行播放
    备选流

    系统在监听到用户点击播放按钮的回调后,系统查找播放列表,判断播放列表是否有上一首歌曲。系统没有找到歌曲,系统提示用户播放列表没有上一首歌曲

    3.3.1.4 播放下一首
    基本流

    用户启动应用并进入播放界面后播放界面有播放,上一首,下一首三个按钮,用户点击下一首按钮系统监听到用户点击播放按钮的回调后,系统查找播放列表,判断播列表是否有下一首歌曲。系统找到歌曲,系统将歌曲信息发送给MediaPalyer,MediaPlayer根据歌曲信息找到播放源进行播放
    备选流

    系统在监听到用户点击播放按钮的回调后,系统查找播放列表,判断播放列表是否有下一首歌曲。系统没有找到歌曲,系统提示用户播放列表没有下一首歌曲

    3.3.1.5 歌曲下载
    基本流

    用户进入在线音乐并点击下载音乐系统弹出下载页面,并且下载音乐
    备选流

    假如网络错误,系统弹出错误界面

    3.3.1.6 评论歌曲
    基本流

    用户点击菜单的评论歌曲系统弹出输入框用户输入评论并点击提交,系统提交数据
    备选流

    假如网络错误,系统弹出错误界面。

    3.3.1.7 分享歌曲
    基本流

    用户点击分享按钮系统弹出分享途径选择,用户选择途径,系统根据选择分享到所选择的平台
    备选流

    假如网络错误,系统弹出错误界面

    3.4 领域涉及模型
    4 系统设计4.1 概念模型CDM:concept data model,即概念数据模型。简称概念模型,是面向数据库用户的实现世界的模型,主要用来描述世界的概念化结构,它使数据库的设计人员在设计的初始阶段,摆脱计算机系统及DBMS的具体技术问题,集中精力分析数据以及数据之间的联系等,与具体的数据管理系统(Database Management System,简称DBMS)无关。概念数据模型必须换成逻辑数据模型,才能在DBMS中实现。其只描述信息的特征和强调语义,而不涉及信息在计算机中的表示,是现实世界到信息世界的第一层抽象,根据需求分析及系统设计综合考虑,本系统的概念模型如下:

    4.2 物理模型PDM(Physical Data Model)即物理数据模型,提供了系统初始设计所需要的基础元素,以及相关元素之间的关系;数据库的物理设计阶段必须在此基础上进行详细的后台设计,包括数据库的存储过程、操作、触发、视图和索引表等;本系统的物理如下图:

    4.3 数据库设计根据关系化得到的各个模式,创建音乐播放器系统的各数据表如下。
    4.3.1 歌曲表


    字段名
    字段码
    数据类型
    数据长度
    备注
    主键




    ID
    songid
    bigint


    X


    唱片ID
    albumid
    bigint





    歌手ID
    singer_id
    bigint





    歌曲名
    songname
    varchar(32)
    32




    歌手名
    singername
    varchar(20)
    20




    播放链接
    m4a
    varchar(255)
    255




    下载地址
    downUrl
    varchar(255)
    255




    唱片小图
    albumpic_small
    varchar(255)
    255




    唱片大图
    albumpic_big
    varchar(255)
    255




    唱片名
    albumname
    varchar(32)
    32




    4.3.2 唱片表


    字段名
    字段码
    数据类型
    数据长度
    备注
    主键




    唱片ID
    albumid
    bigint


    X


    唱片名
    albumname
    varchar(20)
    20




    唱片大图
    albumpic_big
    varchar(255)
    255




    唱片小图
    albumpic_small
    varchar(255)
    255




    4.3.3 歌手表


    字段名
    字段码
    数据类型
    数据长度
    备注
    主键




    歌手ID
    singer_id
    bigint


    X


    歌手名
    singername
    varchar(20)
    20




    4.3.4 评论表


    字段名
    字段码
    数据类型
    数据长度
    备注
    主键




    评论ID
    comment_id
    bigint


    X


    用户ID
    user_id
    bigint





    ID
    songid
    bigint





    评论内容
    content
    varchar(517)
    517




    时间
    data
    date





    对应的评论的id
    to_comment_id
    bigint





    用户表


    字段名
    字段码
    数据类型
    数据长度
    备注
    主键




    用户ID
    user_id
    bigint


    X


    用户名
    user_name
    varchar(255)
    255




    4.4 目录结构设计4.4.1 RUP面向对象设计模式的可视化建模用例视图

    4.4.2 客户端工程文件目录图
    目录文件说明:

    Adapter:存放各种适配器
    Aidl:存放在不同进程间传递的Entity
    Application:存放Android的Application
    Contract:存放一下比如URl或者常量
    MVP

    base:存放BaseModle,BasePresent的接口和抽象类其他基于MVP模式的模块
    Interfac:存放一下监听接口
    Service:存放Android的Service
    Tool:存放一下工具类
    Weight:存放一下自定义的控件

    4.4.3 服务端工程文件目录图
    目录文件解释:

    controller:存放控制类,即各个请求相应的逻辑处理
    bean:存放数据实体类Entity
    util:存放开发的公共资源处理类和工具类
    repository:DAO层接口
    service:service层
    annotation:注解处理器
    map:Mybatis的Mapper
    Modle:Modle层
    tool:工具类

    5 系统详细设计5.1 系统时序图5.1.1 播放音乐
    5.2 系统界面及其核心代码5.2.1 播放器界面的实现
    播放界面的xml代码:

    播放控制代码:(播放器和界面分开为两个进程,界面使用AIDL远程控制播放器的进程)


    AIDL接口(通过在AIDL接口定义一个注册监听器的方法使得界面的进程可以接收到播放界面进程的返回参数,然后可以根据参数判断播放进程的状态):


    关键代码如下(歌词主要是通过一个Recycleview实现,通过解析lrc文件获取歌词和不同的时间段中间的歌词位置):


    播放列表主要使用Popwindwos实现,弹出播放列表的时候播放背景变灰,然后监控背景的点击事件,当被点击时播放列表收回,同时还为弹出很收回设置动画,用于获得更好的用户体验。
    关键代码:


    Android使用sharePrefrence来保存本地音乐列表,要获取本地音乐只需要扫描本地的sharePrefrence获取本地的音乐,为了保证主线程不被阻塞,使用AsynTask进行扫描数据,在OnpostExcute刷新界面数据。
    关键代码:



    分享歌曲是通过Android的系统分享途径分享音乐。
    关键代码:

    同时还可以删除音乐,通过删除音乐文件然后重新扫描本地歌曲的方法来删除歌曲;设置为铃声,通过Android系统提供的方法进行设置,这个需要Android系统的写入权限来实现。



    本系统是使用百度音乐API来获取音乐榜单,主要分类有:百度热歌榜,百度新歌榜,华语金曲榜,欧美金曲榜,情歌对唱榜,网络歌曲榜,经典老歌榜,摇滚榜,KTV热歌榜,Billboard,Hito中文版,叱咤歌曲榜等十二个榜单,适应更多用户的需求。列表的封面使用榜单第一名的歌曲,榜单显示全三场的歌曲的名字和歌手。
    关键代码:


    榜单详情使用Google原生的MaterialDesign风格,头部是可折叠的ToolBar,下面是一个RecycleView。
    界面详情:


    分享的实现很本地歌曲的分享是一样的,都是通过Android系统分享的途径来进行分享歌曲,同时也可以支持很多平台的分享,包括当前最流行的QQ和微信。
    关键代码:


    下载歌曲时会判断当前的网络状态,假如时使用移动网络那么会提醒是否要继续下载。
    代码实现:


    下载歌曲时会在通知栏显示下载内容和进度,这是调用系统的DownloadManger实现。
    关键代码:


    当DownloadManger下载完成后会有一个回调,可以通过回调来刷新本地歌曲的列表。
    关键代码:


    Android端可以通过播放界面的菜单进行评论歌曲,当点击发送时会向服务器发送该歌曲的ID和评论内容还有当点的登陆的user,所以要使用该功能必须要登陆以后,代码中的Contract.TOKEN是当用户登陆之后服务器返回的一串token值。
    关键代码:


    用户可以点击评论然后输入内容对已有的评论进行评论。

    在主菜单界面有天气的功能,这个是继承了高德地图API的定位服务和天气服务,首先先定位用户的经纬度,然后将经纬度发送给高德地图服务后台来获取当前的天气状况。
    关键代码:




    这是登陆和注册页面,登陆和注册页面可以相互切换,登陆只需要用户名和密码,点击登录后,Android端会向后台发送登陆验证,假如验证成功,就会向Android端返回一串TOKEN值,当使用到必须要登陆才能使用的服务比如评论歌曲时,Android端会给服务器的请求Http的header里面添加TOKEN值,服务器通过这串TOKEN值解析出用户,然后进行其他相关操作,同时Android端有一个记住密码的功能,只要用户有登陆成功,那么Android端就会在SharePrefernce报错密码和用户名。下次再次点击登录的时候就可以直接显示用户名和密码,方便用户操作。
    关键代码:


    搜索歌曲也是使用百度音乐API接口,可以根据歌手名称,歌曲名等相关联的进行搜索。当点击搜索结果时就可以听该歌曲。
    关键代码:

    6 系统测试6.1 软件测试常识及主要技术软件测试是在规定的条件下对程序进行操作,以发现程序错误,衡量软件质量,并对其是否能满足设计要求进行评估的过程。 从软件开发者的角度出发,希望表明软件产品不存在错误和缺陷,验证软件能正确地实现用户需用户求,确立人们对软件质量的信心。从用户角度出发,希望通过软件测试暴露软件隐藏的错误和缺陷,从而考虑是否接受该产品。一般来说软件测试应由独立的产品评测中心负责,严格按照软件测试流程,制定测试计划、测试方案、测试规范,实施测试,对测试记录进行分析,并根据回归测试情况撰写测试报告。测试是为了证明程序有错,而不能保证程序没有错误。
    测试工具介绍:
    Monkey是Android SDK自带的测试工具,在测试过程中会向系统发送伪随机的用户事件流,手势输入,触摸屏输入,如按键输入等,它实现对正在开发的应用程序进行压力测试,也有日志输出。实际上该工具只能做程序做一些压力测试,由于测试事件和数据都是随机的,不能自定义,所以有很大的局限性。
    MonkeyRunner类似于Monkey,它们都是Android SDK原有的。严格意义上来说MonkeyRunner其实是一个Api工具包,比Monkey强大,可以编写测试脚本来自定义数据、事件。但是MonkeyRunner的脚本是用Python来写,这样无疑会加重测试人员的负担。
    Instrumentation是早期Google提供的Android自动化测试工具类,相对于Junit Instrumentation允许你对应用程序做更为复杂的测试,甚至是框架层面的。通过Instrumentation你可以模拟按键按下、抬起、屏幕点击、滚动等事件而JUint几乎都是进行简单的方法测试。Instrumentation是通过将主程序和测试程序运行在同一个进程来实现这些功能,你可以把Instrumentation看成一个类似Activity或者Service并且不带界面的组件,在程序运行期间监控你的主程序。缺点是对测试人员来说编写代码能力要求较高,需要对Android相关知识有一定了解,还需要配置AndroidManifest.xml文件,但是它存在一个缺点就是不可以同一套测试方法只能在一个APP上使用。
    主要测试技术和方法介绍:
    黑盒测试,软件测试的主要方法之一,也可以称为功能测试、数据驱动测试或基于规格说明的测试。测试者不了解程序的内部情况,不需具备应用程序的代码、内部结构和编程语言的专门知识。在黑盒测试中,被测对象的内部结构,运作情况对测试人员是不可见的,测试人员对测试产品的验证主要是根据其规格,验证其与规格一致性。就像对一台自动售货机,为了验证其能否自动售出货物,你可以指定需要购买的物品,塞入钱币,然后观测售货机能否输出正确的货物并找出正确的零钱。在这个过程中你不需要关注自动售货机是如何判定钱币数额,如何选择货物,如何找出零钱等内部操作。这是白盒测试关注的范围,黑盒测试关注的是结果。
    此测试方法可适合大部分的软件测试,如集成测试(integration testing)以及系统测试(system testing)。
    白盒测试(white-box testing)又称透明盒测试(glass box testing)、结构测试(structural testing)等,软件测试的主要方法之一,也称结构测试、逻辑驱动测试或基于程序本身的测试。白盒测试(white-box testing)分为逻辑驱动测试:(语句覆盖,判定覆盖(分支覆盖),条件覆盖,判定/条件覆盖,条件组合覆盖)和基本路径测试。
    白盒测试可以应用于单元测试(unit testing)、集成测试(integration testing)和系统的软件测试流程,可测试在集成过程中每一单元之间的路径,或者主系统跟子系统中的测试。尽管这种测试的方法可以发现许多的错误或问题,它可能无法检测未使用部分的规范。
    6.2 测试用例及结果6.2.1 播放音乐


    Step Name
    Description
    Expected Result




    Step 1
    打开APP
    系统进入音乐播放界面


    Step 2
    点击播放音乐按钮
    系统开始播放音乐


    Step3
    点击播放上一首
    系统播放上一首音乐


    Step4
    点击播放下一首
    系统播放下一首音乐


    Step4
    点击暂停
    系统暂停播放音乐


    Stpe5
    点击歌词
    系统切换到歌词界面


    Step6
    拖动进度条
    系统播放对一个进度的音乐



    6.2.2 评论歌曲


    Step Name
    Description
    Expected Result




    Step 1
    打开APP
    系统进入音乐播放界面


    Step 2
    点击右边菜单栏
    系统展开菜单


    Step 3
    点击登录
    系统进入登录界面


    Step 4
    输入用户名和密码点击登录
    系统显示登录成功


    Step 5
    返回点击唱片图片
    系统进入播放界面


    Step 6
    点击菜单按钮选择评论
    系统进入评论界面


    Step 7
    在输入框输入评论内容发送
    系统显示新增的评论



    6.2.3 下载歌曲


    Step Name
    Description
    Expected Result




    Step 1
    打开APP
    系统进入音乐播放界面


    Step 2
    点击在线音乐
    系统进入在线音乐节目


    Step 3
    点击新歌榜
    系统进入新歌榜单


    Step 4
    点击第一首音乐点击菜单
    系统显示菜单界面


    Step 5
    点击下载音乐
    系统添加下载任务



    7 总结与展望7.1 总结本系统是基于Android的音乐播放器的设计与实现,本系统实现音乐播放器的基本功能,同时也拥有不错的界面设计。论文首先从现在Android音乐播放器的现状说起,分析音乐播放器的需求,然后对整个系统进行分析和设计,接下来就是代码实现,最后再用测试样本进行测试,以验证其可行性。
    尽管本系统实现了音乐播放器的基本功能但是还是有很多不足之处,比如说本系统只集成百度音乐API而不是各个平台的音乐API,因为版权关系,各家音乐播放器拥有不同的版权,导致很多用户需要下载多个音乐播放器才能满足日常需求,加入可以加入各个平台的音乐API就可以为用户提供更好的服务。其次,本系统缺少比较新颖的功能比如说听歌识曲和歌单等,新颖的功能无疑可以更加吸引用户。后台服务只是本地服务导致评论歌曲的功能在不同局域网的手机无法连接。
    7.2 展望正如上面所说本系统还存在各种不足之处,对此对如何改进各种不足做出展望:

    集成更多平台的音乐API
    利用第三方平台开发听过识曲等新颖功能
    买入阿里云服务器,上线服务

    参考文献[1] Android 开发者官网https://developer.android.com/index.html
    [2] Retrofit官网https://square.github.io/retrofit/
    [3] RxJava官网https://github.com/ReactiveX/RxJava
    [4] SpringBoot官网https://projects.spring.io/spring-boot/
    [5] MyBatis官网 http://www.mybatis.org/mybatis-3/zh/index.html
    [6] Mysql 官网 https://www.mysql.com/
    [7] Glide 官网 https://github.com/bumptech/glide
    [8] 《第一行代码Android》郭霖 人民邮电出版社2016.12
    [9] 《Android开发艺术探索》任玉刚电子工业出版社 2015.9
    [10] 《轻量级Java Web整合开发入门》李占波 清华大学出版社 2015.9.1
    [11] 《Spring MVC实战》张龙、覃璐、李哲、丁涛译电子工业出版社 2017.5.1
    [12] 《MyBatis技术内幕》徐郡明 电子工业出版社 2017.6.1
    [13] 《Android源码设计模式解析与实战》何红辉、关爱民 人民邮电出版社 2017.7
    [14] 《Android开发模式和最佳实战》菲尔 达特森 电子工业出版社 2017.2.1
    [15] 《软件工程》萨默维尔 机械工业出版社 2011.5.1
    1 评论 3 下载 2020-03-30 08:28:34 下载需要20点积分
  • JAVA实现基于k-means聚类算法实现微博舆情热点分析系统

    摘要微博在这短短几年时间内发展迅速,成为了传播信息的一种很重要的载体,仅新浪微博注册用户早已超过3亿,每日发博量超过1亿条,微博是研究大量舆情信息的最佳场所。微博中如此大的信息量,必然要对信息进行甄选,这是很自然的需求,所以以原始驱动为出发点,从数亿网民之中找到热点话题。监督规范网络行为,净化网络环境,更重要的还能从中获取各类有用信息,进行诸如商业价值(用户兴趣挖掘),信息传播学(网络拓扑与热点追踪),以及一些社会学方面的研究。从而能够满足人们的需求,同时对于社会的和谐、网络舆论生态的健康、国家的发展都有重要的现实意义。
    微博舆情分析系统就是来实现热点事件的挖掘与分析,本文首先介绍了舆情分析的理论基础和一些相关算法,然后是对整个系统从零到整的完整开发记录,最后是通过本软件分析出微博的热点事件。
    关键词:微博,舆情分析,向量空间模型,k-means聚类算法
    AbstractWeibo in this few yearshas developed rapidly, and become a important tools th at spread information,only the user of sina weibo has more than 300 million, daily s end Weibo are more than 100 million, weibo is the best place to study a lotof public information. The weibo so large amount ofinformation, is bound to the infor mation select ion,it is very natural demand, so to the original drive as a starting point, find hot topi cs from among hundre ds of millions ofInternet users. Supervision and stand ard netw ork behavior,purify network environment, the more important of this can o btain all ki nds of useful information, such as business value (user)interested in mini ng, information and communication (network topologyand the hot spot tracking), as well as some sociological research. So that they can meet people’s needs, at the sam e time forsoci al harmony, ecological health network public opinion, the country’s development has important practical significance.
    Microblogging public opinion analysis system is toimplement the hot issues mi ning and analysis,firstly ,this paper introduces the basic theory of public opinion ana lysis and some related algorithms, and then introduce how to build thewhole system, finally, through the software analysis themicroblogging hot issues.
    KeyWords: Weibo,public opinion analysis, vectorspace model, k-means
    第一章 引言1.1 研究背景及意义微博在这短短几年时间内发展迅速,成为了群主传播信息的一种很重要的载体,仅新浪微博注册用户早已超过3亿,每日发博量超过1亿条,微博是研究大量舆情信息的最佳场所。微博中如此大的信息量,必然要对信息进行甄选,这是很自然的需求,所以以原始驱动为出发点,从数亿网民之中找到热点话题。监督规范网络行为,净化网络环境,更重要的还能从中获取各类有用信息,进行诸如商业价值(用户兴趣挖掘),信息传播学(网络拓扑与热点追踪),以及一些社会学方面的研究。从而能够满足人们的需求,同时对于社会的和谐、网络舆论生态的健康、国家的发展都有重要的现实意义。
    本系统侧重于关于人际关系网络的热点分析,目标是可以迅速找到用户周边圈子内的热点事件,依靠周围用户周边圈子的茹着度来满足用户的信息获取需求。
    1.2 国内外相关问题研究现状舆情挖掘是以话题检测与跟踪的相关技术为理论前提进行发展的。1996年,为了更好的解决网络背景下事件的提取问题,美国国防高级研究计划局(DARPA)提出了话题检测与跟踪(Topic Detection and Tracking)即TDT任务。TDT就是面向多语言文本和语音形式的新闻报道,主要从事报道边界自动识别、锁定和收集突发性新闻话题、跟踪话题发展以及跨语言检测与跟踪等相关任务。为了更好的解决TDT的相关问题,国内外诸多研究团队提出了许多不同算法,并取得了较为不错的结果。
    在国外TDT的早期研究中,主要是以Allan[ 1]和Lam[2]的研究为代表。其中 Allan等人提出了single-pass算法,但是因为随着事件的发展,同一事件可能会因为报道侧重点的不同而被定义为不同的事件,因而这种方法会产生很高的误判。
    Lam等人提出用新闻簇来代替单一文档作为类,这种方法因为事件的重点分散同样存在很高的误判。
    在TDT后续的研究中,对命名实体的改进技术是一个主要的方向。Yang[3] 等人最早引入了命名实体的概念。他们对命名实体进行分类,直接对地点类的命名实体特征赋予四倍的权重。这种权重计算存在很大的主观因素,使得该算法在大部分环境下不稳定。Giridhar[4]等人随后为了改善这种不稳定性,提出将报道分为包含全部特征的向量、仅包含NE特征的向量和排除NE特征的向量三种向量空间。提出要分情况应用命名实体。但由于分类依旧过于简单,所以在结果的准确率上受到很大的制约。很多研究对文本表示形式进行了改进。Yang[5]等人在划分报道类别的基础上,只选择对类别中最优的报道进行数学描述。并且指出在离线检测的情况下应用组平均的算法(GAC)效果较好;而对于在线式检测则应用单路径聚类(1NCR)效果较好。Brants[6]等人在基于原有算法思想的基础上对文档间相似度和增量式TFIDF模型进行进一步的改进。还有一些研究是对关键词提取方法的改进。比如:Christian Wartena和RogierBrussee[7]提出通过提取关键词并对关键词基于不同的相似度量应用k-bisecting算法进行聚类,并提出使用Jensen-Shannon距离来代替余弦相似度量可以得到更好的结果。该改进算法在Wikipedia中进行检测显示该聚类与Wikipedia固有的分类保持高度的一致性。
    TDT算法中的一个重要的发展就是语义链的研究,Stocks[8]在基于语义链的思想上提出从两种对文本内容的不同表示中分别提取特征,并结合建立文本表示。
    Hath[9]等人在构造语义链时结合词典信息(WordNet)和文本的上下文信息,在语义链的文本表示下应用单路径聚类解决事件检测的问题。Ulli Waltinger[ 101提出一种新概念的语义链模型,即建立了一种基于在线的应用多语料库的模型,来弥补单一语料库资料有限片面的缺点,在一定程度上改善了词义混淆的现象。
    相对于国外在该领域的研究,国内的相关研究起步较晚。贾自艳[11]较早的在TDT中引入了命名实体的方法,他将文本中的信息按人名,地名等特征进行分类标记,并分别赋予不同类别不同的加权系数,在计算文本特征权重时,将特征的词频和所属类别的加权系数的乘积作为最后的权重。清华大学的张阔[12]等人利用2分布对 TDT语料中命名实体和话题类别间的关联性进行统计。详细的区分了各种类别的 NE同各类新闻报道的联系。该算法在TDT数据集上的结果取得了很大的改善。除了对命名实体的改进外,国内很多研究还侧重于改善文本的应用质量。哈尔滨工业大学的洪宇[13]等人提出将话题化为不同的子话题的分治匹配方法,通过句子间相关度的下降坡度识别子话题边界。其后在各子话题间建立话题识别模型,不仅有效地避免了由子话题互为噪声而产生的歧义,而且对于一篇报道多个话题的现象提出了一种有效地切分方法。
    在语义链方向,文献[14]提出将文档结构和语义特性结合来提取重要词语和文档聚类,并且将传统的语义聚类模型进行了改进,对标题,关键词和摘要的相似度进行单独计算并考虑到聚类模型之中。文献[15]的主要贡献是应用DSLM(dependency structure language model)模型[16]代替传统的一元或二元模型,并将时间信息添加进模型中来增加新闻与相应话题之间相似度的准确性。其中DSLM模型克服了TDT中一元和二元语言模型的表述制,它的结构是从数学模型角度进行描述的,并扩展一些简单的语义信息。话题模型层次化和结构化是目前TDT领域重要的研究方向。其中,层次化面向将同一话题下的相关报道组织为宏观到具体的层次体系;结构化则侧重挖掘和表征同一话题的不同侧面。国内尝试建立层次化话题模型的研究来自骆卫华[17]和张阔[18]。前者首先基于时序关系对报道分组,然后进行组内自底向上的层次聚类,最后按时间顺序采用单路径聚类策略合并相关类;后者则面向报道全集建立层次化的索引树,树中第一层节点对应特定话题,而其子树则描述了该话题的层次体系,其建树过程基于输入的报道相对于树中各层次节点是否为新事件进行组织[19]。
    国内在该领域还有其它一些较新的研究方向,比如:基于容错集进行话题聚类[20] 通过容错集模型(TRSM)有效的减少了在脱机情况下,由“噪音”引起的话题漂移;文献[21]提出了针对互联网环境下论坛网页的方法,通过设置两层选择框架综合考虑文本间的相似度和用户的活跃度,来改善论坛网页中语言非正式带来的困难;文献[22]提出了处理新闻事件的改进算法,文中指出,新闻事件不同于话题的是随着时间持续一段时间内话题会变得没有价值,而新闻事件会转化为有价值的记录。
    1.3 论文的理论意义与实用价值本系统以新浪微博为信息源,以新浪微博的一个用户为起始点,获取与挖掘以该用户为中心的人际网络之间的热点事件,以匹配到用户的最佳兴趣点。不仅仅进行诸如商业价值(用户兴趣挖掘),信息传播学(网络拓扑与热点追踪),以及一些社会学方面的研究。从而能够满足人们的需求,同时对于社会的和谐、网络舆论生态的健康、国家的发展都有重要的现实意义。
    第二章 相关技术介绍2.1 开发平台简述2.1.1 Eclipse简介课题是在Eclipse上编译和调试的应用程序,下面简单介绍Eclipse信息:
    Eclipse简介:Eclipse是一个开放源代码的、基于Java的可扩展开发平台,对eclipse而言,它仅是是一个框架和一组服务,可以通过各种各样的插件和组件来搭建开发环境。
    Eclipse的目标不仅是将其当做Java IDE来使用,还要利用其插件开发环境 (Plug-in DevelopmentEnvironment, PDE),通过开发各种插件来扩展Eclipse的软件开发人员,这使软件开发人员能构建与Eclipse环境无缝集成的工具。
    Eclipse最初是替代由IBM公司开发的价值四千万美金的商业软件Visual Age for Java的下一代IDE开发环境,2001年11月交给非营利软件供应商联盟Eclipse 基金会(Eclipse Foundation)管理。2003年,Eclipse 3.0选择OSGi服务平台规范为运行时架构。
    Eclipse采用的技术是IBM公司开发的((SWT),这种技术基于Java的窗口组件,类似Java本身提供的AWT和Swing窗口组件。Eclipse的用户界面还使用了 GUI中间层JFace,这样一来大大简化了基于SWT的应用程序的构建。
    Eclipse的插件机制是轻型软件组件化架构。在RCP平台上,Eclipse使用软件人员开发的各种插件来提供所有的附加功能,例如android的ADT插件,这使得软件开发人员能使用Eclipse来编译android应用软件,完成软件的编译测试还有调试等工作。还有的插件不仅能支持JAVA,还可以支持C/C++(CDT)、 PerLRuby, P帅ont和数据库开发。这种插件架构带来非常多的便利,能够支持任意的扩展使其加入到当前的开发环境中,缩短开发周期,节约金钱。
    2.1.2 新浪微博api新浪微博API是新浪为了方便第三方应用接入微博这个大系统而开放的API, 有了这个API我就不用重新写爬虫程序获取新浪微博上的大量微博,直接调用新浪微博的API完成我的扒取任务。
    新浪微博api的验证登陆方式是OAuth2.0方式,现在对OAuth2.0进行简要介
    2.2 OAuth2.0简介由于需要使用新浪api替代网络爬虫来进行数据收集,所以在介绍了新浪api 之后,我们队新浪api的代理接入方法做介绍即OAuth2.0。
    1.OAuth前言
    OAuth 1.0已经在IETF尘埃落定,编号是RFC5849,这也标志着OAuth已经正式成为互联网标准协议。OAuth2.0早已经开始讨论和建立的草案。OAuth2. 0很可能是下一代的“用户验证和授权”标准。现在百度开放平台,腾讯开放平台,新浪微博开放平台等大部分的开放平台都是使用的OAuth 2. 0协议作为支撑。
    OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。
    2.OAuth
    允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要分享他们的访问许可或他们数据的所有内容。
    OAuth是OpenID的一个补充,但是完全不同的服务。OAuth 2. 0是OAuth协议的下一版本,但不向后兼容OAuth 1. 00 OAuth2. 0 关注客户端开发者的简易性,同时为Web应用,桌面应用和手机,和起居室设备提供专门的认证流程。
    Facebook的新的Graph API只支持OAuth2.0, Google在2011年3月亦宣布 Google API对OAuth 2. 0的支援。
    3.认证和授权过程
    在认证和授权的过程中涉及的三方包括:

    服务提供方,用户使用服务提供方来存储受保护的资源,如照片,视频,联系人列表。
    用户,存放在服务提供方的受保护的资源的拥有者。
    客户端,要访问服务提供方资源的第三方应用,通常是网站,如提供照片打印服务的网站。在认证过程之前,客户端要向服务提供者申请客户端标识。

    使用OAuth进行认证和授权的过程如下所示:

    用户访问客户端的网站,想操作用户存放在服务提供方的资源。 客户端向服务提供方请求一个临时令牌。服务提供方验证客户端的身份后,授予一个临时令牌。
    客户端获得临时令牌后,将用户引导至服务提供方的授权页面请求用户授权。在这个过程中将临时令牌和客户端的回调连接发送给服务提供方。
    用户在服务提供方的网页上输入用户名和密码,然后授权该客户端访问所请求的资源。
    授权成功后,服务提供方引导用户返回客户端的网页。
    客户端根据临时令牌从服务提供方那里获取访问令牌。
    服务提供方根据临时令牌和用户的授权情况授予客户端访问令牌。
    客户端使用获取的访问令牌访问存放在服务提供方上的受保护的资源。

    4.历史回顾
    OAuth 1.0在2007年的12月底发布并迅速成为工业标准。
    2008年6月,发布了OAuth 1.0Revision A,这是个稍作修改的修订版本,主要修正一个安全方面的漏洞。
    2010年四月,OAuth 1.0的终于在IETF发布了,协议编号RFC 5849。 OAuth 2. 0的草案是在2011年5月初在IETF发布的。
    OAuth是个安全相关的协议,作用在于,使用户授权第三方的应用程序访问用户的web资源,并且不需要向第三方应用程序透露自己的密码。
    OAuth2.0是个全新的协议,并且不对之前的版本做向后兼容,然而,OAuth2.0 保留了与之前版本OAuth相同的整体架构。
    这个草案是围绕着OAuth2. 0的需求和目标,历经了长达一年的讨论,讨论的参与者来自业界的各个知名公司,包括Yahoo!, Facebook, Salesforce, Microsoft, Twitter, Deutsche Telekom, Intuit,Mozilla, 和 Google。
    2.3 空间向量模型向量空间模型(VSM: Vector Space Model)由Salton等人于20世纪70年代提出,并成功地应用于著名的SMART文本检索系统。
    VSM概念简单,把对文本内容的处理简化为向量空间中的向量运算,并且它以空间上的相似度表达语义的相似度,直观易懂。当文档被表示为文档空间的向量,就可以通过计算向量之间的相似性来度量文档间的相似性。文本处理中最常用的相似性度量方式是余弦距离。
    M个无序特征项ti,词根/词/短语/其他每个文档dj可以用特征项向量来表示(a1j, a2j, …, aMj)权重计算,N个训练文档AM*N= (aij)文档相似度比较。

    Cosine计算,余弦计算的好处是,正好是一个介于0到1的数,如果向量一致就是1,如果正交就是0,符合相似度百分比的特性,余弦的计算方法为,向量内积/各个向量的模的乘积。内积计算,直接计算内积,计算强度低,但是误差大。
    向量空间模型(或词组向量模型)是一个应用于信息过滤,信息撷取,索引以及评估相关性的代数模型。SMART是首个使用这个模型的信息检索系统。
    文件(语料)被视为索引词(关键词)形成的多次元向量空间,索引词的集合通常为文件中至少出现过一次的词组。
    搜寻时,输入的检索词也被转换成类似于文件的向量,这个模型假设,文件和搜寻词的相关程度,可以经由比较每个文件(向量)和检索词(向量)的夹角偏差程度而得知。
    实际上,计算夹角向量之间的余弦比直接计算夹角容易:
    余弦为零表示检索词向量垂直于文件向量,即没有符合,也就是说该文件不含此检索词。
    通过上述的向量空间模型,文本数据就转换成了计算机可以处理的结构化数据,两个文档之间的相似性问题转变成了两个向量之间的相似性问题。
    本文中使用空间向量模型主要用于下面2个目的:

    使用向量表示微博文档
    借以来判断2条微博的相似性

    下面详细介绍如何实现:
    1.向量表示文档
    首先,我们知道任何一条微博都是由单词构成的,我们在最初之时就构建了一个包含全部文档集合的词典,只要文档集合中出现了的单词,我们的词典之中就会有。于是我们根据词典里面单词的个数N构建出一个N维的向量\<al, a2, a3, ..., an\>,对于每一个文档都有这样的转换:
    文档A对应的向量A=\<al ,a2, a3, ..., an\>;若ai !=0,则表示ai这个单词在这个文档中出现,反之则不出现,这样我们就将文档向量化了。
    2.相似性计算
    余弦距离经常被用在文本相似性比较中。余弦结果为一个0到1的数,1表示向量一致,0则表示正交,符合相似性百分比的特性。不同文档长度的归一化是通过计算向量内积与文档向量的长度的比值实现的,即前提是忽略文档向量长度的影响。
    比如:比较的两个文档是
    D=(d1, d2, d3, ..., dn)Q=(Q1, Q2, Q3, ..., Qn)则他们之间的距离是:

    但是要是仅仅由余弦来判定距离那是有一定的误差的,原因如下:
    在构建向量的时候单词之间的权重是不一样的,我们直接按照单词出现或者不出现来构建向量是与原本的向量有一定的误差,所以我们还需要按照权值给文档向量化。
    这里我们使用TF-IDF(Term Frequency-Inverse Document Frequency)权重计算相结合的方法。TF-IDF (term frequencyinverse document frequency)是一种用于资讯检索与资讯探勘的常用加权技术。TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。 TF-IDF加权的各种形式常被搜索引擎应用,作为文件与用户查询之间相关程度的度量或评级。除了TF-IDF以外,因特网上的搜索引擎还会使用基于链接分析的评级方法,以确定文件在搜寻结果中出现的顺序。
    TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。TFIDF实际上是:TF*IDF, TF词频(Term Frequency),IDF反文档频率(Inverse Document Frequency)。 TF表示词条在文档d中出现的频率。IDF的主要思想是:如果包含词条t的文档越少,也就是n越小,IDF越大,则说明词条t 具有很好的类别区分能力。如果某一类文档C中包含词条t的文档数为m,而其它类包含t的文档总数为k,显然所有包含t的文档数n=m+k,当m大的时候,n 也大,按照IDF公式得到的IDF的值会小,就说明该词条t类别区分能力不强。但是实际上,如果一个词条在一个类的文档中频繁出现,则说明该词条能够很好代表这个类的文本的特征,这样的词条应该给它们赋予较高的权重,并选来作为该类文本的特征词以区别与其它类文档。这就是IDF的不足之处。
    TFIDF的原理是:在一份给定的文件里,词频((term frequency, TF)指的是某一个给定的词语在该文件中出现的次数。这个数字通常会被归一化,以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词频,而不管该词语重要与否。)
    逆向文件频率((inversedocument frequency, IDF)是一个词语普遍重要性的度量。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。
    某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于保留文档中较为特别的词语,过滤常用词。
    2.4 文本聚类算法文本聚类(Text clustering)文档聚类主要是依据著名的聚类假设:同类的文档相似度较大,而不同类的文档相似度较小。作为一种无监督的机器学习方法,聚类由于不需要训练过程,以及不需要预先对文档手工标注类别,因此具有一定的灵活性和较高的自动化处理能力,已经成为对文本信息进行有效地组织、摘要和导航的重要手段,为越来越多的研究人员所关注。
    文本聚类的算法主要有如下几类:
    1.划分法(partitioning methods)
    给定一个有N个元组或者纪录的数据集,分裂法将构造K个分组,每一个分组就代表一个聚类,K<N。而且这K个分组满足下列条件:

    每一个分组至少包含一个数据纪录;
    每一个数据纪录属于且仅属于一个分组(注意:这个要求在某些模糊聚类算法中可以放宽);

    对于给定的K,算法首先给出一个初始的分组方法,以后通过反复迭代的方法改变分组,使得每一次改进之后的分组方案都较前一次好,而所谓好的标准就是:同一分组中的记录越近越好,而不同分组中的纪录越远越好。
    使用这个基本思想的算法有:K-MEANS算法、K-MEDOIDS算法、CLARANS 算法;
    2.层次法(hierarchical methods)
    这种方法对给定的数据集进行层次似的分解,直到某种条件满足为止。具体又可分为“自底向上”和“自顶向下”两种方案。例如在“自底向上” 方案中,初始时每一个数据纪录都组成一个单独的组,在接下来的迭代中,它把那些相互邻近的组合并成一个组,直到所有的记录组成一个分组或者某个条件满足为止。代表算法有:BIRCH算法、CURE算法、CHAMELEON算法等;
    3.基于密度的方法(density-based methods)
    基于密度的方法与其它方法的一个根本区别是:它不是基于各种各样的距离的,而是基于密度的。这样就能克服基于距离的算法只能发现“类圆形” 的聚类的缺点。这个方法的指导思想就是,只要一个区域中的点的密度大过某个阀值,就把它加到与之相近的聚类中去。代表算法有:DBSCAN算法、OPTICS算法、DENCLUE算法等;
    4.基于网格的方法(grid-based methods)
    这种方法首先将数据空间划分成为有限个单元(cell)的网格结构,所有的处理都是以单个的单元为对象的。这么处理的一个突出的优点就是处理速度很快,通常这是与目标数据库中记录的个数无关的,它只与把数据空间分为多少个单元有关。代表算法有:STING算法、CLQUE算法、 WAVE-CLUSTER算法;
    5.基于模型的方法(model-basedmethods)
    基于模型的方法给每一个聚类假定一个模型,然后去寻找一个能很好的满足这个模型的数据集。这样一个模型可能是数据点在空间中的密度分布函数或者其它。它的一个潜在的假定就是:目标数据集是由一系列的概率分布所决定的。通常有两种尝试方向:统计的方案和神经网络的方案;
    这里我们使用的k-means算法进行聚类。k-means描述如下:
    K-means算法是很典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。k个初始类聚类中心点的选取对聚类结果具有较大的影响,因为在该算法第一步中是随机的选取任意k个对象作为初始聚类的中心,初始地代表一个簇。该算法在每次迭代中对数据集中剩余的每个对象,根据其与各个簇中心的距离将每个对象重新赋给最近的簇。当考察完所有数据对象后,一次迭代运算完成,新的聚类中心被计算出来。如果在一次迭代前后,J的值没有发生变化,说明算法已经收敛。
    算法过程如下:

    从N个文档随机选取K个文档作为质心
    对剩余的每个文档测量其到每个质心的距离,并把它归到最近的质心的类
    重新计算已经得到的各个类的质心
    迭代2~3步直至新的质心与原质心相等或小于指定阂值,算法结束

    具体如下,输入:k, data[n];

    选择k个初始中心点,例如c[0]=data[0], …c[k-1]=data[k-1];
    对于data [0]…data [n],分别与c[0]…c[k-1]比较,假定与C [i]差值最少,就标记为1;
    对于所有标记为1点,重新计算c [i]={所有标记为1的data[j]之和}/ 标记为1的个数;
    重复(2) (3),直到所有c [i]值的变化小于给定阂值。

    2.5 数据库方案该系统的数据库服务器采用比较适合中型数据量的mysql。
    2.5.1 MYSQL简介MySQL是一个开放源码的小型关联式数据库管理系统,开发者为瑞典MySQL AB 公司。目前MySQL被广泛地应用在Internet上的中小型网站中。由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,许多中小型网站为了降低网站总体拥有成本而选择了MySQL作为网站数据库。
    2.5.2 MYSQL背景MySQL最初的开发者的意图是用mSQL和他们自己的快速低级例程(ISAM)去连接表格。经过一些测试后,开发者得出结论:mSQL并没有他们需要的那么快活。这导致了一个使用几乎和mSQL一样的API接口的用于他们的数据库的新的 SQL接口的产生,这样,这个API被设计成允许为用于mSQL而写的第三方代码更容易移植到MySQL。
    MySQL这个名字是怎么来的已经不清楚了。基本指南和大量的库和工具带有前缀 “my”已经有10年以上,而且不管怎样,MySQL AB创始人之一Michael Widenius 的女儿也叫My。这两个到底是哪一个给出了MySQL这个名字至今依然是个迷,包括开发者在内也不知道。
    MySQL的海豚标志的名字叫“sak i la”,代表速度、力量、精确,它是由MySQL AB的创始人从用户在“海豚命名”的竞赛中建议的大量的名字表中选出的。获胜的名字是由来自非洲斯威士兰的开源软件开发者Ambrose Twebaze提供。根据 Ambrose所说,Sakila来自一种叫SiSwati的斯威士兰方言,也是在Ambrose的家乡乌干达附近的坦桑尼亚的Arusha的一个小镇的名字。
    2008年1月16号MySQL AB被Sun公司收购。而2009年,SUN又被Oracle 收购。就这样如同一个轮回,MySQL成为了Oracle公司的另一个数据库项目。
    2.5.3 MYSQL系统特性
    使用C和C++编写,并使用了多种编译器进行测试,保证源代码的可移植性
    支持AIX、FreeBSD、 HP-UX、 Linux、MacOS、NovellNetware、 OpenBSD、OS/2 Wrap、 Solaris、 Windows等多种操作系统
    为多种编程语言提供了API。这些编程语言包括C、 C++、Python、 Java、 Perl、PHP、Eiffel、Ruby和Tcl等。
    支持多线程,充分利用CPU资源
    优化的SQL查询算法,有效地提高查询速度
    既能够作为一个单独的应用程序应用在客户端服务器网络环境中,也能够作为一个库而嵌入到其他的软件中。
    提供多语言支持,常见的编码如中文的GB 2312、BIG5、日文的Shift_JIS等都可以用作数据表名和数据列名。
    提供TCP/IP、ODBC和JDBC等多种数据库连接途径。
    提供用于管理、检查、优化数据库操作的管理工具。
    支持大型的数据库。可以处理拥有上千万条记录的大型数据库。
    支持多种存储引擎。
    第三章 系统设计3.1 热点分析策略本系统是通过根据入口用户进行分析,力求得到入口用户最喜爱的热点话题,新浪微博的一般用户都是信息接收者,而新浪微博的大量加V的明星用户有很多,他们是信息的产生着,会有巨量的粉丝关注,并且有大量的粉丝对其每条微博进行评论。
    我们可以进行假设,若是一条微博有巨量的评论数,无论是好评还是差评,那么它的关注度一定是很高的,可以从另一个方面反映出大家对这条微博所描述的事件的兴趣度,所以本系统的分析策略如下图描述:

    3.2 系统总体设计该系统重点在于数据的获取与分析,并未强调运算速度,故采用单机开发,所以本系统是PC上的一个应用程序。
    总体设计框图如图3-2所示:

    如图所示该系统总分为3个模块:

    信息获取模块:该模块从微博上获取大量相关数据,并且将这些数据进行简单的处理,建立倒排索引。
    信息处理模块:该模块主要将信息获取模块处理过的数据进行深加工,进行聚类,以及热点评价。
    数据显示模块:该模块将信息处理模块处理好的数据显示出来,供用户使用

    3.3 系统模块详细设计3.3.1 数据获取模块该模块从微博上获取大量相关数据,并且将这些数据进行简单的处理,最终建立倒排索引,插入数据库之中。内部模块如图3-3:

    新浪api:获取数据源的模块,借用新浪微博的开放平台。.微博文档:暂时存放获取数据。

    分词系统:建立词典专用。倒排索引:处理好数据,以便后面数据分析用
    3.3.1.1 分词系统微博是一条一条的文档,我们需要提取其特征指纹,我们才能将大量微博聚类,提取特征指纹,本文是使用空间向量模型,这意味着我们需要将微博划分为大量的单个的单词,这里本系统采用iK-analyzer分词器。
    IK Analyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始,IK Analyzer已经推出了4个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。从3.0版本开始,IK发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。在2012版本中,IK实现了简单的分词歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化。
    IK Analyzer 2012特性:

    采用了特有的”正向迭代最细粒度切分算法”,支持细粒度和智能分词两种切分模式;
    在系统环境:Core2 i7 3.4G双核,4G内存,window 7 64位,SunJDK1.6_29 64位普通PC环境测试,IK2012具有160万字/秒(3000KB/S)的高速处理能力。
    2012版本的智能分词模式支持简单的分词排歧义处理和数量词合并输出。
    采用了多子处理器分析模式,支持:英文字母、数字、中文词汇等分词处理,兼容韩文、日文字符。
    优化的词典存储,更小的内存占用。支持用户词典扩展定义。特别的,在2012版本,词典支持中文,英文,数字混合词语。

    分词原理,主要有三种方法:
    1.基于词典匹配的分词方法
    基于字典匹配的分词方法按照一定的匹配策略将输入的字符串与机器字典词条进行匹配,如果在词典中找到当前字符串,则成功匹配输出识别的词汇。按照匹配操作的扫描方向不同,词典匹配分词方法又可以具体分为正向匹配和逆向匹配,以及结合了两者的双向匹配算法;按照不同长度有限匹配的情况,可以分为最大(最长)匹配和最小(最短)匹配;按照是否与词性标注过程相结合,又可以分为单纯分词方法和分词与词性标注相结合的方法。集中常见的词典分词方法如下:

    正向最大匹配
    逆向最大匹配
    最少切分

    实际引用中上述方法经常组合使用,达到最好的效果,从而衍生出了结合正向最大匹配方法和逆向最大匹配的双向匹配分词法。由于中文分词最大的问题是歧义处理,结合中文语言的自身特色,经常采用逆向匹配的切分算法,处理的精度高于正向匹配,产生的切分歧义现象也少。
    2.基于语义理解的分词
    基于语义理解的分词方法是模拟人脑对语言和句子的理解,达到识别词汇单元的效果。基本模式是把分词、句法、语义分析并行进行,利用句法和语义信息来处理分词的歧义。
    一般结构中通常包括分词子系统、句法语义子系统、调度系统。在调度系统的协调下,分词子系统可以获得有关词、句子等的句法和语义信息,模拟人脑对句子的理解过程。基于语义理解的分词方法需要使用大量的语言知识和信息。
    3.基于词频统计的分词
    这种做法基于人们对中文词语的直接感受。通常词是稳定的词的组合,因此在中文文章的上下文中,相邻的字搭配出现的频率越多,就越有可能形成一个固定的词。根据n元语法知识可以知道,字与字相邻同时出现的频率或概率能够较好的反应成词的可信度。
    基于词频统计的分词方法只需要对语料中的字组频率进行统计,不需要切分词典,因而又叫做无词典分词法或者统计分词法。
    3.3.1.2 倒排索引倒排索引[23]源于实际应用中需要根据属性的值来查找记录。这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。带有倒排索引的文件我们称为倒排索引文件,简称倒排文件(inverted file)。
    在关系数据库系统里,索引是检索数据最有效率的方式,。但对于搜索引擎,它并不能满足其特殊要求:

    海量数据:搜索引擎面对的是海量数据,像Google,百度这样大型的商业搜索引擎索引都是亿级甚至几千的网页数量,面对如此海量数据,使得数据库系统很难有效的管理。
    数据操作简单:搜索引擎使用的数据操作简单,一般而言,只需要增、删、改、查几个功能,而且数据都有特定的格式,可以针对这些应用设计出简单高效的应用程序。而一般的数据库系统则支持大而全的功能,同时损失了速度和空间。最后,搜索引擎面临大量的用户检索需求,这要求搜索引擎在检索程序的设计上要分秒必争,尽可能的将大运算量的工作在索引建立时完成,使检索运算尽量的少。一般的数据库系统很难承受如此大量的用户请求,而且在检索响应时间和检索并发度上都不及我们专门设计的索引系统。

    倒排列表用来记录有哪些文档包含了某个单词。一般在文档集合里会有很多文档包含某个单词,每个文档会记录文档编号(DodD),单词在这个文档中出现的次数(TF)及单词在文档中哪些位置出现过等信息,这样与一个文档相关的信息被称做倒排索引项(Posting),包含这个单词的一系列倒排索引项形成了列表结构,这就是某个单词对应的倒排列表。右图是倒排列表的示意图,在文档集合中出现过的所有单词及其对应的倒排列表组成了倒排索引。
    在实际的搜索引擎系统中,并不存储倒排索引项中的实际文档编号,而是代之以文档编号差值(D-Gap)。文档编号差值是倒排列表中相邻的两个倒排索引项文档编号的差值,一般在索引构建过程中,可以保证倒排列表中后面出现的文档编号大于之前出现的文档编号,所以文档编号差值总是大于0的整数。如图2所示的例子中,原始的3个文档编号分别是187、196和199,通过编号差值计算,在实际存储的时候就转化成了:187、 9、3。
    之所以要对文档编号进行差值计算,主要原因是为了更好地对数据进行压缩,原始文档编号一般都是大数值,通过差值计算,就有效地将大数值转换为了小数值,而这有助于增加数据的压缩率。
    现将相关术语描述如下:
    倒排索引(英语:Inverted index),也常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。它是文档检索系统中最常用的数据结构。通过倒排索引,可以根据单词快速获取包含这个单词的文档列表。倒排索引主要由两个部分组成:“单词词典”和“倒排文件”。
    倒排索引有两种不同的反向索引形式:

    一条记录的水平反向索引(或者反向档案索引)包含每个引用单词的文档的列表。
    一个单词的水平反向索引(或者完全反向索引)又包含每个单词在一个文档中的位置。

    后者的形式提供了更多的兼容性(比如短语搜索),但是需要更多的时间和空间来创建。
    现代搜索引起的索引都是基于倒排索引。相比“签名文件”、“后缀树”等索引结构,“倒排索引”是实现单词到文档映射关系的最佳实现方式和最有效的索引结构.
    构建倒排索引主要有“合并法”和“简单法”:
    简单法
    索引的构建相当于从正排表到倒排表的建立过程。当我们分析完网页时,得到的是以网页为主码的索引表。当索引建立完成后,应得到倒排表,具体流程如图所示:
    流程描述如下:

    将文档分析称单词term标记,
    使用hash去重单词term
    对单词生成倒排列表

    倒排列表就是文档编号DocID,没有包含其他的信息(如词频,单词位置等), 这就是简单的索引。这个简单索引功能可以用于小数据,例如索引几千个文档。然而它有两点限制:

    需要有足够的内存来存储倒排表,对于搜索引擎来说,都是G级别数据,特别是当规模不断扩大时,我们根本不可能提供这么多的内存。
    算法是顺序执行,不便于并行处理。

    合并法
    归并法,即每次将内存中数据写入磁盘时,包括词典在内的所有中间结果信息都被写入磁盘,这样内存所有内容都可以被清空,后续建立索引可以使用全部的定额内存。
    合并流程:

    页面分析,生成临时倒排数据索引A, B,当临时倒排数据索引A, B占满内存后,将内存索引A, B写入临时文件生成临时倒排文件,
    对生成的多个临时倒排文件,执行多路归并,输出得到最终的倒排文件 (inverted file)。

    索引创建过程中的页面分析,特别是中文分词为主要时间开销。算法的第二步相对很快。这样创建算法的优化集中在中文分词效率上。
    倒排索引建立起之后,有时候会根据需要进行更新,于是就出现了更新的决策问题,有如下几个主要方法:完全重建、再合并策略、原地更新策略以及混合策略。
    完全重建策略:当新增文档到达一定数量,将新增文档和原先的老文档整合,然后利用静态索引创建方法对所有文档重建索引,新索引建立完成后老索引会被遗弃。此法代价高,但是主流商业搜索引擎一般是采用此方式来维护索引的更新。
    再合并策略:当新增文档进入系统,解析文档,之后更新内存中维护的临时索引,文档中出现的每个单词,在其倒排表列表末尾追加倒排表列表项;一旦临时索引将指定内存消耗光,即进行一次索引合并,这里需要倒排文件里的倒排列表存放顺序已经按照索引单词字典顺序由低到高排序,这样直接顺序扫描合并即可。其缺点是:因为要生成新的倒排索引文件,所以对老索引中的很多单词,尽管其在倒排列表并未发生任何变化,也需要将其从老索引中取出来并写入新索引中,这样对磁盘消耗是没必要的。
    原地更新策略:试图改进再合并策略,在原地合并倒排表,这需要提前分配一定的空间给未来插入,如果提前分配的空间不够了需要迁移。实际显示,其索引更新的效率比再合并策略要低。
    混合策略:出发点是能够结合不同索引更新策略的长处,将不同索引更新策略混合,以形成更高效的方法。
    3.3.1.3 模块内流程图

    人物爬虫:以用户为单位,获取该用户的粉丝以及该用户的近期微博。人物列表:分为待处理与已处理,待处理用户会被放入待取任务队列。加入待取任务队列:这里存放下一个需要获取的用户微博的对象。获取近日微博:将待取任务队列中的一个用户提取出,并且获得他近日的微博,然后将其加入已处理用户集。分词系统:将即时获得的微博经过分词系统,将新词加入到词典,旧词则更新IDF。建立倒排索引:根据词典以及微博建立倒排索引,最终加入到数据库中,供下一个模块使用。
    3.3.1.4 模块类图设计
    dataMining:这个是数据获取模块的主入口。

    DBHander:这个封装了对数据库的一系列操作。

    Doc:这个是微博文档对象类 。

    Global:这个类是存放全局共享数据的。

    Liexicon:这个类是词典类,记录单词以及他出现的文档 ID 以及 IDF。

    People:这个是人物类,主要包含了其用户 ID,主要作用是获取微博以及粉丝的ID。

    PeopleQueue:这个是人物队列类 。

    splitSystem:这个是分词系统类,封装了 iK-analyzer 的相关操作,方便开发。

    3.3.2 数据分析模块根据数据获取模块建立的倒排索引,依据聚类算法以及评分获得最热点事件,形成最终结果。该内部模块如下图:

    3.3.2.1 模块类图设计
    dataAnalyzer:该类是本模块的主运行类。

    DBHander:该类是专门是对读取数据库的一些操作进行的封装。

    dovVector:该类是将一条微博进行向量化之后的向量类。

    Global:该类是全局共享数据。

    TermVector:存放向量集的类。

    zplCluster:划分出来的聚类。

    zplKMean:K-means 算法的实现类。

    3.4 数据库设计方案本数据库主要是存放词典、微博文档以及倒排索引。 根据需要设计出下面几张表:
    1.Doc 表,存放微博文档

    2.Lexicon 表,存放单词词典

    3.Postingitem 表,存放倒排索引

    4.Usedlist 表,存放已经使用过的用户

    第四章 系统实现4.1 数据获取模块实现4.1.1 核心代码dataMining 类:
    package DataMining; //这个是数据获取模块的主程序 public class dataMining { public boolean mainDataMining(){ initDB(); //初始化微博与人物队列 if(loginWeibo()) { process(); } else { return false; } return false; } //登陆微博并且初始化人物队列 public boolean loginWeibo(){ People tmp = null; int size = Global.usedIDList.size(); if(size == 0) { tmp = new People(Global.uIDString); } else { tmp = new People(Global.usedIDList.get(size -1)); } tmp.getFriends(Global.queue); return true; } public boolean process(){ People tmp; //处理数据,建立倒排索引 while(Global.queue.getCount() != 0){ tmp = Global.queue.getOut(); if(tmp == null) return false; //数据处理 if(tmp.getDoc() == false) return false; tmp.getFriends(Global.queue); Global.usedIDList.add(tmp.getID()); Global.dBer.insertUsedList(tmp.getID()); } return true; } public boolean initDB(){ Global.dBer.connectDB(); Global.dBer.initUsedList(); Global.dBer.initValue(); return false; } }
    4.1.2 相关时序图时序图如下:
    1.初始化

    从首个用户开始,抓取用户粉丝,塞入待获取任务队列。
    2.数据获取

    先从队列之中得到一个待抓取用户,然后在得到该用户的近期微博,获得微博之 后,进入其他类进行处理,处理完后,获取该用户的粉丝,然后又加入到待抓取 队列之中,等待一下次的处理。
    3.建立倒排索引

    获取到一个用户的微博之后,首先将这个微博加入到数据库之中,然后对这条微 博进行分词,将分完的单词加入到词典之中。这样子就完成了倒排索引的建立。
    4.2 数据处理模块实现4.2.1 核心代码Dataanalyzer 类:
    package DataAnalyzer; public class dataAnalyzer { public void mainAnalyzer(){ Global.dBer.connectDB(); zplKMeans kMeans; kMeans = new zplKMeans(20); kMeans.readVectorSet(); kMeans.initRandom(); kMeans.start(); kMeans.showAll(); Global.dBer.closeDB(); }}
    4.2.2 相关时序图1.数据分析

    步骤如下:

    连接数据库 将数据库中的全部文档向量化,将一个向量化方法如下:

    读取整个单词库,获得所有单词的数目 n,创建一个 n 维的向量 v(a1,a2,,,,an)。 遍历该文档,若出现第i号单词,则将v的第i个位置改成该单词的TF*IDF的值。 遍历完后,则 v 为该文本的向量化

    从全部向量化之后,从向量化集中随机提取出几个向量作为基本中心点
    进行 k-means 聚类算法
    显示结果
    关闭数据库连接

    2.建立向量集

    3.K-means 算法

    4.状态图

    第五章 系统运行结果5.1 源码结构展示

    DataMining 包:数据挖掘模块 DataAnalyzer:数据分析模块 Org.wltea 包:Ik-analyzer 中文分词器源码 Weibo4j 包:新浪微博 api 源码 Testcase 包:开发测试用例
    5.2 数据抓取模块运行展示1.运行测试用例 testMining

    2.数据库中数据
    Doc 表

    Lexicon 表

    Usedlist 表

    Postingitem 表

    5.3 数据分析模块1.运行测试用例 testAnalyzer

    2.调试运行结果

    3.将最终结果输入到 excel 中

    第六章 总结与展望6.1 系统主要作用本系统在互联网的背景下,建立了对大量本地生活信息处理、分析的系统,实现了如下几点:

    通过该系统,我首先学习了网络爬虫的原理以及搜索引擎相关知识,最后通过新浪微博的 api 对网络数据模块进行了简化,并且通过学习、模仿搜索引擎建 立倒排文件,对数据进行了初步处理,方便以后操作。 中文字符串匹配:该系统之中,不仅仅采用了开源的中文分词器,而且在中文分词器之外,自己还做了过滤模块,将无用微博如:“抱歉,该微博以被….” 将其滤去;还有相应的无用单词,如“你”“我”“他”“的”“之”等。该过滤 模块使用正则表达式来进行实现该功能。 热点分析策略:本系统中的热点分析策略,主要是依靠 k-means 聚类算法对大量微博进行聚类,经过我的反复试验,将 k 值设为 20 效果最佳。 最终实现了一款微博舆情热点分析系统。
    6.2 系统难点与解决事件挖掘是一个发展很广阔的领域,而热点事件挖掘是这个领域之中较复杂的过程。在实现该系统之中,还是遇到一些问题,下面是遇到的问题以及解决方案:
    1.新浪微博 api 调用限制
    由于新浪对开放平台的应用有不同的测试等级,不同的等级可调用 api 的次数限制不同,由于我是测试用户,一个小时只能调用150 次新浪微博 api。 对于该问题,我的解决方案如下: 使用断点策略,若是在一次数据获取中达到了新浪 api 调用限制,我将会把断点保存入数据库,待限制时间取消之后,我就可以继续从断点执行。
    2.中文字符集
    从微博上获取的微博内容,好像大多数是 utf-8,但是我将微博插入数据库之后,数据库之中显示的是乱码,甚至有些微博插入数据库中直接会报错。
    对于该问题,我的解决方案如下:
    我将每条微博都无论是什么字符编码都进行了 utf-8 编码的转换,且我将系统容错性大大提升,若是某条微博真的不能插入数据库之中,系统将会把该条微博放弃。
    3.广告用户的微博
    由于有广告微博的存在,有时候会使分析到的数据有误,比如:某条微博转发次数很高,系统不能判断这个是广告微博用户到处转发,还是真正用户都喜欢这条微博,故判断难度增加。 对于该问题,我的解决方案如下: 肉眼观看最终结果,自己剔除。
    致谢经过近两个多月的努力,我顺利完成了这篇论文。我衷心地感谢各位领导和老师对我的关心和帮助,特别是我的指导老师,一次又一次的评阅我的论文,并提出了许多宝贵的意见和建议,使我进一步熟悉和掌握了系统开发的流程和方法,最终顺利地完成了本系统的开发。
    同时也感谢四年来各科任课老师的教导,您们授予的宝贵知识为我以后的学习、工作奠定了基础。 感谢在百忙之中参加论文评审和答辩的各位专家!
    参考文献[1] Allan J, Papka R, Lavrenko V. On-Line New Event Detection and Tracking [J]. Proceedings of SIGIR ‘98:21st Annual International ACM SIGIR Conference on Research and Development in Information Retrieval [C]. New York: ACM Press, 1998, 37-45
    [2] Lam W.Meng H.Wong Ketal. Using contextual analysis for news event detection[J]. International Journal on Intelligent Systems.2001,16(4):525-546
    [3] Y Yang, J Carbonell, C Jin. Topic-conditioned novelty detection[J]. In:Hand D,etal.Proceedings ofthe 8th ACM SIGKDD International Conference on Knowledge Discovery and Data Mining[C]. New York: ACM Press, 2002,688-693
    [4] G Kumaran and J Allan. Text classification and named entities for new event detection [J]. In Proceedings of the SIGIR Conference on Research and Development in Information Retrieval [C]. Sheffield, South Yorkshire: ACM,2004, 297–304
    [5] Y Yang, T Pierce, J Carbonell. A study on Retrospective and On-Line Event detection [J]. Proceedings of the 21st annual international ACM SIGIR conference on Research and development in information retrieval [C]. 1998,CMU, USA: ACM, 28-36
    [6] T Brants, F Chen, and A Farahat. A system for new event detection [J]. In Proceedings of the 26th SIGIR conference on Research and development in information retrieval [C], 2003.
    [7] Christian Wartena, Rogier Brussee. Topic Detection by Clustering Keywords[C].2007.
    [8] Nicola Stokes, Paula Hatch, Joe Carthy. Lexical Semantic Relatedness and Online New Event Detection [J]. Proceedings of the 23rd annual international ACM SIGIR conference on Research and development in information retrieval [C]. Greece: ACM, 2000, 324-325
    [9] Hatch P, Stokes N, Carthy J. Topic detection, a new application for lexical chaining [J]. British Computer Society IRSG 2000 [C]. Cambridge: British Computer Society , 2000, 94 - 103
    [10]Ulli Waltinger, Alexander Mehler, and Maik Stührenberg. 2008b. An integrated model of lexical chaining: Application, resources and its format.[J] In Angelika Storrer, Alexander Geyken, Alexander Siebert, and Kay-Michael Würzner,editors, Proceedings of KONVENS 2008 — Ergänzungsband Textressourcen und lexikalisches Wissen[C], pages 59—70
    [11]贾自艳,何清,张俊海等. 一种基于动态进化模型的事件探测和追踪算法[J].计算机研究与 发展.2004,41(7):1273 -1280
    [12]张阔,李娟子,吴刚等.基于词元再评估的新事件检测模型[J].软件学报.2008.4:817-828
    [13]洪宇,张宇,范基礼等.基于话题分治匹配的新事件检测[J].计算机学报.2008.4:688-695
    [14]Hei-Chia Wang, Tian-Hsiang Huang, Jiunn-Liang Guo. Journal Article Topic Detection Based on Semantic Features. [C]Springer-Verlag Berlin Heidelberg,2009.
    [15]JingQiu, LeJian Liao, XiuJie Dong. Topic Detection and Tracking for Chinese News Web Pages.[C]2008.
    [16]Changki Lee, Gary Geunbae Lee, Myunggil Jang. Dependency structure language model for topic detection and tracking.[J] Information Processing and Management, Vol. 43, No. 5, Sep. 2007, pp. 1249-1259.
    [17]骆卫华,于满泉,许洪波,王斌,程学旗. 基于多策略优化的分治多层次聚类算法的话题 发现研究[J]. 中文信息学报. 2006,20(1): 29-36
    [18]Zhang Kuo, Li Juan Zi, Wu Gang. New Event Detection Based on Indexing-tree and Named Entity[A]. Sigir2007[C]. ACM: Amsterdam, 2007.
    [19]洪宇,张宇,刘挺,等.话题检测与跟踪的评测及研究综述[J].中文信息学报.2007,21(6):71-87
    [20]Yonghui Wu, Yuxin Ding, Xiaolong Wang, Jun Xu. On-line Hot Topic Recommendation Using Tolerance Rough Set Based Topic Clustering[J]Journal of Computers, Vol. 5, No. 4, April 2010.
    [21]Mingliang Zhu, Weiming Hu, Ou Wu. Topic Detection and Tracking for Threaded Discussion Communities.[C]2008.
    [22]Canhui Wang, Min Zhang, Shaoping Ma. Automatic Online News Issue Construction in Web Environment.[C]BeiJing 2008 April
    [23]张俊林 电子工业出版社 2012 年 1 月 《这就是搜索引擎-核心技术详解》 第三章
    3 评论 73 下载 2018-09-29 22:48:45 下载需要17点积分
  • 基于Python的图片及音频搜索引擎

    在此次实验报告中将会分为五个部分进行单独分析,这五个部分分别是:爬虫、界面、文本搜索、图片搜索以及音频搜索。
    一爬虫1.1 库
    requests
    urllib

    1.2 实现功能
    能够通过requests.get获得网页上的内容,并使用json.loads进行解析
    能够快速定位歌曲、专辑的信息,包括专辑名、歌手、歌词、专辑简介、发行时间、流派、发行公司等
    能够从网页上下载歌曲和图片

    1.3 实现过程
    爬取QQ音乐网站的榜单,通过榜单下载歌曲
    分析发现搜索各首歌曲的 url 地址中的区别在于其中的一段内容代表的是搜索输入的文字的编码,利用这一特性模拟搜索从榜单上爬取下来的歌曲
    通过分析网页的 url 地址,发现每一首歌曲都有自己特定的”media_mid”属性,这个属性是各个歌曲的下载url地址唯一不同的地方。通过将该属性替换到url中的固定位置,可以完成歌曲、专辑、歌词定位
    定位到歌曲、专辑、歌词、图片地址后完成文本的写入

    1.4 难点
    reques 取得 url 地址是搜索页面下的单曲一栏,然而这里面并没有歌词,故将搜索歌曲的页面从单曲切换到歌词


    由于该页面中有大量中文字符,会出现json无法解析的编码,故使用正则表达式作类似处理
    专辑信息只能通过歌曲的 js 代码中获得的 media_mid 属性定位后,再通过正则表达式来提取

    二、界面2.1 库
    Wow.min.js
    animate.css
    jquery.min.js

    2.2 实现的功能2.2.1 翻页
    由于文本搜索的结果较多,故使用javascript实现了分页的效果。设置最大显示量为20个结果,每页显示4个结果,共五页。 并实现了翻页、上一页、下一页的功能。
    效果如下

    代码如下
    <script language="JavaScript" type="text/javascript" > var total="20";//最大数据量 var pagesize="4";//每页的显示量 var pagenum=Math.ceil(total/pagesize);//一共有多少页 //生成导航 function initpage(nowpage){ var pagenav='<a href="#" onclick=up('+ nowpage+');>上一页</a>'; for(i=1;i<=pagenum;i++){ pagenav += (i==nowpage)?'<span class="now">' + i + '</span>':'<a class="number" href="#" onclick=goToPage(' + i + ');>' + i + '</a> '; } pagenav += '<a href="#" onclick=down('+ nowpage+');>下一页</a>'; document.getElementById('pages').innerHTML=pagenav; } //翻页 function goToPage(page){ var start=(page-1)*pagesize; var max=page*pagesize; for(vs=0;vs<total;vs++){ var obj=document.getElementById('item_' + vs); obj.style.display="none"; } if(max>total)max=total; for(v=start;v<max;v++){ var obj=document.getElementById('item_' + v); obj.style.display="block"; } initpage(page); } //上一页 function up(nowpage){ if(nowpage==1)return false; if(nowpage>1)goToPage((nowpage-1)); } //下一页 function down(nowpage){ if(nowpage==pagenum)return false; if(nowpage<pagenum)goToPage((nowpage+1)); }</script>
    2.2.2 轮播图可自动滚动播放海报,亦可点击左右切换按钮或下方圆形选择按钮切换海报。
    效果如下

    代码如下
    //轮播图函数function jAutoPlay() { if (curIndex < $jUlLis.length) { curIndex++; } else { curIndex = 1; $jUl[0].style.left = 0; } $jUl.stop().animate({ left: -liWidth * curIndex }); if (jOlIndex < $jOlLis.length-1) { jOlIndex++; console.log(jOlIndex) } else { jOlIndex = 0; } $jOl.children().eq(jOlIndex).addClass("current").siblings().removeClass("current");}
    2.2.3 NEW SONGS板块从上部飞入slideInDown的动画效果当下拉至NEW SONGS这一板块时,图片从左到右依次从上部向下飞入指定位置。

    当检测到鼠标滑过图片区域时,图片下部的歌曲信息由原先的一行专辑名再增加一行歌手名。

    2.2.4 PROMOTION板块的bounceInDown弹跳飞入动画效果当检测到鼠标进入图片区域时,浮于图片上显示图片的专辑名、歌手名等信息。

    代码如下
    <!-- t-promot-start --><div class="t-promot w"> <div class="title"> <h2>PROMOTION<br><span>热门推荐</span></h2> </div> <div class="t-promot-t clearfix"> <a href="javascript:;" class="t-a-imgs wow bounceInDown" data-wow-delay="0.2s"><span><i>你身边还有我<br/>阿里郎</i></span><img src="/static/images/t-promot1.jpg"/></a> <a href="javascript:;" class="t-a-imgs wow bounceInDown" data-wow-delay="0.3s"><span><i>别对我动情<br/>关晓彤</i></span><img src="static/images/t-promot2.jpg"/></a> <a href="javascript:;" class="t-a-imgs wow bounceInDown" data-wow-delay="0.2s"><span><i>新世界<br/>小贱</i></span><img src="static/images/t-promot3.jpg"/></a> <a href="javascript:;" class="t-a-imgs wow bounceInDown" data-wow-delay="0.2s"><span><i>星星照亮回家的路<br/>庞龙</i></span><img src="/static/images/t-promot4.jpg"/></a> </div></div>
    2.2.5 回到顶部按钮按钮置于页面右侧,点击即可返回到页面顶部。

    代码如下
    //返回顶部var timer = null;$(".t-btn7").click(function(){ var leader = scroll().top; clearInterval(timer); timer = setInterval(function(){ var target = 0; var step = (target-leader)/10; step = step>0 ? Math.ceil(step):Math.floor(step); leader = leader+step; window.scrollTo(0,leader); if(target == leader){ clearInterval(timer); } },25)})function scroll() { // 开始封装自己的scrollTop if(window.pageYOffset != null) { // ie9+ 高版本浏览器 // 因为 window.pageYOffset 默认的是 0 所以这里需要判断 return { left: window.pageXOffset, top: window.pageYOffset } } else if(document.compatMode === "CSS1Compat") { // 标准浏览器 来判断有没有声明DTD return { left: document.documentElement.scrollLeft, top: document.documentElement.scrollTop } } return { // 未声明 DTD left: document.body.scrollLeft, top: document.body.scrollTop }}
    2.2.6 上传图片、音频使用 GET 方法提交表单,用户浏览得到文件及其文件名,将文件名传递给处理函数以进行进一步的处理。
    代码如下
    <!--search部分 start--><div style="margin-top:50px;margin-left:50px"> <form action="/a_s" method="GET"> <input type="file" name="uploadfile" id="uploadfile" style="height:35px;color:#68838B" value="Browse..." /> <button type="submit">上传</button> </form></div><!--search部分 end-->
    2.3 问题及解决遇到的问题主要是在界面的整合过程中。在运行代码过程中报错“Codec with name ‘Lucene410’does not exist”查阅一些资料后,发现大部分出现此类问题的情况是由于缺少 META-INF/services 这样的文件夹,可以通过将 jar 包中的META-INF复制到src目录的方式解决。但多次尝试之后发现并不可行,再次研究思考报错内容后,认为问题在于 整合界面的同学所使用的 Lucene 的版本为 4.9.0 而写音频搜索的同学的Lucene 的版本为4.10.0,两者版本不一,使用版本低的lucene时会报错。整合界面的同学使用了miniconda安装了4.9.0版本,利用conda update 更新lucene 后,版本仍为 4.9.0,原因应是 miniconda 中的 lucene 最高版本号是4.9.0,故采取了卸载原来安装的4.9.0版本的lucene,通过lucene PPT中提到的第二种安装方式安装了4.10.0版本的lucene最终解决了这一问题。
    三、文本搜索3.1 库
    lucene
    jieba

    3.2 原理使用jieba与lucene对文本内容进行分词以此实现快速搜索
    3.3 实现步骤
    建立索引
    实现搜索文件

    四、图片搜索4.1 库
    H5py
    OpenCV
    Numpy

    4.2 原理利用 SIFT 算法对图片进行特征提取,然后利用 Hash 对图片特征分类建立数据库,在搜索过程中对待检索图片做同样操作以完成匹配。
    由于sift特征具有尺度不变性、旋转不变性等良好特征,故图片进行匹配时,两张图片相似度要求并不是很高。
    4.3 实现步骤对爬虫得到的文件中的所有图片用OpenCV的内置sift进行特征提取:
    sift=cv2.SIFT()
    将每张图片提取的sift特征做归一化处理
    r,c=des.shapeargmaximum=np.argmax(des)argminimum=np.argmin(des)nmax=argmaximum/cnmin=argminimum/cmaximum=des[nmax][argmaximum-nmax*c]minimum=des[nmix][argmiximum-nmix*c]
    将归一化处理后的数据使用直方图统计,并将 bins 设为下图所示:
    b=[0.07, 0.1, 0.13, 0.16, 0.19, 0.22, 0.25]
    以得到的直方图为依据做Hash处理,将得到的矩阵变为字符串储存为一个字典的 key 值,然后再将具有同样 Hash 值得图片信息作为 value 储存入该字典中:
    if nt dic.has_key(hashname): grphash=f.create_group(hashname) dic[hashname]=grphashimgname="img"+str(count)desname="des"+str(count)grpimg.create_dataset(imgname, data=imgori)grppath.create_dataset(imgname, data=imgpath)dic[hashname].create_dataset(imgname, data=des)
    检索图片时,对待检索图片进行上述相同操作之后,从H5py中取得同样Hash值的图片信息,然后对这些图片一一使用欧氏距离匹配:
    bf=cv2.BFMatcher()keys=imggroup.keys()paths=[]matchimgs[]for k in keys: des1=imggroup[k][:] matches=bf.match(des1, des) d=0 for j in matches: d+=j.distance if d<400 path.append(imgpaths[k].value) matchimgs.append(imgs[k][:])
    4.4 测试从网上下载各类不同的专辑图片来对库中的图片进行匹配,可以得到:

    所使用的 bins 划分是能够比较均匀的将库中的图片划分在各个不同的 Hash值下面的
    网上的图片与库中原有的图片的欧式距离是小于400的
    库中有4913首歌曲,搜索到对应图片的时间需要3s,但若将搜索嵌入到搜索引擎中,页面上出来结果大致需要6s,猜测与电脑渲染页面速度有关

    4.5 对比与使用颜色空间创建Hash值相对比,该使用sift特征值来Hash的办法可以排除颜色的干扰,也就是即使亮度、灰度有变化,也不会影响图片的匹配。
    五、音频搜索5.1 库
    ffmpeg
    wave
    pyaudio
    mysqldb

    5.2 原理基于内容的音频检索与基于内容的图片检索在实际实现上面临着类似的问题,包括巨大的信息量以及特征点相对位置对于搜索结果的巨大影响,对于检索的准确度要求以及对于检索速度的要求同样限制着音频检索的实现。这里参照图片检索的相关方式对音频检索进行了尝试,主要思想是在音乐的频谱中提取频率峰值特征点,基于这些特征点对不同的歌曲进行匹配。(主要用lucene解决了音频匹配速度问题)
    5.3 实现步骤5.3.1 音频格式转码网页爬虫下载后的音频格式为 m4a,为使用 wave 库,需对下载的音频进行转码,将其转为wav格式,这里使用安装在linux中的ffmpeg进行转码,转码后的文件存入与原文件相同的目录下,与原文件只有后缀名不同。
    代码:
    try: subprocess.call(["ffmpeg", "-i", origin, newsr]) sss.addsong(newsr2, extra, album)except: continue
    目录下的文件组成:

    5.3.2 提取音频特征打开步骤1转码后的音频文件,该文件的一个声道是一个一维数组的形式,图形化如图:

    这种时间对应幅值的一维数组信息量巨大,难以提取特征信息,故我们利用傅里叶变换将其转化到频域中:

    转化的结果:

    这样,音频信息转为了其对应的众多频率波形的叠加,而人耳正是靠着所听到的音乐的特定频率序列来区分音频的。在频域信号的众多特征中,我们认为峰值特征是最具代表性的,这种特征代表着这一频率能量最大,它容易提取,同时对于噪声有一定的容忍度。如果只是简单地提取整首歌曲中的一些峰值点,则我们会丧失重要的时间信息,故应当对整段音频进行分段,对每一段音频做傅里叶变换并提取特征峰值点,这样我们在得到特征点的同时也较好地保留了时间的信息。
    这里将音频的1s分成40个块,在每一块的4个对应区间中得到4个峰值点,这4个峰值点组成的序列即是在一个块中得到的音频指纹。
    5.3.3 数据存储为了应用的方便,这里将得到的指纹序列存入了mysql数据库中,如图所示:

    5.3.4 匹配方法这里设计了两种匹配方法,dtw以及分词法匹配,考虑到对检验速度的要求,实际应用中选择了后者,但如果要求更高的精度,建议选择前者:
    dtw,即动态时间规划,这种方法适于匹配两个不同长度的音频文件,主要思想是找出穿过m*n矩阵的最佳路径,图中上方和左方为我们要匹配的两个不同长度的音频文件,中间为这两个音频文件构造的矩阵,矩阵中每一个格点为两音频中对应点的相似度,中间的线即为找出的最佳路径:

    具体实施原理及方法参照:http://blog.csdn.net/zouxy09/article/details/9140207
    分词法匹配,这种方法的精度不高,但相比于dtw的匹配所花费的时间要大大减小。主要思想是把音频特征提取过程中提取出的特征点(即四个数字组成的序列)看作是文字检索中的一个词,如将2,40,13,77看作是文字搜索中的一个词,并用空格将这些词隔开,使用lucene中的whitespace分词器对特征点组成的“文章”进行分词以及语法分析,构建索引。这样,对特征点的检索就变成了简单的文字检索。
    5.3.5 搜索主要搜索过程:

    从本地上传一个音频文件
    对该音频文件进行转码,将其转化为wav格式
    对转码后的音频文件提取特征点
    用逻辑与连接这些特征点,构建query,与索引结果进行匹配,返回得分最高的50个结果

    5.4 测试测试结果显示,dtw将测试音频与库中的音频进行匹配时平均每一首歌需花费1.5s,这表明当库的容量非常大时其所消耗的时间将是难以想象的,因此,我们选择用lucene的分词系统对音频进行过滤。最终测试的结果是,其中百分之八十的正解将会出现在lucene打分结果的前五名中,有大概百分之15的正解将会出现在5至40名中,只有极少数的结果会出现在40名之后(出现这种现象的主要原因是不同的音频可能有相同的特征点,并且一些音频中含有的某种特征点的数量可能比正确结果的数量更大),故这种方法的精度可能不如dtw,但在一定程度上可以满足检索的基本要求。
    2 评论 7 下载 2019-05-23 11:42:23 下载需要11点积分
  • 基于QT与mplayer的视频播放器

    一、课题的介绍和课题的任务1.1 课题的介绍本次课程设计我选的题目是视频播放器。目前市场上各种应用商店上有各种播放器,而且功能都很强大。一直对里面的具体实现有兴趣,所以这次就尝试着写了个视频播放器。并且加进去了一些很实用的功能,比如截屏和录屏。
    1.2 课题的任务包括视频的播放暂停、音量的加减、播放速度的设置、以及视频文件的添加删除、屏幕的截屏以及录屏。画面不卡顿。播放时进度条能刷新。
    二、设计的要求
    能进行视频的播放
    能暂停正在播放的视频
    能播放正在暂停的视频
    能调节视频播放的视频
    能进行视频播放进度的调节
    能停止正在播放的视频
    能添加新的视频文件到播放列表
    能删除播放列表中选中的视频
    能改变视频播放的速度
    能对正在播放的视频进行截屏
    能录制正在播放的视频

    三、系统的分析和系统中类的设计
    窗口类QMainWidndow
    按钮类QPushButton
    标签类QLabel
    列表类QList
    滑动条类QSilider
    显示类QWidge

    四、系统的实现及调试系统模块框架图

    程序具体实现
    4.1 添加文件进视频播放列表
    代码实现:
    void mplayer_video::on_open_clicked(){ QStringList filenames =QFileDialog::getOpenFileNames(this,tr("选择文件"),"/",tr("视频文件(*mp3 *mp4 *wma *3gp *wav *avi *flv *rmvb *mkv *ts *wmv)")); // *号和前面的要隔开至少一个空格,不能连起来。 if(filenames.count()!=0) ui->list->addItems(filenames);}
    4.2 双击列表选项进行播放
    代码实现:
    void mplayer_video::on_list_itemDoubleClicked(QListWidgetItem *item){ speed=1; ui->lupin_lable->setVisible(false); play(item->text());}void mplayer_video::play(QString fileName){ QStringList arg1; process->kill(); process=new QProcess(this); arg1 << fileName; arg1 << "-slave";//默认情况下,mplayer接受键盘的命令,而"-slave"使其不再接受键盘事件,而是作为后台程序运行, //接受以“\n”结束的命令控制,这样我们可以在进程中给他发送命令,而不需要操作键盘了. arg1 << "-quiet"; //尽可能的不打印播放信息 arg1 << "-zoom"; //视频居中,四周黑条,全屏播放 arg1 << "-wid" << QString::number((unsigned int)(ui->widget->winId())); // "-wid <窗口标识>" 是指让MPlayer依附于那个窗口, //ui->widget->winId() 这个指令就是用来获取widget的标识码 , //这样视频播放的时候,就在这个部件里播放,相当于给他固定起来。 connect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(dataRecieve())); process->start(arg,arg1); //开始播放进程 ui->zanting->setText("暂停");}void mplayer_video::dataRecieve(){ process->write("get_time_length\n"); process->write("get_time_pos\n"); process->write("get_percent_pos\n"); while(process->canReadLine()) { QByteArray b=process->readLine(); if(b.startsWith("ANS_TIME_POSITION")) { b.replace(QByteArray("\n"),QByteArray("")); QString s(b); currentStr=s.mid(18); ui->horizontalSlider->setValue(s.mid(18).toFloat()); //更新进度条 } else if((b.startsWith("ANS_LENGTH"))) { b.replace(QByteArray("\n"),QByteArray("")); QString s(b); totalTime=s.mid(11); ui->label_time->setText(currentStr+"秒/"+totalTime+"秒 "); //显示时间进度 ui->horizontalSlider->setRange(0,s.mid(11).toFloat()); } else if((b.startsWith("ANS_PERCENT_POSITION"))) { b.replace(QByteArray("\n"),QByteArray("")); QString s(b); currentPercent=s.mid(21); ui->percentLabel->setText(currentPercent+"%"); } }}
    4.3 播放与暂停的实现
    代码实现:
    void mplayer_video::on_zanting_clicked(){ ui->lupin_lable->setVisible(false); process->write("pause\n"); //ui->list->currentRow()!=-1 判断是否有选中某条数据 //play(ui->list->item(ui->list->currentRow())->text()); 播放选中的某条数据 if(ui->zanting->text()=="播放") { if(ui->list->count()==0) QMessageBox::warning(this,"提示","播放列表为空",QMessageBox::Yes); else { connect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(dataRecieve())); process->write("get_time_length\n"); process->write("get_time_pos\n"); process->write("get_percent_pos\n"); ui->zanting->setText("暂停"); } } else { disconnect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(dataRecieve())); ui->zanting->setText("播放"); }}
    4.4 快进与回退代码实现:
    void mplayer_video::on_back_clicked(){ process->write("seek -10\n");}void mplayer_video::on_quick_clicked(){ process->write("seek +10\n");}
    4.5 加速与减速代码实现:
    void mplayer_video::on_back_clicked(){ process->write("seek -10\n");}void mplayer_video::on_quick_clicked(){ process->write("seek +10\n");}
    4.6 停止播放代码实现:
    void mplayer_video::on_stop_clicked(){ process->write("quit\n"); ui->horizontalSlider->setSliderPosition(0); ui->label_time->clear(); ui->percentLabel->clear(); ui->zanting->setText("播放");}
    4.7 从播放列表中删除中选中的视频
    代码实现:
    void mplayer_video::on_del_clicked(){ if(ui->list->currentRow()==-1) QMessageBox::warning(this,"提示","未选中项目或列表为空",QMessageBox::Yes); else { ui->list->takeItem(ui->list->currentRow()); process->close(); ui->horizontalSlider->setSliderPosition(0); //更新进度条 ui->label_time->clear(); ui->percentLabel->clear(); }}
    4.8 加速播放与减速播放
    代码实现:
    定义一个全局静态浮点型变量 speed并初始化为1,每次点击加速,speed的值乘以二,每次点击减速,speed的值除以2
    void mplayer_video::on_jiansu_clicked(){ speed=speed/2; process->write(QString("speed_set "+QString::number(speed)+" 2\n").toUtf8());}void mplayer_video::on_jiasu_clicked(){ speed=speed*2; process->write(QString("speed_set "+QString::number(speed)+" 2\n").toUtf8());}
    4.9 视频播放进度条的刷新这是本程序里最复杂的部分之一。
    主要实现是用connect函数链接进程与DataRecieve函数
    代码实现:
    void mplayer_video::dataRecieve(){ process->write("get_time_length\n"); process->write("get_time_pos\n"); process->write("get_percent_pos\n"); while(process->canReadLine()) { QByteArray b=process->readLine(); if(b.startsWith("ANS_TIME_POSITION")) { b.replace(QByteArray("\n"),QByteArray("")); QString s(b); currentStr=s.mid(18); ui->horizontalSlider->setValue(s.mid(18).toFloat()); //更新进度条 } else if((b.startsWith("ANS_LENGTH"))) { b.replace(QByteArray("\n"),QByteArray("")); QString s(b); totalTime=s.mid(11); ui->label_time->setText(currentStr+"秒/"+totalTime+"秒 "); //显示时间进度 ui->horizontalSlider->setRange(0,s.mid(11).toFloat()); } else if((b.startsWith("ANS_PERCENT_POSITION"))) { b.replace(QByteArray("\n"),QByteArray("")); QString s(b); currentPercent=s.mid(21); ui->percentLabel->setText(currentPercent+"%"); } }}
    4.10 声音滑动条对声音的调节
    代码实现:
    void mplayer_video::on_voice_slider_sliderMoved(int v){ if(ui->zanting->text()=="播放") { process->write(QString("volume "+QString::number(v)+" 2\n").toUtf8()); process->write("pause\n"); } else{ process->write(QString("volume "+QString::number(v)+" 2\n").toUtf8()); }}
    4.11 设置图片按钮
    代码实现:
    QPixmap pixmap; pixmap.load("G:/mplayer_video/voice.jpg"); ui->voice->setFixedSize(pixmap.width(),pixmap.height()); ui->voice->setIcon(pixmap); ui->voice->setIconSize(QSize(pixmap.width(),pixmap.height())); ui->voice->setToolTip("音量"); ui->voice->show();
    4.12 屏幕截图
    代码实现:
    void mplayer_video::on_jietu_clicked(){ cout<<"ok"<<endl; process->write("pause\n"); if(ui->zanting->text()=="播放") { cout<<"1"<<endl; QPixmap snapImage = QPixmap::grabWindow(QApplication::desktop()->winId()); QString filename; QString slcStr; filename = QFileDialog::getSaveFileName(this,tr("保存图片"),"./未命名",tr("PNG(*.png);;JPG(*.jpg);;BMP(*.bmp)"),&slcStr);//弹出保存图片的文件窗口 if(slcStr.left(3)=="JPG") { if(filename.right(3)!="jpg") { filename+=".jpg"; } } if(slcStr.left(3)=="PNG") { if(filename.right(3)!="png") { filename+=".png"; } } if(slcStr.left(3)=="BMP") { if(filename.right(3)!="bmp") { filename+=".bmp"; } } if(filename!=NULL) { snapImage.save(filename); } } else { cout<<"2"<<endl; disconnect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(dataRecieve())); ui->zanting->setText("播放"); QPixmap snapImage = QPixmap::grabWindow(QApplication::desktop()->winId()); QString filename; QString slcStr; filename = QFileDialog::getSaveFileName(this,tr("保存图片"),"./未命名",tr("PNG(*.png);;JPG(*.jpg);;BMP(*.bmp)"),&slcStr);//弹出保存图片的文件窗口 if(slcStr.left(3)=="JPG") { if(filename.right(3)!="jpg") { filename+=".jpg"; } } if(slcStr.left(3)=="PNG") { if(filename.right(3)!="png") { filename+=".png"; } } if(slcStr.left(3)=="BMP") { if(filename.right(3)!="bmp") { filename+=".bmp"; } } if(filename!=NULL) { snapImage.save(filename); } connect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(dataRecieve())); process->write("get_time_length\n"); process->write("get_time_pos\n"); process->write("get_percent_pos\n"); ui->zanting->setText("暂停"); }}
    4.13 屏幕录制代码实现:
    void mplayer_video::on_lupin_clicked(){ if(ui->lupin->text()=="录屏") { photoStart(); timer->start(50); ui->lupin->setText("停止"); } else { timer->stop(); ui->lupin->setText("录屏"); }}void mplayer_video::photoStart(){ QDir *d = new QDir(); QString dirName("D:\\video"); if(!d->exists(dirName)) { d->mkdir(dirName); }}void mplayer_video::timerUpdate(){ QPixmap p; QString dirNamee("D:\\video\\"); dirNamee=dirNamee+QString::number(number)+".jpg"; p = QPixmap::grabWindow(QApplication::desktop()->winId()); p.save(dirNamee); number+=1;}
    4.14 屏幕录屏播放代码实现:
    void mplayer_video::on_lupinstart_clicked(){ process->write("quit\n"); QString dirName("D:\\video"); qdir = new QDir(dirName); qdir->setSorting(QDir::Reversed|QDir::Time); list = qdir->entryInfoList(); number2=0; timer2->start(100);}void mplayer_video::on_stop_bofang_clicked(){ timer2->stop(); ui->lupin_lable->setVisible(false);}
    五、系统的使用说明打开程序,点击添加文件进行视频播放列表视频的添加。双击列表中某条记录进行视频的播放,播放按钮自动转换成暂停按钮。点击播放将会播放视频,点击暂停视频会暂停。除了一些视频播放器的基本功能外,本程序还加入了屏幕截图与屏幕录制的功能。具体操作用按钮可以实现。
    2 评论 178 下载 2018-11-15 11:06:06 下载需要8点积分
  • 基于Android和C#实现的停车管理系统

    摘 要随着我国现代化进程的不断加快,私家车的数量急剧增加,各类停车场的车流量不断增多,对机动车的保管越来越成为社会倍受关注的问题。
    本论文主要介绍了Android系统架构,并且针对现在普遍采用的人工收费管理方法存在的弊端,提出了一套由Android SDK和Visual C#开发设计的车库车位管理信息系统,使用Socket技术进行电脑服务端和手机客户端之间的通信,手机端软件和电脑端软件分别采用SQLite和XML保存用户数据,采用流行的C/S 结构,也就是客户端/服务器模式。该系统在入口处由用户使用智能手机输入用户的姓名,车牌号,手机号等信息,在出口处服务端根据车牌号在停车记录中自动查找该车信息,并自动计费,收取停车费,当用户停车超过一定时间时,系统会自动发送短信提醒。该系统共分为登录模块、计费模块、查询模块、用户管理模块、短信提醒模块,文中对各模块的功能、操作界面、工作流程做了详细的介绍。
    关键词:C/S结构;Android操作系统;Socket通信;停车管理
    AbstractWith the development of economy, the number of cars increasing drastically, so a serious problem emerge: how to supervise the park of cars.
    This paper mainly introduce the framework of Android Operating System and bring out a new car management system that can replace the old which is done by human power. The system is based on Android SDK and Visual C# development platform. It uses Socket technology to communicate between mobile phone and computer and employs XML file on computer, SQLite on mobile phone accordingly to store user data. The system needs user entering their name, phone number, car number when they arrive, and calculate parking time and fee when they leave. This system contains login module, counting fee module, query module, user management module and SMS notification module.
    Keywords: C/S Architecture; Android Operating System; Socket Communication; Garage Management
    引 言在现代社会中管理的作用越来越显得重要和突出。一般来讲,管理通过计划、组织、指导与领导、控制等手段,为组织制定目标,应用组织的各种要素,以实现组织的目标。对企业来说,人们按照一定的营销计划、人力、物力资源,对人员、物质、资金等加以计划和协调,以达到预期的目的,即称为企业管理。传统的企业管理活动中,把人、才、物作为企业的主要资源。但是随着社会化大生产的不断扩大和社会对产品多样化的需求,人们越来越重视信息在生产经营及企业管理中的作用,并把它当做企业的一种极其重要的资源,人们称之为“信息资源”,信息资源的处理已经成为当今世界上一项主要的社会活动。同样,停车场中也不例外,其中加强对车位信息的管理,一方面能更好为车主服务,另一方面能加强对停车场效益的监控。
    本世纪以来,由于社会生产力的迅速发展和科学技术的突飞猛进,人们进行信息交流的深度和广度不断增加,管理所需要的信息量急剧增长,同时对信息的处理要求及时、准确,这导致了传统的信息处理方法和手段已不能适应现代管理的需要;电子计算机的诞生和在信息处理中的应用,标志着一个崭新时代——“信息时代”的开始,它使企业管理现代化成为可能。
    一定意义上说,管理信息系统的产生和发展是建立在电子计算机基础之上的。随着智能手机一步步走进普通人的生活,它将成为人们获取信息的主要设备。因此,手机的娱乐应用服务将会有很大的发展空间,基于智能手机的停车管理软件就是其中之一
    第一章 绪论1.1 所选课题的研究背景与意义信息作为生产力中最活跃的因素,很早就在人类经济生活中发挥着不可替代的作用,但把信息纳入企业经营管理系统中高效处理和应用是在计算机发明以后的50年代末。
    目前人们所提到的管理信息系统,通常是指以计算机为工具,对管理信息进行收集、存贮、检索、加工和传递,使其应用于组织机构及企业管理领域的“人-机系统”,该系统是70年代初“后工业经济”时代的产物,在企业管理信息系统在其发展的初期,是单一的人—机系统,系统功能简单,效率低,对管理的作用有限。
    进入20世纪80年代末,随着计算机网络和通信技术的大力发展,企业管理信息系统进入网络化的发展时期。世界发达国家已建立起了完善的先进的管理信息系统体系,在其社会经济发展领域中发挥着巨大的作用。
    我国的管理信息系统大发展是在80年代末90年代初,国家相继建立起了“金卡”、“金关”、金桥“工程,多数企事业单位建立了局域网和广域网管理信息系统。随着世界经济和我国经济逐步向知识经济迈进,无论是基于工业经济的管理信息系统,还是面向少数专家和管理人员的专家系统 (ES)或决策支持系统 (DSS),其处理对象和服务对象,自身的系统结构,处理能力,都有了进一步的发展。停车场管理(Car Park Management)并不是一个新鲜词。想想看,您是如何管理您的车辆信息的?其实您在日常生活中不自觉地运用着各种管理方法。但科学管理的前提是建立正确的管理观、正确管理科学管理的含义。
    如何科学管理?正确的管理观念非常重要,科学管理方式选择将成为决定车辆贫富差距的关键性因素。停车场管理的核心是投资收益的最大化和车辆信息分配合理化的集合。管理服务通过充分利用各种管理工具,帮助您达到合理分配的目的、满足您对管理安全性、收益性等多样化要求。
    开发一个停车场车辆管理系统迎合了现代的公司发展趋势,对居民合理管理公司和他人的联系信息起到重要意义。
    1.2 设计系统所要达到的要求目标系统应该达到以下要求:

    时间经济性。优化逻辑设计与物理设计,使系统运行效率高,反映速度快
    可靠性。能连续准确的处理业务,有较强的容错能力
    可理解性。用户容易理解和使用该系统
    可维护性和适应性。系统应易于修改、易于扩充、易于维护,能够适应业务不断发展变化的需要
    可用性。目标系统功能齐全,能够完全满足业务需求
    安全保密性。保证系统的物理安全、数据存储和存取的安全与保密、数据传输的安全与保密,做好使用人员的授权管理

    1.3 C/S结构简介C/S 结构,即众所周知的客户机和服务器结构。它是软件系统体系结构,通过它可以充分利用两端硬件环境的优势,将任务合理分配到Client端和Server端来实现,降低了系统的通讯开销。目前大多数应用软件系统都是Client/Server形式的两层结构,由于现在的软件应用系统正在向分布式的Web应用发展,Web和Client/Server 应用都可以进行同样的业务处理,应用不同的模块共享逻辑组件;因此,内部的和外部的用户都可以访问新的和现有的应用系统,通过现有应用系统中的逻辑可以扩展出新的应用系统。这也就是目前应用系统的发展方向。
    1.4 本文研究内容及章节安排本文所实现的是基于智能手机平台的停车管理系统,并对当前智能手机软件开发环境进行了研究。
    第一章是绪论,首先论述本课题的研究背景以及意义,其次介绍了本系统所达到的设计要求,最后给出了本文的结构和主要内容安排。
    第二章 开发平台和开发语言简介2.1 Android操作系统的介绍2.1.1 Android简介Android是Google在2007年11月宣布的基于Linux平台的开源手机操作系统的名称,而在Android系统底层方面,Android使用C/C++作为开发语言。该平台由操作系统、中间件、用户界面和应用软件组成,号称是首个为移动终端打造的真正开放和完整的解决方案。
    Android系统就是一个开发式的手机和平台电脑操作系统[5],早期由Google开发,后由开放手机联盟开发。它提供了从底层操作系统到上层的程序界面的所有软件,使用这个平台无需缴纳任何的授权许可费用,同时不同的厂商还可以根据自身的需求修改和扩展Android平台。
    2.1.2 Android的特点Android开发平台是由谷歌与开放手机联盟合作开发的一个开放、自由的移动终端平台,它由操作系统、中间件、应用软件三部分组成。该平台备有完善的程序开发环境,包括模拟器、除错工具、程序执行所耗用存储器、性能评介等功能。Android为开发人员提供了大量的使用库和工具,使得开发人员可以快速地创建自己的应用程序。
    在Android平台下,除了应用程序运行的载体虚拟机之外,所有的Android应用程序之间是完全平等的。所有的应用程序都运行在虚拟机上面,虚拟机提供了一系列用于应用程序和硬件资源间通信的API。Android打破了应用程序之间的界限,在Android平台下开发应用程序,可以很方便的实现应用程序之间的数据共享。一个应用程序不但可以通过API访问系统提供的功能,还可以通过申明自身的功能供其他应用程序调用
    2.1.3 Android架构Android 是首个基于 Linux 平台的开源手机操作系统,该平台由操作系统、中间件、用户界面和应用软件组成,是首个为移动终端打造的真正开放和完整的软件。Android手机系统是基于Linux平台的开源手机操作系统,分为4个层,下面是对于每一层的具体介绍:

    第一层:底层的Linux kernel,采用的是Linux kernel 2.6版,也是目前最新的版本, 主要的功能包括硬件的驱动、网络、电源、以及系统安全和内存管理等。
    第二层:Library函数库,有大多数开放源代码的函数库所组成,例如标准的C函数库Libc、OpenSSL、SQLite等,还包括WebKit函数库,负责Android网页浏览器的 运行,还包括有OpenGL图形库等。当然在这层还有很重要的Android Runtime,在此提 供Android特有的Java内核函数库与可转换Java运行码Bytecode,为Android专属的 Dalvik Executable (.dex)文件格式的Dalvik虚拟机,可以通过Java语言编写Android 应用程序。
    第三层:则是Application Framework (应用软件架构),它是所有Android重点应用程 序Framework API的集合,方便开发者使用这些API进行设计架构。常见的API包括了 显示功能(按钮、内嵌式浏览器),消息提示功能(访问信息、分享信息),提示信息(显示警告信息),位置管理等。
    第四层:Java应用程序,例如Google Maps, E-mail,浏览器、等应用程序。


    2.2 开发工具和开发语言的介绍2.2.1 客户端软件开发工具Eclipse简介Eclipse 最初是IBM的一个软件产品,前期投入了4000万美金。2001年11月,IBM宣布将其捐给开放源码组织Eclipse.org。目前Eclipse的市场占有率已经超过了Borland公司的JBuilder,成为Java开发平台中的主流。Eclipse的设计思想是:一切皆为插件。它自身的核心是非常小的,其它所有的功能都以插件的形式附加到该核心上。Eclipse是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse附带了一个标准的插件集,包括Java开发工具(Java DevelopmentTools,JDT)。虽然大多数用户很乐于将Eclipse当作Java IDE来使用,但Eclipse的目标不仅限于此。
    Eclipse还包括插件开发环境(Plug-in DevelopmentEnvironment,PDE),这个组件主要针对希望扩展Eclipse的软件开发人员,因为Android手机查询公交信息系统的设计与实现6它允许他们构建与Eclipse环境无缝集成的工具。由于Eclipse中的每样东西都是插件,对于给Eclipse提供插件,以及给用户提供一致和统一的集成开发环境而言所有工具开发人员都具有同等的发挥场所。这种平等和一致性并不仅限于Java开发工具。Eclipse框架还可用来作为与软件开发无关的其他应用程序类型的基础。Android开发平台提供了在Eclipse中的集成工具ADT(Android DevelopmentTools),在Eclipse中开发Android应用程序需要嵌入ADT。

    本文选择Eclipse作为开发工具,主要原因是Edipse将会是未来最流行的集成开发工具之一。它所具有的漂亮的界面、免费且强大的功能、国际化、灵活的插件式体系结构、支持多种操作系统平台等特点,无一不是其魅力所在。
    2.2.2 服务端软件开发工具Visual Studio简介Microsoft Visual Studio(简称VS)是美国微软公司的开发工具包系列产品。VS是一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如UML工具、代码管控工具、集成开发环境(IDE)等等。所写的目标代码适用于微软支持的所有平台,包括Microsoft Windows、Windows Mobile、Windows CE、.NET Framework、.NET Compact Framework和Microsoft Silverlight 及Windows Phone。
    2.2.3 开发语言简介手机端软件以JAVA为基础的,但是开发环境不一样。在编写的过程中不是单纯的Java语言,而是与android相结合。
    电脑端软件使用c#语言开发Windows窗体应用程序。
    第三章 开发中的关键技术3.1 客户端与服务端之间的通信技术3.1.1 套接字通信原理套接字的英文名为“socket”。套接字允许程序员把网络连接当成一个流,并向这个流读写字节。
    我们都知道在Java中有两个重要的类Socket和ServerSocket。Socket和ServerSocket都被放在java.net包中。通过这两个类就能完成客户端与服务器、甚至是客户端与客户端的即时通讯。首先通过ServerSocket类在服务器某固定端口等待连接,当有Socket请求连接到此服务器的此端口时,就完成Socket连接,然后相互之间就可以发送和接收信息。
    Socket类是Java用来实现客户端TCP操作的基础类,在Java编程中,一切与TCP有关的操作,包括连接的建立、传输、连接关闭及Socket选项的设置都由Socket类负责,这个类本身使用直接代码通过主机操作系统的本地TCP栈进行通信。Socket类的消息收发都是通过流来实现。通过new Socket()创建需要连接的指定的服务器host和端口号port的对象,并向服务器发送连接请求。通过close()方法关闭已建立的套接字。
    ServerSocket类能够在服务器端指定的端口监听。ServerSocket类通过new ServerSocke()能实现等待某客户端的连接请求的功能。跟Socket一样,也是通过close()方法关闭。
    在C#中,与Socket通信相关的函数使用方法与Java中完全相同。
    3.1.2 数据报通信在TCP/IP协议中有一个重要的定义,那就是IP数据报(IP Datagram)。IP数据报是在Internet上传输的包。它和硬件的配置无关,是由两部分组成:首部和数据。首部的前20个字节是固定的,它是所有IP数据报都必须要有的,首部剩下部分的长度是可变的。根据需要进行相应分配。例如考虑排错或者安全等因素需要。
    3.2 多线程编程多线程的目的是使对CPU的利用率提高到最大。操作系统由原来的单任务发展到现在能够同时进行多任务。实现多任务就可以通过多线程。我们知道进程是指在电脑内存运行的一个应用程序。在内存中每个进程都是独立占用的内存空间。一个进程可以有很多个线程在运行。例如火车的售票系统,在售票系统运行过程中,在同一时间可能有很多人在进行买票操作。通过多线程方式能很好解决同时进行的操作。在操作系统中,每个线程都会有一个优先级。优先级高的线程在正常情况下比优先级低的先执行。
    Java实现多线程有两种方式:通过继承java.lang.Thread类和实现java.lang.Runnable接口。而C#主要使用System.Threading类的.Start()方法运行线程
    3.2.1 Java和C#中的Thread类Thread类提供了用来启动、挂起、恢复以及终止线程的方法,除此之外,还提供控制线程的优先级以及线程的名字等其他方面的方法。使用Thread类最简单的方法是扩展它,并覆盖run()方法,当线程启动时会调用这个方法。通过覆盖run()方法,就可以使线程在后台完成一些有用的任务。而C#则需要在Thread类的构造方法里指定一个运行线程所需要的目标函数,如Thread listenerThread = new Thread(new ThreadStart(listener));其中listener即为目标函数。
    3.3 停车场用户数据存储3.3.1 数据库SQLiteAndroid 数据库使用的是系统内嵌的 SQLite,下面简单的介绍 Android 平台下的 SQLite 数据库的特点。
    SQLite是遵守的关系型数据库管理系统,它包含在一个相对小的C库中。不像常见的客户-服务器范例,SQLite引擎不是个程序与之通信的独立进程,而是连接到程序中成为它的一个主要部分。
    SQLite 是一个非常流行的嵌入式数据库,它支持 SQL 语言,并且只利用很少的内存就有很好的性能。此外它还是开源的,任何人都可以使用它。SQLite 由以下几个组件组成:SQL 编译器、内核、后端以及附件。SQLite 通过利用虚拟机和虚拟数据库引擎(VDBE),使调试、修改和扩展 SQLite 的内核变得更加方便。
    Android 运行时环境包含了完整的 SQLite。Android 在运行时(Run-Time)集成了 SQLite,所以每个 Android 应用程序都可以使用 SQLite 数据库。对于熟悉 SQL 的开发人员来时,在 Android 开发中使用 SQLite 相当简单。这样的环境更有利于开发人员对项目的开发。
    3.3.2 XML文件1998年2月,W3C正式批准了可扩展标记语言的标准定义,可扩展标记语言可以对文档和数据进行结构化处理,从而能够在部门、客户和供应商之间进行交换,实现动态内容生成,企业集成和应用开发。可扩展标记语言可以使我们能够更准确的搜索,更方便的传送软件组件,更好的描述一些事物。例如电子商务交易等。它被设计用来传输和存储数据;
    超文本标记语言被设计用来显示数据。它们都是标准通用标记语言的子集。
    第四章 停车管理系统的设计4.1 系统设计概述智能停车管理系统的设计跟普通程序的设计有着许多不同的地方,采用C/S结构的智能停车管理需要考虑到手机数据与电脑数据之间共享的问题,当用户拿着智能手机在入口处登记用户信息时,需要将手机上的数据上传到服务端中,当汽车出库时,手机要监听服务端发送过来的出库信息,才能够将出库信息即使提醒用户。因此,在设计停车管理系统的过程中,必须要考虑好以下几个设计要点:
    在网络中的管理系统程序需要以服务器提供服务端连接响应,使用者通过客户端程序与服务器建立起联系,这样才能实现手机与电脑之间数据的共享,这是一个面向连接的通信过程。因此,程序要在TCP/IP环境下,实现服务器端和客户端两部分程序。

    4.2 系统设计层次图
    4.3 各模块详细功能4.3.1 服务端
    服务端程序清单:

    Program.cs:服务端主界面,负责用户进库,出库及计费。
    SocketHost.cs:服务器端监听客户端连接,并处理各种请求。
    SocketResponse.cs:服务器端发送客户端消息。
    XmlParser.cs: XML解析程序

    4.3.2 客户端
    客户端程序清单:

    HomeActivity.java:客户端主界面
    LoginActivity.java:用户进库主界面
    LogoutActivity.java:用户出库主界面
    SocketServer.java:Serivce服务,负责监听服务端发送的出库信息
    AppUtil.java:工具集程序
    SendSMSTask.java:发送短信提醒的定时器
    SqlHelper.java:数据库操作类

    4.4 主要模块分析4.4.1 服务端数据保存模块经分析发现每个用户的进库信息只有姓名,车牌号码,手机号,和进库时间这四个项目,数据量并不大,所以服务端用户采用轻量级XML文件存储用户数据的方法,这样做的好处是服务端不需要部署数据库,降低了使用成本。
    C#使用XmlDocument类对XML文件进行解析。XmlDocument将XML视为树状结构,它装载XML文档,并在内存中构建该文档的树状结构。
    在本程序中,我们首先检测程序路径下是否存在data.xml文件,如果不存在则先在xml容器中创建XmlDeclaration并且调用CreateElement(“”, “GarageInfo”, “”);创建名为GarageInfo的根节点,之后存入data.xml中。一个新创建的data.xml如下:
    <?xml version="1.0" encoding="UTF-8"?><GarageInfo />
    每次启动程序是,我们需要对data.xml文件进行解析,我们使用方法User [] parse_xml(filename),该方法返回一个用户数据结构数组。通过该数组能够获得xml文件中所有用户信息。parse_xml()方法的代码如下:
    private User[] parse_xml(String filename) { XmlDocument doc = new XmlDocument(); doc.Load(filename); XmlNode node = doc.SelectSingleNode("/GarageInfo"); XmlNodeList nodeList = node.ChildNodes; int i = nodeList.Count; User[] all_usr = new User[i]; //read all data into User[] array for(int j=0;j<i;j++) { XmlNode internal_node = nodeList.Item(j); if (internal_node != null) { User user = new User(); user.NAME = internal_node.Attributes["name"].Value; user.CAR_NUMBER = internal_node.Attributes["carnum"].Value; user.PHONE_NUMBER = internal_node.Attributes["phonenum"].Value; user.TIME = internal_node.Attributes["TIME"].Value; all_usr[j] = user; } } return all_usr; }
    当客户端发送用户进库信息时,我们要把用户进库信息写入xml文件,我们使用write_xml(String NAME, String CAR_NUMBER, String PHONE_NUMBER, String TIME)方法。该方法调用需要提供用户名,车牌号,电话号码,以及入库时间。该方法代码如下:
    private void write_xml(String NAME, String CAR_NUMBER, String PHONE_NUMBER, String TIME) { //加入另外一个元素 XmlDocument doc = new XmlDocument(); doc.Load("data.xml"); XmlNode root = doc.SelectSingleNode("GarageInfo"); XmlElement xe1 = doc.CreateElement("User");//创建一个<User>节点 xe1.SetAttribute("name", NAME); xe1.SetAttribute("carnum", CAR_NUMBER); xe1.SetAttribute("phonenum", PHONE_NUMBER); xe1.SetAttribute("TIME", TIME); root.AppendChild(xe1); doc.Save("data.xml"); }
    4.4.2 服务端监听模块在用户点击服务端上的侦听按钮之后,服务端会初始化一个ServerSocket,并开始对端口7631进行监听,为了使监听程序不至于阻塞主线程,我们需要新开一个线程,在此线程中将监听程序放入一个while(true)循环中。一旦遇到有客户端与服务端的TCP三次握手连接完成时,serverSocket.Accept()便会被触发,并返回一个客户端clientSocket,当每建立一个TCP连接时,都会新开一个线程用以接受数据。这样做可以提升服务器的并发访问量。关键代码如下:
    //set connection ipep = new IPEndPoint(IPAddress.Any, 7631); serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); serverSocket.Bind(ipep); serverSocket.Listen(10); //start a listener thread in order to avoid jamming the main thread listenerThread.Start();
    侦听线程代码:
    private void listener() { while (true) { try { //create a new thread when a tcp connection accepted to recive data clientSocket = serverSocket.Accept(); Thread clientThread = new Thread(new ThreadStart(ReceiveData)); clientThread.IsBackground = true; clientThread.Start(); } catch (Exception ex) { MessageBox.Show("listening Error: " + ex.Message); } } }
    当我们获取了一个clientSocket之后,我们需要获得其中汽车进库的数据,我们从输入流中提取客户端所发来的信息,然后将其写入用户列表listview和xml文件中,这里我们使用了C#自带的线程同步机制Invoke()来确保多线程的安全写入。在读取数据完成后,我们关闭套接字和线程,以便释放资源。代码如下:
    private void ReceiveData() { bool keepalive = true; Socket s = clientSocket; Byte[] buffer = new Byte[1024]; clientep = (IPEndPoint)s.RemoteEndPoint; while (keepalive) { int bufLen = 0; //client socket recive bufLen = s.Available; s.Receive(buffer, 0, bufLen, SocketFlags.None); clientep = (IPEndPoint)s.RemoteEndPoint; //get stuff from buffer string clientcommand = System.Text.Encoding.UTF8.GetString(buffer).Substring(0, bufLen); string[] stringSeparators = new string[] { "EOF" }; string[] split = clientcommand.Split(stringSeparators, StringSplitOptions.RemoveEmptyEntries); Invoke(new MethodInvoker(delegate() { add_listitem(split[0], split[1], split[2], split[3]); write_xml(split[0], split[1], split[2], split[3].Trim()); })); keepalive = false; } s.Shutdown(SocketShutdown.Receive); s.Close(); Thread.CurrentThread.Abort(); }
    4.4.3 客户端汽车进库模块当用户在智能手机上输入用户信息进行进库操作时,我们首先从控件中提取文本信息,然后新开一个线程,将用户信息保存到数据库中,并且通过套接字将用户信息发往服务器,关键代码如下:
    Runnable doBackGroundOperation = new Runnable() { public void run() { if(helper.insert(name, carNumber, phoneNumber, time)){ mHandler.post(new Runnable(){ startActivity(intent); try { // 实例化Socket Socket socket = new Socket(HOST, PORT); PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())), true); out.println(name+"EOF"+carNumber+"EOF"+phoneNumber+"EOF"+time); out.close(); socket.shutdownOutput(); socket.close(); } catch (IOException e) { e.printStackTrace(); } }else{ } } Thread thread = new Thread(doBackGroundOperation,"BackGroundOperation"); thread.start();
    4.4.4 客户端接监听提醒模块在实现客户端我们利用一个Android特有的机制Service来实现对服务端消息的长期监听。一个Service也是一种应用程序组件,它运行在后台以提供某种服务,通常不具有可见的用户界面。其它的应用程序组件可以启动一个Service,即使在用户切换到另外一个应用程序后,这个Service还是一直会在后台运行。此外,一个应用程序也可以绑定到一个Service然后使用进程间通信(IPC)方式与Service之间发生交互。例如一个Service可以处理网络事物,播放音乐,读写文件或者读写ContentProvider,所以这些都在后台运行。
    在本系统中,我们在HomeActivity的onCreat()方法中显式的调用startService(intent)来启动一个Service服务。在Service主程序内,我们使用与C#服务端监听模块相类似的Socket监听方法,进行数据监听。首先我们需要初始化一个ServerSocket实例,并指定监听端口24358。为了使监听程序不至于阻塞主线程,我们需要新开一个线程,在此线程中将监听程序放入一个while(true)循环中。每当遇到TCP连接请求时,serverSocket.Accept()便会被触发,在serverSocket.Accept()调用后,服务端和客户端便会完成TCP三次握手连接,并返回一个客户端clientSocket,当每建立一个TCP连接时,都会新开一个线程用以接受数据。
    当数据接收完成时,Service会调用NotificationBuilder通知用户汽车出库信息,并且将数据库中的用户信息删除。关键代码如下:
    public class AcceptRunnable implements Runnable { public void run() { while (true) { try { final Socket client = serverSocket.accept(); workHandler.post(new Runnable() { public void run() { clientSocket = client; new Thread(new RecieverRunnable()).start(); } }); } catch (IOException e) { e.printStackTrace(); } }
    数据接收线程主要代码:
    public class RecieverRunnable implements Runnable { public void run() { while (runnable) { try { read = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); String inputString = read.readLine(); runnable=false; } catch (IOException e) { runnable = false; e.printStackTrace(); } }
    4.4.5 客户端用户数据保存模块客户端用户数据存储采用Android系统自带的关系型数据库SQLite,当用户初次运行程序时,需要创建数据库,当用户进出库时,我们需要对数据库进行增加,删除和查询。
    经过分析,我们需要一张表,表中含有4个字段NAME,CAR_NUMBER,PHONE_NUMBER,TIME。分别为姓名,车牌号,电话号码,入库时间。我们以车牌号码为主键,当用户出库时需要输入车牌号码以便对数据库进行查询。
    用户数据表



    字段名
    数据类型
    是否主键
    是否为空
    字段含义




    NAME
    Varchar(50)


    车主姓名


    CAR_NUMBER
    varchar(50)


    车牌号


    PHONE_NUMBER
    varchar2(20)


    站经度


    TIME
    Varchar3(20)


    入库时间



    本程序的数据库操作模块在SqlHelper.java文件中。在该文件中,我们实现了对数据库进行创建,增加,删除和查询的功能。数据库关键代码如下:
    数据库创建代码:
    private static final String DATABASE_CREATE = "create table " + DATABASE_TABLE + " (" + CAR_NUMBER + " TEXT primary key, " + NAME + " TEXT not null, " + PHONE_NUMBER + " TEXT, " + TIME + " TEXT);"; public SqlHelper(Context context, int version) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } // Called when no database exists in disk and the helper class needs // to create a new one. @Override public void onCreate(SQLiteDatabase db) { db.execSQL(DATABASE_CREATE); }
    数据库查询代码:
    public Cursor query(String carNum) throws SQLException { StringBuffer bfr=new StringBuffer(carNum); bfr.insert(0, "'"); bfr.append("'"); SQLiteDatabase db = getWritableDatabase(); Cursor cursor = db.rawQuery("select * " + "from GarageMgr where CAR_NUMBER=" + bfr, null); if(cursor != null) { cursor.moveToFirst(); } return cursor; }
    第五章 停车管理系统的测试运行5.1 服务端运行界面运行软件后直接进入主界面,主界面显示车库内的停车情况。界面右上角是监听按钮,当用户点击后即可开启服务端监听服务。界面右下角是汽车出库按钮,当用户选中一个左边列表中的用户后,用户点击出库按钮该选中用户即可出库,并告知客户端。


    5.2 客户端运行界面客户端共分为三个运行界面,分别为运行主界面,汽车进库界面,汽车出库界面。在主界面中,用户可以通过点击按钮跳转进入汽车进库或者出库界面。如图所示。
    汽车进库界面中,用户输入自己的姓名,车牌号,手机号用来登记自己的入库信息,点击入库按钮后用户信息登记成功,系统跳转回主界面。如图所示。
    汽车出库界面中,用户输入自己的车牌号对数据库进行查询,当系统找到用户输入的车牌号后,系统进行出库操作并显示费用,当系统未找到该车牌号时,系统提示查询错误。如图所示。



    结 论经过一个多月的设计和开发,系统基本开发完毕。其功能基本符合用户需求,能够完成停车场车辆管理存储和。并提供部分系统维护功能,使用户方便进行数据备份和恢复、数据删除。,对于数据的一致性的问题也通过程序进行了有效的解决。
    但是由于毕业设计时间较短,所以该系统还有许多不尽如人意的地方,比如功能较少等多方面问题。这些都有待进一步改善。
    在软件的编写过程中,我充分体会了软件编程工作者的辛苦,因为每一个细微的细节都必须十分的注意,如果稍有不慎,就会全盘皆输,而且往往很多的时候,程序我自己觉得非常的正确,但是就是编译通不过,在查找错误的过程中,面临着否认自己的过程,非常的痛苦,而且由于自己的经验及各方面的能力的不足,所以进展的速度非常的缓慢,往往几天的时间还没有一点进展。
    在开始编写程序的时候,我看到别人的软件功能非常的详细,而且界面非常的漂亮,总希望自己的软件也非常的完善,但是,经过二个月的学习,发现编一个优秀的软件决不是一蹴而就的事情,需要长时间的积累和经验,而这个方面又是我的弱项,因此,在朋友的帮助下,我终于认清自己的不足及劣势,不要贪图大而全,只要尽我所能,编制一个实用简单的软件也是件很不容易的事情。
    在反反复复的学习及虚心请教之下,我的辛勤努力有了汇报,终于做出了一个简单的软件,虽然这个软件的功能非常的简单,而且我想,在实际的运用中,肯定会有所不足,但是,它毕竟代表了我辛勤的结晶。
    参考文献[1] 孟凡荣.数据库原理与应用.中国矿业大学,2009(8)28-30
    [2] 盖所林.Google Android 开发入门指南 —北京:人民邮电出版社 2009.
    [3] 罗军舟等. TCP/IP协议及网络编程技术.清华大学出版社.2008(10)
    [4] 孙一林,彭波.Java网络编程实例.清华大学出版社.2003(4)
    [5] 张运芳.Android 创赢路线与产品开发实战[M]. 北京:电子工业出版社, 2010.
    [6] 李树青.Java通用范例开发金典.电子工业出版社.2009
    [7] 王以忠,迟成,陈绍慧,张平,李达,黄国全. SQLite数据库在嵌入式果蔬保鲜运输车监测系统中的应用[J]. 保鲜与加工. 2011(04)
    [8] Hofmann C, Weindorf M, Wiesel J. Integration of GIS as a Component in Federated Information Systems.International Archives of Photogrammetry and Remote Sensing, 2000,33, 33 :1173~1180 .
    [9] Michael A P, Jeremy E W, Rocco Z. Integration of the Global Positioning System and Geographical Information Systems for Traffic Congestion Studies .Transportation Research. 2000,86, 8(6):257~285 .
    [10] Lan F Akyildiz, Janise McNair, Joseph Ho, Huseyin Uzunalioglu, Wenye Wang. Mobility Management in Current and Future Communications Networks .IEEE Network, 1998,124, 12(4) :39~49 .
    [11] Levinsohn A. Geospatial interoperability: The holy grail of GIS .GeoWorld, Oct, 2000
    3 评论 22 下载 2019-03-01 14:17:04 下载需要12点积分
  • 基于QT实现的基础图形绘图系统

    摘 要PaintWorks实现了图形数据的输入、编辑、填充、裁剪、变换、显示与保存功能。可绘制图形包括直线、圆、椭圆、多边形、曲线和3D六面体。交互界面简洁美观,操作实用方便。
    本绘图系统采用了面向对象设计,以C++11为基础,交互使用了Qt,基础图形的绘制使用了OpenGL,直线绘制使用了Bresenham算法,圆的绘制使用了中点圆生成算法,椭圆绘制用了中点椭圆生成算法,曲线绘制使用了3次Bézier曲线,多边形填充使用了多边形扫描填充算法,线段裁剪使用了梁友栋-Barsky算法,多边形裁剪使用了逐边裁剪算法。
    1 软件概述1.1 软件用途本软件主要用于基础图形绘制与保存,绘制完成之后可以对图形进行进行编辑、填充、裁剪等操作。
    1.2 特点本软件操作与显示简洁自然,简单方便。
    图形越新,所在图层越高;当用户选中某一图形时会自动切换到该图形对应的绘制模式并将该图形移动到最高图层。
    本软件的所有操作均可通过点击鼠标完成,其中,PaintWorks为使用频繁的操作与较为精细的操作提供了快捷键。
    2 软件安装为了免去用户安装的烦恼,PaintWorks给出了绿色免安装版,解压之后直接点击安装包中的PaintWorks.exe便可运行。(注:经过测试,不解压就运行可能会导致未知错误)
    3 使用指南3.1 图形绘制3.1.1 画笔颜色选取点击上方工具栏中的颜色选取工具(或按快捷键Ctrl+P),即可打开颜色选取对话框选取画笔颜色,之后线条颜色和填充色均为所选取的颜色。

    若不选取颜色,则默认线条颜色为黑色,填充色为绿色。
    3.1.2 2D图形PaintWorks可以绘制直线、圆、椭圆、多边形、曲线等二维图形,并可以对圆和多边形进行填充。绘制前首先点击菜单栏中的“新建画布”(或按快捷键Ctrl+N)新建画布。

    直线绘制:点击工具栏中的 按钮(或按快键键Alt+L),即可切换到直线绘制模式(软件启动默认绘制模式为直线)。点下鼠标左键并拖动,松开鼠标左键便可完成绘制,点下和松开的位置分别为直线的两端点。

    圆绘制:点击工具栏中的 按钮(或按快捷键Alt+C),即可切换到圆绘制模式。点下鼠标左键并拖动,松开鼠标左键便可完成绘制,点下鼠标左键的点为圆心,拖动的距离为圆的半径。点击工具栏中的 工具(或按快捷键Ctrl+F),即可完成对圆的填充。


    椭圆绘制:点击工具栏中的 按钮(或按快捷键Alt+E),即可切换到椭圆绘制模式。点下鼠标左键并拖动,松开鼠标左键便可完成绘制,拖动的横向偏移量为椭圆的横轴长度,纵向偏移量为椭圆的纵轴长度,拖动位移的中点为椭圆中心。

    多边形绘制:点击工具栏中的 按钮(或按快捷键Alt+P),即可切换到多边形绘制模式。单击鼠标左键绘制多边形第一个顶点,之后多次单击绘制多边形其他顶点,若要完成绘制只需单击第一个顶点,如图7. 选择填充色为绿色然后点击工具栏中的 工具(或按快捷键Ctrl+F)。


    曲线绘制:点击工具栏中的 按钮(或按快捷键Alt+V),即可切换到曲线绘制模式。先后单击4次鼠标左键绘制曲线的4个控制点,便可完成曲线的绘制。

    3.1.3 3D图形PaintWorks可以绘制3D六面体。点击点击菜单栏中的“新建3D画布”(或按快捷键Ctrl+T)新建3D画布标签页。

    此时新3D标签页中已经绘制完成一个3D六面体,如图11. 按键盘上的左右方向键可以控制这个六面体旋转。


    3.2 图形选中与编辑3.2.1 图形选中刚绘制完成的图形默认已经被选中,其关键点用蓝色圆点标记(如3.1.2中各图所示)。若要选中其他图形,只需点击想要选中的图形,该图形就会被选中且浮动到最高图层。

    3.2.2 图形编辑点击并拖动已选中图形的蓝色标记点,即可对图形形状进行编辑,操作与图形绘制时类似。

    直线标记点:两端点
    圆标记点:矩形四个端点
    椭圆标记点:矩形四个端点
    多边形标记点:各个顶点
    曲线标记点:四个控制点

    3.3 图形变换3.3.1 平移在选中情况下,图形中心有一个带十字的中心标记点。点击并拖动这个中心标记点,即可拖动这个图形。

    3.3.2 旋转在选中情况下,图形中心标记点有一条蓝色的直线延长出来的一个蓝色标记点,称为旋转标记点,旋转标记点与中心标记点的连线称为handle,如图14,中心标记点上方的蓝色圆点即为旋转标记点。点击并拖动这个旋转标记点,即可旋转该图形。


    直线旋转:以直线中点旋转
    圆的旋转:以圆心旋转,但由于圆是中心对称图形,所以旋转中视觉上没有明显效果
    椭圆旋转:以中心旋转,但由于椭圆旋转之后可以会出现变形,所以椭圆只能进行90度旋转,即只有在handle水平或垂直时做90度的旋转
    多边形旋转、曲线旋转:均绕中心标记点旋转

    3.3.3 缩放用户对当前选中的图形进行放大或缩小,放缩的中心为该图形的中心标记点。点击工具栏的放大与缩小按钮分别可以进行放大与缩小(快捷键为Ctrl + + 和Ctrl + -),如下图左右两侧图为曲线缩小和放大的效果。



    缩小
    原图
    放大










    3.4 图形裁剪用户可以使用工具栏中的 工具对当前选中的图形进行裁剪,裁剪仅限直线或多边形。
    首先点击这个工具(或按快捷键Ctrl+C),这个工具会显示被按下,此时可以在画布中绘制出一个红色的虚线框作为裁剪窗口。

    此时可以拖动红色虚线框的四个顶点对裁剪窗口进行调整,也可以直接重新绘制一个裁剪窗口。
    确定裁剪窗口之后,再次点击 工具(或按快捷键Ctrl+C),便可完成裁剪。其中需要说明的是,裁剪之后图形会被重绘,因为当前选择的画笔颜色为绿色,所以轮廓为绿色,与填充色融为了一体(而不是轮廓消失了)。

    3.5 图形删除与保存3.5.1 删除与清空
    用户可以对当前选中的图形、画布进行删除或清空操作
    要删除当前图形,只需点击工具栏中的 (或按快捷键Delete)即可将该图形删去
    要清空当前画布,只需点击工具栏中的 (或按快捷键Ctrl+Delete)即可清空画布

    3.5.2 保存图形用户可以保存画布上的图形为BMP文件(普通画布与3D画布均可保存),点击菜单栏中的“文件”>“另存为…”,即可打开一个文件保存对话框。


    输入文件名,选择路径,便可把当前画布的图像保存成BMP格式的文件。
    3.6 出错处理经过测试,本软件鲁棒性较好,但仍难以避免一些意外发生,如果出现了错误,重启即可。
    3.7 注意事项
    在新图形绘制过程中不要点到原有图形上,否则会选中原有图形,中断新图形的绘制。即便如此,原先的绘制信息也不会丢失,将绘制模式切换回来就可以继续绘制了
    由于裁剪算法所限,在裁剪凹多边形的一些特定情况下可能会出现一些不完全正确的裁剪结果

    4 系统框架设计4.1 开发环境


    操作系统
    Windows 10家庭中文版




    编程语言
    C++ 11


    外部库
    Qt 5.4,OpenGL 2.7


    编译器
    MinGW 4.9.1 32bit


    IDE
    Qt Creator 3.3.0



    4.2 系统架构概览用Qt向用户提供交互,用OpenGL提供底层绘制,考虑到Qt与OpenGL的兼容性,使用了继承自QWidget的子类QGLWidget实现Qt环境下的OpenGL绘制:

    QMainWindow负责与用户交互,并以标签页的形式集成了QGLWidget
    QGLWidget负责绘制本标签页的内容,并集成了各类FigureControl,用于将本标签页的交互信号送给不同的图形控制类
    FigureControl负责该类型图形的交互,有LineControl、CircleControl、EllipseControl、PolygonControl等,用于分别提供不同图形的不同交互方式
    Figure负责保存该图形的数据信息,包括顶点、圆心、半径以及轮廓点、填充点等,集成了Point类,图形绘制通过调用Point的draw函数完成
    Point负责实现绘制单个普通点或标记点,并向上提供其他常用功能函数支持

    系统核心架构图

    其中GLWidget派生出一个GL3DWidget,作为3D标签页,用于3D图形的绘制;在FigureControl层有一个CutWindow类,用于绘制裁剪窗口。系统架构中的聚集关系如下图:

    Point类作为轮廓和填充的构成部分聚集在Figure类中;Figure类的数组放在FigureControl中,由FigureControl处理本Figure的相关交互;CutWindow用于管理裁剪窗口;GLWidget为2D画布的标签页,GL3DWidget继承自GLWidget,作为3D画布标签页;所有标签页聚集在QMainWindow中,由QMainWindow与用户交互并向下发送消息。
    4.3 图形管理类:FigureControl图形管理类之间的关系较为简单,主要用于存储本图形的数据,并进行与本图形相关的交互,如鼠标点击、键盘按下、图形绘制、设置聚焦、裁剪当前图形等,类继承关系如下图:

    4.4 图形类:FigureFigure为所有图形的虚基类,继承关系如下图:

    Figure类提供所有图形都应有的共同接口:

    基础绘制:绘制图形、绘制图形标记点、清空图形
    基础变换:平移、旋转、缩放
    判断某点是否在该图形上


    SimpleFigure是对所有简单图形的抽象,SimpleFigure的轮廓均直接由点构成。而Polygon的边为Line,所以不属于SimpleFigure。SimpleFigure中提供了通用的draw()、clear()、isOn()。
    Area是对所有可填充图形的抽象,用于填充点管理,提供了与填充相关的函数。
    Line、Circle、Ellipse、Curve、Polygon分别为直线、圆、椭圆、曲线、多边形。其中由于Ellipse和Polygon与OpenGL库中命名冲突,所以在实现中命名为MyEllipse和MyPolygon,但相应代码文件名仍为Ellipse和Polygon。
    4 评论 109 下载 2018-12-10 20:51:16 下载需要8点积分
  • 基于SSM的网上购物系统的设计与开发

    摘 要本论文主要对网上购物商城的设计与开发进行了一些论述,包括了系统的设计和实现一共两个大部分,设计部分主要对系统和数据库的分析与设计进行了描述;实现部分主要包括系统的各个功能的实现。
    网上购物商城包括两大模块:前台用户模块和后台管理员模块,前台用户可以通过浏览器客户端页面进行登陆和一系列的购物操作。后台管理员可以查看所有用户的所有信息;可以对网站中所有的商品分类进行修改,同时也可以对所有用户的订单状态进行查看。
    系统前台通过JSP页面来来展示数据,后台基于java技术和eclipse (朱诺)和tomcat 7.x开发,前台运用html+css技术渲染页面,后台使用springmvc、spring、myBatis对数据进行封装和操作,该系统运用MySql 5.X 数据库进行数据的维护。页面美观,使用方便。
    关键词:MySql数据库; JAVA; SSM;网上购物商城
    AbstractThis paper mainly focuses on the clothing sales system design and development of a number of paper, including the system design and implementation of a total of two parts, part of the system design and database analysis and design were described; the realization part includes the various functions of the system.
    Clothing sales system includes two modules: front user module and the background administrator module, the front desk users can browse through the browser client page and a series of shopping operations. The background administrator can view all the information of all users can be on the site of all the clothing category to modify, but also for all users to view the order status.
    In front of the system through the JSP page to display the background data, Java technology and based on eclipse (Zhu Nuo) and Tomcat 7.x development, the use of html+css technology to render the page, the background using springmvc, spring, myBatis package and operation of data, the system uses MySql 5.X database for data maintenance. Beautiful page, easy to use.
    Keywords: MYSQL DB;JAVA;SSM;CLOTHING SALES SYSTEM
    1 绪论1.1 研究背景在如今这个信息时代,“网上购物”这种购物方式已经为越来越多的人所接受。在这种背景之下,一个安全稳定并且强大的网络购物平台不可或缺,在这种成熟的市场需求的推动下,在先进的信息技术的支持下,商品产品销售系统应运而生。它可以使消费者和商家更紧密地联系起来,以更快地满足顾客的需求,也可以让用户选择自己真正喜欢的商品。目前市面上已经有此类的网上购物商城,但是现有商品网站系统或多或少存在着功能比较单一、维护比较复杂、操作比较繁琐等问题。有的系统甚至直接采用静态网页发布商品商品信息,这些因素在一定程度上限制了网上购物商城在目前市场上的推广。如何开发出费用低廉、功能强大的系统正是我们需要解决的课题。
    1.2 目的和意义本软件旨在降低商品销售商家的工作强度,提高工作效率,大大地减少了操作员手工录入数据的工作量,极大限度的避免了人力浪费,有效避免重复操作时间消耗;而且此软件方便了用户对自己所需商品的查询和购买,打破了传统的销售模式,极大限度的方便了用户。商家应用此软件之后,可以拓展销售门路,增加销售业绩。应用此软件是为了在传统销售模式之外,再开辟一条销售通路,减少库存堆积,利用网络共享和互动的优点,结合地面销售的优点,借助数据库管理技术,开发此平台,是为了实现规范化、个性化、人性化的商品网上销售。此软件的数据统计分析功能灵活完善,稳定安全、使用方便、界面友好、操作简单,可以成为一个能真正帮助商品销售行业管理发展的有力工具。
    1.3 开发工具及技术该网上购物商城前端使用了jsp来实现数据的展示,后端通过java代码来对数据进行一系列的操作,前端使用了原生的html页面技术进行渲染,同时也加入了jquery技术制作了一下控件效果,后端使用了经典的spring技术对整个系统进行统一调度,使用springMvc框架实现了前端和后端的交互。开发工具使用了Eclipse以及tomcat服务器,同时使用了Mysql数据库对数据进行存储和维护。
    在该系统实现的过程中,使用spring和springMvc的同时后端还使用了MyBatis技术对数据进行封装和操作。前端还采用了dtree框架规范了页面的显示。整个系统的架构也是基于经典的mvc设计模式来设计的。
    Mybatis是一个经典的后端开源框架,它的前身就是iBatis,MyBatis的执行原理是应用程序根据XML配置文件创建出SqlSessionFactory,然后SqlSessionFactory根据配置文件或者注解创建出SqlSession,SqlSession这个对象包含了所有的执行sql所需要的所有方法,可以通过SqlSession这个实例执行所有的方法对数据库进行操作,操作结束后执行相应的事物控制,本系统中的事物控制全部交由spring容器进行统一调度,本次采用的是spring的申明式 方式。MyBatis相对于 其他的ORM框架具有很多的优点,比如mybatis本身属于轻量级框架简单易学,没有第三方的依赖。mybatis比较灵活,开发人员可以自己编写sql语句来对数据进行操作。mybatis提供了xml标签,支持编写动态sql.
    dtree框架就是一个简单的树形菜单js组件,开源免费,自身不需要复杂的操作,同时也支持动态的将数据引入jsp页面。
    MVC模式是一种软件架构模式。它将系统分为三个部分:模型,视图和控制器。MVC模式出现的目的就是方便了后续程序的修改和扩展简化,同时使系统中某一段代码的重复利用成为可能。此模式降低了模块之间的耦合度,对自身各个部分进行了分离的同时也使得各个部分具备了应有的功能。
    Spring是从实际开发中抽取出来的开源框架,为企业的开发提供一个轻量级的解决方案。该解决方案包括:基于Ioc(控制反转)的核心机制,以及AOP(面向切面编程)的思想,能与多种持久层技术的整合,是优秀的Web MVC框架等。Spring致力于Java EE应用各层的解决方案而不是仅仅专注于某一层的方案,它贯穿表现层、业务层、持久层,降低各层组件的耦合度,实现软件各层的解耦.Spring内部最核心的就是IOC了,动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射,反射其实就是在运行时动态的去创建、调用对象,Spring就是在运行时,跟xml Spring的配置文件来动态的创建对象,和调用对象里的方法的。还有一个核心就是AOP这个就是面向切面编程,可以为某一类对象 进行监督和控制(也就是 在调用这类对象的具体方法的前后去调用你指定的 模块)从而达到对一个模块扩充的功能。这些都是通过配置类达到的。Spring是一个容器,凡是在容器里的对象才会有Spring所提供的这些服务和功能。
    2 需求分析2.1 功能需求分析2.1.1 网站前台功能
    首页:提供一个网站首页,显示该企业的商标,该网站用户的登录,注册,所有商品的一级分类,热门商品和最新商品的展示等
    用户的注册:针对还未注册的用户完成注册功能的使用,在注册的过程中涉及数据的合法性校验,以及利用ajax完成用户名是否已被注册的异步校验
    用户的登录:对于已经注册并且激活的用户提供的登录操作
    用户的退出:对于已经登录的用户,退出系统
    首页商品展示:展示出最新商品和热门商品
    分类页面商品展示:根据一级分类和二级分类去展示该分类下的所有商品
    商品详情展示:点击某个商品时可以展示该商品的具体详细信息
    购物车:用于存放用户的购物内容,用户可根据自己的情况修改自己的购物车
    订单:对于已经登录的用户可以对购物车内容进行付款生成订单,可以为自己的订单进行付款或者查看
    留言评价分享:网站单独开辟了留言分享区域,供登录的用户自由发表评价分享心得信息,进行交流互动

    2.1.2 网站后台功能
    管理员登录:管理者根据账户和密码进行登录
    商品一级、二级分类管理:管理者可以对前台显示的一级、二级分类进行管理,包括添加、删除、修改操作
    商品管理:管理者可以对前台显示的商品进行管理包括添加,修改,删除,查询的功能,也可以上传商品的图片
    用户管理:管理者可以查看该网站中已经注册过的所有用户的所有信息

    2.2 性能分析响应时间:忽略网络、硬件以及插件的因素,以本地测试为准,前台响应时间为0.8秒,后台操作响应时间:0.9秒。
    2.3 系统用户用例图用户用例图
    用户为系统的使用者,可以通过前台注册激活登录后进行一系列的购物操作。

    管理员用例图
    管理员是整个系统的最高权限拥有者,他用于对所有用户的所有信息的查看,网站商品显示的增删改查,更换图片,所有商品所属一级二级分类的修改。

    3 系统设计3.1 系统的总体设计该系统的开发采用B/S模式,整个系统的构建基于ssm(Spring+SpringMvc+MyBatis)整合框架。
    深入研究JavaEE体系结构,所项目的技术选型中选取的个个框架分别进行分析和研究。SpringMvc是一个web端框架。Mybatis是一个轻量级的持久层框架,以面向对象的方式提供了持久化类到数据库之间的映射,是一种优秀的ORM框架。Spring也是一种轻量级框架,它的IOC和AOP思想,值得架构师学习。通过三大框架的整合,可以很方便的构建出可扩展,可移植,可维护的软件系统。
    SSM框架是目前J2EE领域中最热门而且用的比较成熟的一套开源框架,它是基于MVC设计模式之上,充分发挥了MVC的优点。SSM是一套轻量级框架,相对于EJB而言,SSM继承了它的优点的同时,在开发和执行效率上也有了明显的提高,而对于开发者而言,它比EJB更加易学和掌握。目前SSM框架也正在不断地进行优化和维护,运行也是越来越稳定。
    根据以上功能分析,得到系统功能模块结构图如图3-1所示:

    3.2 数据库的分析与设计数据库,我们可以形象的将它称为一个仓库,因为它一般被用来存放汉字、字符、数据、货币、日期等信息,并且对这些信息按照一定规则存放,对数据进行安全、低冗余性、规范的进行集成化管理。从发展的历史历程来看,数据库可以看成是由文件管理系统发展而来的。
    数据库的基本结构可以分为三个层次包括物理数据层、概念数据层、逻辑数据层。数据库不同层次之间的联系是通过映射进行转换的,数据库的特点包括实现数据共享、减少数据的冗余度、数据的独立性、数据实现集中控制、数据一致性和可维护性。
    本系统采用的的数据库是Mysql5.0,本系统所有与数据库相关的开发都遵循Mysql5.0数据库开发原则。
    3.2.1 数据库概念设计用户实体
    用户实体包括编号、用户账号、姓名、联系方式、性别、用户状态、用户邮箱和密码等属性。用户实体的实体联系图(E-R图)如下所示:

    管理员实体
    管理员实体包括编号、账号和登录密码属性。管理员实体的实体联系图(E-R图)如下所示:

    商品实体
    商品实体包括商品id、商品名称、市场价、商场价、商品图片、商品描述、上架日期、所属二级分类id。商品实体的实体联系图(E-R图)如下所示:

    订单实体
    订单实体主要包括订单id、订单总价、订单状态、收货人、收货地址、收货电话、下单时间、购买者id、购买商品id。订单实体的实体联系图(E-R图)如下所示:

    3.2.2 数据库物理结构为该系统设计了7张表,在这里列出7张表分别为如下所示:



    数据表
    描述




    adminuser
    后台管理员表


    category
    一级分类表


    categorysecond
    二级分类表


    orderitem
    订单项表


    orders
    订单表


    product
    商品表


    user
    前台用户表



    管理员表主要记录了管理员的基本消息,表结构如表3-1所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    id
    int(11)
    YES
    YES
    账号


    username
    varchar(1000)
    NO
    NO
    用户名


    password
    varchar(1000)
    NO
    NO
    密码



    一级分类表主要记录了一级分类的基本信息,表结构如图3-2所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    cid
    int(11)
    YES
    YES
    一级分类ID


    cname
    varchar(1000)
    NO
    NO
    一级分类名



    二级分类表主要记录了二级分类的基本信息,表结构如图3-3所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    Csid
    int(11)
    YES
    YES
    二级分类id


    Csname
    varchar(1000)

    NO
    二级分类名称


    cid
    varchar(1000)

    NO
    所属一级分类id



    订单项表主要记录了订单项的基本信息,表结构如图3-4所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    Oiid
    int(11)
    YES
    YES
    订单项id


    count
    varchar(1000)


    购买数量


    subtotal
    double


    单项总价id


    Pid
    int(11)


    所购商品id


    cid
    int(11)


    所属订单id



    订单表主要记录了订单的基本信息,表结构如图3-5所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    oid
    int(11)
    YES
    YES
    订单id


    money
    double


    订单总价


    state
    Int(11)


    订单状态


    Receiveinfo
    Varchar(255)


    收货地址


    phonum
    Varchar(255)


    收货人电话


    Order_time
    datetime


    下单时间


    Uid
    Int(11)


    所属用户id



    商品表主要记录了商品的基本信息,表结构如图3-6所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    Pid
    int(11)
    YES
    YES
    商品id


    Pname
    Varchar(255)


    商品名称


    Market_price
    Int(11)


    市场价


    Shop_price
    Varchar(255)


    商城价


    image
    Varchar(255)


    商品图片


    Pdesc
    Varchar(255)


    商品描述


    Is_hot
    int(11)


    是否热门


    Pdate
    datetime


    商品上架日期


    csid
    int(11)


    所属二级分类id



    前台用户表主要记录了前台用户的基本信息,表结构如图3-7所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    Uid
    int(11)
    YES
    YES
    用户id


    Username
    Varchar(255)


    用户名


    password
    Varchar(255)


    用户密码


    Name
    Varchar(255)


    用户真实姓名


    Email
    Varchar(255)


    用户游戏


    Phone
    Varchar(255)


    用户手机号


    Addr
    Varchar(255)


    用户地址


    State
    int(11)


    用户状态



    3.3 小结本章主要是对数据库进行了设计和说明。对数据库的概念设计思路和物理结构进行了详细的说明,并对数据库中涉及到的实体进行了说明。
    4 系统主要功能实现4.1 系统注册页面实现4.1.1 客户端用户注册用户登录网站出现页面,点击“注册”,进入注册页面,填写数据,点击注册按钮进行注册,注册完之后保存数据库表中,即可登录网站。
    注册效果如图4-1所示:

    var username = document.getElementById("username").value;var xmlHttp = creatXMLHttpreauest();xmlHttp.open("GET","${pageContext.request.contextPath}/registFindByid.action?username="+ username, true); xmlHttp.send(null); xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { document.getElementById("span1").innerHTML = xmlHttp.responseText;
    服务器端二次数据合法性校验(此处采用的配置文件加注解的方式)
    user.username.length.error=用户名的名字的长度必须是1至30user.email.notNull=邮箱不可为空@Size(min=2,max=30,message="{user.username.length.error}") private String username; @NotNull(message="{user.email.notNull}") private String email;
    4.2 系统登录页面实现4.2.1 用户登录用户在注册后,在客户端登录页面输入正确的用户名和密码,进入网站进行购物。 程序运行如下图4-2所示:

    设计思路
    编写用户登录的页面login.jsp,用户在首页点击“登录”按钮后,浏览器跳转到登录页面,用户可以填写用户名和密码进行登录,当用户填写用户名并使光标移开 时,触发onblur()事件,进行ajax异步请求,判断用户名是否可以登录,用户在填写验证码时可以点击图片,进行跟换验证码,触发onclick=”change()” 事件进行更换,当用户点击“登录”按钮时,服务器进行数据判断,如果用户名和密码都正确则跳转到首页并显示该用户的用户名,如果有错误则跳转到msg.jsp全局页面显示错误消息。
    4.2.2 管理员用户登录后台管理员通过访问正确的路径之后进入到管理员登录页面,如果访问的不是正确页面但出现了admin路径则自动跳转到admin页面,然后输入正确的用户名和密码进行登录,如果出错,服务器会将错误信息回显到登录页面,如果正确则跳转到管理员页面。
    程序运行结果如图所示,图4-3显示了管理员登录的页面,图4-4则是管理员登录成功后的主页面:


    4.3 系统前台功能实现系统前台页面包括以下几个部分:首页一级分类,热门商品,最新商品的显示,二级分类的显示,已登录用户的订单以及用户所操作过的购物的展示,其中一级分类和二级分类在各个页面中都有所设计,因此这里采用的是页面包含技术。
    4.3.1 一级分类模块查询一级分类描述
    本系统中首页显示的一级分类都是存放于数据库中,当用户访问该网站首页的同时就查询了一级分类。一级分类显示效果如图4-5所示:

    设计思路
    一级分类展示于系统的首页,当用户访问index.action时,最终跳转至系统首页即index.jsp,跳转之前,服务器内部已经进行了一级分类的查询,并将已经查询到的以及分类存放于List集合中,最终存放于session域中。
    查询某个一级分类描述
    用户在进入系统首页时,当点击一级分类时就要求查询系统在下一个页面中显示出该一级分类中包含的所有二级分类。查询某个二级分类的效果图如图4-6所示:

    设计思路
    当用户点击首页中的一级分类时系统则根据此一级分类的id查询出该一级分类下所有的二级分类,并存放于session域中,将页面进行跳转,并进行展示。
    主要代码
    request.getSession().setAttribute("cid",cid);PageBean<Product> proPageBean = productService.findProductyBycid(cid,page);model.addAttribute("pageBean",proPageBean);return "category";
    4.3.2 商品模块查询最热商品描述
    当用户访问该网站时,首先显示的是网站的首页,首页中将显示本网站中最热的商品。程序运行结果如图4-7所示:

    设计思路
    用户访问首页index时,根据路劲“/index.action”首先调用的是系统的index.action,最后跳转至系统的首页index.jsp,因为最热商品显示于首页中,因此在页面跳转之前必须前往数据库查询出本系统中所有的热门商品,因此使用了findHotProduct()这个方法,由于首页中仅仅显示了最新商品中的前十个,因此这里是使用的分页查询,最终查询的结果是一个list集合,最终保存在Model中。
    前段控制层代码
    List<Product> hList= productService.findHotProduct();
    service层代码
    List<Product> list = productMapper.selectByExample(example);
    查询最新商品描述
    当用户访问该网站时,首先显示的是网站的首页,首页中将显示本网站中最新的商品。程序运行结果如图4-8所示:

    设计思路
    用户访问首页index时,根据路劲“/index.action”首先调用的是系统的index.action,最后跳转至系统的首页index.jsp,因为最新商品和最热商品一样都是显示于首页中,因此在页面跳转之前必须前往数据库查询出本系统中所有的最新商品,因此使用了findNewProduct()这个方法,查询最新商品的依据是商品被上传的时间,根据时间来进行排序,由于首页中仅仅显示了最新商品中的前十个,因此这里是使用的分页查询,最终查询的结果是一个list集合,最终保存在Model中。
    前端控制层代码
    List<Product> nList =productService.findNewProduct();
    service层代码
    ProductExample example = new ProductExample();ProductExample.Criteria criteria = example.createCriteria();example.setOrderByClause("pdate DESC");example.setBeginPage(0);example.setEnd(10);
    查询分类商品描述
    用户在点击首页的一级分类时,系统自动跳转页面,同时要求在右面显示某个二级分类下的商品。程序运行结果如图4-9所示:

    设计思路
    首先导入页面,页面和查询二级分类下的商品使用的是同一个页面category.jsp。当用户点击按钮时,客户端向服务器请求发送请求并携带一级分类的主键id,因此服务器端应该接受参数并使用这个参数来调用方法然后去数据库进行查询数据,最后将查询出的数据把保存于Model中,最后跳转页面。
    由于页面大小的关系,这里仅仅显示12个商品,因此这里采用了分页查询,并在右下角设置相应的按钮,方便用户来回查看该分类下所有的商品。
    前端控制层接收参数并调用service层代码
    //根据一级目录查找二级目录下面的商品productService.findProductyBycid(cid,page);model.addAttribute("pageBean",proPageBean);
    Servive层代码
    int totlePage = 0;totlePage = productMapper.countProducyByCid(cid);if(Math.ceil(totlePage % limitPage)==0){totlePage=totlePage / limitPage;}else{totlePage=totlePage / limitPage+1;pageBean.setTotlePage(totlePage);int beginPage= (page-1)*limitPage;
    查询二级分类商品用户在点击首页的一级分类时,系统自动跳转页面,并且在页面的左面显示所有一级分类包含的二级分类,同时要求在右面显示某个二级分类下的商品。程序运行结果如图4-10所示。

    设计思路
    首先编写页面category.jsp,这个页面用来显示某个二级分类下的所有的商品,当用户点击二级分类时系统访问对应的action,并且携带参数(相应二级分类的主键id),到前端控制层,然后findCategorySecond1()方法接收主键id和分页的数目去product表查询商品,最终将查询到的结果存放于Model中。由于页面大小的关系,这里仅仅显示12个商品,因此这里采用了分页查询,并在右下角设置相应的按钮,方便用户来回查看该分类下所有的商品。
    前端控制层接收参数并调用service层
    // 根据csid来分页查询商品PageBean<Product> proPageBean = productService.finbProductByCsid(csid,page);model.addAttribute("pageBean",proPageBean);
    查询商品信息用户再浏览该商场,查看某个商品的详细信息。程序运行结果如图4-11所示:

    设计思路
    首先编写页面,这里使用的是product.jsp,在这个页面中显示了以及分类的信息,还有每个一级分类下的二级分类,右下方是某个商品的具体信息,其中包括商品的名称,商品的商城价和市场价,包括一个选择框,用于用户选择购买数量,最下面则是商品的具体介绍。当用户点击某个想要查看的商品图片时,其实就是点击了某个超链接,向服务器发送链接并携带参数(商品的主键id),服务器端接收这个参数,并使用这个参数去数据库中查看这个商品的具体信息最后封装于product中,最终存放于Model中。
    前端控制层接收参数并调用service层,Service层直接调用Mybatis提供的mapper接口
    //根据pid来查询商品Product product = prodcutService.productFindByPid(pid);model.addAttribute("product", product);
    4.3.3购物模块添加到购物车对于已经登录的用户,可以将看中的商品具体信息保存于自己的购物车中。

    设计思路
    首先编写cart.jsp用于显示登录用户的购物车,如果用户没有登录会有提示,用点击查看商品的详情之后会出现一个“加入购物车”按钮,当点击此按钮时,自动访问服务器,并通过隐藏表单携带参数(商品的主键id),服务器端在接受此参数,并接收用户选购的数量,最终保存于我们为每个用户在session域中创建的cart。最后进行页面跳转,在cart.jsp中展示购物车的信息,主要包括:商品的具体信息和每项的价格和购物车的总价。对于已登录用户的页面,可以看到一个购物车的图标,用户可以查看自己的购物车。
    主要代码
    //添加到购物车Product product = productService.finbProductByPid(pid);//存进一个购物项CartItem cartItem = new CartItem();cartItem.setCount(count);cartItem.setProduct(product);cartItem.setSubtotle(count*product.getShopPrice());//存进购物车Cart cart=getCart(request);cart.addCart(cartItem);
    从购物车中移除商品用户点击购物车页面中每个购物项后面的删除按钮即可删除该购物项。程序运行结果如图4-13所示:

    设计思路
    当用户点击 “删除”按钮时,向服务器端进行请求,并携带参数(商品的主键id),服务器端在设计购物车时采用的是用Map集合存储的,key值即商品的id,因此删除的时候只需从session中拿到购物车直接根据主键删除,最后将页面重定向到cart.jsp.
    主要代码
    Cart cart=getCart(request);cart.delProFromCart(pid); //删除某个购物项
    清空购物车用户点击“清空购物车”按钮,购物车里面的购物项全部删除。程序运行结果如图4-17所示:

    设计思路
    当用户点击 “清空购物车”按钮时,向服务器端进行请求,服务器端收到请求之后,从session域中取出cart购物车,由于cart在设计的时候使用的是Map集合,所以只需调用Map中的clear()方法即可,并且还需将购物车的总价改为0,最后将页面重定向到cart.jsp.
    主要代码
    // 清空购物车Cart cart=getCart(request);cart.clearCart();
    4.3.4 订单模块生成订单当用户点击“生成订单”按钮时,页面跳转至order.jsp,并让用户填写相关信息。程序运行结果如图4-15所示:

    设计思路
    首先编写order.jsp页面,其中包含用户的购物信息和收货地址、收货人和联系方式。当用户点击cart.jsp中的生成订单按钮时,向服务器发送请求,服务器端从session域中拿到cart中的信息,并将这些信息保存于order表中,此时,需要清空购物车并且将订单信息保存到session域中,最后跳转到order.jsp页面让用户填写相关信息,并付款。
    主要代码
    Orders orders = new Orders();Cart cart = (Cart) request.getSession().getAttribute("cart");User loginUser = (User) request.getSession().getAttribute("loginUser");if(loginUser==null){ model.addAttribute("message", "对不起您还没有登录"); return "msg";}//生成订单
    我的订单用户对自己的选购的商品所生成的订单项进行付款。即可生成订单,进入我的订单列表界面;程序运行结果如图4-16所示:

    设计思路
    为订单付款页面还是使用的是order.jsp,当用户点击cart.jsp中的提交按钮时,页面进行跳转并显示相关的订单信息,此时,用户可以暂时不对订单进行付款,此时订单的状态为0。如果用户在生成订单的同时一并付款,或者点击用户的最上方右边的红色字体“我的订单”时,页面会进行跳转,并显示该用户的所有订单和订单的状态,此时想要付款则点击按钮“付款”,也会跳转到order.jsp,此时需要用户填写订单的具体信息,包括收货地址、收货人、联系方式以及付款的银行,此时客户端和服务器端一样会进行非空和数据合法性校验,当用户填写好信息并点击“付款”按钮时,其实就是服务器端拿订单的具体信息,并将订单的状态改为“1”,同时将用户填写的关于收货的信息保存于数据库order表中,最终服务器端会将页面重定向到orderList.jsp,向用户展示他的所有的订单以及订单的具体信息。在orderList.jsp中展示该用户的所有订单时采用的是分页查询,在订单的右下角同时也设置了按钮,方便用户查看自己的所有按钮。
    4.3.5 留言模块留言板当用户点击“留言板”按钮时,页面跳转至messageList.jsp,并让用户填写相关信息。程序运行结果如下图所示:

    4.4 系统后台功能实现4.4.1 用户模块查询用户管理员进入后台管理页面之后,当他点击“用户管理”按钮时,则在主页面中显示所有用户的详细信息。程序运行结果如图4-17所示:

    设计思路
    先编辑list.jsp页面,当用户点击“用户管理”按钮时,服务器端收到请求,调用service层的admin_findAll()方法由service 层调用myBatis提供的mapper接口,返回一个list集合,最终所有信息封装于Model中将页面跳转到list.jsp并进行展示。
    主要代码
    if(adminuserLogin==null){ request.getSession().setAttribute("message","对不起您还没有登录"); return "admin/index";
    4.4.2 一级分类模块添加一级分类此功能属于管理员的权限范围内,用户管理员为网站添加新的一级商品系别。程序运行结果如图4-18所示:

    设计思路
    首先编写add.jsp页面,当用户在一级分类list.jsp页面点击“添加”按钮时, 服务器将页面跳转至add.jsp,在此页面共有三个按钮,“确定”按钮用于提交信息,“重置”按钮清空表单中的内容,“返回”按钮返回前一个页面。当用户填写好要添加的一级分类的名称之后点击“确定”按钮,服务器端接收此表单中的内容,然后调用service层的addCategory()方法,将新增的一级分类保存到数据库category表中,最后将页面重定向到list.jsp页面,展示所有的一级分类。
    主要代码
    Category addCategory = new Category();addCategory.setCname(cname);categoryService.addCategory(addCategory);
    修改一级分类此功能属于管理员的权限范围内,管理员用户修改网站中各大服饰的一级分类的名称。程序运行结果如图4-19所示:

    设计思路
    首先编写edit.jsp页面,当用户在一级分类list.jsp页面点击“添加”按钮时, 服务器将页面跳转至edit.jsp,在此页面共有三个按钮,“确定”按钮用于提交信息,“重置”按钮清空表单中的内容,“返回”按钮返回前一个页面。当用户填写好要修改的一级分类的名称之后点击“确定”按钮,服务器端接收此表单中的内容,然后调用service层的adminCategory_update()方法,将修改的一级分类更新到数据库category表中,最后将页面重定向到list.jsp页面,展示所有的一级分类。
    删除一级分类后台管理员点击每个一级分类后面的删除按钮即可删除该一级分类。程序运行结果如图4-20所示:

    设计思路
    当用户点击每个一级分类后面的“删除”按钮时,服务器接收到请求然后接收携带过来的参数(一级分类主键id),当我们准备删除一级分类时,如果删除了改一级分类那么相应的二级分类和二级分类下的商品就得全部删除,因此我们根据myBatis的规则。先根据外键删除二级分类然后再删除一级分类,因此首先调用adminCategorySecond_deleteByCid(cid)删除二级分类然后再调用categoryService.deleteCategoryByCid(cid);删除一级分类,最终将页面重定向到list.jsp页面。
    主要代码
    categorySecondService.adminCategorySecond_deleteByCid(cid); categoryService.deleteCategoryByCid(cid);
    查询一级分类管理员点击“一级分类管理”按钮时,展示所有的一级分类的详细信息。程序运行结果如图4-21所示:

    设计思路
    首先编写list.jsp页面,当管理员用户点击“一级分类管理页面”按钮时,服务器端接收请求然后调用adminbFindCategory()方法最终由service层调用myBatis提供的Mapper接口将所有的一级分类的信息查询出来保存到list集合中,最终保存到Model中并将信息进行展示。考虑到一级分类比较多,这里使用了分页查询,在页面展示的效果就是每页显示固定的个数,并在右下角提供了相应的按钮方便用户进行查看其他的一级分类。
    主要代码
    List<Category> categoryList = categoryService.adminbFindCategory();model.addAttribute("categoryList", categoryList);
    4.4.3 二级分类模块添加二级分类管理员用户为新增加的一级分类添加二级分类。程序运行结果如图4-22所示:

    设计思路
    首先编写二级分类添加页面add.jsp,管理员用户点击“添加”按钮时,页面跳转到add.jsp,同时服务器端将查询出所有的一级分类的名称,用于管理员选择新增的二级分类的归属,这在add.jsp页面中通过一个下拉列表进行显示。管理员用户在填写好新增的二级分类的名称并选择好所属的一级分类之后点击“确定”按钮,服务器端接收新增的二级分类名称和所属的一级分类的主键id,然后调用adminCategorySecond_save()方法将新增的Categorysecond保存于数据库的categorysecond表中。最后将页面重定向到二级分类的list.jsp页面进行展示。
    主要代码
    Categorysecond categorysecond = new Categorysecond();categorysecond.setCsname(csname);categorysecond.setCid(cid);categorySecondService.adminCategorySecond_save(categorysecond);
    修改二级分类管理员用户可以为网站中所有的二级分类的名称进行编辑。程序运行结果如图4-23所示:

    设计思路
    首先编写二级分类修改页面edit.jsp,管理员在list.jsp点击“编辑”按钮时,页面跳转到edit.jsp页面,跳转之前,服务器端查询到对应的二级分类的名称并将二级分类的名称保存到edit.jsp对应的表单中,这样方便用户知道自己修改的是哪个二级分,增加了用户体验度
    查询出对应的二级分类的名称存放于表单中,增加了用户体验
    Categorysecond findByCsid = categorySecondService.findByCsid(csid);model.addAttribute("findByCsid", findByCsid);
    更新修改的二级分类
    Categorysecond categorysecond = new Categorysecond();categorysecond.setCsname(csname);categorysecond.setCsid(csid);CategorySecondService.adminCategorySecond_update(categorysecond);
    删除二级分类后台管理员根据查询出的二级分类列表对二级分类进行操作,根据系统的要求,管理员用户在删除二级分类的同时应该删除该二级分类下的所有商品。
    设计思路
    管理员用户在点击“二级分类用户”按钮时,在管理员页面展示所有的二级分类,当用户点击“删除”按钮时,服务器端收到客户端发来的请求,并接受客户端传来的数据(二级分类的主键id),然后根据二级分类的主键id调用adminCategorySecond_delete(csid)方法,删除二级分类,然后根据外键删除商品。最后将页面重定向到二级分类的list.jsp页面。
    主要代码
    // 删除二级分类,二级分类关联二级分类下面的商品categorySecondService.adminCategorySecond_delete(csid);categorySecondService.adminProduct_deleteByCsid(csid);
    查询二级分类管理员通过点击“二级分类管理”来查看网站中所有的二级分类。程序运行结果如图4-24所示:

    设计思路
    首先得编写二级分类的list.jsp页面。管理员用户点击“二级分类管理”按钮时,给服务器发送请求,并携带分页参数,服务器端接收此参数之后开始查询所有的二级分类,这里创建了一个pageBean对象用于封装查询出来的数据,包括二级分类的集合,当前的页数,一共的页数等信息,最后直接返回一个pageBean对象,因为二级分类较多,这里采用了分页查询,需要用到这些数据因此直接封装在了pageBean对象里。用户可以通过二级分类的list.jsp页面右下方的按钮来查看所有的二级分类。
    4.4.4 商品分类模块添加商品管理用户通过点击商品展示页面list.jsp上的“添加”按钮可给网站添加新的商品。程序运行结果如图4-25所示:

    设计思路
    首先编写商品添加页面add.jsp。管理员用户点击商品展示页面list.jsp上的“添加”按钮之后客服端跳转到add.jsp页面,在客户端页面跳转之前,服务器端需要查询出所有商品的二级分类,方便上传用户选择该商品所属的二级分类。管理员需要填写页面上的信息包括商品名称、选择是否热门、市场价格、商城价格、上传商品图片、选择所属二级分类和编写商品描述这些信息。管理员用户点击“确定”按钮之后客户端将数据提交给服务器,客户端在上传上传组件时必须将上传组件表单type设置为file类型,这样服务器端才能正确的识别。最后服务器端接收到数据之后封装于product对象中,并调用adminProduct_save(product);将新上传的product保存到数据库中的product表中,最后将页面重定向到商品的list.jsp页面。
    主要代码
    product.setPdate(new Date());if (file != null) { String path = request.getServletContext().getRealPath("/products"); String uploadFileName = file.getOriginalFilename(); String fileName = UUIDUtiils.getUUID()+uploadFileName; File diskFile = new File(path + "//" + fileName); product.setImage("products/" + fileName);
    删除商品管理员用户点击“商品管理”来到展示所有商品页面,通过点击页面上的删除按钮即可删除指定的商品。
    设计思路
    这个功能是基于商品的展示页面list.jsp进行开发的,展示用户页面时pageBean里面封装了product的所有信息,当用户在点击“删除”按钮时即向服务器发送请求并携带参数(商品的主键id),服务端在接收到请求之后,根据客户端传来的参数进行删除该商品,最终将页面重定向到商品的展示页面list.jsp.
    jsp页面方法主要代码
    function deletecs(pid) { window.location.href = " ${pageContext.request.contextPath}/ admin/adminProduct_deletecs.action?pid="+pid;
    查询商品管理员通过点击“商品管理”按钮来查看本网站中所有的商品信息。程序运行结果如图4-26所示:

    设计思路
    首先编写商品下面的list.jsp页面,管理员用户在点击“商品管理”按钮时,给服务器发送请求,并携带分页参数,服务器端接收此参数之后开始查询所有的商品信息,这里创建了一个pageBean对象用于封装查询出来的数据,包括商品的集合,当前的页数,一共的页数等信息,最后直接返回一个pageBean对象,因为商品个数较多,这里采用了分页查询,需要用到这些数据因此直接封装在了pageBean对象里。用户可以通过商品文件夹里面的list.jsp页面右下方的按钮来查看所有的是商品信息。
    主要代码
    // admin的商品管理(查询所有的商品)PageBean<Product> allProPageBean = productService.findAllProduct(page);model.addAttribute("allProPageBean", allProPageBean);
    4.4.5 留言管理模块管理用户通过点击留言管理链接,即可打开前台顾客的留言列表界面,并且可以删除不合时宜的留言信息。程序运行结果如图4-26所示:

    5 系统测试与维护5.1 系统测试环境5.1.1 硬件环境
    CPU:英特尔酷睿四核
    内存:4G

    5.1.2 软件环境
    操作系统:windows 7
    服务器:Tomcat 7
    浏览器:Mozilla Firefox 和chrome

    5.2 系统测试内容使用eclipse编程软件编写Java源程序是遇到语法错误会自动报错,需要及时修改错误。对系统进行测试视为系统能有效运行并且没有异常产生。
    在程序模块编写时,每编写完一个模块需要进行模块单元测试,保证单元模块功能正常,在所有单元测试进行结束之后,需要进行整个系统的集成测试。本系统需要做如下的测试:

    登录注册测试:多次注册用户并且登录。则表达式检验的文本框输入错误信息,检测代码是否可行,注册成功后,检验用户是否可以正常显示,并查看数据库,检验数据是否成功插入。登录时,交叉使用正确和错误的密码进行登录测试,校验是否有异常
    查询一级分类测试:测试当用户访问index.action时,是否可以至系统首页即index.jsp,测试成功
    查询二级分类测试:测试用户在点击首页的一级分类时,系统是否会自动跳转页面,并且在页面的左面显示所有一级分类包含的二级分类
    购物车测试:测试已登录的用户是否可以将商品添加到购物车、移除购物车内商品、清空购物车
    订单模块测试:测试是否可以正常生成订单、取消订单、为订单付款

    5.3 系统维护系统维护是为了让系统能够在正常运行的基础上,对系统中的一些小问题进行修复并且不断完善的过程,通过系统维护能够使系统保证在不同的运行环境下均可以正常的工作,各个模块功能正常运行。
    由于本系统的本质就是一个电子商城,所以难免会有很多过期的没用的数据。所以需要定期进行“垃圾”信息的删除,对于系统中重要的一些内容如用户和商品等。要定期对数据库备份,保证数据的正确性。本系统的维护就是为了使本系统能够稳定的运行,所以需要定期维护,并且备份数据。
    小结:本章首先介绍了系统的测试环境,接下来详细介绍了单元模块测试的方法和整体集成测试的主要内容,最后介绍了系统维护的方案。
    6 总结如今,JavaEE是一个非常优秀的企业信息化开发平台,由于其拥有一些很好的性质包括稳定的性能、良好的开发性和非常高的安全性因此被广泛运用于企业级开发。这篇论文基于当前比较流行的电商系统为项目背景,遵循javaEE应用软件的规则进行开发,将系统划分为四个层次包括模型model层,持久层,业务逻辑service层和表现层,并整合了目前在企业中广泛运用的spring、springMvc和myBatis框架进行开发。Spring用于整个系统的统一调度,贯穿于各层之间,springMvc框架着重于mvc模式的实现,myBatis框架完成数据的映射和持久化工作,myBatis的逆向工程极大的方便了dao层的开发,也方便了系统dao层的维护。
    本论文主要完成了以下的任务:

    正确分析了电商目前的发展形势,特别是对网购的发展进行了深入的调查和研究
    深入明确了系统的总体架构,在技术选型上选取了三个主流的框架,对三者的功能,整合做了详细的描述
    系统项目的开发严格遵循软件的开发规范,制定了详细的系统开发步骤,开发之前做了大量的工作包括:需求分析、技术选型、架构设计等
    完成了预期赋予系统的功能的实现

    本文虽然完成了预期研究和目标,但后期还有很多工作需要完成:,随着web应用的快速发展,处于信息时代下会有更多的技术应运而生,不光需要对框架进行深入学习和研究还要对系统的架构进行研究。目前客户端技术正在崛起,我们需要认真做调查和研究做出一能让用户体验度更好的产品。以上只是目前的构想,接下来会继续深入研究并作进一步的完善和设计开发。
    7 参考文献[1] 杨开振等. Java EE互联网轻量级框架整合开发— —SSM框架(Spring MVC+Spring+MyBatis)和Redis实现[M]. 电子工业出版,2017.07.
    [2] 李俊民.HTML 5+CSS 3网页设计经典范例[M].电子工业出版,2010.
    [3] 邹红霆. 基于SSM框架的Web系统研究与应用[J]. 湖南理工学院学报(自科版), 2017, 30(1):39-43.
    [4] 王珊 萨师煊 数据库系统概论[M] 北京:高等教育出版社 2007
    [5] 陈雄华 Spring企业级应用开发详解[M] 北京:电子工业出版社 2009
    [6] 原著施奈德 成栋翻译 电子商务[M] 北京:机械工业出版社 2008
    [7] 阿里巴巴网络技术有限公司 中小企业电子商务之路[M] 北京:清华大学出版社 2007
    [8] 刘克强 电子商务平台建设[M] 北京:人民邮电出版社 2007
    [9] 程杰 大话设计模式[M] 北京:清华大学出版社 2010
    [10] 雷之宇 朱训雨 张麟 JAVA实用组件集[M] 北京:电子工业出版社 2008
    4 评论 186 下载 2019-05-15 16:25:48 下载需要17点积分
  • 基于SOGOU电子地图和GPS定位的车辆管理系统

    摘 要时至今日,信息化管理为我们节省了大量的人力物力,同时也加快了我们生活的节奏,提高了我们的工作效率,使得我们变得越来越“懒”,并且变得更加依赖于信息化的管理。由于社会的高速发展,信息变得越来越海量化,使用传统的管理方式已经变得很不现实,因为不仅要投入大量成本,并且也极为繁琐,如果能够使用信息化管理技术,将大大提高我们的工作效率并降低成本。计算机科学技术的快速发展,使这一想法成为可能,现在的生活中,信息管理技术的使用无处不在,它可应用于任何领域,并带来了不可估量的成效。
    在本系统的实现中,使用到的技术有SOGOU地图API,SQL SERVER2000,ADO控件编程和VC6.0 的MFC编程,将这几种技术充分地结合起来,就可以开发出具备强大功能的软件系统。通过使用SQL来保存资料信息,再使用ADO控件提供的功能来对这些资料信息进行增删改查,同时将结果显示到用户界面上。并在用户界面上的地图上显示车辆的信息。
    现在市场上也有不少免费或收费的车辆信息管理系统,当中有许多可取之处。本系统不仅结合了其它管理系统的优点,还添加了许多属于自己的其它系统没有的新特性。比如,系统将车辆管理与地图、GPS有效地结合起来,不仅能对车辆信息、用户信息进行管理,而且如果需要,还能对车辆进行实时监控、回放历史路径,或者给车辆设定区域,使得某车辆不能进(出)某些区域,这是其它管理系统所不具备的新特性。本系统的设计尽可能地使用扩展性、实用性、简洁性、友好性达到更好,使系统更稳定、高效地运行。本系统适用于车辆较多的公司或事业单位,特别是出租车公司、汽车公司、政府或物流公司,本系统的地图功能、GPS功能等,都能让他们对车辆进行更好更高效的实时管理。
    关键词:车辆信息管理;地图;GPS;数据库;VC6.0;MFC;信息化管理
    AbstractToday, the management of information technology will save us a lot of manpower and resources, but also accelerated the pace of our lives, improve our work efficiency, so that we become more and more “lazy”, and become more dependent on information of management. Due to the rapid development of society, information is becoming more and more sea quantify using traditional management approach has become very realistic, because not only want to invest a lot of cost, and extremely complicated, if we can use information technology management, will greatly enhance our work efficiency and reduce costs. The rapid development of computer science and technology, this idea became possible in the present life, the use of information management technology is everywhere, it can be applied to any field, and brings immeasurable results.In the implementation of this system, the use of technology to the SOGOU Maps API the SQL SERVER2000, ADO control programming and VC6.0 MFC programming, fully integrated into these several techniques you can develop a powerful software system . Save data by using SQL, then use the CRUD functions to these data and information provided by the ADO control, and display the results to the user interface. And vehicle information displayed on the map in the user interface.Now on the market, there are many free or fee-vehicle information management system, which has many merits. This system not only combines the advantages of other management systems, and also adds new features not found by many other systems of their own. For example, the vehicle management and mapping, GPS effectively combine, not only to manage vehicle information, user information, and if needed, but also real-time monitoring, playback history path of the vehicle, or set the region to the vehicle, making the a vehicle can not import (export) certain areas, and other management systems do not have new features.The design of this system to extend the use of as much as possible, practical, simple, friendly and achieve better, making the system more stable and efficient operation. This system is suitable for vehicles more companies or institutions, especially the taxi companies, car companies, logistics companies, the map features of the system, the GPS function, can make them better and more efficient real-time vehicle management.
    Keywords: VehicleInformation Management; maps; GPS; database; VC6.0; the MFC; informationmanagement
    引 言随着社会经济的发展,使用车辆的人越来越多,对于拥有各种类型的大量车辆的机关事业单位或汽车公司来说,车辆的管理日益成为日常事务中的一项重要的工作内容。如何让管理人员及时了解车辆状况,合理安排出车提高工作效率和提高车辆的使用效率,降低车辆使用费用和维修费用,就成为了各单位期待解决的一个课题。目前很多单位虽然使用上了信息化的车辆管理系统,但这些系统有的或许已经过时,有的或许并不能达到更好的效果,所以,提供一个更现代化的车辆管理系统是非常有必要的。
    一个真正好的车辆信息管理系统不仅以能够对车辆的信息进行管理,满足正常的一些管理需求,还要能够提高工作人员的效率,让工作人员合理的安排出车,可以有效地提高车辆的使用效率,并可以通过裁剪来使系统更适合各公司的不同的需求。
    在本系统中,除了提供车辆管理的一些基本需求外,还有基于地图和GPS的车辆管理,这些特性能让管理变得更实体化、人性化。为了使系统易于裁剪,适应各种不同需求,系统的设计就变得非常重要,本系统主要使用了模块化设计,各模块之间的耦合性尽可能地低,能够只要修改很少的代码,就轻松地将某些模块从系统中删除或添加到系统中,大大地提高的系统的可裁剪性和可扩展性,维护成本也可随着降到最低。
    1 系统概述1.1 系统开发背景计算机技术的迅猛发展,越来越多的传统管理方式被信息化管理方式所取代,计算机管理系统软件也是乘机起势,各种管理系统像雨后春笋一样纷纷推出。但各种各样的管理系统虽然数量众多,但也不一定能满足更新速度很快的系统需求。所以,制作一个易于更新,易于进行功能需求改变的系统非常重要。
    经过近十几年来经济的高速发展,汽车产业的发展势头也是势不可挡,而各公司的车辆也同样是增加了不少,目前,车辆信息管理系统已经逐步被物流部门所使用,功能也在不断的完善。
    车辆作为最重要的交通工具,在企事业单位中得以普及,单位的车辆数目已经远远不止简单的几辆,与此同时就产生了车辆资源的合理分配使用问题。该问题涉及到车辆的档案管理;驾驶员档案管理;车辆(维修费用、洗车费用、养路费、燃料费用等)管理;车辆使用管理和交通事故管理等。如何对一个企事业单位的车辆进行合理分配使用,使其发挥最大的使用价值,所以该系统对于一个用车单位来说,不但可以对车辆的使用进行合理的管理,而且对车辆的使用情况进行跟踪记录,这对于单位车辆责任到人,费用清晰,避免责任混乱、费用虚假等一系列相应问题的解决。
    1.2 基于GPS和电子地图的车辆管理系统开发前景和意义近年来随著卫星导航系统的蓬勃发展,其在日常生活中的应用日见广泛,车用导航系统对部份有车一族来说,已成为不可或缺的行车辅助工具,因此也有愈来愈多的汽车制造商将行车导航系统列为新车出厂时的配备。卫星测时测距导航/全球定位系统(GPS),在基本功能上可提供使用者精确的坐标定位及时间等信息,目前民用GPS的定位精度已可达到10米左右的范围,此种等级的精度己符合大多行车导航运行的需要,也使得GPS技术及商机得以迅速成长。
    项目开发一套基于GPS和地图车辆管理信息系统,以求对车辆的行驶里程进行管控。根据GPS定位记录中的行车轨迹,可进行行车里程、行车速度、超速、堵塞、停留时间等信息的计算与管理。以GPS记录器记录的行车里程数据,由系统运算里程距离,进而开发行车里程计算、行车轨迹显示等功能,以掌握车辆的行驶动向及行车里程,并可针对特定车种及特定路段给予特定的监控。透过GPS所提供精确的导航讯息,由系统运算行车速度,进而开发超速及堵塞路段的轨迹、停车时间与费用计算等功能,提供管理者管控其行车速度及停车时间的信息。针对GJS电子地图位置显示和GPS定位轨迹记录方面加以研究,探讨将以何种设备、方式、技术,会使得行车轨迹能有效率及在可接受的误差范围内正确收取记录,接著研究系统可达到的功能并开发。
    2 系统需求分析虽然现在市场上已经有了不少的车辆管理系统,这些系统也有它们的一些可取之处,但这些系统往往都是只能够进行一些简单的车辆信息管理,即只能提供一些最基本的需求,或者甚至有的用户使用体验非常差,使用起来很繁琐,并不能更好的满足用户的需要。显然,这并不是用户所希望使用到的系统,用户希望使用的是一个简单易用的系统,除了能满足一些基本需求之外,还需要其它额外的有助于提高工作效率和工作体验的新特性,很明显现在市场还缺少这样的一个车辆管理系统。
    首先,现在的车辆管理系统一般只能够进行基本的车辆资料管理,以及其它的一些维护管理、加油管理、驾驶员档案管理之类的基本功能。但随着社会经济的发展,汽车变得越来越多,对于车辆管理的要求也变得越来越高,普通的车辆管理系统已经不能满足用户的需求了,所以在该领域的研究还有很大的发展空间,开发出一个符合目前用户需求的车辆管理系统也是目前的市场所需要的。其次,现在市面上的车辆管理系统有些并没能让用户的管理变得更简单,还有很多能够改进的地方,如果能做到这些,会大大提高用户的工作效率,并可以让用户的管理不会那么枯燥。
    本系统为了更好的满足用户的需求,一直致力于高效、简单、易用、体验等几个方面上的研究,系统除了提供基本的功能,比如权限管理、车辆管理之外,还引进了其它更多的一些新特性,比如将车辆跟地图和GPS结合起来,让管理变得更清晰、更实体化。这样,当用户使用本系统的时候,就可以轻松地掌握车辆的各种实时信息、地理位置,管理就变成了一件简单的事情。
    为了将车辆跟GPS结合起来,本系统还引进了一个终端的概念,终端就是安装在车辆上的一个仪器,它能够实时获取车辆的地理位置并将位置信息发送到服务器上。车辆的实时信息如果需要可以在客户端的地图上实时显示出来,这样就能够给用户一个实时掌握车辆信息的功能,本系统尽力让用户对车辆管理有一个全新的体验,让用户意识到管理还可以这么简单(或者也会感觉到有趣)。
    本系统是车辆管理系统中的客户端,用例图如图3.1所示:

    具体的需求如下:
    2.1 车辆管理车辆管理是车辆管理系统最基本的需求之一,车辆管理包括车辆资料管理、派车/收车管理、终端管理等功能,用户可通过这些功能来完成车辆的日常管理和一些基础资料的管理,比如查询、新增、修改、删除和派车/收车等。车辆管理必须设计得尽可能的易用、简单而又不失实用性。为了满足日常管理的一些需求,目前在该功能需求中包括三个子功能:车辆资料管理、派车/收车管理、终端管理。
    2.1.1 车辆资料管理车辆资料管理主要提供的是对车辆基本资料的管理,包括车辆信息查询、查看、新增、修改、删除等一些基本功能。不过要想使用这些功能,必须管理员分配这些权限方能使用,如果没有使用这些功能的权限是无法执行这些功能的。车辆资料的内容有:车辆编码、车牌号、品牌型号、车辆类型、所属部门、车辆状态、驾驶员、购买日期、登记日期、终端号码,需要实现的功能有:

    新增车辆资料
    修改车辆资料
    删除车辆资料
    查看选中的某车辆资料
    根据条件查询车辆资料
    打印(可选项)

    2.1.2 派/收车管理车辆管理系统一般都提供有派车/收车的功能,本系统同样也不能例外。用户可通过派车/收车管理的功能来分配车辆的使用和收回已经派出的车辆,根据情况来分配车辆可提高车辆的使用效率,减少费用。因为用户有时候需求查阅历史派车记录或收车记录,所以在该功能里面,必须能够根据用户所提供的查询条件来查阅这些记录,同时,为了能够方便用户收车,也要提供一个查阅未收车辆的查阅的功能,这样,用户就能够通过该功能来轻松查阅未收车辆和很方便的对未收车辆进行收车。
    因为在派车的时候可能会对同一辆车进行多次派车,而这些派车之间也可能会产生时间冲突,所以在派车的时候要先对该车辆的使用时间进行检测,如果与其它的派车时间产生冲突就要提示用户冲突的时间,这样就方便用户改变派车时间或使用其它没有冲突的车辆。
    派车/收车记录所维护的信息有:车辆编码、车牌号、驾驶员、驾驶员电话、用车人、用车人电话、用车部门、用车时间、估计返程时间、出发地点、途经地点、目的地点、用车原因、派车人、审批人、登记日期、是否已收车、收车人、备注。
    如果想要使用这些功能的用户必须具备这些权限。需要实现的功能有:

    派车
    收车
    根据条件查询历史派车记录
    根据条件查询历史收车记录
    根据条件查询未收记录

    2.1.3 终端管理因为车辆要与地图和GPS结合起来,所以必须要在汽车上安装一个定位地理位置并将位置信息发送到服务器上的终端。
    在终端管理功能模块中,用户可对终端信息进行新增、修改、删除,同时也可指定查询信息对终端进行查询操作。终端中的一些动态信息会根据终端返回到服务器的数据进行实时更新,比如终端对应车辆所处的实时地理位置信息和车辆的实时速度等。终端信息的内容有:终端号、终端名、当前地址、证书、终端电话、权限、是否在线、所属车队、用户组、备注、登记时间。
    使用该功能的用户必须具备该权限。需要实现的功能有:

    新增终端资料
    修改终端资料
    删除终端资料
    根据条件查询终端资料

    2.2 权限管理为了让系统用户的操作在一个可控的安全范围之内,本系统将权限管理作为一个基础功能需求,权限管理包括了系统用户管理、角色管理、和权限管理。有权限的用户可通过该功能来给用户分配角色、给角色分配权限或给角色分配车队(该角色有权限管理的车队),同时也可对用户、角色进行管理,即:权限管理不单纯的是权限管理,同时也包括了系统用户、系统角色的管理,这些都被隶属于权限管理之中。
    2.2.1 系统用户管理系统用户是登入系统的凭证,进入系统后只能使用该用户有权限使用的功能。为了提高系统的可控性以及实用性,本系统提供了系统用户管理,使得系统管理员可对系统用户进行有效的一致性管理。系统用户所维护的信息有:id、名称、密码、性别、生日、地址、籍贯、证件号码、部门、入职时间、手机号码、家庭号码、创建时间(注册时间)、创建者ID。其中密码需要使用MD5算法加密。需要实现的功能有

    新增用户资料
    修改用户资料
    删除用户资料
    根据条件查询用户资料

    2.2.2 角色管理为了使系统中与用户对应的权限易于管理,系统引进了角色管理,每个角色对应不同的权限,给需要给用户分配权限时,只需给用户分配角色即可,一个用户可对应多个角色,他真正的权限就是他所对应角色的权限的并集。需要实现的功能有:

    新增角色
    删除角色

    2.2.3 权限管理系统中有很多的功能,但为了使系统更安全、稳定、可控,并不是每个系统用户都能使用所有的这些功能,而权限是决定系统用户是否能够使用某个系统功能的标志,所以在本系统中,用户能够使用的功能都是根据权限来分配,而用户的权限都是根据他所对应的角色来获取,这就产生了两个映射:用户 -> 角色;角色 -> 权限。需要实现的功能:

    给角色添加权限
    给角色删除权限
    保存角色—权限的对应关系

    2.2.4 系统用户对应的角色的管理为了方便用户权限的管理,如果需要给用户分配权限,只需要给用户分配对应的角色即可。一个用户可对应多个角色,他的权限就是用户所对应角色的权限的并集。这种权限管理方式大大提高了权限分配的方便性,也大大减少了系统管理员的工作量。需要实现的功能有:

    给用户分配角色
    给用户删除角色
    保存用户—角色的对应关系

    2.2.5 角色对应车队的管理在系统中可能会存在多个车队,而为了让管理划分得更清晰明了,也不是每个系统用户都能对所有的车队进行管理。给用户分配车队也是基于角色来分配的,我们只需要给角色分配该角色有权限管理的车辆,然后按照需要来给用户分配对应的角色即可。用户所能管理的车队就是该用户对应的角色有权限管理的车队的并集,换句话说,我们只要能获取到该用户的角色,就知道该用户能管理哪些车队。需要实现的功能有:

    给角色添加车队
    给角色删除车队
    保存角色—车队对应关系

    2.3 地图地图功能是本系统的新特性。
    提供地图除了可以让用户对车辆管理有一个全新的体验外,还大大地提高了系统的实用性,系统管理员可借助该功能让管理变得更实体化,对于车辆的监控变得更加明显、可靠。本系统将车辆与地图和GPS有效地结为一体,将车辆的实时位置在地图上显示出来,让用户能够在地图上实时监控车辆的实时位置信息和速度信息,同时还可以在地图上添加标注、绘制路线、绘制区域,也可以将绘制的区域分配给指定的车辆,规定该车辆不能进区域或不能出区域,大大地提高了监控的方便性和系统的实用性。在该功能模块中主要包含了以下的子功能模块:

    GPS功能
    地图编辑

    具备的功能需求如下:
    2.3.1 GPS功能要想在地图上定位车辆的位置信息,必须要将GPS跟车辆关联起来。GPS功能就是将GPS终端跟车辆结合起来的一个功能,因为一个终端跟一辆车是一对一的关系,所以只要通过终端将位置信息发送到服务器就可定位到地图上的一辆车。
    同时为了更好地对车辆进行管理,在该功能模块中还必须要提供对某个车辆进行动态跟踪、数据统计和轨迹回放的功能,通过这几个功能,用户可以很方便地了解车辆的历史状态信息的实时状态信息。在本功能模块中需要实现的功能列表如下

    查找车辆:可以按车牌号、编号、驾驶员、终端号、终端名等模糊信息查找,只要按确定后会自动转到该车在地图上的位置,同时在车辆信息列表栏中也会选中。
    列表车辆:在树型列表KH 按照车队分类来列出用户有权限管理的车辆,列表车辆时显示车辆在线/不在线的标志,在树型列表选中车辆时,在地图上显示车辆和车辆详细信息,地图以车辆为中心。
    查看车辆信息:可以查看地图上看到的车辆信息,包括运行状态和车辆详细信息。
    车辆信息查询:可以实时查询在地图上看见的任何一辆车子的静态信息,无需去车辆详细信息管理栏去找,并可了解当前车辆的运行状况。
    车辆跟踪定位:实时性地对车辆的情况进行跟踪,双击车辆信息列表栏的车牌号,自动转到该车在地图上的位置。
    动态跟踪:新建窗口对选定的车辆进行实时监控,显示车辆轨迹,地图以车辆为中心,也就是地图会随着车辆的移动而移动。
    轨迹回放:可以随时查看每台车辆任意时间段行驶轨迹图,方便直观地展示某车在某时间段内的行驶轨迹,能在回放结束之后选择重新回放或重新选择时间段来回放。半年内的数据均可调出进行回话,方便管理人员对车辆进行系统的监控和检查。
    数据统计:可根据时间区段和设定的速度阀值绘制速度曲线图,非常直观地显示车辆工作过程中的速度变化,对超速和车辆的平稳驾驶性一目了然,便于管理从员了解车辆的违规情况以及驾驶平稳性的情况。列表超速信息,双击超速信息会转到地图上相应的超速位置,并绘制出超速的轨迹。还能够列表出失去监控车辆的统计列表并打印。

    2.3.2 地图编辑为了方便用户的使用,提高地图的实用性,本系统增加了地图编辑的功能,在该功能模块中,用户可根据需要在地图上添加自己的标注、绘制区域,并可选择将之保存到数据库中,以后登录时都会在地图上显示该用户对应的标注和路线,同时用户也可对这些标注和路线进行管理,比如重命名、删除等。区域是针对整个系统来管理而不是针对用户来管理的的,即一个用户绘制了一个区域并保存到数据库中时,其他的系统用户同样能对该区域进行分配、管理。在本功能模块中要实现以下几个子功能模块以满足用户的需求:

    搜索:可通过输入地名来进行地图搜索。
    刷新地图:可对地图进行刷新。刷新后系统会重新从数据库中查询标注、路线、区域、车辆终端来在地图上标注出来。相当于对车辆终端进行重新定位。
    添加标注:用户可根据需要在地图上添加自己的标注,比如为了方便查找某个地方,可在该地方加上一个标注,以后可通过该标注找到该地方。标注可以选择保存到数据库中,如果不保存到数据库中下次登录时将不会在地图上显示标注。每次登录时系统都会从数据库查询出属于该登录用户的标注来在地图上显示出来。
    绘制路线:当有的一些道路比较偏僻地图上没有或者不详细,可自己进行绘制并给该道路命名。绘制好的路线同样可以保存到数据库中,如果不保存到数据库中下次登录时将不会在地图上显示出来。每次登录时系统都会从数据库查询出属于该登录用户的路线来在地图上显示出来
    绘制区域:可以在地图上绘制区域并用于分配给车辆,并选择是进报警区域(某车辆进入该区域时报警)还是出报警区域(某车辆出了该区域时报警),绘制的区域可选择保存到数据库中,不保存到数据库中的区域无效,下次登录时也不会在地图上显示。每个系统用户,只要具有使用地图功能的权限,都可对区域进行修改、删除等编辑操作,因为区域是针对于整个系统的。
    给车辆终端分配/删除报警区域:如果需要给车辆终端分配报警区域时要使用该功能。通过列表出来的区域和车辆终端,可以把指定区域分配给指定的车辆终端,分配时需要能够选择该区域是进报警区域还是出报警区域,需要能够同时给一个车队或者一个车辆的终端分配一个或多个报警区域。删除报警区域跟分配报警区域差不多,也需要能够同时删除一个车队或一个车辆的一个或多个报警区域。
    双击区域时跳转到地图对应位置上:为了方便查看区域或某车辆终端对应的报警区域,双击区域进可自动跳转到地图的对应位置上。

    3 相关技术和开发平台3.1 Microsoft Visual C++ 6.0Visual C++ 6.0,简称VC或者VC6.0,是微软推出的一款C++编译器,将“高级语言”翻译为“机器语言(低级语言)”的程序。Visual C++是一个功能强大的可视化软件开发工具。自1993年Microsoft公司推出Visual C++1.0后,随着其新版本的不断问世,Visual C++已成为专业程序员进行软件开发的首选工具。虽然微软公司推出了 Visual C++.NET(Visual C++7.0),但它的应用有很大的局限性,只适用于Windows 2000、Windows XP和Windows NT4.0。所以实际中,更多的是以Visual C++6.0为平台。
    选用VisualC++ 6.0的原因有:

    效率:借助Visual C++ 6.0环境进行MFC开发具有强大的控件支持和可视化操作,提高开发效率。结构清晰:能够实现MVC框架,界面代码与业务逻辑代码能够分离,代码结构清晰,易懂,易于维护。易于配置:使用Visual C++ 6.0开发MFC只需要安装即可,并不需要其它额外的配置,非常方便。
    3.2 SQL Server 2000SQL Server 2000, 是Microsoft 公司推出的SQLServer 数据库管理系统的新版本。该版本继承了SQL Server 7.0 版本的优点,同时又比它增加了许多更先进的功能,具有使用方便、可伸缩性好、与相关软件集成程度高等优点。
    本车辆信息管理系统使用SQLServer 2000数据库来保存车辆的各种信息,并通过SQL语句来对这些信息进行管理。
    3.3 SOGOU地图APISogouMaps JavaScript API 是由javascript语言编写的地图应用程序接口。使用Sogou Maps JavaScript API 可以轻松的在网站中构建丰富的地图应用。用户从搜狗地图的官网上得到这些API的详细说明及参考实例。
    在本系统中,地图部分的功能都是使用Sogou地图的API结合JavaScript、HTML和MFC来完成。
    3.4 C/S结构C/S 结构,即大家熟知的客户机和服务器结构。它是软件系统体系结构,通过它可以充分利用两端硬件环境的优势,将任务合理分配到Client端和Server端来实现,降低了系统的通讯开销。目前大多数应用软件系统都是Client/Server形式的两层结构,由于现在的软件应用系统正在向分布式的Web应用发展,Web和Client/Server 应用都可以进行同样的业务处理,应用不同的模块共享逻辑组件;因此,内部的和外部的用户都可以访问新的和现有的应用系统,通过现有应用系统中的逻辑可以扩展出新的应用系统。这也就是目前应用系统的发展方向。

    Client:Client程序的任务是将用户的要求提交给Server程序,再将Server程序返回的结果以特定的形式显示给用户
    Server:Server程序的任务是接收客户程序提出的服务请求,进行相应的处理,再将结果返回给客户程序

    本系统主要是进行客户端的开发。
    3.5 系统所需配置简介
    服务器配置

    数据库服务器:CPU P4 3.0G以上,内存1G以上,硬盘80G以上,Windows server 2000 及以上
    应用服务器:CPU P4 3.0G以上,内存1G以上,硬盘80G以上,Windows server 2000 及以上

    客户端系统配置

    IBMPC 及其兼容机:CPUP4 2.0G以上,内存256M以上,硬盘40G以上,Windows 2000/2003/NT/XP 中文操作系统
    浏览器:InternetExplorer 6
    注册 MSCHART 控件


    3.6 系统开发所需关键技术由于本系统的开发在地图模块涉及到JAVASCRIPT语言跟MFC之间的通信,所以这两者之间通信的实现是系统能正常进行开发关键,在本系统的实现中,将JAVASCRIPT(JS)与MFC之间的通信分别分为两部分来实现:JS跟MFC的通信和MFC跟JS的通信,以下分别对这两个部分的实现和使用进行详细说明。
    3.6.1 MFC跟JS的通信在本系统的开发中,MFC嵌入的浏览器控件将会是IWebBrowser2 控件,MFC 跟 JS 之间的通信可以通过以下几个步骤来完成:

    获得IHTMLDocument2接口指针。因为本系统中使用的是IWebBrowser2,这一步可以略过
    在HTML文档中获取JS对象的IDispatch。该指针可通过IWebBrowser2的GetDocument接口函数来获得
    通过提供的JS函数得到DISPID,DISPID可以通过IDispatch的GetIDsOfNames接口函数来获取
    把JS函数所需的参数都添加到DISPPARAM结构体中
    通过使用IDispatch接口的Invoke方法调用JS函数

    为了方便使用起见,把以上的步骤都封装到了CWebPage类中,实例化该类后,只需通过IWebBrowser2的GetDocument接口函数来获取浏览器控件的IDispatch指针,然后通过CWebPage对象的SetDocument接口函数来设置IDispatch指针,最后就可以通过CWebPage对象的CallJScript接口函数来直接调用浏览器控件对应的JS函数。
    3.6.2 JS跟MFC的通信在本系统通过自定义CWebBrowser2类来实现JS调用MFC的函数,同时也将COleControlSite和IDispatch分别封装成CCustomControlSite和CImpIDispatch类。要想使某个VC的函数在JS代码中能够被调用,必须要在VC的代码中实现某些代码,比如要想在JS中调用VC的某个函数 Func(),必须要经过以下几个步骤:
    1.在ImpIDispatch.cpp中添加:
    CString cszCB_Func="CB_Func";
    2.在ImpIDispatch.cpp中添加宏定义:
    #define DISPID_CB_Func xx(自定义)
    3.在ImpIDispatch的GetIDsOfNames函数的for循环中附加以下判断:
    if (cszName == cszCB_Func) { rgDispId[i] = DISPID_CB_ Func}
    4.在ImpIDispatch的Invoke函数中添加以下判断:
    if (dispIdMember == DISPID_CB_ Func) { if (wFlags & DISPATCH_METHOD) { Func(); }}
    5.以上的步骤完成后,可以在JS中通过以下的代码来对Fucn函数进行调用:
    if(bIsCustomBrowser){ window.external.CB_Func(); }
    bIsCustomBrowser是用来验证当前执行JS代码的浏览器控件是否是自定义的浏览器控件,可以在JS代码中通过调用判断window.external.CB_IsOurCustomBrowser是否为空来识别是不为自定义浏览器,如果为空,是自定义浏览器,不为空则否。
    4 总体设计4.1 系统设计目的系统设计的目的:根据新系统的逻辑模型建立模型,详细地确定新系统的功能需求和结构以及具体实施方案的过程,即解决“怎么做”的问题。对于开发大型的信息管理系统,具体的、系统的分析与设计尤为重要,这关系到系统开发的效率以及系统实施的成功与否,是否在对的方向上做事。在软件工程的思想中,系统需求分析是放在首位的,是一切系统工作的开始。明确而正确的系统设计能很大程度地提高后期的开发效率,降低开发成本,同时也能从根本上降低后期维护花费的成本。所以,为了能收获以上的好处,必须明确系统设计目的,从而能够指导后期的开发工作,使开发工作走上正确的轨道。
    4.2 系统总体构架本车辆管理系统的系统构架主要以增强系统的可扩展性为主,系统管理人员只需要修改极少的代码即可将新功能添加到系统或从系统中删除一些不必要的功能。所以本系统很容易就能够满足各种不同的需求。
    本系统的总体构架应该以TAB控件的形式显示出来,如果需要将新功能添加到系统中,只需要在合适的TAB上添加一个对应的新标签就可将功能添加到系统中,而如果要从系统中删除某个TAB上的功能的时候,同样只需要在代码中功能对应的TAB标签删除即可,当然也要删除代码中与之相关的代码。TAB的各标签之间的关联性尽可能地低,互相之间不存在依赖,它们只是共用一组基础类。这样,系统的扩展性就可以得到很好的体现。这种可扩展性大大提高了系统的灵活性和可维护性,降低系统后续的各种费用,有助于今后系统的升级。
    本系统的大休划分为以下几个大块:

    车辆管理
    权限管理
    地图

    本系统的总体结构图如图4.1所示:

    为了降低代码的复杂度和便于系统今后的维护,本系统将尽可能地将界面代码跟业务逻辑代码区分开来,这样的代码将更有模块性和阅读性。
    在本系统中,用户界面都是基于MFC对话框在TAB控件中呈现出来,而对于数据库的操作除了有一个连接数据库和对数据库进行操作的基础类之外,其它的都是基于该基础类的针对于某个功能的数据库操作类,比如专门操作用户的类、操作车辆资料的类或操作终端资料的类,各个模块的划分非常清晰明了。总的来说,本系统将是严格按照模块化来进行系统的开发设计,各个界面模块、业务逻辑模块和数据库操作模块都是互相独立的。
    系统的逻辑结构图如图4.2所示:

    在本系统的开发研究中,使用的是面向对象的C++语言,依据系统的总体结构,本系统类的设计主要也是分为三层类:用户界面层的类、业务逻辑层的类和数据库连接操作层的类,各层之间有一定的依赖关系,比如用户界面层对数据库的操作要依赖于业务逻辑层,而不是直接依赖于数据库连接操作层,而业务逻辑层对数据库的操作则要依赖于数据库连接操作层,同样数据库连接操作层的类和业务逻辑层的类不会对用户界面层的类有任何依赖关系,关键类的关系如图 4.3所示:

    4.3平台系统结构现在的桌面软件一般采用的都是C/S结构,C/S是将任务分配到客户端和服务器来发挥两端硬件环境优势。客户端的任务是将用户的请求提交给服务器程序,再将服务器程序返回的结果以特定的形式显示给用户。而服务器的任务是接收客户程序提出的服务请求,进行相应的处理,再将结果返回给客户程序。
    本系统在设计上采用的是C/S结构来实施,客户端主要的任务是提供给用户使用的功能接口并将各种处理结果在UI上显示给用户;服务器则主要是处理客户端发过来的各种请求,并将处理结果回发给客户端,同时服务器还接收终端发过来的地理位置信息和其它信息,并将这些信息保存到数据库中。多个客户端可同时连接到服务器并可以同时向服务器发送各种请求,服务器能够处理多个客户端的并发请求,并且要能够准备无误地将客户的请求结果返回到客户端。
    本系统的平台应用体系架构如图4.4所示:

    4.4 数据库设计数据库设计是管理系统实现中的一个重中之重,良好的数据库设计能大大的提高系统的安全性、稳定性和可靠性,对系统的性也能够得到一定程序上的提高,并且良好的数据库设计对后面的系统设计开发实现都有着深远的影响,因为良好的数据库设计能使开发变得更容易,更高效,也能够使今后的维护变得更简单。
    本系统的一些数据流图如图4.5 , 图4.6 所示:

    本系统的数据库表比较多,依据系统具体功能划分,得到的实体有:车辆、终端、系统用户、角色、权限、驾驶员、部门、车队、派车/收车信息、标注、路线、区域等。数据库的E-R如图 4.7 所示:

    4.4.1 车辆管理4.4.1.1 车辆资料管理车辆详细资料表:该表定义了车辆的所有详细数据,车辆各种内容在该表中都能体现出来。对车辆进行管理时需要直接对该表进行操作,比如车辆资料资料的增删改查都必须跟该表直接打交道。对应系统的车辆资料管理的功能界面。具体定义如表4.1所示:



    字段名称
    数据类型
    字段说明




    Id
    int
    主键


    Coding
    varchar(16)
    车辆编码,唯一索引值


    Number
    Varchar(16)
    车牌号


    Carbrand
    Varchar(64)
    车辆商标


    Cartype
    Varchar(64)
    车辆类型


    Belongdept
    Varchar(16)
    所属部门


    Carstatus
    Bit
    车辆状态


    Driver
    Varchar(16)
    驾驶员


    Buytime
    Datetime
    购买日期


    Entertime
    Datetime
    登录日期


    Terminalnum
    Varchar(16)
    终端号码



    驾驶员资料表:驾驶员可能会是公司的主要组成部分,对于出租出公司或其它汽车公司来说,驾驶员更加显得重要,所以保存驾驶员资料是一件非常重要的事情。驾驶员资料表就是用于在数据库中保存驾驶员资料的,对于驾驶员的管理,比如增删改查都要直接操作该表,该表的具体定义如表4.2:



    字段名称
    数据类型
    字段说明




    Id
    Int
    主键


    Coding
    Varchar(16)
    驾驶员编码


    Name
    Varchar(16)
    驾驶员名字


    Sex
    Tinyint
    驾驶员性别


    Status
    Tinyint
    驾驶员状态


    Dept
    Varchar(16)
    所属部门


    Type
    Varchar(32)
    驾驶类型


    Phone
    Varchar(16)
    驾驶员电话


    Identitycard
    Varchar(24)
    身份证号码


    intme
    Datetime
    入职日期


    adress
    varchar(64)
    家庭住址


    Comment
    varchar(64)
    备注



    部门表:公司内部可能会有不同的部门,公司的车辆也可能隶属于不同的部门,所以为了方便各个部门对属于自己部门的车辆进行管理,本系统中添加一个部门表来保存各个部门的车辆信息,但该表不用于专门对部门进行更深一步的管理,所以该表的设计比较简单。该表的的定义如表4.3:



    字段名称
    数据类型
    字段说明




    id
    int
    部门ID


    coding
    varchar(16)
    部门编码


    name
    varchar(16)
    部门名称



    4.4.1.2 派车/出车管理派车收车表:当公司的成员要使用车辆时,必须要登记好用车的原因、目的等明细情况,以便今后对各用车记录进行详细调查。该表的的定义如表4.4:



    字段名称
    数据类型
    字段说明




    id
    int
    派车记录的ID


    coding
    varchar(16)
    派车记录的编码


    number
    varchar(16)
    用车车辆的车牌号码


    driver
    varchar(24)
    出车的驾驶员


    driverphone
    varchar(16)
    出车驾驶员的手机号码


    user
    varchar(16)
    用车人


    userphone
    varchar(16)
    用车人号码


    dept
    int
    用车人部门


    usertime
    datetime
    使用时间


    backtime
    datetime
    估计返回时间


    startplace
    varchar(64)
    起始地址


    viaplace
    varchar(64)
    途经地址


    destination
    varchar(64)
    目的地址



    4.4.1.3 终端管理终端表:为了使车辆与地图和GPS结合起来,必须得要将终端的信息记录到数据库中,所以数据库中也需要有相应的表来保存终端的信息,终端表就是用来保存终端信息记录的表,该表的定义如表 4.5所示:



    字段名称
    数据类型
    字段说明




    id
    int
    终端ID


    coding
    varchar(16)
    终端编码


    name
    varchar(64)
    终端名称


    adress
    varchar(64)
    终端当前地址


    contract
    varchar(20)
    合同


    phoneno
    varchar(20)
    终端电话


    deny
    tinyint
    权限


    online
    bit
    终端是否在线


    longitude
    float
    终端对应车辆当前地理位置的经度


    latitude
    float
    终端对应车辆当前地理位置的纬度


    speed
    float
    终端对应车辆的当前实时速度


    degrees
    float



    time
    datetime
    终端登记时间


    comment
    ntext
    备注


    password
    varchar(33)
    终端密码


    usergroup
    int
    终端对应车辆所属用户组


    cargroup
    int
    终端对应车辆所属车队


    inzone
    ntext
    终端对应车辆所对应的进入报警区域


    outzone
    ntext
    终端对应车辆所对应的出去报警区域



    4.4.2 权限管理系统用户表:系统用户表中保存的是用户的信息数据,每个系统用户信息都可在系统用表中查询得到,该表对应的是权限管理中的用户管理,比如增删改查,该表的定义如表4.6所示:



    字段名称
    数据类型
    字段说明




    id
    int
    系统用户的 ID


    name
    varchar(20)
    系统用户的名称


    password
    char(33)
    系统用户的密码


    sex
    char(2)
    用户性别


    birthday
    datetime
    用户生日


    adress
    text
    用户住址


    nativeplace
    text
    用户籍贯


    credentialnum
    char(20)
    用户证件号码


    dept
    int
    用户所属部门


    entertime
    datetime
    入职时间(或注册时间)


    mobile
    char(11)
    用户手机号码


    homephone
    char(12)
    用户家庭号码


    createtime
    datetime
    创建账号时间(注册时间)


    craeteby
    int
    创建者



    角色表:角色表是保存系统角色的信息,但由于本系统不提供专门用于角色管理的功能,对于角色管理只提供一个简单的添加角色和删除角色的功能,所以根据需要该表的设计比较简单,该表的定义如表4.7所示:



    字段名称
    数据类型
    字段说明




    id
    int
    角色的 ID


    name
    text(16)
    角色名称


    mid
    int
    创建该角色的系统用户


    createtime
    datetime
    角色的创建时间



    角色权限表:系统中的每个角色都应该有与这对应的权限,而角色—权限表就是用于保存角色对应的权限信息,角色权限的获取就是通过查询该表并按照特定的算法来分析得到的权限编码,该表的定义如表 4.8 所示:



    字段名称
    数据类型
    字段说明




    id
    int
    角色—权限映射的 ID


    rid
    int
    映射的角色ID


    mid
    int
    创建该映射的系统用户


    createtime
    datetime
    角色的创建时间


    purviewcoding
    ntext
    角色的权限编码



    系统用户角色表:系统中的每个系统用户都应该对应某一个或几个角色,而系统用户—角色表就是用于保存系统用户对应的角色信息,该表的定义如表 4.9 所示:



    字段名称
    数据类型
    字段说明




    id
    int
    角色—权限映射的 ID


    rid
    int
    映射的角色ID


    mid
    int
    创建该映射的系统用户


    createtime
    datetime
    角色的创建时间


    purviewcoding
    ntext
    角色的权限编码



    角色车队表:在系统中用户有权限管理的车队是根据角色来定义的,某个用户能够管理管理即是他所对应的角色有权限管理的车队的并集,在系统中的角色一般都会对应该角色所能管理车辆,而该对应关系就是保存到角色—车辆队表,该表的定义如表4.10所示:



    字段名称
    数据类型
    字段说明




    id
    int
    角色—车队映射的 ID


    rid
    int
    映射的角色ID


    cid
    int
    映射的车队ID


    mid
    int
    创建该映射的系统用户ID


    createtime
    datetime
    映射的创建时间



    4.4.3 地图4.4.3.1 GPS 功能跟踪表:跟踪表是记录终端对应车辆历史经过的轨迹,以便日后对车辆历史经过轨迹进行清查,该表的详细定义如表4.11所示:



    字段名称
    数据类型
    字段说明




    id
    int
    跟踪记录的 ID


    tid
    int
    跟踪记录对应的终端ID


    longitude
    float
    跟踪到某个点车辆的经度


    latitude
    float
    跟踪到某个点时车辆的纬度


    speed
    float
    跟踪到某个点时车辆的速度


    degrees
    float



    waterlevel
    float



    time
    datetime
    跟踪到某个点时的时间



    4.4.3.2 地图编辑标注表:为了方便用户的使用和提高地图的实用性,本系统提供了添加标注的功能。为了保存用户添加到地图上的标注,在数据库中添加一了个标注表,该表的定义如表4.12所示:



    字段名称
    数据类型
    字段说明




    id
    int
    标注ID


    name
    varchar(24)
    标注名称


    longitude
    float
    标注在地图地理位置上的经度


    latitude
    float
    标注在地图地理位置上的纬度


    entertime
    datetime
    标注添加到数据库的时间


    picpath
    varchar(30)
    标注图片路径


    mastered
    int
    标注所属的系统用户,也就是标注的创建者



    系统用户路线表:为了方便用户的使用和提高地图的实用性,本系统提供了添加路线的功能。为了保存用户添加到地图上的路线,在数据库中添加一了个系统用户和路线的对应表,该表的定义如表4.13所示:



    字段名称
    数据类型
    字段说明




    id
    int
    路线 ID


    masterid
    int
    路线所属的系统用户的ID


    polyid
    varchar(20)
    路线ID


    polyname
    varchar(34)
    路线名称


    entertime
    datetime
    路线添加到数据库的时间



    系统用户区域表:为了方便用户的使用和提高地图的实用性,本系统提供了添加区域的功能。为了保存用户添加到地图上的区域,在数据库中添加一了个系统用户和区域的对应表,该表的定义如表4.14所示:



    字段名称
    数据类型
    字段说明




    id
    int
    区域 ID


    masterid
    int
    区域所属的系统用户的ID


    zonecoding
    varchar(20)
    区域编码


    zonename
    varchar(24)
    区域名称


    entertime
    datetime
    区域添加到数据库的时间



    路线表:路线表是为了能够保存系统用户在地图上绘制上的路线,该表的设计比较简单,它的定义如表 4.15 所示:



    字段名称
    数据类型
    字段说明




    id
    int
    路线 ID


    longitude
    float
    路线一个点的经度


    latitude
    float
    路线一个点的纬度



    区域表:区域表是为了能够保存系统用户在地图上绘制上的区域,该表的设计比较简单,它的定义如表 4.16 所示:



    字段名称
    数据类型
    字段说明




    id
    int
    区域 ID


    longitude
    float
    区域一个角对应的经度


    latitude
    float
    区域一个角对应的纬度



    5 系统功能模块的技术实现本章节描述的是系统的详细设计。在该节中,会较为详细地说明系统中各个模块的设计、各个模块之间的接口和模块之间的依赖性。
    车辆管理系统采用的C/S架构,而本文档讨论的是客户端系统的设计。
    本系统的用户界面是基于TAB来实现的,即基本每个功能模块都是基于TAB标签中的对话框来设计,这样设计的好处是容易保持各功能模块之间的独立性,并且容易对功能进行新增或删除,也方便于日后的维护。
    因为本系统使用的是面向对象的C++语言来开发,所以系统的详细设计都是基于类来设计的,在类的设计中层次分明。
    5.1 登录系统用户一般会对应一个或几个该用户有权限管理的车队,在用户登录时可对他所能管理的车队进行选择性管理,比如只管理某个车队或某几个车队。该流程如图 5.1所示:

    5.2 车辆管理车辆管理功能模块是管理车辆管理系统的基础资料,比如车辆资料管理、派车/出车管理、终端管理等。该功能模块包含以下几个子功能模块:

    车辆资料管理
    派车/出车管理
    终端管理

    车辆管理的功能图如图 5.2所示:

    各功能模块的详细设计如下:
    5.2.1 车辆资料管理本模块主要是实现车辆详细资料的管理,用户可使用该功能来管理车辆的资料数据,比如车辆资料的增删改查等。
    该功能的实现非常简单,先从数据库中查询出登录用户所选择车队中的所有车辆,并将查询出来结果显示在窗口的列表中。用户可根据窗口中提供的按钮来使用增删改查的功能。
    5.2.1.1 查询可通过输入文本来进行模糊查询,查询的关键字有车辆编码、’车牌号、品牌型号、车辆类型、所属部门、’驾驶员、’终端号,当用户点击“查询”按钮时,先获取用户输入的按钮,再组装成一条模糊查询的SQL语句,返回执行语句的查询结果并在列表中显示出来,查询功能的流程图如图 5.3 所示。

    5.2.1.2 新增通过“新增”按钮可以将新的车辆资料录入到数据库中。当用户点击“新增”按钮时,会弹出资料录入对话框,用户可以在该对话框中输入车辆资料,新增的流程图如图 5.4 所示。

    5.2.1.3 修改通过“修改”按钮可以修改选中的车辆资料。当用户点击“修改”按钮时,弹出修改车辆资料的窗口,用户点击保存按钮后,获取用户修改过后的车辆资料,组装成更新数据库的SQL语句,通过更新数据库来将修改过后的车辆资料保存到数据库中,修改车辆资料的功能流程图如图 5.5 所示。

    5.2.1.4 删除可以通过“删除”按钮来删除某些车辆资料。当用户点击“删除”按钮时,先获取用户所选择的车辆资料,再获取所选择的车辆资料的ID,根据ID来删除这些车辆资料数据,删除车辆资料的功能流程图如图 5.6 所示。

    5.2.2 派车/收车管理派车/收车管理是车辆管理系统的重要的一部分,系统用户会经常性地使用该功能模块,所以该模块的设计要尽可能地方便用户的使用,以便提高用户的工作效率。在本功能模块中,包含了派车、收车、按条件查询派车记录、按条件查询收车记录、按条件查询未收记录,同时在该模块中,列表将会三个不同的视图模式:

    派车记录:在这个模式下,列表默认显示数据库中所有的派车记录,当用户在这个模式下使用查询功能时,只会按照用户输入的条件来查询数据库中对应的派车记录并在列表中显示出来
    收车记录:跟上个模式差不多,只是列表中只会显示收车记录
    未收车辆:跟以上两个模式差不多,只是列表中只会显示未收车辆的记录

    5.2.2.1 查询 查询的条件有:用车的起始时间、用车结束时间、用车部门、目的地、用车人。当用户点击“查询”按钮时,系统会获取用户所输入的查询条件和当前列表的视图模式,组装成SQL语句从数据库中查询,并将查询结果显示到列表中,查询记录的功能流程图如图 5.7 所示。

    5.2.2.2 派车派车是一个经常使用的功能。当用户点击“派车”按钮时,会弹出一个派车窗口,用户只需要在该窗口中选择性的填充内容再点击“确定”按钮即可成功派车。但是在保存派车选项数据之前,必须要对某些选项的合法性进行检测。要检测的项目有:

    估计返程时间是否小于开始用车的时间
    所选择的车辆在开始和估计返程这段时间内是否与该车辆的其它派车有冲突

    使用派车的流程图如图 5.8 所示。

    5.2.2.3 收车收车跟派车一样也是个经常使用的功能。当用户点击“收车”按钮时,获取列表中选中的项,如果只是选中了一个项,判断选中的项是否已经收车,如果没有则弹出收车信息录入窗口;如果选中的是多个项,将遍历所有选中的项,并判断选中的项是否已经收车,如果还没有收车,就将收车人默认设置为登录的用户并直接将收车信息保存到数据库中,然后更新列表中的信息内容。使用收车的流程图如图 5.9 所示。

    5.2.3 终端管理终端管理是功能模块能够对终端的资料进行增删改查等功能。终端管理功能模块初始化时,先从数据库中将用户所能有权限管理的终端从数据库中查询出来,再将查询结果显示在列表中。该功能模块的子功能模块有:查询终端资料、新增终端资料、修改终端资料、删除终端资料,这些功能模块主要依赖于终端的操作类。
    5.2.3.1 查询查询是获取用户输入的搜索文本,再将用户输入的文本组装成对某些特定的字段进行模糊查询的SQL语句并用该SQL语句查询数据库,最后再将查询结果在用户界面上显示出来。终端查询的模糊查询的字段有:终端名、当前地址、所属车队、所属用户组等,在以后的升级中,可能会提供更强大的模糊查询功能。使用终端查询的流程图如图 5.10 所示。

    5.2.3.2 新增通过“新增”按钮可以添加新的终端资料。当用户点击新增按钮时,弹出新增终端资料的窗口,用户点击保存按钮后,获取用户录入的终端资料,首先要对用户输入的合法性进行检测,检测合法后再将终端资料数据组装成插入SQL语句,通过插入数据来将终端资料保存到数据库中,如果不合法则提示用户错误信息。需要检测的有两次输入密码是否一致、密码长度是否过长。新增终端资料的流程图如图 5.11 所示。

    5.2.3.3 修改通过“修改”按钮可以修改选中的终端资料。当用户点击“修改”按钮时,弹出修改终端资料的窗口,用户点击保存按钮后,获取用户修改过后的终端资料,同样首先要对用户输入的合法性进行检测,检测合法后再将修改后的终端资料组装成更新数据库的SQL语句,通过更新数据库将修改内容保存到数据库中,如果不合法则提示用户错误信息。需要检测的有两次输入密码是否一致、密码长度是否过长,修改终端资料的流程图如图 5.12 所示。

    5.2.3.4 删除通过“删除”按钮可以删除选中的终端资料。当用户点击“删除”按钮时,首先获取用户选择中的终端资料中的终端编码,通过终端的唯一索引之一终端编码来从数据库中删除对应的终端资料,并更新终端列表内容,删除终端资料的流程图如图 5.13 所示。

    5.3 权限管理权限管理是用于管理用户、角色、用户角色对应关系、角色权限对应关系、角色车队对应关系。在权限管理功能模块中,主要包括的子功能模块有:

    用户管理
    角色管理
    保存权限(保存用户-角色对应关系、角色-权限对应关系、角色-权限对应关系)

    其中用户管理和角色管理的实现都比较简单,只是涉及关于数据库的一些操作,跟车辆资料管理的实现在雷同之处,所以在这里就不再详细叙述,若要了解详细内容,可借鉴车辆资料管理中的实现。
    权限管理的功能模块图如图 5.14 所示。

    5.3.1 保存权限当用户点击“保存权限”按钮后,系统要完成的工作有以下几个:首要获取系统用户当前选中的用户和当前选中的角色,再获取角色的勾选项、权限的勾选项及车队的勾选项,再分别将选中的用户跟勾选的角色对应起来、选中的角色跟权限的勾选项对应起来、选中的角色跟车队对应起来。
    将三组关系正确对应起来之后,再依次将这三组关系与原来的关系进行对比,得出两者之前不同的部分,比如新增的对应关系或删除的对应关系,分类保存新增的对应关系和删除的对应关系,如果既没有新增的对应关系也没有删除的对应关系,也就是对应关系没有任何改变,就不用对数据库进行修改,否则就分别将新增的对应关系和删除的对应关系保存到数据库中。该模块的活动图如图 5.15所示:

    5.4 地图功能地图是本系统最主要的需求功能之一。在本系统中,地图的实现使用了SOGOU地图的API结合JAVASCRIPT和MFC的WEBBROSWER2控件来实现。而在地图功能的实现当中,最主要的难题是JAVAXRIPT 和MFC 程序之间的相互通信。在本系统中,JAVASCRIPT和MFC之间的通信使用了CWebPage类和ImpIDispatch技术。
    5.4.1 地图初始化在地图初始化的时候,首先从数据库中读取登录用户的标注和路线,还有全部的区域,通过调用JAVASCRIPT的函数来在地图上将这些内容显示出来。在往地图上添加标注的时候,顺便给标注添加上响应单击事件和右键事件,往地图上添加路线和区域时也顺便给路线和区域添加单击事件。地图初始化的活动图如图 5.16所示:

    5.4.2 GPS功能当GPS功能模块初始化时,先从数据库中根据车队来分类查询出终端-车辆对应的车辆资料,再按照这种对应关系来在树形列表中显示出来。GPS功能模块中主要包括的子功能模块有动态跟踪、轨迹回放、数据分析、查看车辆信息等。以下是分别对这几个子功能模块的设计进行详细分析。
    5.4.2.1 动态跟踪动态跟踪提供的是对某辆特定的车辆进行实时监控,并在地图上绘制出车辆经过的轨迹,地图会随着车辆的移动而移动。
    当用户点击“动态跟踪”按钮时,首先获取用户在树形列表中选中的项包含的数据,该数据是选中车辆的ID,将该ID和终端名传递到动态跟踪窗口中。在跟踪窗口内定时查询数据库中对应ID的实时位置和速度信息,并将实时信息显示到动态跟踪的地图上,同时地图会根据车辆的实时位置而改变地图的中心。动态跟踪的活动图如图 5.17所示。

    5.4.2.2 轨迹回放当用户点击“轨迹回放”按钮时,首先获取用户在树形列表中选中的项的数据,这个数据即是选中车辆的终端ID,点击按钮后,会弹出一个轨迹回放窗口,并将终端ID和终端名称传递给轨迹回放窗口,在该窗口中,首先要选择轨迹回放的时间段点击下载后会从数据库中下载该终端的对应时间段内历史经过的地理位置和经过各个位置时的速度和时间。如果选择的时间段内有历史轨迹数据,则初始化轨迹回放地图,并定时依次地按时间顺序来将查询出来的地理位置信息、速度信息、时间信息作为参数传递到轨迹回放地图的JAVASCRIPT函数中,以便在地图上将这些信息作为轨迹回放标注的标题来显示出来。轨迹回放播放完后可选择重新播放或重新选择时间段下载或关闭。轨迹回放的活动图如图 5.18所示。

    5.4.2.3 数据分析当用户点击“数据分析”按钮时,弹出数据分析的窗口。
    在数据分析窗口中,主要有三个控件:MSCAHR控件、车辆-终端列表、超速列表,其中MSCHAR控件用于绘制速度曲线,车辆-终端列表用于显示用户有权限管理的车辆与终端对应关系的列表,超速列表显示的是某车辆在某个时间段内的超速信息,双击超速信息列表自动跳转到地图并在地图上显示选中超速信息的轨迹。当车辆-终端的选项发生改变时,获取当前选中的项的终端编码并从数据库内查询到对应的时间段内的速度信息, 将这些速度信息在MSCHART中显示出来,同时根据速度阀值来求出所有的超速区域段并在超速列表中显示出来。数据分析的活动图如图5.19所示。
    5.4.3 地图编辑地图编辑是主要是对地图搜索、标注、路线、区域进行管理和将区域分配到终端车辆。在本功能模块中,提供新增标注、路线或区域的方法有两种,一是通过地图编辑窗口的新增按钮,另一是在浏览器地图上右键选择对应功能即可。
    5.4.3.1 新增标注当用户在窗口或地图右键菜单中点击“新增标注”后,如果是在窗口中点击“新增标注,标注的默认位置为地图当前的中心,如果是在地图的右键菜单中点击“新增标注”,则将标注的默认位置设置为右键事件发生的位置,然后在该位置弹出新增标注的信息窗,输入标注信息后点击保存,JAVASCRIPT的函数首先获取用户输入的标注信息,再调用MFC的函数将标注信息保存到数据库中。
    5.4.3.2 新增路线当用户在窗口或地图右键菜单中点击“添加路线”后,地图会进入绘图模式,并在JAVASCRIPT的路线模块中新建一条路线,在地图上点击任何一点都会将该点添加到该新建路线的折点中,在地图右键菜单中点击结束绘制时会在地图上最后的一个点击点处弹出编辑路线的信息窗,点击“保存”后JAVASCRIPT的函数获取路线的名称和ID并调用MFC的函数来在数据库的用户-路线表中新增一条记录,然后再循环遍历路线的折点并调用MFC函数将折点的地理位置保存到数据库中。
    5.4.3.3 新增区域当用户在窗口或地图右键菜单中点击“添加区域”后,地图会进入绘图模式,并在JAVASCRIPT的路线模块中新建一条路线,在地图上点击任何一点都会将该点添加到该新建路线的折点中,在地图右键菜单中点击结束绘制时,会将该新建的路线闭合成一个区域,并在地图上最后点击处弹出区域编辑信息窗,点击“保存”后先调用MFC函数在数据库的用户-区域表中新建一条区域记录,然后再在JAVASCRIPT中用函数顺序循环获取区域各个角的地理位置并调用MFC函数将这些地理位置信息保存到数据库中。
    5.4.3.4 给车辆终端分配区域在地图编辑窗口中,有三个列表,一个是列表数据库中所有区域,一个是列表当前登录用户有权限管理的所有车辆终端,一个是列表当前车辆终端列表中选中的项对应的进报警区域或出报警区域。当要给某车辆终端添加报警区域时,先获取当前车辆终端列表中被选中的车辆,然后判断当前报警区域列表的模式是进报警区域还是出报警区域,再依次获取区域列表中被选中的区域,判断选中的区域是否已经在对应车辆的进(出)报警区域当中,如果不在,添加进去,如果已经在,继续区域区域列表中被选中的项并进行同样的动作,直到获取完为止。
    6 系统测试6.1 测试目的软件测试的目的是尽可能多地发现软件产品(主要是指程序)中的错误和缺陷。
    明确测试的目的是一件非常重要的事,因为在现实世界中对测试工作存在着许多模糊或者错误的看法,这些看法严重影响着测试工作的顺利进行。因此,在测试的过程中,不仅是本作者对系统进行测试,还邀请相关同学测试炎光高校团购网系统,并利用宿舍局域网以本人主机为服务器,让其他同学访问测试本系统。
    在测试和调试应用程序后,系统应达到以下要求:

    运行不会导致崩溃或产生错误信息
    在一般情况下操作正常
    在一定范围内,操作合理,或能提供适当的错误信息

    6.2 开发与测试环境本系统的开发及运行环境如下:

    硬件平台

    CPU: Intel® Pentium® M processor 1.86GHz
    内存:1G

    软件平台

    操作系统:WindowsXP SP3
    数据库:MS Sql
    浏览器:IE6.0


    6.3 测试计划基于电子地图和GPS 的车辆信息管理系统在开发过程的各个阶段都安排有相应的测试,主要是为了及早发现系统模块中的错误,尽快解决问题,损失降到最小。炎光高校团购网系统的开发过程的各个阶段都有相应的测试,为了及早发现系统模块中的错误,尽快解决问题,损失降到最小。在本系统的测试过程中,全面地测试了系统各部分,使用了数据测试、操作测试、确认测试及系统测试。

    数据测试:即用大量实际数据进行测试,不仅输入了大量的合法数据,还有很多非法的数据,以及各种“边值”、“端点”特殊数据项,对系统模块进行数据测试
    操作测试:即从操作到各种显示、输出做全面检查,对系统各个模块操作多次,确认其与系统设计要求是否相一致
    确认测试:即黑盒测试,测试人员不管程序内部是如何编制的,对模块进行测试。这样正符合用户不懂程序编写,只根据功能使用的现实来进行测试
    系统测试:即对系统进行综合测试,不仅是系统本身,还有软/硬件环境和网络环境的性能要求是否符合实际情况

    表6-1列举了系统主要模块的测试报告。



    模块
    预计测试功能
    输入/输出功能
    造成差别原因




    登录
    注册时,有信息有效性验证;登陆时,跟数据库用户名、密码一致。
    与预期一致



    车辆管理测试
    对车辆资料、终端资料正确进行增删改查,正常派收车
    与预期一致



    权限管理
    正确赋予权限,并能根据权限来决定各种操作
    与预期一致



    地图
    正确显示地图和地图上的标注、路线和区域
    与预期一致



    数据分析
    正确在控件上显示速度曲线,列表超速信息
    曲线显示不完全正确
    X时间轴的划分不正确


    轨迹回放
    根据下载的内容在地图上依次回放车辆所经过的历史位置
    与预期一致



    动态跟踪
    定时获取车辆的实时位置信息并在地图上呈现
    与预期一致




    6.4 测试过程开发后期为了保证系统的正确性,对本系统做了大量的测试,比如操作测试、数据测试、确认测试、系统测试等,下面只提供了确认测试的过程,因为确认测试的正确性能够更好的说明系统是否能够正确地完成系统应该完成的功能。
    6.4.1 登录模块的测试]登录模块主要测试系统用户能否正确登入系统和提供错误的用户名或密码的时候还能不能登入到系统。错误的用户名或密码测试过程如图 6.1 所示。

    正确的用户名和密码测试过程如图6.2 所示。

    6.4.2 地图模块的测试地图模块的测试主要是测试地图能否正确地在地图上显示和新增标注、路线和区域,该模块的测试过程如图 6.3 所示。

    6.4.3 轨迹回放模块的测试对轨迹回放主要进行的测试有对于所选的时间段的轨迹记录进行正确的回放,测试过程如图 6.4 所示。


    6.4.4 动态跟踪模块的测试动态跟踪模块的测试主要是测试该功能模块是否能对特定的车辆进行实时性的跟踪,在该模块的测试过程中通过改变某特定车辆的位置信息进行改变来达到效果,如图 6.5 所示。

    6.4.5 数据分析模块的测试数据分析模块的测试主要是测试能否对某个特定的车辆的速度信息进行分析,比如能否正确绘制出速度曲线和计算出超速信息,该模块的测试过程如图 6.6 所示。

    6.5 测试结论在测试过程中,通过模块测试、性能测试、安全性测试,检查出系统在某些功能上设计不够完善,导致了一些问题的出现,通过对这些问题的分析与排查,并经过修改与检验后,所具有的功能模块基本能正常工作,无明显的错误;在性能上的测试表明使用系统时各种操作都无明显的延时;在安全性上,前台的安全设置能够保证系统的非法登录。总体看来,本系统的稳定性和安全性都能够得到保障。整个系统的设计和实现已达到了预期要求。
    7 出错处理设计7.1 出错输出信息出错输出信息表如7.1所示。



    序号
    错误
    输出信息




    1
    用户名或密码错误
    提示用户名或密码错误


    2
    数据长度小于设定值
    长度小于


    3
    数据不在设定范围内
    的值不在和之间


    4
    数据未输入
    必须输入


    5
    数据库无法连接
    服务器连接失败


    6
    起始时间小于终止时间
    提示用户终止时间应大于等于起始时间


    7
    设置密码两次输入不一致
    提示用户两次输入不一致,重新输入


    8
    地图载入失败
    提示地图载入失败,是否连上互联网



    7.2 出错处理对策出错处理对策表如7.2所示。



    序号
    错误
    处理对策




    1
    用户名或密码错误
    停在登录界面,不进行下一步操作


    2
    数据长度小于设定值
    停在录入界面,不进行下一步操作


    3
    数据不在设定范围内
    停在录入界面,不进行下一步操作


    4
    数据未输入
    停在录入界面,不进行下一步操作


    5
    数据库无法连接
    提供用户手动重试的功能


    6
    起始时间小于终止时间
    停在录入界面,不进行下一步操作


    7
    设置密码两次输入不一致
    停在录入界面,不进行下一步操作


    8
    地图载入失败
    提供用户手动刷新的功能



    8 安全保密设计
    进行系统的唯一方法是拥有一个能登录系统的用户账号
    输入密码时在界面上显示为******
    关键性的操作(比如删除)都会提示用户是否确认
    存放在数据库的密码必须是加密后的密文
    进行系统的系统用户只能执行系统管理员分配给他的功能
    尽力提高系统的鲁棒性、避免因用户的疏忽对系统造成损害
    对于有些需要限制长度的字段要限制用户输入的长度;避免保存失败
    用户的一些数据是保密的并且其他用户不能管理和查阅

    结 论经过了几个月来的学习和努力,在指导老师的帮助下,我终于完成了基于电子地图和GPS的车辆信息管理的系统和毕业论文。从开始确定开发一直到系统实现,再到论文文章的完成,每走一步对我来说都是新的尝试与挑战。我很享受这其中的过程,因为在这当中我学到的东西让我受益终身,这次经历是我一辈子都不会忘记的珍贵回忆,并且对我今后的发展,可能也有着深远的影响。
    在完成基于电子地图和GPS的车辆信息管理系统之后,现在回顾起来,感触颇多,在这过程当中,固然遇到了不少的难题和挫折,也有不少酸甜苦辣的感受,这其中的“人生百味”是难以用文字来表达,但这其中的经历,也让我学到了许许多多的平时生活没没办法学到的东西,受用一辈子。有时对于折腾了好却仍无法解决的问题感到非常的灰心,有时因受到了挫折而倍感沮丧想要放弃,但庆幸的是每次在我想要放弃的时候我都说服了我自己:只要我坚持下去,我就能解决它,我一定会解决它!也就是我的执着和坚持和指导老师的悉心帮助,我克服了一个又一个的困难,一点点地提高我了自己的能力水平,一步一步的向前走来,一直坚持到了最后。每次向前走一步都是一次自我提高的过程,每一次进步,都让我充满自信和斗志,这也是我不断进取的动力,也更让我相信只有努力进取,才能让自己变得更强大;只有不放弃,才能达到自己的目标。
    基于电子地图和GPS的车辆信息系统已经在我手下顺利完成,但其中还是有些许可以改进或者必须改进的地方,比如有些地方还可以做得更好,有些地方的实现方法不正确导致系统还隐藏存在有一些的问题等等。虽然现在系统有这些真正存在的问题,但我依然可以自豪的说:这是我的作品,这里面的每一段代码、每一个功能实现都有我的辛勤劳动,都是我亲手去做的,就是现在发现的每一个问题,都是我自己找出来的。看着自己做的系统达到预期目的并且自己的辛勤付出得到了收获是一件很快乐的事情,我非常享受这其中的过程。
    参考文献[1] David Lane著Windows Via C/C++ ; 清华大学出版社2010
    [2] anthony janes,jim ohlund编著NETWORK PROGRAMING FOR MICROSOFT WINDOWS清华大学出版社,2002
    [3] Windows网络编程技术.胡鸣编科学出版社,2008
    [4] Windows网络编程 黄超 编著 人民邮电出版社 2002
    [5] 轻松掌握用-用VISUAL C++6对数据库编程 lynRobison 编著 电子工业出版社 2007
    [6] 许家珆主编.软件工程:方法与实践[M].北京:电子工业出版社,2007
    [7] 王珊 萨师煊编著.数据库系统概论[M].北京:高等教育出版社,2006.
    [8] (英)BobHughes,(英)MikeCotterell著;软件项目管理[M].北京:机械工业出版社
    [9] (美) JeffreyRichter著; windows核心编程[M]第五版.北京:清华大学出版社
    [10] (谭浩强 著;C语言程序设计(第三版)[M].北京:清华大学出版社,2005.7
    2 评论 19 下载 2018-12-01 16:33:34 下载需要12点积分
显示 0 到 15 ,共 15 条
eject