分类

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

资源列表

  • 基于JSP实现的课程资源管理系统网站

    一、系统需求1.1 用户信息管理
    用户:系统管理员、教师、学生
    登录:用户进行账号、密码等信息填写登陆后,教师、学生可以查看账号信息或进行课程、教学资源、作业管理等操作,系统管理员登录后可以行使增删账号的权限
    忘记密码:教师、学生填写学/工号和姓名,重置密码为学/工号后六位,系统管理员只允许后台操作重置密码
    修改密码:填写账号、当前密码、新密码

    1.2 课程管理规定每名教师可以教授多门课程,一门课程可以由多名老师授课,学生可以选修多门课程,每门课程可以被多名学生选择,课程名可以相同,但课程号唯一,对应特定的授课教师。
    1.3 教学资源的管理
    课件管理:教师每门课程只能有一个课件,每个课件可以有多个章节,教师可以上传/下载授课课程对应的课件。学生可以搜索、下载、在线查看其选修课程的课件
    作业管理:每门课程每个课时有相应的作业,教师可以发布作业要求、查看学生作业提交状态、下载学生的作业、对作业进行评分、给出批改意见并做统计分析。学生可以查看课程的作业要求,进行作业的提交,查看作业的批改情况

    1.4 教学信息发布老师可以发布其教授课程的学生成绩,或对学生的成绩进行修改。学生可以查询自己选修课程的成绩,并对教师进行教学评价。
    二、系统架构2.1 构架该系统采用表示层、业务逻辑层、数据访问层三层构架。
    在系统主页面,用户可以通过已有的账号密码进行登录,验证成功则进入个人信息页面;也可以进行忘记密码之后的重置操作,验证成功则完成重置并返回系统主页面再次登录
    在个人信息页面,用户可以修改当前账号密码,验证成功则完成修改则返回系统主页面。在此之外,不同身份的用户可以有不同的操作。

    管理员:查看现有帐号信息,对帐号进行增、删等操作
    教师:查看课程信息,包括预览、下载课件,查看作业情况(提交、批改意见、评分)等;修改课程信息,包括上传、重传课件,下载作业,提交作业批改意见、评分,发布新作业要求,更新系统公告等
    学生:查看课程信息,包括预览、下载课件,查看作业情况(提交、批改意见、评分)等;修改课程信息,包括上传、重传作业等

    2.2 系统流程
    表示层效果采用HTML5、CSS等语言和前端框架jQuery,实现用户交互界面。交互界面包括用户登录界面,个人信息展示页面,课程、课件、作业查看页面等
    业务逻辑层利用Servlet,JSP来处理来自前端的请求,获取数据库数据,并作出相应的处理,将处理数据提交到前端,显示给用户
    数据访问层利用Hibernate架构操作数据库,通过应用程序经过Hiberante持久层来访问数据库。数据访问层的关键是确定表结构和表属性,便于业务逻辑层进行对数据库的查询,良好的数据库结构,对数据操作有很大的用处

    2.3 系统结构
    三、数据库设计与构架3.1 E-R图
    3.2 物理设计admin(管理员账号信息表)



    adm_id
    password




    varchar
    varchar



    teacher(教师账号信息表)



    tea_id
    name
    password




    varchar
    varchar
    varchar



    student(学生信息表)



    stu_id
    name
    password




    varchar
    varchar
    varchar



    course(课程信息表)



    course_no
    title
    credit
    tea_id




    varchar
    varchar
    decimal(3,1)
    varchar



    stu_course(选课信息表)



    course_no
    stu_id
    grade
    tea_evaluation




    varchar
    varchar
    decimal(3,1)
    decimal(3,1)



    courseware(课件信息表)



    course_no
    file_title






    varchar
    varchar



    tea_homework(发布作业情况表)



    course_no
    homework_no




    varchar
    varchar



    stu_homework(提交作业评分表)



    course_no
    homework_no
    stu_id
    status
    grade
    opinion




    varchar
    varchar
    varchar
    bit
    decimal(3,1)
    varchar



    四、模块设计4.1 用户模块
    4.2 教学信息模块
    4.3 作业管理模块
    4.4 课件管理模块
    4 评论 183 下载 2018-11-06 12:56:48 下载需要5点积分
  • QT和MYSQL实现的基于CS架构的学生成绩管理系统

    一、系统设计目标随着学科与时代的发展,大学课程种类增多,课程以及有关的作业、任务等的种类也越来越多,设计并实现一个有条理的课程管理系统显得较为重要。这一实验的目标则是设计一个功能完善,性能优良的课程、选课、授课、成绩等信息的管理系统。
    此系统需要提供师生的选课、授课、布置任务,成绩管理等多方面的需求,同时达到较高的性能,又不失安全性。此外,还需要进行模块化的设计,使得这一系统随着时间的推移可以自由的增删需求而无需过多的更改,同时与第三方程序保持一定的兼容性。
    二、需求分析采用B/S或C/S模式实现一个成绩管理系统。完成课程、学生、教师、选课、授课、成绩等信息的管理。功能上需要提供管理员、学生、教师三类用户的录入、查询界面,课程可以有多次作业或测试,作业或测试的数量不能由系统预先指定,而应由教师本人指定自己所负责课程的作业及测试的数量,系统应支持等级评定,允许对不同的级别指定分隔点,提供学生、课程等不同角度的成绩统计功能等等。
    对于功能需求进行翻译,则在数据库的层面,需要收这些关系约束:

    学生可以选修多门课程,一门课程可以被多个学生选修
    教师可以教授多门课程,一门课程可以被多个教师教授
    一位教师可以布置多个任务,一个任务只对应一门课程
    学生可以完成多个教师布置的任务,多个学生可以完成同一个任务
    学生和教师可以提交多个申请(如选课、开课、授课申请等)
    一个申请只由一个管理员批准,一个管理员可以批准多个申请

    此外,三种角色自己具有的权限如下:

    教师用户需要获得有关自身的账号信息、自己教授的课程信息、自己布置的任务的信息,并可以为完成的任务打分,可以提交教师相关的申请
    学生用户需要获得有关自身的账号信息、可选的课程信息、已选课程有关的任务信息,并可以完成、提交相应的任务,可以提交学生相关申请
    管理员可以获得并修改所有关系的信息,并具有批准申请的能力

    在性能方面,需要一次能够处理大量的请求,并且在高负荷情况下对于请求可以缓存处理,此外,当请求不能得到及时的处理时需要向客户端返回必要的信息。
    在安全性方面,需要保证每一个角色只对于自己的个人信息有访问权限,只对于自己这一角色提供的服务有调用权限,此外没有其他的权限,而在客户端图形界面之外不能直接连接数据库,在客户端内无法通过注入进行攻击。
    三、总体设计总体上而言,系统为C/S结构包含5个部分:数据库、服务端、教师客户端、学生客户端、管理员客户端。只有服务端能够直接访问数据库,而客户端只能通过与服务端的沟通来间接的访问数据库,从而达到较高的安全性。总体架构图如图 4.1所示。

    图中,自定义协议是一套使用json包装的,在HTTP上进行传输的协议,使用这一套协议可以最大限度的保证数据库的安全性。
    四、数据库设计将功能需求转换为E-R图,则如图 4.2所示。图中,所有的主码已用下划线标出。

    接下来,将E-R图转换为实际的数据库结构。图中的每一个实体对应一张表,1对n关系在n端连接的表中引用1端所在表的主码作为外码,n对n关系则将关系本身构建为一张独立的表,这张独立的表含有两个实体的主码。以此构建的数据库中含有的表如表 4.1所示。



    表名
    说明




    Course
    课程列表


    Teacher
    教师列表


    Student
    学生列表


    Manager
    管理员列表


    Task
    教师布置的任务列表


    StudentCourse
    学生选课表


    TeacherCourse
    教师授课表


    StudentTask
    学生完成任务列表


    StudentApplication
    学生申请列表


    TeacherApplication
    教师申请列表



    为了能够更为完整的展示各表的内容以及表之间而约束关系,列出各表的创建语句如下:
    课程列表Course的各字段以及说明如表 4.2:



    字段
    类型
    说明




    id
    char(10)
    课程号


    name
    varchar(50)
    课程名


    span
    int(11)
    时长


    season
    int(11)
    开课季度



    创建列表的SQL语句为:
    CREATE TABLE `Course` ( `id` char(10) COLLATE utf8mb4_unicode_ci NOT NULL, `name` varchar(50) CHARACTER SET utf8 NOT NULL, `span` int(11) DEFAULT NULL, `season` int(11) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    管理员列表Manager的各字段以及说明如表 4.3:



    字段
    类型
    说明




    id
    char(10)
    管理员编号


    name
    varchar(50)
    管理员名称


    username
    varchar(20)
    用户名


    password
    char(64)
    密码(hash,下同)



    创建列表的SQL语句为:
    CREATE TABLE `Manager` ( `id` char(10) COLLATE utf8mb4_unicode_ci NOT NULL, `name` varchar(50) CHARACTER SET utf8 NOT NULL, `username` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `password` char(64) COLLATE utf8mb4_unicode_ci NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    学生列表Student的各字段以及说明如表 4.4:



    字段
    类型
    说明




    id
    char(10)
    学号


    name
    varchar(50)
    姓名


    username
    varchar(20)
    用户名


    password
    char(64)
    密码



    创建列表的SQL语句为:
    CREATE TABLE `Student` ( `id` char(10) COLLATE utf8mb4_unicode_ci NOT NULL, `name` varchar(50) CHARACTER SET utf8 NOT NULL, `username` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `password` char(64) COLLATE utf8mb4_unicode_ci NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    教师列表Teacher的各字段以及说明如表 4.5:



    字段
    类型
    说明




    id
    char(10)
    教工号


    name
    varchar(50)
    姓名


    username
    varchar(20)
    用户名


    password
    char(64)
    密码



    创建列表的SQL语句为:
    CREATE TABLE `Teacher` ( `id` char(10) COLLATE utf8mb4_unicode_ci NOT NULL, `name` varchar(50) CHARACTER SET utf8 NOT NULL, `username` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `password` char(64) COLLATE utf8mb4_unicode_ci NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    任务列表Task的各字段以及说明如表 4.6:



    字段
    类型
    说明




    id
    char(10)
    任务编号


    courseId
    char(10)
    所属课程Id


    teacherId
    char(10)
    布置此任务的教师编号


    question
    text
    任务内容


    start
    timestamp
    开始时间


    end
    timestamp
    截止时间


    type
    char(10)
    任务类型



    创建列表的SQL语句为:
    CREATE TABLE `Task` ( `id` char(10) COLLATE utf8mb4_unicode_ci NOT NULL, `courseId` char(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `teacherId` char(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `question` text COLLATE utf8mb4_unicode_ci, `start` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `end` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `type` char(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL, PRIMARY KEY (`id`), KEY `teacherId` (`teacherId`), KEY `courseId` (`courseId`,`teacherId`), CONSTRAINT `Task_ibfk_1` FOREIGN KEY (`courseId`, `teacherId`) REFERENCES `TeacherCourse` (`courseId`, `teacherId`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    学生选课列表各字段及说明如表 4.7:



    字段
    类型
    说明




    studentId
    char(10)
    学生Id


    courseId
    char(10)
    课程Id



    创建列表的SQL语句为:
    CREATE TABLE `StudentCourse` ( `studentId` char(10) COLLATE utf8mb4_unicode_ci NOT NULL, `courseId` char(10) COLLATE utf8mb4_unicode_ci NOT NULL, PRIMARY KEY (`courseId`,`studentId`), KEY `studentId` (`studentId`), CONSTRAINT `StudentCourse_ibfk_1` FOREIGN KEY (`studentId`) REFERENCES `Student` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `StudentCourse_ibfk_2` FOREIGN KEY (`courseId`) REFERENCES `Course` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    学生完成任务列表各字段及说明如表 4.8:



    字段
    类型
    说明




    studentId
    char(10)
    学生Id


    taskId
    char(10)
    任务Id


    answer
    text
    答案


    score
    int(11)
    分数


    finsihTime
    timestemp
    完成时间



    创建列表的SQL语句为:
    CREATE TABLE `StudentTask` ( `studentId` char(10) COLLATE utf8mb4_unicode_ci NOT NULL, `taskId` char(10) COLLATE utf8mb4_unicode_ci NOT NULL, `answer` text COLLATE utf8mb4_unicode_ci, `score` int(11) DEFAULT NULL, `finishTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`studentId`,`taskId`), KEY `taskId` (`taskId`), CONSTRAINT `StudentTask_ibfk_1` FOREIGN KEY (`studentId`) REFERENCES `Student` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `StudentTask_ibfk_2` FOREIGN KEY (`taskId`) REFERENCES `Task` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    学生申请列表StudentApplication的各字段以及说明如表 4.9:



    字段
    类型
    说明




    id
    char(10)
    申请编号


    statement
    text
    申请内容


    studentId
    char(10)
    申请人学号


    approved
    bool
    是否同意


    managerId
    char(10)
    处理人编号



    创建列表的SQL语句为:
    CREATE TABLE `StudentApplication` ( `id` char(10) COLLATE utf8mb4_unicode_ci NOT NULL, `statement` text COLLATE utf8mb4_unicode_ci, `studentId` char(10) COLLATE utf8mb4_unicode_ci NOT NULL, `approved` tinyint(1) DEFAULT NULL, `managerId` char(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL, PRIMARY KEY (`id`), KEY `studentId` (`studentId`), KEY `managerId` (`managerId`), CONSTRAINT `StudentApplication_ibfk_1` FOREIGN KEY (`studentId`) REFERENCES `Student` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `StudentApplication_ibfk_2` FOREIGN KEY (`managerId`) REFERENCES `Manager` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    教师申请列表TeacherApplication的各字段以及说明如表 4.10:



    字段
    类型
    说明




    id
    char(10)
    申请编号


    statement
    text
    申请内容


    teacherId
    char(10)
    申请人教工号


    approved
    bool
    是否同意


    managerId
    char(10)
    处理人编号



    创建列表的SQL语句为:
    CREATE TABLE `TeacherApplication` ( `id` char(10) COLLATE utf8mb4_unicode_ci NOT NULL, `statement` text COLLATE utf8mb4_unicode_ci, `teacherId` char(10) COLLATE utf8mb4_unicode_ci NOT NULL, `approved` tinyint(1) DEFAULT NULL, `managerId` char(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL, PRIMARY KEY (`id`), KEY `teacherId` (`teacherId`), KEY `managerId` (`managerId`), CONSTRAINT `TeacherApplication_ibfk_1` FOREIGN KEY (`teacherId`) REFERENCES `Teacher` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `TeacherApplication_ibfk_2` FOREIGN KEY (`managerId`) REFERENCES `Manager` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    五、详细设计与实现5.1 服务端实现此系统的核心部分为服务端,其接受服务端的所有请求,分析并缓存请求,处理请求,分析并处理数据库操作结果并返回结果。对于权限的管理,请求完整的验证以及数据库操作的处理均在服务端完成。服务端的具体架构如图 4.3所示。

    图中,协议模块是一个客户端与服务端共同使用的C++模块,其中定义了服务端提供的服务类型、服务的请求格式、对于服务请求的一些基本操作、客户端的角色、客户端的请求内容等。在定义好服务端的http服务器以及客户端的http客户端后,双方直接通过此协议模块定义的协议层进行通信,而底层的http模块对于客户端则是透明的,这样,与底层分离协议便十分易于修改。
    请求预处理器对于客户端发来的请求进行预处理,检验请求是否完整,以及权限是否匹配(即客户角色是否能够使用请求)。为了防止客户端伪造身份,使用客户端发送过来的密码(hash后)进行身份验证。这样确实、加重了数据库的负担,但在更进一步的修改中可以只在第一次登录时进行验证,此后服务端向客户端发送随机动态口令并使用加密过的动态口令进行身份验证,这样可以极大地减少数据库的负担。但由于时间的限制,在本次的实现中未采用这种较为复杂的方法。
    经过预处理器的初步验证后,请求分发器将请求发送给(可能的)存在于多个线程上的锁个服务提供程序,以达到并行处理的效果。但在实际的测试中,CPU的处理速度并不是瓶颈,对于数据库的访问才是,因此使用多线程对于处理速度的提升不大,而对于数据库的存储优化则会产生比较大的影响。
    最后模块化的服务提供程序初步进行数据库访问,处理数据库的返回结果后及结果返回给客户端。在协议处理时,为了避免注入攻击采用参数化查询,使用预编译的sql指令进行数据库的操作。
    服务端提供的程序如表所示。



    服务
    说明
    SQL**语句**




    login
    登录
    select * from Student/Teacher/Manager where id=:realId


    getCourse
    获得课程列表
    select * from Course


    getRegisteredCourse
    学生获得已选课程
    select * from StudentCourse inner join Course on StudnetCourse.courseId = Course.id where studentId=:realId


    getRelaventTaskList
    获得与已选课程有关的任务列表
    select * from (select Task.id, Course.name, StudnetCourse.studnetId as sid from (Task inner join Course on Task.courseId = Course.id inner join StudnetCourse on StudnetCourse.courseId = Course.id) where StudentCourse.studnetId = :stuId) as base left join StudentTask on (base.sid = StudnetTask.studentId and base.id = StudentTask.taskId)


    getSpecificTask
    获得特定的任务
    select * from Task where id = :taskId


    submitTask
    提交任务
    insert into StudentTask values(:sId, :tId, :and, null, :time)


    registerCourse
    注册课程
    insert into StudentApplication values(:aId, :stmt, :sId, null, null)


    getRelaventAppList
    获得已提交的申请
    select * from StudentApplication/ TeacherApplicatoin where studentId/teacherId = :sId/:tId


    unRegisterCourse
    取消课程注册
    insert into StudentApplication/ TeacherApplication values (:aId, :stmt, :sId, null, null)


    getTeachingCourse
    获得正在教授的课程列表
    select * from TeacherCourse inner join Course where Course.id = TeacherCourse.courseId where id = :tId


    getAssignedTaskList
    获得自己布置的任务
    select * from Task inner join Course on Task.courseId = Course.id where Task.teacherId = :id


    selectCourseToTeach
    注册教授课程
    insert into TeacherApplication values (:aId, :stmt, :sId, null, null)


    getStudentsForTask
    获得关于某个任务的学生列表
    select Student.id, Student.name, StudnetTask.score from Student inner join StudentTask on Student.id = StudentTask.studentId where StudentTask.studentId = :sId


    getSpecificAnswer
    获得某个学生针对某个任务的答案
    select * from StudentTask where (studentId, taskId) = (:sId, :tId)


    gradeStudent
    给某个学生的某个任务打分
    update StudentTask set score = :grade where (studentId, taskId) = (:sId, :tId)


    addTask
    添加任务
    insert into Task values (:id, :cId, :tId, :q, :start, :end, :type)


    getStudents
    获得学生列表
    select * from Student


    getTeachers
    获得教师列表
    select * from Teacher


    approveApplication
    批准申请
    1. select * from StudentApplication/ TeacherApplication where id = :aId 2. 组成并执行预先存储的语句 3. update StudentApplication/ TeacherApplication set managerId = :mId, isApproved = :acc where id = :aId


    declineApplication
    拒绝申请
    update StudentAplication/ TeacherApplication set managerId = :mId, isApproved = :acc where id = :aId


    getTeacherAppList
    获得教师申请列表
    select * from TeacherApplication where isApproved is null


    getStudentAppList
    获得学生申请列表
    select * from StudentApplication where isApproved is null



    其中,以冒号开头的为占位符,在运行时动态绑定值并执行
    5.2 客户端实现客户端的架构如图 4.4所示。其中,用户通过前端与程序进行交互,前端传递信息给后端,后端使用协议模块构造请求后通过http客户端发送给服务器,等待服务器响应后处理服务器返回的数据,通过协议模块进行解析后在界面上进行显示。

    由于服务端已经定义好了所有的服务,客户端只需通过协议模块构造请求并发送即可,客户端剩下的任务就是给用户一个简单易懂的,易于交互的界面。客户端的4个模块的界面设计如下,其界面设计也反映了客户端给用户提供的功能。由于使用了C/S架构,且由于时间上的关系,服务器提供的一些服务并没有在客户端实现,不过大部分需求均已实现。
    其中,登录界面如图 4.5所示,上方输入用户名和密码,下方选择登录角色。

    一个不成功的登录如图 4.6所示,在下方会提示错误原因。不止是登录界面,所有的界面中均有这样一个状态条显示当前的状态。

    学生登录后的界面如图 4.7所示,主页的4个信息面板分别显示个人信息、已选课程、课程相关任务以及已提交的申请。

    点击到Course tab,进入选课界面。选课界面如图 4.8所示。选课界面上有一排过滤栏以及一个刷线按钮和一个选课按钮。在刷新按钮按下后,会向服务器发送请求将本地的课程与服务器的课程进行同步,更新本地课程到最新。通过顶部的过滤栏可以按照课程编号、名称以及时长进行过滤,如图 4.9所示。这样对于课程的筛选而言更为方便。
    刷新后的选课界面

    过滤后的选课界面

    最后一个Task Tab则是任务Tab,学生用户可以浏览与自己已选课程有关的任务并完成、提交任务。如图 4.10所示。

    教师界面与学生界面格式基本相同,但功能有所不同。此处不再展示重复的界面。教师可以为课程添加任务,其界面如图 4.11所示。

    教师的任务列表与学生有所不同,使用了两级列表的方式展现了所有布置的任务以及对应的学生,如图 4.12所示。

    对于管理员而言,其界面只有2个tab,主界面如图 4.13所示。

    除了主界面用于显示部分表的信息外,Application Tab用于显示学生和老师的申请,一个空的Application Tab如图 4.14所示。

    六、系统测试通过一次完成的对于3个角色的模拟,对于系统的功能进行测试:
    首先打开服务器,登录学生账号S20180003,登录后如图 4.15所示,可以看出此学生只选择了2门课程。

    然后进入选课列表,选择“线性代数”这一门课程,如图 4.16所示。图示为点击Register之前的情形。

    这时,登录任意一个管理员的界面(此处选择M201800001),进入Application Tab,可以看到学生的选课申请如图 4.17所示。若已经提前登录,则不会显示学成的申请,需要手工点击刷新按钮从服务器重新同步数据。

    同意本选课申请后此申请消失。如果拒绝此申请,申请也会消失,但无法继续进行接下来的实验,因此这里点击Accept按钮同意这一申请。在有多个申请的情况下,可以同时同意或拒绝多个申请。这一同意或拒绝的列表将由服务端程序逐个进行处理。
    回到学生界面,点击刷新按钮,可以看到申请已被同意(申请列表中),如图 4.18所示。

    进入教师界面,让教师选择教授线性代数这一门课,如图图 4.19所示。图示为选课之后的情形,可以看到,选课之后复选框消失,阻止了可能的重复选择。实际上,即使重复选择也不会对于数据库的稳定性造成任何影响,只会产生重复的请求,而服务器在处理重复的请求是会将除了第一个之外的请求视作无效请求并拒绝掉。

    同样的,由任意一个管理员批准后教师就能够教授这一门课程了。此时回到教师的主界面,点击刷新按钮,同步服务器数据,然后点击Add Task,为线性代数添加一个任务,如图 4.20所示。

    添加完成后,学生可以在自己的Task面板中看到并完成这一任务,如图 4.21所示。

    完成后,教师可以在Task页面看到学生的答案并打分,如图 4.22。

    最后,在教师打分后,学生在自己的主页面可以看到这一门课程的分数,如图 4.23,此时已无法再次修改答案。

    至此,程序的功能测试完成,基本功能正常。
    经测试,由于使用了参数化查询,类似”=-1 or 1=1; — ”这样的针对典型数据库注入攻击对于本程序是无效的,又由于客户端无法直接连接数据库,在服务器本身不被攻破的情况下外界是无法知道数据库的内部结构的,从而更进一步的增加了其安全性。
    此外,经过压力测试,在主频2GHz,SATA ssd的机器上每秒可以接受并预处理约20000个来自客户端的请求,平均每秒可以处理约8000个请求并返回给客户端。
    七、系统设计与实现总结在这次课程设计中,我对于一个C/S模式带数据库的学分管理系统进行了完整的设计。完成的主要工作如下:

    完成了对于数据库结构以及软件的需求分析
    完成了数据库的表格创建,数据的生成以及导入
    设计并实现了模块化服务端
    设计并实现了用户友好的客户端
    进行了较为完整的功能、性能以及安全性测试
    2 评论 32 下载 2019-03-09 15:23:20 下载需要14点积分
  • 基于C#的超市进存销管理系统

    第一章需求分析1.1 需求分析1.2 用例模型及分析类图的描述1.2.1 用例Use Case:账号密码登录
    参与者:用户
    主事件流:

    用户选择账号登录选项并输入账号密码
    将用户输入的EmpLoginName和EmpLoginPwd与数据库中相应的字段进行匹配
    若匹配成功,则跳转页面,转到主窗口。反之,则提示登陆失败

    1.2.2 用例图用例模型本系统以管理员对数据库的操作为主,实现用例图如下:

    根据对用例的分析,做出用例图如上,管理员主要利用本系统,实现对进货信息、库存信息、销售信息和职工信息、供应商信息的管理。系统采用VS环境开发,实现C/S结构,管理员对各个信息的修改都直接写入数据库。
    1.3 分析类1.3.1 用户登录模块用户登录用例图
    用户登录的用例图,如图1-3-1-1所示:

    用户登录时序图
    如图1-3-1-2所示,表示用户登录的时序图。

    用户登录分析类图(协作图)
    如图1-3-1-3所示,表示用户登录的协作图。

    1.3.2 进货模块进货用例图
    进货的用例图,如图1-3-2-1所示:

    用户登录时序图
    如图1-3-2-2所示,表示用户登录的时序图。

    用户登录分析类图(协作图)
    如图1-3-2-3所示,表示用户登录的协作图。

    1.3.3 销售模块进货用例图
    进货的用例图,如图1-3-3-1所示:

    用户登录时序图
    如图1-3-3-2所示,表示用户登录的时序图

    用户登录分析类图(协作图)
    如图1-3-3-3所示,表示用户登录的协作图

    1.3.4 库存模块进货用例图
    进货的用例图,如图1-3-4-1所示:

    用户登录时序图
    如图1-3-4-2所示,表示用户登录的时序图。

    用户登录分析类图(协作图)
    如图1-3-4-3所示,表示用户登录的协作图。

    1.3.5 职工管理模块进货用例图
    进货的用例图,如图1-3-5-1所示:

    用户登录时序图
    如图1-3-5-2所示,表示用户登录的时序图

    用户登录分析类图(协作图)
    如图1-3-5-3所示,表示用户登录的协作图

    1.3.6 供应商管理模块进货用例图
    进货的用例图,如图1-3-6-1所示:

    用户登录时序图
    如图1-3-6-2所示,表示用户登录的时序图

    用户登录分析类图(协作图)
    如图1-3-6-3所示,表示用户登录的协作图

    第二章 概要分析2.1 系统架构设计
    2.2 数据库设计2.2.1 数据库总体概念设计数据库总体E-R图如图2-2-1所示。

    2.2.2 数据库概念设计通过对于系统的需求分析,整套系统可以设计出六个实体,他们分别是职工实体、供应商实体、进货实体、销售实体、库存实体。
    系统的使用者涉及到多种用户,多以需要一个用户表来保存登陆账号和登陆密码。
    职工表E-R图

    职工数据库表

    供应商表E-R图

    供应商数据库表

    进货表E-R图

    进货数据库表

    销售表E-R图

    销售表

    库存数据库表E-R图

    库存数据库表

    2.3 系统类图设计分析系统,本系统主要包含数据库类和操作类。数据库类包括有进货信息数据库、销售信息数据库、库存信息数据库。操作类主要是对数据库的操作,包括有添加进货、销售、库存、职工、供应商详细信息两个操作。其中添加进货单可以对进货、销售、库存信息数据库执行添加,修改,删除、查找的操作,添加职工、供应商信息可以对物品信息数据库执行添加修改删除的操作。操作类还包含对数据的查询操作,可以根据关键字进行查询;分析以上各个类,作出类图如2-4所示。

    第三章 系统详细设计及实现3.1 系统功能描述本系统主要实现登陆注册模拟超市进货增删改查、销售增删改查、库存增删改查以及对超市内员工的增删和超市供应商的增删。
    3.2 用户登录界面用户登录界面如图3-2所示。

    3.3 职工管理功能职工管理如图3-3所示。

    3.4 供应商管理功能供应商管理如图3-4所示。

    3.5 进货管理功能进货增删改管理如图3-5-1所示。

    进货查询如图3-5-2所示。

    3.6 销售管理功能销售增删改管理如图3-6-1所示。

    销售查询如图3-6-2所示。

    3.7 库存管理功能库存增删改管理如图3-7-1所示。

    库存查询如图3-7-2所示。

    3.8 系统主页面系统主页面如图3-8所示。

    3.9 退出系统退出系统功能如图3-9所示。
    3 评论 32 下载 2019-09-02 12:26:43 下载需要9点积分
  • 基于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 评论 271 下载 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 评论 104 下载 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 评论 139 下载 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 评论 77 下载 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 评论 247 下载 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 评论 56 下载 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点积分
显示 0 到 15 ,共 15 条
eject