分类

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

资源列表

  • Qt实现的宠物小精灵对战游戏阶段二-用户的联网注册和登录

    1、题目要求
    每个用户需要注册一个账号,用户名全局唯一,不能有任何两个用户名相同,要考虑注册失败的场景时的反馈
    实现注册、登录、登出功能,均采用C/S模式,客户端和服务端用socket进行通信,服务端保存所有用户的信息(文件存储或数据库均可,数据库有额外加分)
    每个用户拥有:用户名、拥有的精灵,两个属性。 用户注册成功时,系统自动随机分发三个1级精灵给用户
    用户可以查看所有成功注册用户拥有的精灵,也可以查看所有当前在线的用户
    如有界面设计可酌情加分
    题目考察点:socket通信,交互场景反馈

    2、总体设计在第一阶段的基础上,实现以下改进:

    增加用户类
    使用数据库存储信息
    实现socket网络通信
    完成服务端接口

    第一版本的设计是从小精灵类的实现入手的。第二版本不同,将从服务端接口的角度开始设计,并同时考虑数据库的引入
    服务器在启动时将处于一个阻塞持续监听的状态,使用多线程技术实现按下任意键停止监听。所以在Hub里面设置了两个线程函数listenFunc和terminateFunc,前者用于实现正常的阻塞监听,后者实现按键停止服务器。
    针对多用户登录的问题,服务器设置一个统一的登录端口A0,这个端口将写死到客户端程序中。客户端向服务端的端口A0请求登录时,服务端程序将分配给客户用户一个目前未被使用的endpoint端口Ax,客户端将连接此Ax端口来实现持续的连接。
    用户名格式要求:

    不包含空格、回车、制表等空白字符
    长度6-30

    密码格式要求:
    仅包含字母、数字、下划线_长度6-30


    数据库schema:
    User( id integer primary key, name text unique not null, password text not null);Pokemon( id integer primary key, userid integer not null, name text not null, race int not null, atk int not null, def int not null, maxHp int not null, speed int not null, lv int not null, exp int not null,);
    其中设置User的id为integer类型的primary key的话,可以由sqlite3自动生成id
    Endpoint有一个timer,当用户超过timer没有给服务器发数据时服务器断开连接并delete Endpoint
    多Endpoint管理:

    使用vector保存Endpoint的指针,使所有Endpoints可以通过下标访问,并方便处理内存。
    Endpoint结束条件:当timer超时且发现socket链接已断开,则告诉Hub关闭此Endpoint。具体方案如下:

    public Endpoint::start()函数启动服务并返回端口号,如果返回0则表示启动失败public Endpoint::process()函数里面写socket的accept函数,并在process函数中处理各种请求,返回时代表endpoint结束(超时或用户退出)Hub::mornitor(Endpoint *)是线程函数,每当新建Endpoint的时候新建一个线程,调用此函数,参数为新的Endpoint的指针Hub首先使用Endpoint::start()获取端口号,然后新建线程把mornitor函数detach。Hub::mornitor函数中调用Endpoint::process()开始recv,当process函数返回时表示此endpoint结束运行,在Hub的Endpoint指针容器中清除此对象并delete之
    因为Hub的mornitor线程和listenFunc线程函数都需要访问Endpoint指针容器,所以设置锁来防止多线程出现故障

    通信方式:客户端发送一条请求,服务器回复一条信息,服务端不需持续监听。客户端发送注销请求时服务器不回复。
    Endpoint断线重连方案:

    Endpoint使用长连接
    客户端断开时,recv函数返回SOCKET_ERROR,设置online为false
    Endpoint在accept成功后设置online为true
    timer超时后如果online仍为false则判定玩家长时间未登陆而退出
    如果timer超时前玩家重新登陆则终止timer

    使用condition_variable实现带有条件的sleep

    Hub提供的接口:
    login <username> <password>logon <username> <password>
    Endpoint提供的接口:
    logoutresetPassword <oldPassword> <newPassword>getPlayerListgetPokemonList [playerID]getPokemon <pokemonID>pokemonChangeName <pokemonID> <newName>
    编码相关:
    服务端使用GB2312编码,客户端识别时使用QString QString::fromLocal8Bit(const char *str, int size = -1)来实现字符转换,发送时如果信息包含中文也需要使用QString.toLocal8Bit来实现转换,以此实现中文信息传递。
    目前能够出现中文的地方有:

    用户名
    精灵名
    种族名

    需要安装LAV filters才能播放音频。音频文件保存在exe目录下的media目录下
    使用QSS实现样式与内容分离。注意QSS文件一定不要使用UTF-8编码,建议使用ASCII编码。此处使用了GB2312!
    3、服务端设计与实现3.1 宏观设计关于Socket通信:服务器使用vs 2017作为开发环境,使用原生windows Socket作为通信基础。客户端使用Qt Creator作为开发环境,使用Qt提供的QTcpSocket作为通信基础。
    关于数据存储:使用Sqlite3作为数据库管理程序,所有数据保存在服务器以防止外挂程序。
    关于中文显示与信息传递:Qt使用UTF-8作为编码。由于vs 2017不支持不带BOM的UTF-8编码,所以服务端出现中文的文件使用GB2312编码。客户端识别时使用QString QString::fromLocal8Bit(const char *str, int size = -1)来实现字符转换,发送时如果信息包含中文也需要使用QString.toLocal8Bit来实现转换,以此实现中文信息传递。所以玩家可以把用户名和精灵名设置为中文。
    背景音乐:Qt的媒体播放器库使用了第三方的插件。如果程序启动后没有背景音乐,可以尝试安装LAV filters。
    资源文件:图片、音频等文件均作为资源文件保存在exe中,防止被用户替换。
    界面美化:使用了类似于CSS语法的QSS设置程序样式,实现了样式与内容的分离。QSS文件不能使用UTF-8编码,此处使用了GB2312编码。
    3.2 详细设计-数据库相关数据库schema设计:数据库采用sqlite3数据库,包含两个表,分别是用户表和精灵表。用户的用户名全局唯一,且用户拥有一个唯一的内部id。精灵表中保存了每个精灵的持有者的id,以便查询用户拥有的所有精灵。精灵表保存了所有精灵的属性。具体格式如下:
    User( id integer primary key, name text unique not null, password text not null);Pokemon( id integer primary key, userid integer not null, name text not null, race int not null, atk int not null, def int not null, maxHp int not null, speed int not null, lv int not null, exp int not null,);
    4、详细设计-网络通信相关服务器分为两个部分:一个Hub和一个Endpoint集合。Hub运行在7500端口,负责处理注册和登录的请求,为短链接,返回数据后立即断开连接。如果是登录请求,在登录成功的情况下会new一个Endpoint负责与用户对接,Socket会返回一个新的端口号。此端口号为操作系统分配的空闲端口号。
    Endpoint将和每个用户进行长链接,直到用户退出登录。Endpoint处理用户在登录状态下的各种请求,包括:

    重置密码
    获取玩家列表
    获取精灵列表
    获取单个精灵详细信息
    精灵改名
    退出登录

    此外,Endpoint还能够检测用户的意外断线。如果用户没有正常退出登录,则Endpoint不会立即销毁,而是会等待一段时间给用户重连,防止用户频繁掉线时Endpoint被频繁生成与销毁的问题。
    网络通信接口定义如下:

    Hub提供的接口

    login <username> <password>
    返回端口号则登录成功,否则返回错误信息
    logon <username> <passwprd>
    返回Accept.\n则注册成功,否则返回错误信息

    Endpoint提供的接口

    logout
    退出登录,无返回消息
    resetPassword <oldPassword> <newPassword>
    重置密码。返回Accept.\n则重置成功,否则返回错误信息
    getPlayerList
    返回所有玩家的信息。单个玩家信息格式为<userID> <userName> <online: 0 | 1>不同玩家信息使用换行符隔开
    getPokemonList [playerID]
    如果不给出playerID则返回自己的小精灵概要信息。否则返回指定玩家的小精灵概要信息单个小精灵信息格式为<id> <name> <raceName> <lv>不同小精灵信息使用换行符隔开
    getPokemon <pokemonID>
    根据小精灵id获取小精灵的详细信息返回信息格式为<id> <name> <raceName> <atk> <def> <maxHp> <speed> <lv> <exp>
    pokemonChangeName <pokemonID> <newName>
    返回Accept.\n表示改名成功


    4.1 Hub类的设计与实现Hub类被设计为单件,其所有构造函数的访问属性均为private,且除了默认构造函数外的其他构造函数与赋值函数均被delete。只能通过public静态函数getInstance来获得单件的引用。
    Hub管理着一个Endpoint的列表。此列表使用vector实现频繁的插入与删除。
    因为endpoints会被多线程访问,所以使用互斥量std::mutex保护多线程下的endpoints。
    初始情况下Hub只有两个线程,一个是listenFunc线程,用来处理登录和注册的请求。另一个是ternimateFunc线程,用来实现Hub运行时按下任意键停止Hub的效果。
    用户发出登录请求时,首先会判断此用户在数据库是否存在。如果存在则检查当前是否已经有对应此用户的Endpoint。如果有,而且此Endpoint正在运行,则因为用户多次登录而拒绝请求。如果Endpoint处于用户意外断线的等待状态,则重新激活此Endpoint并和用户建立连接。如果不存在对应的Endpoint,则new一个Endpoint,并detach出去一个mornitor线程。mornitor线程中会调用Endpoint::process函数以启动Endpoint。因为Endpoint::process是阻塞函数,所以当此函数返回时,mornitor线程会从endpoints中delete掉此Endpoint。所以每个Endpoint都会有一个对应的mornitor线程在运行。拓扑图如下:

    调用Hub::start函数以启动服务器(阻塞方式)。此函数会连接数据库(或新建数据库),初始化Socket,并启动上述两个Hub中的基础线程。任何一个初始化项目失败,或者两个基础线程终止,则start函数会返回。
    4.2 Endpoint类的设计与实现Endpoint类负责实现登陆后的其他用户请求。这些请求无非就是简单数据库操作,此处不再赘述。下文将重点描述如何实现Endpoint检测用户意外离线后的等待机制。
    Endpoint::process函数如下:
    void Endpoint::process(){ while (running) { online = false; timing = true; thread timerThread(&Endpoint::timer, this); thread listenThread(&Endpoint::listenFunc, this); timerThread.join(); listenThread.join(); }}
    Endpoint类设置了两个标志变量online和timing负责记录“是否在线”和“是否在计时”两个值。然后启动了timer线程和listen线程。也就是说用户发送登录请求,Hub回复Endpoint的端口之后,Hub::mornitor线程调用Endpoint::process的时候,计时就已经开始了。玩家需要在指定时间之内连接到Endpoint,否则也会因为长时间未连接而导致Endpoint被销毁。
    当用户连接到Endpoint,Endpoint::listenFunc中的accept函数被触发后,Endpoint将会把online置为true,然后尝试停止计时。此处使用了std::condition_variable条件变量来实现。在timer线程中,函数被condition_variable::wait_for函数阻塞,相当于是一个非忙等待的条件sleep函数。listenFunc会调用condition_variable::notify_one函数来通知timer中的wait_for函数,以此实现timer停止等待的效果。timer停止等待后判断online标志,如果online为true表示online已经被listenFunc处理了,则把timing设置为false。否则即为等待超时,关闭Socket以停止listenFunc,并把running设置为false以停止process函数的循环。process函数执行完毕后就会被Hub::mornitor函数销毁。
    客户端连接Endpoint后timer线程执行完毕。客户端意外断开时listen线程也会执行完毕,但是running此时仍为true,此时就会执行process函数中的循环,重新启动timer和listen线程监听客户端时间与计时,以此实现离线等待机制。
    4.3 Pokemon相关的改动服务器的Pokemon函数增加了构造函数,给出所有属性值以构造一个精灵,用来把从数据库读出的精灵数据构造为精灵。
    Pokemon类内定义了静态public成员变量races,为PokemonBase的指针。用来以静态的方式初始化四个种族。代码如下:
    const PokemonBase *Pokemon::races[4] = {new Race<0>(), new Race<1>(), new Race<2>(), new Race<3>()};
    由于第二版不涉及战斗,所以其他Pokemon相关函数没有进行修改。
    4.4 主程序主程序只要启动Hub即可。代码如下:
    int main(){ srand(time(NULL)); Hub &hub = Hub::getInstance(); hub.start(); system("pause");}
    5、客户端设计与实现5.1 Mainwindow类的设计与实现本次项目并没有很多地使用ui文件,几乎一切Qt控件都是用代码构造出来初始化与管理的。
    MainWindow使用了有限状态自动机来管理当前所处状态(页面)。一共有如下若干状态:

    初始状态START

    显示“开始游戏”按钮和“退出游戏”按钮。
    登录状态LOGIN

    显示登录时需要的输入框、返回按钮、注册按钮和登录按钮。
    主状态MAIN

    显示所有功能,即查看自己的精灵、查看所有用户和他们的精灵、修改密码、退出登录。
    精灵表POKEMON_TABLE

    一个表格,显示精灵的简要属性。表格中有显示精灵属性详情的按钮
    玩家表PLAYER_TABLE

    一个表格,显示玩家的属性。表格中有查看指定玩家精灵的按钮

    界面的转换通过changeState函数实现。此函数首先将所有控件重置并隐藏,然后根据当前状态显示指定的控件,并使用QGridLayout进行布局
    网络通信使用QTcpSocket异步通信实现,使用connect(client, &QTcpSocket::readyRead, this, &MainWindow::getServerMsg);连接readyRead函数与getServerMsg函数,所有信息通过getServerMsg函数进行处理。
    getServerMsg函数也会根据当前状态对来自服务器的信息进行不同的解析,然后对显示的内容进行一定程度的修改。
    MainWindow还使用了QMediaPlayer实现了背景音乐的播放。
    5.2 LogonDlg类的设计与实现LogonDlg是玩家点击注册按钮时弹出的窗体。此窗体使用模式化显示,此窗体关闭前无法对MainWindow进行操作。
    玩家点击注册按钮时,注册按钮会被disable以防网络速度慢时玩家多次点击注册按钮造成其他不可预测结果。但是取消按钮没有disable,玩家依然可以点击取消按钮终止注册。
    玩家注册成功时,窗体会自动消失,并把刚才注册成功的账号与密码自动填充到MainWindow的输入框中。
    5.3 PokemonDlg类的设计与实现PokemonDlg是玩家点击精灵表中的精灵详情按钮时弹出的窗体,显示精灵详情。如图:

    为了方便玩家进行精灵之间属性的对比,玩家可以同时打开不限量个PokemonDlg。玩家每次点击MainWindow中的查看详情按钮都会new一个PokemonDlg出来。对此,为了防止内存泄露,在PokemonDlg的构造函数中添加了setAttribute(Qt::WA_DeleteOnClose);使用户在关闭窗体时就会delete掉窗体。
    玩家可以在MainWindow的精灵表中对自己的精灵进行重命名,也可以在PokemonDlg中进行重命名。双击对应的表项,PokemonDlg会发送一个信号来改变MainWindow中的表项,从而实现和MainWindow的精灵表同步更改精灵名称的效果。
    6、测试服务器初始化

    服务器接收用户登录

    用户正常退出

    用户非正常退出

    用户超时,Endpoint销毁

    按下任意键停止服务器

    客户端初始界面

    登录界面

    注册界面

    客户端主界面

    重置密码界面

    精灵列表界面

    玩家列表界面
    2 评论 137 下载 2019-03-17 15:27:35 下载需要12点积分
  • 基于Jsp和Mysql的教务管理系统

    1.引言1.1 编写目的这个教务管理系统模块是为了实现学校人力资源的优化和学生信息管理的科学管理而设计的,通过试用本系统,可以更加有效的管理学生信息和教师信息,具有信息的增加,查询,修改等功能。
    系统开发的整体任务是实现学校教师和学生信息管理的系统化、规范化、自动化和智能化,从而达到提高学校管理效率的目的。
    1.2 项目目标在当今世界电脑普及的时刻,人们已经习惯用电脑办公,结果自然会产生大量的电子文件,这些文件有宝贵的历史价值,但如今我们将更多时间花费在寻找这些文件,即费时又费力。这次项目则跟此需求开发的。让学校各部门能够有效的掌握,有效的共享文件资源,保护好文件,及促进教务管理的信息化、规范化和集成化,实现计算机的管理,以提高工作效率和经济效益。
    2.总体要求2.1 运行环境
    操作系统:win10专业版
    开发环境支持平台:idea2017
    程序配置环境最低版本要求:jdk1.8, tomcat8.0
    项目基础库最低版本要求:MySQL5.5。
    开发语言:java语言、html前端、jsp语法

    3.功能需求3.1 功能规划通过管理员对各模块的功能需求进行分析,可以将项目大致分为为学生信息管理模块、教师信息管理模块。
    3.2 基本设计概念和处理流程该文档目的在于明确系统的数据结构和软件结构,设计外部软件和内部软件的接口,说明各个软件模块的功能说明,数据结构的细节等。
    系统的总体处理流程如图所示:

    3.3 系统模块设计3.3.1 登录模块类图
    3.3.2 学生信息管理模块类图添加学生信息

    查询学生信息

    3.3.3 教师信息管理模块类图添加教师信息

    查询教师信息

    添加课程信息

    查询课程信息

    3.3.4 学生信息管理流程图添加信息

    查询信息

    3.3.5 数据库表关系图(ER图)
    3.4 数据库设计Managerinfo 管理员信息表



    列名
    数据类型
    是否为空
    说明




    manager_ID
    CHAR(10)
    NOT NULL
    管理员登录账号


    password
    CHAR(10)
    NOT NULL
    管理员登录密码


    manager_Name
    CHAR(10)
    NULL
    管理员真实姓名



    Studentinfo 学生信息表



    列名
    数据类型
    是否为空
    说明




    student_ID
    INT(10)
    NOT NULL
    学生学号(主键)


    student_Name
    CHAR(10)
    NOT NULL
    学生姓名


    student_Gender
    CHAR(2)
    NULL
    学生性别


    born_Date
    DATETIME(8)
    NULL
    出生日期


    class_No
    INT(4)
    NULL
    班级号


    tele_Number
    CHAR(10)
    NULL
    联系电话


    Peoplenumber
    VARCHAR(50)
    NULL
    身份证号码


    comment
    VARCHAR(200)
    NULL
    备注



    Exam-history 学生历史成绩信息表



    列名
    数据类型
    是否为空
    说明




    exam_ID
    INT(10)
    NOT NULL
    考试编号


    student_ID
    INT(10)
    NOT NULL
    学生学号


    course_Name
    CHAR(10)
    NULL
    科目名称


    exam-Date
    DATETIME(8)
    NULL
    考试日期


    result
    FLOAT(8)
    NULL
    考试成绩


    teacher_ID
    INT(10)
    NOT NULL
    监考老师



    TeacherInfo 教师信息表



    列名
    数据类型
    是否为空
    说明




    teacher_ID
    INT(10)
    NOT NULL
    教师号(主键)


    teacher_Name
    CHAR(10)
    NOT NULL
    教师姓名


    teacher_Gender
    CHAR(2)
    NULL
    教师性别


    born_Date
    DATETIME(8)
    NULL
    出生日期


    tele_Number
    CHAR(10)
    NULL
    联系电话


    subject
    VARCHAR(10)
    NULL
    教授科目


    introduction
    VARCHAR(200)
    NULL
    个人简介



    couseInfo 课程信息基本表



    列名
    数据类型
    是否为空
    说明




    course_ID
    INT(4)
    NOT NULL
    课程号(主键)


    courde_Name
    CHAR(10)
    NOT NULL
    课程名称


    teacher_ID
    INT(10)
    NOT NULL
    授课老师编码


    teacher
    CHAR(10)
    NULL
    授课老师姓名


    subject
    VARCHAR(10)
    NULL
    所属科目



    采用了Spring+SpringMVC+MyBatis框架,这里配置一个写入数据库和一个读取数据库并进行对spring框架的配置。


    4.功能实现及实现代码4.1 登录模块jsp代码



    此处设计了一个登录拦截器,若管理员未进行登录将不能正常使用。


    4.2 学生信息管理模块4.2.1 添加学生信息


    4.2.2 修改学生信息


    4.2.3 查询学生信息


    4.2.4 删除学生信息

    4.3 教师信息管理模块4.3.1 查询教师信息


    4.3.2 添加教师信息


    4.3.3 删除教师信息

    4.3.4 修改教师信息

    4.4 课程信息管理模块4.4.1 添加课程信息利用Ajax请求验证课程是否已存在。



    4.4.2 查询课程信息


    4.4.3 删除课程信息

    4.4.3 修改课程信息


    5.总结在这个学期的学习过程中,我在做这个项目当中的收获颇为丰富。因为在此之前只是直接接触的基于jsp的mvc模式架构的开发,然后设计过程之中,表之间的联系,数据的架构的过程比较较少,缺乏知识的完备性和完善性并没有使用过任何的框架。而恰好借助这段时间的学习,我开始接触和了解具体怎么在一个框架去实现项目的功能。这次的项目是基于ssm(spring+springmvc+mabatis)框架去实现的,主要是在B站看了黑马程序员的视频,学习如何开发一个完整的web工程,怎么去用一个框架。这个项目是采用boostap框架技术去设计管理页面前端,然而后端的话,因为是第一次去采用框架,多少有点不习惯,其次是自己对Java的一些基础操作如遍历信息表的操作不是很熟悉,在开发过程,经常是写一部分就会出现一个新的bug,又得停下来去修复它。
    在这个学习的中间,我觉得其中里面比较重点的知识点有:分页代码查询,多条件查询,多表查询,日期信息转化字符串,认识到了框架的好处,主要为三大方面:第一的就是Spring的优势,通过Spring的IOC特性,将对象之间的依赖关系交给了Spring控制,方便解耦,简化了开发;通过Spring的AOP特性,对重复模块进行集中,实现事务,日志,权限的控制提供了对其他优秀开源框架的集成支持。第二是mvc模式使我们开发更简洁与Spring无缝衔接灵活的数据验证,格式化,数据绑定机制。最后就是Mybatis的优势,数据库的操作(sql)采用xml文件配置,解除了sql和代码的耦合,提供映射标签,支持对象和和数据库orm字段关系的映射,支持对象关系映射标签,支持对象关系的组建,提供了xml标签,支持动态的sql。
    4 评论 12 下载 2020-07-13 13:17:40 下载需要14点积分
  • Qt实现的宠物小精灵对战游戏阶段一-宠物小精灵的加入

    1、题目要求
    设计宠物小精灵的类,为简化游戏设计,精灵的属性包括种类(力量型:高攻击; 肉盾型:高生命值; 防御型:高防御; 敏捷型:低攻击间隔,共四种)、名字、等级、经验值、攻击力、防御力、生命值、攻击间隔等(以上属性必须,其他属性可自行添加)(基本要求:本游戏中只有上面的4种类型。 进一步要求:上述4种类型可以进一步深入划分,比如力量型又可以在细分为:沙瓦朗、火爆猴、腕力等)
    每个精灵初始等级为1,满级15级,每当精灵升级的时候,宠物对应的属性值会有少量增加(主属性增加量相对较多)
    每个精灵有自己独特的攻击方式,如“闪电攻击”,“火焰攻击”等等,请设计一个精灵的基类,并将精灵的攻击方法设为虚方法以方便子类重写
    请写一个测试程序对设计的精灵类的相关属性和方法(包括攻击函数,升级函数等)进行测试
    题目考察点:类的继承,对象数据成员设计,成员函数设计

    2、小精灵宏观设计
    设计小精灵包括以下属性

    种族名字攻击力防御力速度(反映攻击间隔)等级经验值
    小精灵的种族包括以下属性

    种族名种族类型(高攻击、高防御、高血量、高速度四种)种族基础攻击种族基础防御种族基础血量种族基础速度种族经验曲线种族技能(四个)、每个技能的描述和技能释放次数(PP点)

    关于小精灵的技能,设置如下规则:

    每个种族的小精灵有四个技能,包括一个普通攻击和三个特殊技能
    普通攻击不消耗技能释放次数,即普通攻击可以无限次释放,防止持久战双方没有技能可以释放
    小精灵在1级的时候只拥有普通攻击,在5级习得第二个技能,10级习得第三个技能,15级(满级)习得第四个技能
    能够对对方造成伤害的技能拥有一定的被闪避几率,此几率和双方小精灵的速度有关

    关于小精灵属性的提升:每个小精灵在初始化的时候会首先被赋予其种族的基础属性(即种族基础攻击等等),在每次等级提升的时候属性的增加具有一定的随机性,这就要求后期使用数据库存储小精灵数据的时候需要把小精灵的所有属性都保存在sqlite3数据库中。
    3、类的设计与实现3.1 预备信息
    在说明以下内容之前需要知道的信息

    定义了dbout作为信息输出,定义了dbin作为信息输入。目前dbout为cout,dbin为cin。
    种族类型(也可以称为精灵类型)为枚举量PokemonType,定义了高攻击、高防御、高血量、高速度这四种种族类型。
    pokemon.h/pokemon.cpp
    根据题目要求,设置枚举类型“精灵类型(PokemonType)”,提供四个枚举值ATK/HP/DEF/SPE来表示此类型的精灵的那个属性比较强
    在设计的时候使用“速度”代替了“攻击间隔”这一个量
    设计基类PokemonBase,用来派生出不同种族的精灵。基类拥有种族名、精灵类型、类型基础攻击、类型基础防御、类型基础血量、类型基础速度、类型经验曲线、种族技能名称、种族技能描述和种族技能PP值。这些属性的访问权限全部设计为protected以便被派生类访问和被基类指针访问
    PokemonBase的构造函数需要传入一个参数type,即精灵类型。PokemonBase会根据精灵类型生成类型基础属性,即同类型的精灵的初始属性是相同的
    PokemonBase提供了纯虚函数attack使精灵可以发动攻击。dodge函数用来判断闪避
    模板类Race为PokemonBase的基类,意为不同的精灵种族。如Race<0>是小火龙,Race<1>是妙蛙种子。此模板类只需要定义两个函数,一个是构造函数,另一个是来自基类的攻击函数attack
    Race类的构造函数会指定此种族的精灵属于哪些类型,比如小火龙种族属于高攻击型,则使用枚举量ATK作为基类PokemonBase的参数。构造函数还会把PokemonBase中没有初始化的属性全部初始化,包括种族名、经验曲线、技能名称、技能描述、技能PP值。
    Race类的attack函数则为此种族的每个技能提供了计算公式。
    Pokemon类是具体的小精灵类,它包括种族、小精灵名、当前攻击力、当前防御力、当前血量上限、当前速度、当前等级和当前经验值这些属性。因为在战斗中有些属性会临时发生变化,所以还有战斗中血量、战斗中攻击、战斗中防御、战斗中速度和战斗中PP点这五个属性。战斗时的临时属性拥有getter和setter函数,但是非战斗时属性只有getter函数,其值只能通过构造函数或升级函数更改。
    Pokemon的构造函数需要一个种族的const引用作为参数,表示这个精灵属于此种族。因为精灵不可能更改种族的属性,所以种族在内部保存为一个const引用。精灵还可以被重命名,如果没有重命名,则默认使用种族名。精灵在生成时会获得一些基础属性,如基础攻击、基础防御等。这些属性还会被附加一些随机因素,使同一种族生成的精灵有不同的属性
    关于攻击函数attack,小精灵Pokemon类中的attack用来实现自动战斗和手动战斗的控制相关操作,确定发动哪个技能后调用种族Race的attack函数。模板类Race中的攻击函数定义了此种族的精灵的攻击计算方式与攻击效果。
    小精灵的技能会随着等级的增长而获得,初始只有普通攻击kick,5级时获得第二个技能,10级获得第三个技能,15级获得第四个技能。
    battlecontroller.h/battlecontroller.cpp
    当需要实现两只小精灵的战斗时需要构造战斗控制器BattleController。其构造函数的参数为两个小精灵的引用和一个自动战斗标识。构造结束后调用start函数即可开启战斗
    战斗时会有两个计时器timer。计时器会从0开始上升,当精灵A的计时器不小于精灵A的速度时,精灵B发动攻击,以此实现速度高的精灵攻击快的效果。
    如果两只小精灵的timer同时达到标准,则速度高的小精灵先发动攻击
    当存在一只小精灵的血量为0时另一只小精灵获得战斗胜利
    3.2 种族基类PokemonBase设计类PokemonBase作为所有精灵种族的基类。
    此类包含了上文中精灵种族应该包含的所有属性,但是在初始化的时候不会给全部这些属性都赋值(如种族名、种族技能这些都需要具体构造种族的时候才能够确定),所以PokemonBase把所有属性的访问属性设置成了protected以便子类(即各个种族类)访问与修改。
    此类还声明了种族各属性的getter函数,以便基类指针能够访问子类(种族类)中初始化的属性。
    此类的构造函数仅需要提供一个参数:种族类型。在此类的构造函数中会先根据种族类型对种族基础攻击、种族基础防御等属性进行初始化。此处的初始化没有添加随机性,所以种族类型相同的精灵在1级的时候拥有完全相同的属性。
    此类提供了攻击函数attack。由于两个小精灵的攻击并不会对种族属性造成影响,只会对小精灵的个体战时属性造成影响,所以此函数是一个const函数,且需要提供两个小精灵的非const引用作为参数以便修改两个小精灵的属性。此函数设计为纯虚函数以便子类实现和被外界通过基类指针访问。
    3.3 种族模板类template Race模板类Race使用精灵种族编号作为模板参数。如0号种族为Race<0>,1号种族为Race<1>。此模板类表示了不同的精灵种族,如妙蛙种子、小火龙等。
    此类的构造函数首先根据种族类型的不同而调用PokemonBase的构造函数,使种族的数值属性(种族基础攻击力、种族基础防御力等)根据种族类型而确定下来,然后对以下没有在PokemonBase的构造函数中初始化的数据进行初始化:

    种族名
    种族经验曲线
    种族技能名(4个)
    种族技能描述(4个)
    技能释放次数

    此类实现了PokemonBase中声明的纯虚函数attack。在此函数中,首先根据传入的参数skillIndex判断攻击方小精灵使用了哪个技能,每个技能有不同的伤害计算公式或效果,如果技能命中且对方血量为0则返回true表示战斗结束。
    3.4 小精灵类Pokemon此类除了包含每个小精灵的个体属性,还要包含小精灵的战时个体属性,因为在战斗中小精灵的某些属性会得到临时性的更改。这些战时个体属性包括:

    血量
    攻击力
    防御力
    速度
    每个技能的剩余技能释放次数

    此类提供了所有属性(包括战时个体属性和普通个体属性)的getter函数,但是仅提供了战时个体属性的setter函数,因为普通个体属性仅能够通过经验获取函数gainExp在判定为升级的情况下被修改。
    关于战斗,此类提供了如下函数:

    restoreAll

    使战时个体属性恢复为普通个体属性,用于战斗前两只精灵的恢复(初始化)
    attack

    指定另一只Pokemon作为目标进行攻击此函数会根据等级和剩余技能释放次数对玩家选择的技能进行判定,如果判定玩家选择了某个剩余技能释放次数不足的技能或某个当前等级无法释放的技能,则会释放普通攻击在选择自动战斗时,此函数会随机选择一个符合等级条件且剩余技能释放次数非0的技能进行释放。选择手动战斗时,将使用dbin从控制台进行输入此函数仅作为战斗的控制函数,实际的战斗会调用种族的战斗函数进行各属性的计算
    takeDamage

    减少当前Pokemon的生命值如果当前Pokemon的生命值为0则返回false表示此精灵战败当参数(精灵应承受的伤害)小于某阈值时,设置伤害为此阈值。防止因对方精灵防御过高而造成的战斗流程缓慢
    gainExp

    给当前精灵增加经验如果精灵升级,返回true如果精灵已经满级(15级)则增加经验无效内部使用一个循环来实现一次性增加大量经验造成的连续升级的效果精灵升级后会在一定浮动范围内增加自己的属性,也会因为自己的种族类型而在某个属性上有更多的增益

    每个小精灵可以拥有自己的名字。如果在构造时没有提供小精灵的名字,则小精灵的名字被初始化为种族的名字。
    3.5 战斗控制器类BattleController构造函数包括两个小精灵的非const引用和一个自动战斗标志位。
    调用函数start后,战斗开始。战斗控制器中的计数器timer将会增加,当达到某个小精灵的速度值时,另一只小精灵应该发起攻击。调用Pokemon的attack函数实现攻击。
    如果判定双方应该同时攻击,则速度快的一方优先进行攻击。
    当战斗的一方血量为0时战斗结束,start函数结束。
    3.6 主程序main主程序首先使用时间函数初始化随机数种子以便后期产生随机数,然后初始化四个种族以便后面初始化小精灵时使用。
    初始化小精灵,调用gainExp以测试升级函数的效果。构造BattleController来实现战斗,调用BattleController::start启动战斗即可。
    3.7 其他细节目前仅设计了小火龙(高攻击)、妙蛙种子(高血量)、杰尼龟(高防御)、波波(高速度)四个种族。
    4、具体实现4.1 种族初始化与精灵生成在tester.cpp中如下代码初始化了四个种族
    Race<0> race1;Race<1> race2;Race<2> race3;Race<3> race4;
    四个种族分别为小火龙(高攻击)、妙蛙种子(高血量)、杰尼龟(高防御)和波波(高速度)
    初始化所有种族之后即可使用Pokemon类的构造函数来生成一只精灵。构造函数的第一个参数是精灵的种族,第二个参数为精灵的名字。如果没有给出精灵的名字,则默认使用种族名。示例:
    Pokemon pokemon1(race1, "pokemon1");Pokemon pokemon2(race2);
    生成精灵后会看到如下输出:
    Init pokemon1 from CharmanderType: High AttackAtk: 13Def: 7MaxHp: 30Speed: 11LV: 1Exp: 0Skills: Name: kick Description: simple attack PP: infinity Name: spark Description: ignore opponent's half defence PP: 10 Name: rage Description: increase attack PP: 3 Name: fireball Description: cause huge damage PP: 54.2 升级此版本仅提供增加宠物经验值的函数(即升级函数),并未给出经验值结算方案。计划将在以后版本设计。
    函数Pokemon::gainExp(int count)可以给精灵增加经验值。经验值达到一定值(升级经验曲线)后即可升级。调用一次此函数可以造成多次升级。参数count应为正整数,不符合条件的count会被默认替换为1
    示例:使用代码pokemon1.gainExp(10),可以看到如下输出
    pokemon1 gains 10 exp!Now pokemon1 has 10 expLevel Up!pokemon1's now LV2!Atk: 10->18!Def: 3->5!MaxHP: 24->34!Speed: 8->13!4.3 战斗如果要进行精灵之间的战斗,则需要构造一个战斗控制器BattleController,其构造函数为BattleController(Pokemon &pokemon1, Pokemon &pokemon2, bool autoFight = true);,即需要传递两个已经存在的精灵(可以是同一只)。第三个参数为自动战斗标识,默认自动战斗,设置为false的时候也可以手动战斗
    构造BattleController之后,使用BattleController::start()即可开启战斗
    示例代码:
    // BattleController battle(pokemon1, pokemon2);//auto fight BattleController battle(pokemon1, pokemon3, false); //manual fight battle.start();
    自动战斗模式下,系统会随机在精灵能够使用的技能中挑选一个释放。自动战斗产生的输出如下:
    pokemon1 VS pokemon2!Battle Start!pokemon1 uses kick!pokemon2 takes 13 damage!pokemon2's HP becomes 24pokemon2 uses kick!pokemon1 takes 10 damage!pokemon1's HP becomes 28pokemon1 uses kick!pokemon2 takes 12 damage!pokemon2's HP becomes 12pokemon1 uses kick!pokemon2 takes 10 damage!pokemon2's HP becomes 2pokemon2 uses kick!pokemon1 takes 10 damage!pokemon1's HP becomes 18pokemon1 uses kick!pokemon2 takes 12 damage!pokemon2 is down!pokemon1 won!手动战斗模式下,玩家可以选择每一步释放哪个技能。关于技能的获取将在下文中提到。手动战斗可以获得如下输出:
    pokemon1 VS pokemon2!Battle Start!pokemon1, your turn!Choose a skill to attack! 1: kick simple attack 2: spark(10/10) ignore opponent's half defence 3: rage( 3/ 3) increase attack 4: fireball( 5/ 5) cause huge damagePlease input a number: 3pokemon1 uses rage!pokemon1's Attack +13pokemon1's Attack becomes 121pokemon2, your turn!Choose a skill to attack! 1: kick simple attack 2: photosynthesis( 5/ 5) restore HP 3: life drain(10/10) cause damage and restore HP, ignore defence 4: razor leaf( 5/ 5) cause huge damagePlease input a number: 4pokemon2 uses razor leaf!pokemon1 takes 82 damage!pokemon1's HP becomes 48pokemon1, your turn!Choose a skill to attack! 1: kick simple attack 2: spark(10/10) ignore opponent's half defence 3: rage( 2/ 3) increase attack 4: fireball( 5/ 5) cause huge damagePlease input a number: 4pokemon1 uses fireball!pokemon2 takes 157 damage!pokemon2's HP becomes 67pokemon2, your turn!Choose a skill to attack! 1: kick simple attack 2: photosynthesis( 5/ 5) restore HP 3: life drain(10/10) cause damage and restore HP, ignore defence 4: razor leaf( 4/ 5) cause huge damagePlease input a number: 3pokemon2 uses life drain!pokemon2 restores 46HP!pokemon2's HP becomes 113pokemon1 takes 46 damage!pokemon1's HP becomes 2pokemon1, your turn!Choose a skill to attack! 1: kick simple attack 2: spark(10/10) ignore opponent's half defence 3: rage( 2/ 3) increase attack 4: fireball( 4/ 5) cause huge damagePlease input a number: 4pokemon1 uses fireball!pokemon2 takes 152 damage!pokemon2 is down!pokemon1 won!请按任意键继续. . .可以看到,精灵的技能有释放次数(PP值),每次释放都会减少此技能的PP值。精灵的第一个技能kick为普通攻击,可以无限次释放。技能后面跟着技能描述,玩家可以根据技能描述来选择释放技能。
    玩家需要输入一个数字来释放技能。如果出现错误输入则默认释放普通攻击。当一个精灵的血量HP为0时,另一个精灵获得胜利。
    5、游戏测试生成小精灵

    获取经验与升级

    战斗开始

    战斗结束
    5 评论 143 下载 2019-03-17 10:04:45 下载需要11点积分
  • 基于Qt实现的植物大战僵尸游戏

    1.总体介绍本次大作业,用面向对象的思想和方法,在实现了所有基本功能以外,还实现了许多其他的附加功能。
    2.UI 设计这次大作业用户界面所用 UI 的资源,均采用的是植物大战僵尸移动版原版的资源,较大程度地还原了原作,尽力提供真实的游戏体验。以下为游戏截图。
    开始界面:实现了要求的所有 ui 设计。

    游戏主界面:实现了要求的所有 ui 设计。

    3.植物与僵尸的设计3.1 植物的设计本次大作业实现了三种植物,向日葵(sunflower)、豌豆射手(pea)、坚果墙(wallnut),均继承自父类 plant 类。
    3.1.1 植物类(plant)plant 类是所有植物的父类,其成员变量为所有植物共同的属性,life(生命值),price(消耗阳光值),coolingtime(冷却时间),row、col(所在的行和列数),mediaPlayer_plant(种植时的声音),plantSwingMovie(植物不在攻击状态时的动画)等等。
    在构造函数里,初始化了 mediaPlayer_plant,保证每种一个植物时会有对应的音效播放。
    3.1.2 向日葵类(sunflower)除了继承自父类的成员变量外,自己的成员变量全部和生产阳光有关。另外还有一个 slot : slot_produceSunshine() ,这个slot 的功能是让每个向日葵每段时间(10 秒)自动产生一个阳光。
    在构造函数里,初始化了向日葵的动画、自己的时间器、和阳光。

    3.1.3 坚果类(wallNut)因为坚果只有挨吃这一项功能,所以除了继承自父类的成员变量外,并没有自己的成员变量。只是在构造函数里将冷却时间和价格初始化了。

    3.1.4 豌豆射手(pea)除了继承自父类的成员变量外,另外还有 attackNumber(攻击力),shootingTriggerTimer(控制射击的时间器),bulletList(子弹的list)。
    在构造函数里,初始化了自己的成员变量,并且将子弹射击的间隔设置成了 1.4 秒,结合 pea 类自己的 slot:slot_shootingbullet 就可以实现自动射击。

    3.2 僵尸的设计(zoobie)本次大作业实现了三种僵尸,普通僵尸(zoobie),铁桶僵尸(bucketZoobie),撑杆跳僵尸(poleVaultingZoobie),后两种僵尸均继承自普通僵尸。
    注:我在一开始命名时将僵尸的英文 zombie 打成了 zoobie,由于发觉过来时程序基本已经写完了,想改回来已有心无力,请谅解这个低级的拼写错误。
    3.2.1 普通僵尸(zoobie)zoobie 类有所有僵尸的共同属性,生命值(life)、移动速度(movingSpeed)、攻击力(damagenumber)、所在行(row)、是否正在吃植物(isEatingPlants)、自己的计时器( zoobietimer )、 走 路 和 吃东西 时 的 两 个 动 作(zoobieMoveMovie、zoobieEatingMovie)。还定义了两个slot , slot_zoobiePositionChange( 僵 尸 位 置 改 变 ) 、slot_zoobieActionChange(僵尸动作改变)。在构造函数里,将吃东西的声音、僵尸的动作初始化。

    3.2.2 铁桶僵尸(bucketZoobie)继承自 zoobie 类,由于铁桶僵尸和普通僵尸除了血厚一点没有其他优势,所以它除了继承自父类的成员变量外,没有自己的成员变量。在构造函数里,将成员变量初始化。

    3.2.3 撑杆跳僵尸(poleVaultingZoobie)继承自 zoobie 类。因为有撑杆跳这个功能,所以这个类除了继承自父类的成员变量外,还有为撑杆跳专门设置的成员变量,isToVault(是否将要跳)、hasVaulted(是否已经跳过了)等等,重写了2 个 slot : slot_zoobieActionChange 和slot_zoobiePositionChange. 以下表格体现了一个撑杆跳僵尸从开始出现到越过一个植物后吃东西的完整的实现逻辑。




    各个状态
    hasVaulted
    isToVault
    isEatingPlants




    走路(没遇到植物)
    false
    false
    false


    第一次遇到植物 后,(还没跳)
    false
    True
    false


    第一次遇到植物 后,已经跳了
    true
    false
    false


    第一次遇到植物 后,正常走路
    true
    false
    false


    第一次遇到植物 后,吃东西
    true
    false
    true



    每个僵尸均有自己的 timer,每隔 20ms 检查一遍僵尸的状态参数是否变化,发生变化后就执行 slot 里不同的 case。实现了程序接口和实现的分离。
    4.游戏逻辑4.1 摆放的植物自动根据特性攻击僵尸gamewindow 里实现了修改植物和僵尸状态的 slot:slot_change_P_and_Z_state(),一旦僵尸出现在游戏画面中,这个 slot 会遍历所有植物并检查是否符合条件,一个符合条件则修改植物和僵尸各自的 flag 标记。植物和僵尸自己的 slot 一旦检测到 flag 变化,则会触发相应的动作。简单运用了老师在课上讲的观察者模式,实现了接口和实现的分离。
    4.2 僵尸在屏幕上出现,前进并攻击植物gamewindow 这个类里有三个 slot 来实现每隔一段时间自动刷新僵尸,分别是slot_produceZoobie, slot_produceBucketZoobie, slot_producePoleVaultingZobie,并且随着游戏进程的推进,产生僵尸的概率将会越来越高。增加游戏的难度。
    前进并攻击植物的实现也是通过 3.1 里所描述的方法 , 在slot_change_P_and_Z_state()里改变 flag,僵尸自己一旦检测到 flag 有变化机会触发相应的动作。由此实现了接口与实现的分离。
    4.3 游戏结束4.3.1 游戏胜利gamewindow 下的 slot:slot_checkGameWin 负责游戏胜利的判断。游戏胜利需要满足以下两个条件:

    每个僵尸出现的轮数 >= 上限
    存储僵尸的 list 判定为空

    满足之后这两个条件后触发函数 func_gameWin,播放胜利动画和音效,暂停所有计时器。
    4.3.2 游戏失败gamewindow 下的 slot:slot_checkGameLose 负责游戏失败的判断。这个 slot 对每一种僵尸 list 里的每一个僵尸进行判断,如果它的 x 坐标小于一定的值,则触发函数 func_gameLose,播放失败动画和音效,暂停所有计时器。
    4.4 删除死亡的僵尸和植物gamewindow 下的 slot_deleteDeadZoobie 和 slot_deleteDeadPlant 负责删除死亡的僵尸和植物。对每一个僵尸和植物进行遍历,如果生命值(life)<= 0, 则在相应的 list 中删除它。
    5.用户交互5.1 进入游戏界面在主窗体上点击”开始冒险游戏”按钮,进入游戏界面。
    5.2 利用鼠标事件收集向日葵产生的阳光这个功能通过重写阳光类(sunShine)下的 mousePressEvent 来实现,只要点击了阳光之后就能触发这个阳光收集的效果,并且增加阳光总量。
    5.3 利用鼠标响应事件摆放,铲除植物。这个功能通过重写 gameWindow 下的 mousePressEvent 来实现,满足以下条件才会种植植物:

    点中有效区域
    那个地方还没种植植物
    鼠标处于能够种植物的状态

    点击鼠标后则可以种植植物。
    6.附加项6.1 游戏音效本次大作业使用了游戏的原版音乐,大量使用音效:主界面的背景音乐、配合着从地而出的僵尸的手的邪恶叫声、游戏界面的背景音乐、警报声、子弹打中普通僵尸的声音、子弹打中铁桶僵尸的声音、种植植物的声音、铲除植物的声音、游戏胜利的音效、游戏结束的音效等等。
    6.2 小推车大作业也实现了原版里的小推车。当一个僵尸碰到小推车后,小推车会启动并推倒这一路上所有的僵尸,这一过程也伴随着音效。
    6.3 特殊的动画效果大作业也实现了许多特殊的动画效果,具体而言有三个:

    子弹碰到僵尸后并不会直接消失,而是会产生爆炸效果后再消失
    点击阳光后阳光会自动移动到阳光栏处,并伴随着形状从大到小的变化
    植物冷却时间倒计时的显示,植物在冷却时,植物卡片上会显示当前剩余的冷却时间,方便查看
    2 评论 16 下载 2020-06-17 11:48:19 下载需要11点积分
  • 基于JSP的房屋出租管理系统设计与实现

    摘 要本文研究并实现了房屋出租管理系统。主要用运了servlet技术、java 技术、jsp网页编程技术、jQuery EasyUI界面美化插件、MySQL数据库技术、Redis数据缓存等技术实现了一个便利、安全、可靠的房屋出租管理平台。在该系统平台上招租者和求租者可以进行信息交流;招租者可以发布房源信息,求租者可以查看房源信息并联系招租者进行房屋租赁。该系统作为人们生活中住房问题的信息承载体,解决了招租者招租难的问题,求租者求租困难的问题,极大的方便了人们的生活。
    关键词: 管理系统;房屋出租;B/S结构;jQuery EasyUI;java
    AbstractThis paper studies and implements the housing rental management system. It mainly uses servelet technology, Java technology, JSP Web programming technology, MySQL database technology, Redis data cache and other technologies to achieve a convenient, safe and reliable rental management platform for housing. The leaseholder and the tenant can exchange information on the system platform; the tenant can publish the information of the house information, and the tenant can check the information of the house sources and contact the tenant for the rental of the house. As the information carrier of the housing problem in people’s life, the system has solved the problem of the renter’s difficult tenancy, and the problem of asking the tenants to seek the difficulty of the rent, which greatly facilitates the people’s life.
    Key words:leaseholder ; Rental housing ;B/S structure; jQuery EasyUI ;Java
    第一章 绪论1.1 论文背景随着科技的发展、GDP的增长、居民生活水平的提高,越来越多的人口到大城市去奋斗发展,力求改变自己贫穷与落后的现状;他们中有的人有文化,有的人只识字,也许有的人什么都不懂,因为他们想着通过自己的劳动力可以赚取一定的工资。然而进了大城市首先解决的就是自己的住所问题,有了住的地方才能安心的工作。找房子就成了一个很大的难题!到底该如何找?找房子该相信谁?成了他们的困扰。尽管市场上有很多的房屋中介公司,但房屋中介公司一般除了房租费还得收取一定的中介费,这就给一般的求租者带了难题。
    到目前为止,国内外租房网站不外乎两种,一种是基于B/S结构的web端租房网站,另一种则是基于手机端的租房APP。不同的方式有不同的优点,而我选择了基于B/S结构的web端租房网站系统。
    与发达国家相比,城镇居民人均住房面积与住房自有率并不低。然而,房地产市场发展的不全面和城市住房保障政策不完善以及数量不断增长的城市新移民群体——进城人口。这些都刺激着房屋租赁市场的发展。
    2014年中国外出就业农民工已达到16 821万人,进程人口为城市经济增长和劳动力市场发育做出了巨大的贡献,但在城市的居住条件却狭窄而简陋,住房问题已成为进城务工人员在城市就业、生活与举家迁移的最大障碍。“体面的住房不仅有利于改善农民工的健康生活状况,心理上得到安慰;也便利子女在自己家里学习,也能解放女性的时间,有助于他们参与劳动力市场,提高生活水平效率,更重要的是,住房状况影响自尊心和自卑感。同时,住房也是最重要的有形资产,如果进程务工人员拥有城市住房,将大大提高其财富水平”。在就业地获得宜居的住房,对提高务工人员及其家庭的幸福生活水平,实现包容性、可持续性的城市化,具有至关重要的意义。
    务工人员住房存在多种供给类型,虽然以非正式住房为主。用工单位是务工人员住房的重要供给主体。根据国家统计局统计,2014年仅有1%的外出农民工在务工地有自购房;即使按国务院发展研究中心与世界银行较高的估计,农民工在城市拥有自有住房的比例也仅为10%。
    农民工收入低,就业流动性大,积蓄有限,子女教育、医疗等方面支出更为紧迫,对城市商品房的购买力相对有限。另一方面,房屋招租者他们有房源却无租客,只能通过房屋中介公司去招纳求租者,房屋中介公司又收取了招租者的钱,这样一来,房屋招租者只能通过提高房价来弥补自己的那一部分损失,只能苦了求租者。房地产也是迅速发展的。房屋出租管理系统应运而生既解决了招租者的难题也为求租者提供了便利。
    介于这种求组难、招租难、房源管理难的问题,显然传统的处理方法与解决手段已经不能适应社会的发展和需要,信息的重要性和处理问题的窘迫性已经空前提高了,面对日益复杂、不断发展和变化着的社会大环境,尤其是是企业之间的日趋激烈的竞争形势,一个想要努力向前发展进步的人或者企业,必须具备足够的基础信息和强有力的信息整合能力与信息处理的手段。
    房屋出租管理不仅仅是一件很琐碎、重要的事,而且又是十分细致、保密的工作。发布房源统计,房屋出租统计,用户信息统计,房源的基本信息管理等都不允许有一点的差池。使用计算机信息技术来管理、记录房屋出租信息的工作,极大的提高了求、出租方的效率。而且使用计算机来管理求租、出租更加的适应现代企业制度和现代信息技术发展、人民生活水平等的要求,推动企业劳动型管理走向科学化、规范化,提高居民的生活水平。最主要的一点就是,使用计算机检索迅速、可靠性高、查找方便、存储量大、保密性极度的高、数据不易丢失且成本较低。这许多的好处都能够提高物业管理的效率,也是企业实行科学化,正规化,智能化管理的推动力。
    1.2 研究目的通过努力的研究,实现招租者和求租者的交易在网络上进行规范的交易。招租者发布房源后,求租者查看浏览房源信息。根据实际需求和自身需要求组房源。其次就是想要为社会工人阶级的人士多一点关心、多一点爱。毕竟他们为社会做出了很大的贡献。想通过此项目对大学4年以来的努力耕耘给一个交代,做一个证明。
    内容主要就是招租者发布自己的房源信息,求租者登录平台后,看到房源信息后可以根据联系方式联系房主求租,房主可以和求租者就行消息交流,让求租者更详细的了解房源的信息;求租者租房后可以根据自己的求租经验和经历以及房主的人品和招租态度对房主进行系统评价,评价会对房主以及房源产生一定的负面影响,通过此评价,后来用户可以酌情对房源进行筛选,达到一种前车之鉴的效果,对维护用户的利益有一定的作用。
    1.3 研究意义随着人们生活水平的提高和科技的发展进步,人们希望通过更简洁更便利的方式去处理问题,市场的需求。本论文以理论分析和可行性分析为出发点,结合国内房屋出租行业的发展情况以及求租者对房源的需求程度和广度,对国内住房租赁市场进行考究和需求分析。在这个研究的基础上,进行了完整详细的系统功能设计和数据库表字段结构设计,开发出了一套包括用户体验端和后台管理端两个端口九个模块的房屋出租管理系统。详细的建立了一个房屋招租、求租信息管理的系统。该系统作为人们生活中住房问题的信息承载体,通过该系统来管理房屋出租情况和求租用户信息,可以解决大量房源信息的查询和管理工作上存在的一些细节问题。既方便了招租者对房源的管理,也为求租者提供了有效的房源新消息。
    1.4 研究方法及思路1.4.1 研究方法
    研究方法采用面向对象的设计开发方法进行系统的分析与实施,把系统各个独立运行的模块分别开发,使得模块内与模块间高度向高内聚低耦合靠近
    各模块采用服务器集群部署,使得模块之间既可以协同运行,同时也能单独运行,降低整个系统的运行风险
    其次采用了前后端分离的技术思想。前后端分离即前端只实现整一个前端页面以及交互逻辑,以及利用ajax与nodejs服务器(中间层)交互;后端提供API接口,利用redis来管理session,与数据库交互,文件服务器fdfs来上传文件或者图片。Redis和fdfs安装在虚拟机VWware14 Centos Linux系统中。通过桥接的方式ping通本地系统和虚拟机Linux系统传输文件数据。最后将服务发布于linux系统中

    1.4.2 设计思路本文的开发主要是基于web端数据库来实现,设计首先分析用户身份认证方面的问题,结合自身对房屋出租行业的经历与认识和研究情况来写出需求分析设计;其次,结合自身的学术技能,选择自己擅长的开发语言和开发工具以及数据库进行此论文的开发;在设计中以需求分析文和系统设计原型图为基础,写出系统、全面的开发计划、实现流程及相关功能的实现方法;与此同时,在开发设计与实现中,选择适当要保存的相关设计文档,为完善以后的系统、修改个别功能模块、更新升级做准备材料。最后,系统开发完成后,进行系统调试和系统测试,做好系统调试和系统测试运行的测试用例的相关记录,为进一步提升系统性能做好准备。论文的主要设计思路如下:

    首先对国内的房屋租赁市场情况进行研究和分析,结合国内的成功及失败的案例,做出适合于国内现状,符合国内租房情况的房屋出租管理系统的构建思路
    熟悉java servelet框架技术的发展情况,选择简单易用的数据库进行后台设计
    对本论文构建的结构体系模型的原理和优势进行可行性分析
    学习模块化软件的结构设计的思想和方法,完成房屋出租管理系统的整体结构设计和功能模块设计

    1.5 论文结构
    第一章绪论,描述了房屋出租管理系统在当前的发展状况以及发展需求推动了房屋出租管理的开发,表达了研究的目的及意义
    第二章需求分析,主要从需求目标、可行性分析到系统技术需求分析分析系统需求,再通过系统划分和性能需求分析系统的需求状况
    第三章概要设计与详细设计,从系统总体模块划分到系统的功能层次,再详细叙述全文核心的算法思想详细阐述本系统,最后通过系统用例图和数据库表详细描述系统。


    第四章系统实现,从系统的环境的搭建、文件服务器的搭建到软件接口实际实现和系统截图来描述系统的实现情况
    第五章系统测试与调试,从不同角度、不同场景测试软件的情况,一方面测试软件的基础功能、性能,另一方面测试软件的易拓展功能的实现
    第六章结论与展望,总结了系统开发过程中的问题以及开发心得和经验,对未来软件维护升级改造进行简要描述

    1.6 本章小结本章主要详细的描述了软件的的设计背景、设计目的、研究意义、设计思路及方法。细致的描述了软件设计起因和实现方法。

    第二章 需求分析2.1 需求概述本系统目的主要是完成一个房屋招租者和房屋求租者可以共享需求的平台,招租者可以注册登录后发布自己的房源信息于该平台上。招租者发布房源信息需要通过文件服务器NGINX和Redis缓存服务器来存储数据。求租者可以查看浏览房源信息,并发布自己的求租信息于本系统上。用户可以对房主的房源信息和房主本人进行打分评价、用户可以收藏房源信息、查看其它用户的评价记录。用户也可以连接推送发放员信息给自己的qq、微信好友,达到共享的目的。
    在本系统中用户和房主可以通过“消息”功能模块进行互动交流,让用户和房主更方便的交谈房源信息详情。
    2.2 功能需求根据软件的基本需求,将房屋出租管理系统功能划分为个人中心管理、房源信息发布、用户收藏房源信息、查看浏览房源信息、用户评价房源及房主、消息交流讨论、房源信息分享、登录注册、后台管理等九个模块。各功能框架图如图2.1所示。

    2.2.1 登录注册注册时使用用户名、用户密码、确认用户密码、验证码进行注册。用户名是由6~18位的中文、大小写拼音字母,数字组成的字符串。用户密码是由大小写英文字母和数字0~9组成的8~18位的字符串。验证码是由大小写英文字母和数字0~9随机组成的4位字符串。注册完成后直接登录成功。登录注册用例如图2.2所示。


    2.2.2 发布房源信息用户登录成功后,点击“招租信息”,弹出发布房源信息页面,填写完整要发布的房源信息后上传房源图片,点击发布,发布成功会在数据库中记录一条发布成功的房源信息。其用例图如图2.3所示。

    2.2.3 查看浏览房源信息用户登录成功后,点击“招租信息”可以查看浏览房源的信息。非发布房源信息的用户只能查看房源信息不能修改删除房源信息。其用例图如图2.4所示。

    2.2.4 用户收藏房源信息用户登录成功后,点击“招租信息”模块,点击页面上的“收藏按钮”,房源信息会收藏到个人中心管理里面“我的收藏”中。收藏的房源信息,用户可以删除掉。其用例图如图2.5所示。

    2.2.5 用户查看招租信息用户登录成功进入系统后,可以点击“招租信息”按钮查看用户发布的招租信息。登录用户既可以查看自己发布的招租信息,也可以查看其它用户发布的招租信息。并且对招租信息可以进行增加、删除、修改的功能。其用例图如图2.6所示。

    2.2.6 用户查看求租信息用户登录成功进入系统后,可以点击“求租信息”按钮查看用户发布的招租信息。登录用户既可以查看自己发布的求租信息,也可以查看其它用户发布的求租信息。并且对求租信息可以进行增加、删除、修改的功能。其用例图如图2.7所示。

    2.2.7 个人中心管理用户登录平台后,可以对自己的用户信息、房源信息、房源记录,联系人记录进行增删改查的功能实现。其用例图如图2.8所示。

    2.2.8 后台管理后台管理主要是用户信息管理、房源信息管理、用户收藏房源管理、后台首页、管理员注销等5个功能。管理员可以查看用户信息、房主信息、房源信息,并且可以删除,增加,修改用户、房主、房源信息。其用例图如图2.9所示。

    2.3 开发环境在开发房屋出租管理系统时,需要具备以下环境:

    操作系统:win7、win8
    集成开发环境:MyEclipse14
    后台数据库服务:MySQL5.7
    服务器:Tomcat6.0,Tomcat7.0
    Redis缓存服务器:redis-4.0.8

    2.4 相关技术本系统采用的技术有:
    前台页面主要使用jsp语言编程技术,jsp是一种特别的java语言,它加入了一个特殊的引擎,这个引擎将HTTPServlet泽这个类的一些对象自动进行初始化,让用户去使用,让用户不再操心前面的工作。这个引擎可以看作是一个jsp到java Servlet的生成器或是翻译器。
    后台功能的实现使用java语言进行编程,java是一门面向对象的语言,它不仅吸收了C++语言的优点,还摒弃了C++里难以理解的多继承、指针等概念;java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,不仅实现了面向对象理论,还允许程序员以优雅的思维方式进行复杂的编程。
    使用EasyUI对代码进行美化和简洁,jQuery EasyUI是一组基于jQuery的UI插件,jQuery EasyUI的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面。开发者不需要编写复杂大JavaScript,也不需要对css样式有深入的了解,开发者只需要了解一些简单的HTML标签。数据库服务器采用MySQL5.7 ,MySQL数据库是一个开放的、快速的、多线程的、多用户的sql数据库服务器;它体积小、速度快、总体拥有成本低,而且是开源的,这一特点让MySQL数据库服务器成了大多数人的选择。
    数据库界面显示使用Navicat for MySQL 11.0,Navicat for MySQL是一款强大的MySQL数据库服务器的管理工具和开发工具,它使用了极好的图形用户界面,可以用一种安全和更容易的方式快速和容易地创建、组织、存取和信息共享。
    2.5 本章小结本章主要详细的描述了软件的需求情况,从软件可行性、功能需求到软件实现所需要的基本技术,再细致分析软件功能方面的需求,同时也分析了软件性能需求和开发环境上的需求。 
    第三章 系统概要设计系统的概要设计目标是使系统实现所要求的全部功能。本系统是基于B/S框架的web端系统。主要功能就是招租者发布房源信息于该系统上,求租者可以查看浏览房源信息后联系房主,咨询房源房源情况;求租者可以收藏房源,对房源及房主进行评价;招租者可以查看自己发布的房源记录,也可以查看浏览过房源的用户的记录。这些功能都是由各个模块之间协作而产生的。
    3.1 系统总体设计本系统设计总体上分为前台设计和后台设计。前台设计主要指针对用户操作功能,后台设计主要是针对管理员操作。前台主要操作功能流程为:用户注册登录、发布房源信息、查看新闻公告、查看招/求租信息、个人中心管理修改个人信息、修改/删除房源信息、收藏房源信息;后台主要操作功能流程为:管理员登录、用户信息管理、房源信息管理、房源收藏信息管理、首页展示、管理员注销。以下为本系统的模块划分和业务处理流程说明。
    模块划分:本系统将房屋出租管理的模块功能划分为个人中心管理、招租信息、求租信息、新闻公告、注册、登录、注销、后台管理等几大模块。主要的功能就是招租者注册登录后发布房源信息,用户注册登录后浏览查看房源信息。用户登后可以查看新闻公告,通过查看新闻公告,了解求租房的一些常识,有助于提高用户对于租房的安全意识。后台管理员可以删除招租者信息和用户信息,以及房源信息。房主可以在个人中心管理里面查看房源记录,修改、删除房源信息。用户在个人中心管理模块,查看、修改、删除自己的求租信息。求租过房的用户可以对房主及房源给出文字评价和打分评价。
    业务处理流程:房屋出租管理的流程是首次进入系统用户或者招租者只能查看新闻公告,停留在新闻公告页面。用户注册后登陆成功才可以查看房源信息以及发布自己的招租信息。招租者跟用户的功能有点儿类似,先注册登陆进去才可以有相关功能模块的权限,招租者登陆成功后可以发布房源,查看房源的浏览记录。管理员后台对招租者信息、用户信息、和房源信息进行管理,增删改查的功能。模块功能流程图如图3.1所示。

    3.2 房屋出租管理平台建模分析房屋出租管理平台建模分析主要基于房屋信息线下查看途径不便利、信息更新不及时。主要是针对房屋住房租赁的行为信息成本产生机制,找到房东、租户交易行为计算表达式。
    房源信息和价格的不对称导致房屋出租管理平台公开发、规范化成为可能。房源信息的不规范、更新不及时增加了租房者的时间成本,而线下价格的不对称和不透明导致房屋出租管理平台建设势在必行。
    住房租赁市场信息成本的测算方法,是依赖房屋租赁双方市场交易成本为原理;房屋交易双方交流信息不知道彼此期望的价格;最后的成交金额与双方彼此期望的价格之间的差异根本来源是信息交换的不及时、不准确,根据这个可以推导出租赁双方成本信息的测算的方法。
    具体的测算方法如下:

    租赁双方决策出发点是根据为追求彼此最大利益,甲方希望用最少的价格租到最合适的房屋,乙方则希望租金和租期最大化
    信息的不公开、不及时导致双方预期和现实差异悬虚会改变双方的房源单价
    租赁成交前,租赁双方利益追求的矛盾导致彼此追求最大的利益,导致房屋公开价格和实际价格有所差异

    假设出租方对建筑属性为D的出租房源的期望租金记为Ql;求租方对建筑属性为D的出租房源的期望租金记为Qt,分析可知最终的实际交易价格Qm通常都介于Q1和Qt之间。
    租赁的双方对房源信息是有偿的。信息的不对称和信息不透明产生的费用会体现在房屋的价格上面,租赁的双方预期的价格和实际房屋租赁价格的绝对值就在其中。出租方对建筑属性为D的房源出租者,将租赁房源的实体成本信息计为Ql,租赁房屋的发布者信息成本计为Qm。则有:

    出租方的成本信息就等于出租房源的期望租金减去最终的实际价格(SX1=Ql-Qm)
    承租方的信息成本就等于实际交易价格减去出租房源的期望租金(SXt=Qm-Qt)而期望租金的多少介于实际交易价格与出租方的期望交易租金之间(Qt<=Qm<=Ql)

    承担方如果以Qt价格租房子,那么出租方要损失|Qt-Q1|的差价,信息传递以后出租方可以少损失Qm-Qt。这表明了信息传递可以降低市场的信息不对称程度。
    在住房租赁市场,出租方的房源信息和求租方的求租信息如果能够通过一个平台快速有效的传递交流,使得交易双方信息的传递过程中,快速地找到自己相匹配的交易对象。这样才能减小不必要的信息成本,降低交易价格。
    本系统的目的旨在建立租赁彼此的信息成本的支出减少。出租者通过平台发布租房的具体信息可以减少中介的成本和信息维护的成本,不仅如此平台发布租赁信息可以将信息公开化解决了租赁双方沟通不透明的问题使得信息更加对称。求租方通过平台查看房源信息将更加方便,解决了空间和时间的成本将会有更多的市场选择性,从而使交易成本大大缩小,租金的实际价格将和实际的价格更加接近,是租赁双方信息不对称大大缩小,使租金不合理得到有效抑制。
    3.3 数据库设计3.3.1 数据库设计类图PROVIDER_INFOEntity是房主实体,登录房屋出租管理平台,可以记录多个房源信息RENTAL_HOUSE_RECORDEntity,通过发布房源信息RENTAL_HOUSE_BASEEntity可以添加房源记录,将该记录保存起来。
    User_infoEntity是用户实体,登录房屋出租管理平台,可以添加收藏房源RENTAL_EVALUATIONEntity,可以对房源进行评价RENTAL_EVALUATIONEntity并将记录保存到数据库表中。数据库设计类图如图3.2所示。

    3.3.2 数据库设计实体图用户信息实体图,包括用户名、用户ID、用密码、用户联系方式。用户实体图如图3.3所示。

    房主信息实体图,包括房主名称、房主ID、房主登录密码、房主联系方式、房源收藏ID、用户房源评价ID。房主实体图如图3.4所示。

    房源信息记录实体,包括房源名称、房源编码、房源ID、房主名称、房源发布时间、房源更新时间、房主联系方式。房源信息记录实体图如图3.5所示。

    房源发布信息实体图,包括房源名称、房源编码、房源所属省份、房源详细地址、小区名、楼栋号码、房源类型、房主联系方式、房源面积大小、房源价格、房源居室、房源描述等。房源发布信息实体图如图3.6所示。

    房源评价实体图,包括房源评价ID、房源编码、星级评价、评价描述、是否匿名、创建人ID、创建日期、最后更新人ID、最后更新日期、删除标识。房源评价实体图如图3.7所示。

    房源收藏信息记录实体图,包括收藏ID、房源ID、收藏者、房主、房源收藏时间、收藏者联系方式、房主联系方式。房源收藏信息记录实体图如图3.8所示。

    3.3.3 数据库表设计本次设计要用到的数据库表设计分别如下:
    用户信息表(USER_INFO)主要是存储注册用户的基本信息,以便登录时匹配数据库登录成功;主要字段设计如表3.1所示。



    字段
    字段类型
    主、外键
    是否为为空
    备注说明




    USER_NAME
    VARCHAR(64)
    主键

    用户名


    USER_ID
    VARCHAR(32)
    外键

    用户ID


    USER_PASSWARD
    VARCHAR(64)


    用户密码


    USER_PHONE
    VARCHAR(100)


    用户联系方式



    房主信息表(PROVIDER_INFO)主要用来存储房主的基本信息,房主再次登录时无需注册,输入用户名、密码登录即可;主要字段设计如表3.2所示。



    字段
    字段类型
    主、外键
    是否为空
    备注说明




    PROVIDER
    VARCHAR2(32)
    主键

    房主名


    PROVIDER_ID
    VARCHAR2(32)
    外键

    房主ID


    PROVIDER_PASSWARD
    VARCHAR2(32)


    房主密码


    PROVIDER_PHONE
    VARCHAR2(100)


    房主联系方式


    HOUSE_BASE_CODE
    VARCHAR(32)


    房源收藏编码


    USER_EVALUAE_ID
    VARCHAR(32)


    用户房源评价id



    房源记录信息表(RENTAL_HOUSE_RECORD)主要用来记录房源记录的基本信息,如“张三”查看过此房源,此房源发布人是谁、联系方式等;主要字段设计如表3.3所示。



    子段
    字段类型
    主、外键
    是否为空
    备注说明




    HOUSE_NAME
    VARCHAR(32)
    主键

    房屋名称


    HOUSE_BASE_CODE
    VARCHAR(32)


    房屋编码


    HOUSE_BASE_ID
    VARCHAR(32)


    房屋ID


    PROVIDER
    VARCHAR(32)


    房主名称


    HOUSE_FABU_TIMEE
    VARCHAR(64)


    房源发布时间


    HOUSE_UPDATE_TIME
    VARCHAR(64)


    房源更新时间


    PROVIDER_PHONE
    VARCHAR(100)


    房主联系方式



    房源发布信息表(RENTAL_HOUSE_BASE)即房源详细的基本信息,记录房源详细而全面的信息;主要字段设计如表3.4所示。



    字段
    字段类型
    主、外键
    是否为空
    备注说明




    HOUSE_BASE_ID
    VARCHAR(32)
    主键

    房源名称


    HOUSE_BASE_CODE
    VARCHAR(32)
    外键

    房屋编码


    HOUSE_PROVINCE
    VARCHAR(100)


    房屋所属省份


    HOUSE_ADDR
    VARCHAR(1000)


    房屋详细地址


    VILLAGE_NAME
    VARCHAR(200)


    小区名


    BUILDING_NUM
    VARCHAR(100)


    楼栋号码


    BUILDING_UNIT
    VARCHAR(100)


    楼栋单元


    HOUING_TYPE
    VARCHAR(100)


    房源类型


    DOOR_MODEL
    VARCHAR(200)


    户型


    BUILDING_AREA
    FLOAT(100,2)


    房屋面积


    FLOOR
    INT


    房屋楼层


    IS_APPLIANCES_COMPLETE
    CHAR(2)


    家电是否齐全:Y是,N否


    IS_TOWARD_SUN
    CHAR(2)


    是否朝阳:Y是,N否


    RENTAL_PRICE
    FLOAT(10,2)


    房源出租价格


    LESSOR
    VARCHAR(200)


    出租人


    LESSOR_PHONE
    VARCHAR(100)


    出租人联系方式


    CREATE_BY
    VARCHAR2(32)


    创建人id


    CREATED_DATE
    DATE


    创建日期


    LAST_UPDATE_BY
    VARCHAR2(32)


    最后更新人id


    LAST_UPDATED_DATE
    DATE


    最后更新日期


    DELETE_FALG
    CHAR(4)


    删除标识



    房屋评价表(RENTAL_EVALUATION)主要记录的是用户对房源及房主评价的相关信息;该表最主要的字段设计如表3.5所示。



    字段
    字段类型
    主、外键
    是否为空
    备注说明




    EVALUATION_ID
    VARCHAR(32)
    主键

    房屋评价id


    HOUSE_BASE_CODE
    VARCHAR(32)
    外键

    房屋编码


    PRAISE
    VARCHAR(20)


    星级评价


    EVALUATION_DESC
    VARCHAR(2000)


    评价描述


    IS_ANONYMOUS
    CHAR(2)


    是否匿名


    CREATE_BY
    VARCHAR2(32)


    创建人id


    CREATED_DATE
    DATE


    创建日期


    LAST_UPDATE_BY
    VARCHAR2(32)


    最后更新人id


    LAST_UPDATED_DATE
    DATE


    最后更新日期



    房源收藏信息表(house_collect)主要记录的是用户收藏的房源信息记录;该表主要的字段设计如表3.6所示。



    子段
    字段类型
    主、外键
    是否为空
    备注说明




    COLLECT_ID
    VARCHAR(32)
    主键

    收藏ID


    HOUSE_ID
    VARCHAR(32)


    房源ID


    COLLECT_USER
    VARCHAR(32)


    收藏者


    PROVIDER
    VARCHAR(32)


    房主


    COLLECT_DATE
    VARCHAR(64)


    房源收藏时间


    COLLECT_PHONE
    VARCHAR(64)


    收藏者联系方式


    PROVIDER_PHONE
    VARCHAR(100)


    房主联系方式



    新闻公告信息表(gonggao)主要记录的是新闻公告的信息记录;该表主要的字段设计如表3.7所示。



    字段
    字段类型
    主、外键
    是否为空
    备注




    SHIJIAN
    VARCHAR(32)


    时间


    CONTENT
    VARCAHR(32)


    内容


    TITLE
    VARCAHR(32)
    主键

    标题


    ID
    VARCAHR(32)
    外键

    公告ID



    3.4 本章小结本章主要详细的描述了系统的概要设计,从系统的总体设计、平台数据建模分析、数据库结构的设计以及数据库表、字段的分析研究对系统进行细致的阐述。 
    第四章 系统详细设计4.1 系统总体详细设计前台功能详细设计主要包括:用户登录注册详细设计、房源信息发布模块功能设计、个人中心管理模块功能设计、用户信息模块功能设计、房主信息模块功能设计、求租信息模块功能设计、房源收藏功能设计、房源分享功能设计、信息交流功能设计等九个模块功能设计。根据数据流程分析,房屋出租管理系统的全局E-R图设计如图3.2所示。

    4.2 系统主要功能模块类图设计房源发布模块类图设计:房源发布模块在house中调用houseDao中的find()、findById()、del()、js()和AddHouse类中insert()、update()、delById()、getList()方法。接着调用getList()方法,该方法主要通过登录名查找数据库house表中的数据,并将查询结果保存在ArrayList<house>的list对象中,接着find()的返回值在Structs.xml配置找到房源发布信息页面。房源发布设计类图如图4.2所示。

    个人中心管理模块类图设计:个人信息查看的实现用到了modifyuser、userDao类,方法有modifyuser类的find()、findById()、update()、delete()、js(),userDao类的getList()、updateById()、save()、update()、querybyId()方法、delete()方法。其设计用例如图4.3 所示。

    房源信息管理模块类图设计:该模块的实现用到houseAction、houseDao类,方法主要houseAction类的find()、findById()、update()、delete()、js()方法和houseDao 类的getList ()、listById()、save()、update()、queryById()方法。其设计类图如图4.4所示。

    用户信息管理模块类图设计:该功能的实现用到UserAction、UserDao 类,方法主要有UserAction 类的findUser()、mdfUserById()、delUserById(),UserDao 类的getUserList()、updateById()、delUser()方法。用户信息管理设计类图如图4.5所示。

    管理员信息管理模块类图设计:实现主要用到AdminAction 类和AdminDao 类,方法有AdminAction 类下的login()、update()、insert()、save()、querybyId()和AdminDao 下的update()、save()、getById()、queryById()方法。其设计类图如图4.6所示。

    新闻公告模块类图设计:该模块的实现主要用到GonggaoAction 类和GonggaoBean 类,方法GonggaoAction 类下的insert()、delete()、modify()、find ()方法和AdminDao 下的insert()、delete()、modify()、find ()方法。其设计类图如图4.7所示。

    4.3 系统主要功能模块时序图设计用户登录注册模块设计:用户信息模块包括普通用户和房主。用户通过发布招租信息升级为房主。用户可以修改自己的基本信息、可以取消删除收藏的房源信息,可以查看评价记录信息,,用户可以查看浏览房源信息系等。用户租过某房主的房子,租完后可以根据房主的态度以及房源的情况、卫生服务方面等对房源做出评价以及给房源打分评价。便于其他用户浏览房源时参考,有利于维护租房者一方的利益。其设计时序图如图4.8所示。

    求租、招租信息模块设计:用户登陆成功后,在系统平台中可以新增、查看自己的求租信息、招租信息。用户可以点击发布房源模块,根据自己的具体的情况发布招租、求租的房源信息,并留下自己的相关联系方式,便于其它用户联系自己。求租信息模块设计跟招租信息模块相似。招/求租信息时序图如图4.9所示。

    房源收藏设计:用户登陆成功后,在“招租信息”中可以收藏房源信息,将房源信息收藏至个人中心管理。可方便用户随时去查看浏览房源信息。房源的收藏功能主要在招租信息模块功能里面,点击“收藏”按钮,可将要收藏的房源信息收藏到个人中心管理里面。收藏设计模块的时序图设计如图4.10所示。

    用户房源评价设计:用户登陆成功后,可以对自己收藏的房源、自己租过的房源或者自己发布的房源信息列表里面对房源做出一些简单的评价,这样更利于用户对房源信息的了解。用户房源评价设计时序图如图4.11所示。

    新闻公告设计:用户登录成功进入平台后可以查看平台的新闻公告,新闻公告是一些关于招租,求租方面的合同以及双方互利的好处和一些必要的建议。新闻公告模块时序图设计时序图如图4.12所示。

    个人中心管理模块设计:用户登录成功后,点击“个人中心管理”,可以在个人中心管理里面对自己的个人信息和自己发布的招/求租房源信息进行修改。可以对个人信息进行用户名、密码修改;对房源信息进行删除、修改操作。个人中心管理设计时序图如图4.13所示。

    4.4 本章小结本章从详细设计出发,描述了系统的详细功能模块的一系列设计,然后又从后台详细设计的角度出发,描述了系统详细的功能层次。

    第五章 系统实现5.1 系统前台功能实现前台功能的实现主要包括:登录注册模块功能实现、房源信息发布模块功能实现、新闻公告模块功能实现、查看房源信息模块功能实现、查看用户信息模块功能实现、个人中心管理模块功能实现、房源收藏模块功能实现等。
    5.1.1 登录注册模块功能实现招租者在查看、收藏、评价房源信息时,必须要进行两种操作:注册和登录。
    注册的实现主要用到useraction类、userDao类和register()、insert()、isExist()方法。首先用户或管理员在form表单中输入用户名、密码、点击‘注册’按钮后,通过form表单的action向web控制器发出注册请求,web控制器拦截该请求后,通过structs.xml配置文件找到对应useraction类下的register()方法,register()方法先获取注册注册表单输入的信息,然后去调用userDao类中的isExist()方法。
    userDao类中的isExist()方法会根据输入的用户名在数据表user表或者provider表进行查询判断输入的招租者或者求租者是否存在,如果存在就会发出弹窗信息提示,让招租者/求租者输入用户名和密码;如果输入的用户名不存在,则会通过insert()方法将数据插入到数据库中。然后web控制器根据register()方法返回值,通过Structs.Xml配置返回到登录页面。
    登录功能的实现主要用到useraction类下的login()和userDao()方法。登录也是要通过form表单向web控制器发出登录请求,web拦截器拦截该请求后,通过Structs.xml配置找到useraction类下的login()方法。Login()方法会获取登录表单提交的用户输入信息,然后调用userDao类下login()方法。userDao类下login()方法会查找数据库中的用户(user)表和房主(provider)表中的用户名和密码和登录记录表单提交的内容相比较,如果比较结果一致,userDao的login()方法会返回一个数值1;如果比较结果不一致,userDao的login()方法会返回一个数值0。然后userAction类下的login()方法会根据userDao类的login()返回的值判断用户是否登录成功。“1”代表用户登录成功,“0”代表用户登录失败。其中注册页面的实现结果如图5.1所示。

    5.1.2 新闻公告模块功能实现新闻公告主要用到的是form表单和title标题以及文本信息。文本信息直接是写在jsp页面里边。逻辑如图5.2所示。

    5.1.3 发布房源信息模块功能实现招租发布房源信息的功能主要包括,招租者发布房源信息,上传房源图片,删除房源信息,修改房源信息,更新房源信息。
    房源信息的查看实现主要用到houseDao类中的find()、findById()、del()、js()和AddHouse类中insert()、update()、delById()、getList()方法。当登录的求租者点击“招租信息”按钮时,web控制器拦截到招租者的操作请求,通过Structs.xml配置找到find()方法,find()方法会获取登录时保存在session中的provider登录名,接着调用getList()方法,该方法主要通过登录名查找数据库house表中的数据,并将查询结果保存在ArrayList<house>的list对象中,接着find()的返回值在Structs.xml配置找到招租信息页面。
    房源信息删除实现过程。当用户点击 “删除按钮”时,该超链接发出删除请求。Web控制器拦截删除请求,通过Structs.xml配置找到del()方法,该方法获取要删除的房源ID,然后调用delHouse类中的findById()根据房源ID的编号删除数据库库house表中对应的数据,然后再调用find()跳转到招租信息页面。
    上传房源图片的实现过程。发布房源信息填写完毕后,点击上传房源图片,跳转到上传房源图片的弹窗页面。在该过程中web控制器拦截该服务请求,通过Structs.xml配置找到js()方法,js()方法先调用findById()查找房源图片,然后调用insert()将对应的查找数据插入到house表中,然后再调用delById()根据房源编号添加到house表中。发布房源信息页面的实现如图5.3所示。

    5.1.4 查看房源信息模块功能实现求租查看房源信息的功能包括,房源信息查看浏览、求租信息发布、修改、收藏房源信息。
    求租信息查看浏览的实现主要用到houseDao类中find()、findById()、del()、js()和houseDao类中的liulan()、insert()、update()、delById()、shoucang()、getList()方法。当登录的求租者点击“求租信息”按钮,web控制器拦截到会员操作请求,继续通过Structs.xml配置找到find()方法,find()方法会获取登录时保存在session中的求租者登录名,紧接着调用getList()方法,该方法主要通过登录名查找数据库user表中的数据,并将查询结果保存在ArrayList<user>的list对象中,接着find()方法获取到getList()的返回值,并将该值保存在ActionContext对象中。然后web控制器根据find()的返回值在Structs.Xml配置中找到求租信息页面。
    求租信息删除过程。当用户点击“删除按钮时”,删除按钮超链接发出删除请求,web控制器拦截删除请求。删除请求是通过Structs.xml配置找到delhouse类中的del()方法,该方法获取要删除的求租信息的ID编号,然后调用delById()根据招租信息的编号删除数据库RENTAL_HOUSE_HISTORY表中对应的数据,然后再调用find()跳转回求租信息页面。
    求租信息修改。当求租者需要修改自己的求租信息时,点击“修改”按钮。就会引发该超链接发出修改请求。Web控制器拦截修改请求,通过Structs.xml配置找到modifyHouse()方法,该方法获取要修改的求租信息的ID编号,然偶调用modifyById()根据求租信息的编号修改数据库中RENTAL_HOUSE_HISTORY表的对应数据。最后再调用find()跳转到求租信息页面。查看房源信息页面的实现如图5.4所示。

    5.1.5 个人中心管理模块功能实现个人中心管理模块主要功能包括:个人(用户)信息修改、个人(用户)信息删除、查看房源记录、查看用户评价记录。个人中心管理信息页面的实现如图5.5所示。

    个人信息查看的实现用到了modifyuser、userDao类,方法有modifyuser类的find()、userDao类的getList()方法。用户点击“个人中心管理”按钮时,会发出查看信息请求,web控制器拦截该请求,并通过Structs.Xml配置文件找到find()方法。Find()方法首先会获取用户登录时保存在session中的用户名,然后调用getList()方法,getList()方法会根据用户名查找数据库USER_INFO表中的数据。将查找结果保存在ArrayList<USERE_INFO>对象中然后返回该对象。Find()方法获取到getlist()方法的结果,将该结果保存在actionContext对象中,然后web控制器根据find()方法的返回值在Structs.Xml配置文件中找到跳转的页面,即个人中心管理myinfo.Jsp。
    个人信息修改实现的过程。该功能的实现用到useraction、userDao类。方法主要有useraction类的update()方法、userDao类的updateById()方法。用户点击“修改”按钮输入要修改的信息,通过“提交”按钮发出修改请求,web控制器拦截该请求,并通过Struts.xml配置文件找到update()方法,该方法获取修改表单提交的内容,然后调用updateById()方法,该方法获取修改表单提交的内容,然后再调用update()方法根据用户主键
    个人信息删除功能。该功能的实现用到userAction、userDao类,方法有userAction类的del()、userDao类的delete()方法。当删除个人信息时,在操作那一栏出现一个删除按钮。用户点击“删除”按钮后,web控制器拦截该请求,通过Structs.xml配置文件del()方法,del()方法获取用户的ID编号和用户登录名。然后再去调用delete()方法根据用户ID编号和用户登录名删除数据库USER_INFO表中对应的数据。并再次调用个人中心管理查看用户信息页面。
    5.1.6 房源收藏模块功能实现该功能的实现用到shoucangAction、userDao 类,方法有shoucangAction 类的insert()和usereDao 类的insert()方法。用户点击“收藏”按钮发送请求,web 控制器拦截该请求,通过Struts.xml 配置文件找到shoucangAction 类的insert()方法,该方法先获取入库表单提交的信息,然后调用shoucangDao 类的insert()方法将获取到的信息插入到数据库RENTAL_HOUSE_RECORD 表中,然后web 控制器根据evaluateAction 类的insert()方法的返回值,通过Struts.xml 配置文件跳转到收藏信息显示页面。房源收藏页面的实现如图5.6所示。

    5.2 系统后台功能实现系统后台功能实现主要包括:后台主页面功能实现、房源信息管理功能实现、用户信息管理功能实现、房源收藏功能实现、管理员管理注销功能实现。
    5.2.1 后台主页面功能实现管理员登录后台管理平台:输入管理员名称、密码后进入后台。后台主页面,该页面主要分为上、中、下三部分,上部分为头部,主要是后台的标题。中部主要为导航栏,显示后台模块功能;下边为主显示区域显示管理功能模块的列表信息。后台主页面的实现如图5.6所示。

    5.2.2 房源信息管理功能实现该管理功能主要包括:新增房源信息、修改房源信息、删除房源信息、更新房源信息、房源信息管理实现过程。
    实现用到houseAction、houseDao类,方法主要houseAction类的nosucees()和success()、success()和OrderDao 类的getList ()方法。当用户点击“发布房源信息管理”菜单时,web控制器拦截该请求,通过Struts.xml 配置文件找到success()方法,该方法调用getList()方法根据处理情况=“未处理”和发布房源情况=“未确认”条件查询数据库t_order 表中的数据,将查询的结果保存在ArrayList<house> 对象中,然后返回该对象,success()方法获取到getList()方法的结果,将该结果保存在ActionContext 对象中,然后web 控制器根据nsuccess()方法的返回值。
    过Struts.xml 配置文件找到房源信息管理页面,在该页面用EL表达式${list}获取ActionContext 对象保存的值,然后通过<c:forEach>标签将查询结果遍历出来,其遍历使用ActionContext 对象调用houseDao 类属性实现,例如${list.f_name}。其实现过程和未发布房源实现过程相似。房源信息管理实现结果如图5.7所示。

    5.2.3 用户信息管理功能实现用户信息管理功能,主要包括用户信息显示、用户信息删除、用户信息修改。
    用户信息显示实现过程
    该功能的实现用到AdminAction、UserDao 类,方法有AdminAction 类的findUser()、OrderDao 类的getUserList()方法。管理员点击“会员管理”发送查看信息请求,web 控制器拦截该请求,并通过Struts.xml 配置文件找到findUser()方法,findUser()方法首先调用getUserList()方法,getUserList()方法会查找数据库t_user 表数据,将查找结果保存在ArrayList<User>对象中,然后返回该对象,findUser()方法获取到getUserList()方法的结果,将该结果保存在ActionContext 对象中,然后web 控制器根据findUser()方法的返回值在Struts.xml 配置文件找到跳转的页面,在该页面用EL 表达式${list}获取ActionContext 对象保存的值,然后通过<c:forEach>标签将查询结果遍历出来,其遍历使用ActionContext 对象调用User 类属性实现,例如${list.userName}。
    用户信息修改实现过程
    该功能的实现用到UserAction、UserDao 类,方法有UserAction 类的mdfUserById()、UserDao 类的updateById()方法。管理员点击“修改”按钮跳转到修改会员信息表单页面,通过“提交”按钮发出修改请求,web 控制器拦截该请求,并通过Struts.xml 配置文件找到mdfUserById()方法,该方法获取修改表单提交的内容,然后调用updateById()方法根据会员主键修改数据库t_user 表中的数据,然后调用会员信息显示实现过程的findUser()方法回到会员信息管理页面。
    用户信息删除实现过程
    该功能的实现用到UserAction、UserDao 类,方法有UserAction 类的delUserById()、UserDao 类的delUser()方法。管理员点击“删除”按钮发出删除请求,web 控制器拦截该请求,并通过Struts.xml 配置文件找到delUserById()方法,该方法获取要删除的会员主键,然后调用delUser()方法根据会员主键删除数据库t_user 表中对应的数据,然后调用会员信息显示实现过程的findUser()方法回到会员信息管理页面。用户信息管理的实现结果如图5.8所示。

    5.2.4 用户评价信息管理该功能的实现用到evaluateAction、userDao 类,方法有evaluateAction 类的insert()和usereDao 类的insert()方法。用户点击“评价”按钮发送请求,web 控制器拦截该请求,通过Struts.xml 配置文件找到evaluateAction 类的insert()方法,该方法先获取用户评价信息表单提交的信息,然后调用OrderDao 类的insert()方法将获取到的信息插入到数据库EVALUATE_INFO 表中,然后web 控制器根据evaluateAction 类的insert()方法的返回值,通过Struts.xml 配置文件跳转到评价信息显示页面。用户评价信息管理页面如图5.9所示。

    5.2.5 房源收藏管理该功能的实现用到shoucangAction、userDao 类,方法有shoucangAction 类的insert()和usereDao 类的insert()方法。用户点击“收藏”按钮发送请求,web 控制器拦截该请求,通过Struts.xml 配置文件找到shoucangAction 类的insert()方法,该方法先获取入库表单提交的信息,然后调用shoucangDao 类的insert()方法将获取到的信息插入到数据库RENTAL_HOUSE_RECORD 表中,然后web 控制器根据evaluateAction 类的insert()方法的返回值,通过Struts.xml 配置文件跳转到收藏信息显示页面。用户收藏页面如图5.10所示。

    5.2.6 管理员信息注销管理管理员信息管理主要功能是:修改管理员用户名称、登录密码以及可以新增管理员功能。
    实现主要用到AdminAction 类和AdminDao 类,方法有AdminAction 类下的update()和AdminDao 下的update()方法。管理员点击“修改”按钮发送请求,web 控制器拦截该请求,通过Struts.xml 配置文件找到AdminAction 类的update()方法,该方法先获取修改密码表单的输入信息,然后调用AdminDao 类的update()方法根据管理员名称和获取的输入信息更改数据库t_admin 表中对应的数据,然后web 控制器根据AdminAction 类的update()方法的返回值,通过Struts.xml 配置文件跳转到管理员信息显示页面。管理员信息管理页面如图5.11所示。

    5.3 本章小结本章主要描述了系统的前、后台功能模块的详细实现设计和方法。前台功能主要有登录注册模块功能实现、新闻公告模块功能实现等,后台功能模块主要有房源信息管理模块、用户信息管理模块、管理员信息模块、用户注销等模块。

    第六章 系统测试测试是对软件产品进行发布上线的最后一道检验。测试可以提高软件产品的质量与品质。测试是我最擅长的了,因为我是做软件测试,目前基于功能测试,但在朝着自动化测试和性能测试的方向努力。
    6.1 测试目的根据房屋出租管理的开发需求和目的,本次开发的目的是开发一个满足用户和招租者要求的方便好用、界面友好、维护方便、而且易于扩展具、有较高工业强度的j2ee轻量级应用系统。本系统提供给求租者和招租者使用,测试时需要按模块功能分别取测试。每一个系统上线前都要经过严格的测试,本系统也不例外。测试的主要目的是是否满足客户需求,设计是否符合规格以及系统是否具备较高的工业强度;其次,测试的目的是确保软件质量、提高软件的可用性和健壮性的关键。全面的测试房屋出租管理系统的各个功能模块,确保系统的整体性能。从而确保该系统能广泛的使用和后期维护更新。
    6.2 测试方法测试的方法主要分为功能测试(白盒测试)和按需求文档要求测试(黑盒测试),以及系统环境、数据库服务是否满足要求的性能测试。
    6.2.1 功能测试功能测试就是测试各个页面的功能使用是否正常。在功能测试中出现了几个比较严重的问题,用户注册成功后点击查看浏览招租房源信息,提示用户“请先登录”,是不能直接查看的,这个bug的主要原因是数据连接失败,调试连接好数据库后,此问题解决。还有遇到的问题就是房屋招租者修改房源信后,点击保存,保存失败,这个bug的原因是点击“保存”时未返回给后台这条房源信息的ID,导致此修改信息后台未获取到,没有保存到数据库。比较严重的bug就这两个。其次就是各个输入框的字段长度的测试,页面跳转测试,数据测试等的测试问题基本没有。
    用户注册测试,对用户注册的字段长度、特殊字符、超短字符串进行测试,看是否符合需求说明书的要求。测试用例如表6.1所示。



    用例序号
    测试点
    预置条件
    期望结果
    实际结果
    是否通过




    1
    输入正确用户名、密码
    打开系统进入平台
    注册成功
    注册成功
    Y


    2
    输入特殊字符
    打开系统进入平台
    注册失败
    注册失败
    Y


    3
    超长字符串
    打开系统进入平台
    注册失败
    注册失败
    Y


    4
    输入超短字符少于6位
    打开系统进入平台
    注册失败
    注册失败
    Y


    5
    输入单一条件,只输入用户名
    打开系统进入平台
    注册失败
    注册失败
    Y



    用户登录,用户登录的校验测试。主要是通过正常情况和异常情况去测试。正常情况只有一条测试用例,异常情况主要有3条测试用例。测试用例设计,如表6.2所示。



    用例序号
    测试点
    预置条件
    期望结果
    实际结果
    是否通过




    1
    输入正确用户名、密码
    打开系统进入平台
    登录成功
    登录成功
    Y


    2
    输入错误用户名
    打开系统进入平台
    登录失败
    登录失败
    Y


    3
    置空登录
    打开系统进入平台
    登录失败
    登录失败
    Y


    4
    输入单一条件,只输入用户名
    打开系统进入平台
    登录失败
    登录失败
    Y



    发布房源模块功能测试,主要测试房源信息能否正常写入、能否正常发布成功以及置空测试。测试用例如表6.3所示。



    用例序号
    测试点
    预置条件
    期望结果
    实际结果
    是否通过




    1
    正常写入房源信息
    打开系统登录进入平台
    发布成功
    发布成功
    Y


    2
    输入错误特殊字符房源信息
    打开系统进入平台
    发布失败
    发布失败
    Y


    3
    置空发布
    打开系统登录进入平台
    发布失败
    发布失败
    Y


    4
    上传房源图片
    打开系统进入平台
    上传成功
    上传成功
    Y



    修改个人信息测试,修改用户的用户名、密码,电话号后保存。修改个人信息成功后弹出的页面如图6.1所示。

    房源基本信息修改测试,修改房源的基本信息,如居室、发布时间、标题、面积、行政区划、大小、房源信息发布人、联系人方式、是否朝阳等。房源信息修改成功后弹出的页面如图6.2所示。

    房源信息删除测试,在个人中心管理对房主发布的房源信息进行删除操作,弹出删除成功后的提示页面如图6.3所示。

    后台用户信息新增测试,点击新增用户信息,弹出新增用户信息弹窗,输入正确的用户信息,点击确定,弹出新增成功用户信息的弹窗提示。弹窗提示页面如图6.5所示。

    后台用户信息编辑修改测试,点击用户信息页面编辑修改按钮,修改用户页面信息,修改结束点击确定,用户信息修改成功。编辑修改成功后的弹窗页面如图6.6所示。

    后台用户信息删除测试,管理点击用户信息页面删除按钮,弹出“确定”删除弹窗提示,点击确定弹出删除成功弹窗提示页面。弹窗提示页面如图6.7所示。

    后台房源信息管理功能模块新增房源信息测试,管理员点击房源信息页面新增按钮,弹出新增房源信息页面,房源信息输入完毕后点击“确定”保存按钮,弹出新增房源信息成功弹窗。新增房源成功的页面提示如图6.8所示。

    后台房源信息编辑修改测试,点击房源信息页面编辑按钮,弹出房源信息编辑修改页面,编辑修改房源信息后点击“确定”按钮,弹出房源信息修改成功弹窗提示,弹窗提示如图6.9所示。

    6.2.2 性能测试性能测试主要是对这个系统的容量测试,例如对这个数据库定义了100个用户,当超过一百个用户,用户注册失败。还有就是多个用户同时注册时,注册是否会失败。经过测试后这些性能都是正常的。
    性能测试,主要是对系统进行的最大承受力测试和最大承受压力测试。负载测试就是页面响应速度测试,压力测试主要测试系统所能达到的最大用户并发量。用例设计如表6.4所示。



    用例序号
    测试点
    预置条件
    期望结果
    实际结果
    是否通过




    1
    少于100个用户登录
    打开系统模拟80个用户同时登录进入平台
    登录成功
    登录成功
    Y


    2
    大于100个用户登录
    打开系统模拟101个用户同时登录进入平台
    登录失败
    登录失败
    Y


    3
    是否超过10s
    打开系统登录进入平台,点击跳转页面
    10s内跳转成功
    成功
    Y


    4
    服务器断掉
    打开系统进入平台
    10s内跳转失败
    上传成功
    Y



    6.3 系统调试调试主要是对代码的调试。某一块代码是否具体实现了某一些功能。调试主要是修改bug时进行的,调试过程及时发现问题及时修改。调试提高了软件代码的时效性。解决bug, 发现bug后,对问题进行分析,分析定位后进行代码bug调试。对代码加断点调试,然后再查看异常的提示说明,根据具体问题具体分析,解决bug。代码调试测试用例如下表6.5所示。



    用例序号
    测试点
    预置条件
    期望结果
    实际结果
    是否通过




    1
    数据库服务连接调试
    服务启动正常,数据库连接正常,
    调试成功
    连接失败
    Y


    2
    页面登录失败调试
    服务启动正常,数据库连接正常,
    调试成功
    登录失败
    Y


    3
    房源信息发布失败
    服务启动正常,数据库连接正常,
    调试成功
    发布失败
    Y


    4
    房源信息修改失败
    服务启动正常,数据库连接正常,
    调试成功
    修改失败
    Y


    5
    个人失败信息修改
    服务启动正常,数据库连接正常,
    调试成功
    修改失败
    Y


    6
    房源信息修改失败
    服务启动正常,数据库连接正常,
    调试成功
    修改失败
    Y


    7
    管理员新增用户失败
    服务启动正常,数据库连接正常,
    调试成功
    新增失败
    Y


    8
    管理员新增房源信息
    服务启动正常,数据库连接正常,
    调试成功
    新增失败
    Y



    6.4 本章小结本章主要从系统的不同方面、不同功能对系统进行测试,主要从测试的目的、测试的方法陈述系统功能测试的一些常用方法和测试所准备的测试用例,确保了系统的正常运行。
    总结项目主要完成了基于B/S体系结构的web端系统。利用了linux系统下文件服务器和Redis缓存服务器大量储存数据的优势,实现了界面友好,操作灵活,页面响应迅速的系统。做成一个好的完整的系统必不可少的要从需求分析设计开始完成需求文档、设计开发原型图,然后需求评审,需求评审完成后进入开发设计,设计数据库以及每个模块要完成的功能,然后建立功能模块的整体框架和后台开发设计,实现该模块的基本功能模块。基本功能模块建成后,再设计整个页面,完善页面,优化界面。不断的完善一些功能,最终完成整个系统的设计。达到想要的结果。在这一准备的过程中学会了系统开发的流程以及如何高效的完成任务。
    前面的准备阶段都完成了,然后进入到具体的代码实现设计阶段了。设计完成后就步入开发了。在本次系统的开发过程中,最大的收获就是学会给项目部署maven项目管理工具,给项目熟练的配置数据库连接,加断点调试代码。遇到了不能解决的问题,也有了更深刻的思考。
    在设计过程中主要使用工具Auxre原型图工具来画原型图。一般的简单的静态图自己看下网上教程可以使用,但是比较高级的动态原型图网上教程也很少。遇到问题如原型图中的阴影图层的画法、动态链接跳转等都是比较高级的操作,这些动作的操作都是咨询需求同事,他手把手教的;这个过程中最大的收获就是做一件事只要努力想办法去做,一定会做成。
    原型图设计完成后接着做开发设计包括数据库设计、后台开发设计、算法设计等,这些设计都是根据需求说明书去设计的,在这个过程中,由于经验不足、设计的数据库表和算法设计不是尽善尽美也存在很多小细节问题。初步设计后让同事帮我参考完善补充一下,多看看别人的设计和思路也是一种成长的方式。
    在这次毕业设计中遇到的最大的问题也是收获最多的问题就是linux系统的安装以及文件服务器和Redis缓存服务器的搭建问题。安装了好多次,也失败了好多次,以至于电脑系统都被搞坏了重装了系统。但是也淡定的面对并解决了问题,虽然有的事情你经历了也不见得对你有用但是你还是得去经历,只有经历才有更深刻的认识与体会。遇到问题努力寻求帮助,寻求同事,有时候同事也很忙,没有时间帮你看的时候,就上网发帖去寻求帮助,去朋友圈寻求帮助,最终解决了问题。
    通过这次项目的编写,最大的体会就是时间和理论相结合的妙处,对Java有了更加深入的认识。在开发过程中学习了很多以前没有接触到的知识,从文件服务器到Redis缓存服务器,对数据的存储有了更深刻的认识。而且提升了面对问题的解决能力,能够自学一些没有接触过的知识,而且能够在很短的时间里将知识技能使用到程序之中。
    参考文献[1] Jon G. Hall, Lucia RapanottiA .design theory for software engineering[J]. Information and Software Technology ,2017-07-15.
    [2] Camelia Muñoz-Caro,Alfonso Niño,Sebastián Reyes.Miriam Castillo. APINetworks Java.A Java approach to the efficient treatment of large-scale complex networks. Computer Physics Communications,2016
    [3] 陈惠贞.网页程序设计HTML5•JavaScript•CSS•XHTML•Ajax[M].清华大学出版社,2016.
    [4] Camelia Muñoz-Caro,Alfonso Niño.Sebastián Reyes.Miriam Castillo. APINetworks Java.A Java approach to the efficient treatment of large-scale complex networks. Computer Physics Communications,2016.
    [5] 刘零凰.《MySQL管理之道》(第2版).机械工业出版社.2016.
    [6] 包乌格德勒.《JSP动态网页开发案例教程》(第二版).机械工业出版社.2016
    [7] IDdo Gal,Irena Ograjenšek.Official Statistics and Statistics EducationBrIDging theGap.Journal of Official Statistics.2015,4(1):76-80.
    [8] Linden B G,Smith B,York J. Amazon.com Recommendations Iem-to-item collaborative filtering[J].IEEE Internet Computing,2015,4(1):76-80.
    [9] 李君.巧用Jsp和Java连接Mysql数据库[J].现代商贸工业,2015(07):98-99.
    [10] 郑建华,朱蓉,邱振国.基于Servlet的MVC控制器框架设计[J].计算机时代,2015(04):49-52.
    [11] David Cochran, Ian Whitley.Bootstrap实战[M].人民邮电出版社,2015.
    [12] Jens Heidrich,Markku Oivo,Andreas Jedlitschka. Software productivity and effort estimation[J]. Journal of Software: Evolution and Process, 2015(7).
    [13] Muhammad Ovais Ahmad,Denis Dennehy,Kieran Conboy,Markku Oivo. Kanban in software engineering: A systematic mapping study[J]. The Journal of Systems & Software,2014.
    [14] Chen B,Yuan S,Wang J.A dynamic pricing model for unifying programmatic guarantee and real-time bidding in display advertising[J].proceedings of the English International Workshop on Data mining for Online Advertising.ACM,2014:1-9.
    [15] 李清海.世通书屋网上书店系统的设计与开发[J].吉林大学.2014-12
    [16] 王栓宝.基于WEB的学生信息管理系统的设计与实现[J].河北科技大学.2014-05
    [17] 眭俊华, 刘慧娜, 王建鑫等. 多核多线程技术综述. 计算机应用. 2013, 33(S1):239-242, 261
    5 评论 155 下载 2019-05-13 22:35:13 下载需要18点积分
  • 基于Python实现的孤立词语音识别系统

    1 任务介绍语音识别是通往真正的人工智能的不可缺少的技术。尽管能真正听懂人类说话的智能机器任然在未来不可捉摸的迷雾之中,但我们必须先解决如何识别出人类语音中包含的自然语言信息的问题。而数字信号处理技术将为这一任务赋能。在本课程项目的任务之中,我们面对的是一个简化的语音识别场景——即孤立词识别。
    我们针对 20 个关键词,采集了所有参与课程的同学朗读每个词 20 遍的语音。我将以此为数据集来构建一个能正确识别这 20 个关键词的孤立词识别系统。
    2 项目实现基于一学期跟随老师学习到的关于信号处理与语音识别技术的知识,我额外查阅多方资料,最终呈现出了我的语音识别系统与报告。
    我实现的语音识别系统的亮点有以下几个方面:

    说话人无关的孤立词识别是语音识别技术发展中一个里程碑。从现代的观点来看,如果将语言信号视作时间序列,那么孤立词识别就是一个模式识别中的分类问题。模式识别问题的解决一般分为特征提取与模型构建两个部分。我们将这两个部分分开处理,使得代码的实现更加具有结构性和层次性。报告也将这两部分的处理分开叙述
    我在整个系统的实现中,除了利用了数值处理函数包 numpy 和自动求导工具包 pytorch之外的所有核心代码都是单纯使用 python 实现。即真正锻炼了代码实现能力,也加深了对语音识别技术的理解。在报告中我也强调了各个方法和过程的代码实现,并将关键代码添加到附录之中以方便检阅
    特别地,我基于课堂上所学的蝶形变换方法,实现了以 2 为基的快速傅里叶变换,并运用到了频域特征的分析之中。这让我更加领略到该算法的优美
    根据我自行实现的快速傅里叶变换,实现了梅尔频率域的倒谱系数的计算,并根据通过梅尔滤波器之后得到梅尔频谱特征设计了基于卷积神经网络的识别算法
    我将计算出的频谱特征视为图片,因而可以使用近年来在大规模图片分类任务上大放异彩的卷积神经网络来进行分类识别。我采用了 2014 年在 ImageNet 的比赛上获胜的VGG Net 作为我们的识别模型,并使用了批归一化和 Dropout 手段来避免过拟合,提高模型的泛化能力

    2.1 预处理首先我对数据进行了清洗。
    各个同学上交的文件结构并不一致,有的是一个压缩包下包含所有文件,有的是一个压缩包中还有以自己的学号命名的文件夹,此外还有一些同学提交的压缩包是在 MacOS 上进行打包的,因此还有一个额外的缓存文件夹。这样的结构不利于我们对数据进行批量的读入。
    因此我编写了程序先解压所有压缩包,然后进行深度优先搜索来遍历所有文件夹,根据文件的命名规则把所有文件提取出来,按照 data/学号/文件名.wav 的格式统一存储。同时因为需要大规模地进行复制提取,为了效率的考量,我使用多线程的方式完成了这一任务。
    此外有几个文件显示已损坏而无法读取,以及一个文件录音长度大于两秒。为了数据的一致性,必须去除掉异常数据,但仅仅删除数据将导致样本不均衡的问题。为此我采用随机替换的方式,用同一个同学在同一个词下的另一个语音文件进行替换。这样就可以缓解数据缺失带来的样本不均衡的问题。

    同时,考虑到最终测试时是采用集外测试的方法,理论上讲应剔除女生的数据。
    在接下来的报告中,如无特殊声明,用 y0, y1 · · · , yt, · · · 来表示离散的信号构成的序列,用 sr来表示采样率。
    2.2 特征提取2.2.1 归一化因为数据在采集的时候声音强度并不一致,为了消除影响,我对每一段音频数据进行归一化。这里只需要对 y 使用 numpy.normailize 方法即可。
    2.2.2 预加重对读入的数据,我首先通过预加重的方法来补偿由于唇和空气导致的声音在产生和传播中高频部分的损失。预加重通常采用一个一阶的线性高通滤波器

    来实现,其中 α = 0.97。在代码实现上,只需要对数组进行加权差分即可。
    2.2.3 分帧一般情况下,语音信号是一种典型的非平稳信号,但是可以认为人说话的语调变换并不是是突然的,因此可假定语音信号在短时间 (10-30ms) 内是平稳的;故而在对语音信号进行分析时,我们可以将语音信号以 10-30ms 的间隔将连续的音频信号截取成一段一段来进行分析。
    用 y[i : j] 来表示 yi, yi+1, · · · , yj−1,为一帧包含为 j − i 个采样点的语音信号,其时长为( j−i)/sr。
    因此,当音频信号采样率为 48kHz 的时候,想要得到时长为 10-30ms 的信号帧,其应该包含480-1500 个采样点。
    另外,从分帧后信号的连续性考量,一般在分帧的时候会让相邻的两帧有 30%-50% 的重叠。分帧的实现是简单的,只需要使用 python 支持的数组切片 (slice) 方法即可方便地取出一帧对应的采样点。
    2.3 加窗对于每一帧数据,我们应当强调该帧数据内中间部分的数据,并将边缘的数据进行弱化。我将使用汉明窗

    作为窗函数。

    而所谓的加窗操作也就是用窗函数与一帧内的采样数据相乘


    考虑之后要进行短时傅里叶变换,对每一帧数据进行加窗的理由将更加充分。观察图 2中的一帧余弦信号,可以看到其开始和结束的位置是断开的。而我们在做离散时间傅里叶变换的时候是将该帧数据在时域上无限延拓成周期信号,这将导致延拓之后的信号在帧的开始与结束会发生跳变。直接进行离散傅里叶变换将导致信号泄露的现象。如图 3所示,左边是取出开始和结束连续的一帧信号的离散傅里叶变换的结果,而中间则没有加窗直接进行变换,右边是加了汉明窗再进行变换的结果。可以观察到中间的结果在信号的主要频率周围有明显的泄露现象,导致在原始数据中不存在的频率成分出现在频率域。而增加了汉明窗后,频率泄露的现象有了明显的改善。

    2.3.1 端点检测为了减少非语音的信号对识别的影响,我首先通过信号的时域特征来检测出语音的端点。可以使用短时平均过零率和短时能量来进行端点的检测。
    想要检测出语音信号的端点,最简单的想法就是通过信号的强度来判断,因为包含语音的信号强度会明显高于背景噪声。而短时能量就是刻画信号强度的一个有效的指标。对信号进行分帧之后,y[i : j] 的短时能量定义为

    即帧内信号的平方和。但如果仅仅采用短时能量作为端点检测的指标,我们将很难检测出清音信号,从而导致语音不完全,譬如说单词”Speech” 中开始的清音就无法检测出来。因此我们引入短时平均过零率这个指标

    即该帧内信号通过 0 的平均次数。
    因为无法检测出来的清音一般出现在单词的开始或者结束,所以我们采用以 SE 指标为主、SC 指标为辅的检测策略。首先观察到不少数据在一开始会有类似敲击键盘的的清脆噪声,导致 SE 指标较大,因此我去掉了前五帧信号;然后我设定一个阈值 E0,对于 SE > E0 的帧,可以断定其包含语音信号;取最开始判定为有语音的帧的开始和最末尾有语音的帧的结束作为粗糙的端点检测结果,再根据 SC 指标,设定一个平均过零率阈值 C0,根据粗糙的结果向前、向后扩展 SC > C0 的帧作为包含清音信号的判定条件。

    问题的难点在于阈值的设定,在多次试验后,我选择了 E0 = 0.98, C0 = 0.002 的参数,可以对大多数数据做到较好的端点检测效果。如图 4所示,上方为用红色标出检测结果的波形,中间为短时能量,下方为短时平均过零率。可以看到,如果仅仅使用短时能量进行检测,将无法测出开始的清音,而短时平均过零率的指标则将清音也一并检测出来了。
    2.3.2 快速傅里叶变换为了得到信号的频域特征,需要对每一帧信号进行离散傅里叶变换,即计算

    假设一帧数据的采样点数 N 是 2 的整次幂,那么

    从而

    用 Ek 表示偶数下标子序列的 DFT,Ok 表示奇数下标子序列的 DFT,则 k < N/2 时

    而 k > N/2 时

    这样就可以按照下标的奇偶性将待变换的信号序列拆成两半,递归地进行计算,然后在从递归计算的两个子序列的结果中计算出整个序列的离散傅里叶变换。该算法被称为基 2 的 CooleyTukey快速傅里叶变换。显然该算法计算量为 T(n) = 2T(n/2) + Θ(n)。根据主定理,该算法的时间复杂度为 Θ(n log(n))。
    在递归的过程中,数据的组合与流向的图样像蝴蝶一般对称而美妙,因此被称作蝶形变换。

    我用 python 实现了该算法,并将其利用到后续的梅尔频率域的频谱特征的计算之中。优美的算法通常在实现上也十分简洁。
    2.3.3 梅尔频率域特征梅尔频率域的理论依据来自于人耳听觉对频率的感受。耳蜗相当于一个滤波器组,在 1000hz以下为线性尺度滤波,在 1000hz 以上为对数尺度滤波。通过 fMel = 2595 + log(1 + f/700) 可以将普通频率变换到梅尔频率尺度,观察这个变换的图形会发现在 1000hz 以下会有更高的分辨率,这和人耳对低频信号更加敏感是相符的。在变换之后的梅尔频率尺度取等间隔的带通滤波器组求倒谱即可得到梅尔倒谱。

    对前述通过预加重、分帧、加汉明窗,离散时间傅里叶变换后得到的频谱变换到梅尔频率域,然后施加等间距的三角形滤波器,对滤波后的结果进行求和和取对数操作,即可得到梅尔频率尺度下的功率谱。

    仔细观察该功率谱的结果,对于同一个词来说,在谱上的图样具有明显的图形特征。我们想到可以将其视为图片,然后利用图片的分类技术对语音进行识别。
    传统上的语音识别特征会继续用离散余弦变换求出倒谱系数。余弦变换是傅里叶变换的一个变种,其结果是实数,没有虚部。离散余弦变换还有一个特点是,对于一般的语音信号,这一步的结果的前几个系数特别大,而后面的系数比较小,就可以忽略。这样就可以对特征进行降维,只需要十几个系数即可作为特征。这对于使用传统的模式识别的方法来说特别重要。
    因为无论是支持向量机、高斯混合模型都需要数据的特征在各个维度上是无关的。而不必要的高维度必然导致特征的相关性,从而使得决策面变得扭曲。但使用深度神经网络的方法则不用担心这一点,因为它可以拟合出任意决策面。
    至此完成了对特征的提取,接下来只需要根据特征图样对进行分类即可。
    2.4 识别模型2.4.1 模型构建我使用了 128 个梅尔滤波器,并使用 30ms 作为分帧长度,以及 10ms 的重叠,因此最终得到的图样大小为 128 × 98。
    我仿照 VGGNet 的设置,使用大小为 3 × 3 的卷积核,并构建了 8 层深度的卷积神经网络。因为经过每一层卷积之前都会对图片进行 1 × 1 的补 0 操作,所以对任意大小的图片都可以进行卷积。在经过卷积网络后,我使用一个多层感知器来作为最后的分类器。
    其具体结构如下:

    为了避免过拟合,我对多层感知机的神经元进行概率为 0.5 的 Dropout,并在每一层的卷积操作和非线性函数之间对进行批归一化。
    2.4.2 数据加载考虑到对模型进行训练和测试的复杂性,需要多种数据的加载方式。首先是对数据集进行划分,我需要将一部分同学的所有语音单独拿出来作为测试集,因为最终测试的时候的说话人并不在我们的训练数据中。其次是因为数据量有限,每个词只有不到 600 个的训练数据,为此我对数据进行了交叉验证的划分,采用 10 折交叉的数据划分方式。我利用 pytorch 提供的 Dataset 和 Dataloader 模块,编写了自己的数据加载器。
    2.4.3 模型训练利用 pytorch 提供的自动反向传播,利用交叉熵损失函数作为优化目标,对模型进行了训练。在一台配置为只需要迭代 5 遍测试数据集即可将模型训练至收敛。

    绘制出训练的损失曲线如下图:

    训练结束后,在训练集上能取得 99.5% 的正确率,而对于不在训练集中的说话人,也能取得98.0% 的正确率。说明该模型的确具有非常好的泛化能力。接下来我编写了交互界面,用于进行直接录音测试。
    2.5 识别交互为了方便测试系统的语音识别效果,我基于我之前设计的录音采集系统进行了修改,使得我的系统可以在任何兼容的浏览器上进行测试,避免了为了测试而配置一系列复杂的环境。
    2.5.1 前端界面基于 Web APIs 技术,通过浏览器获取用户的麦克风进行音频录制。完成录制之后通过 JQuery框架使用 ajax 技术进行语音的上传和获取识别结果,再通过 Vue 框架实现的自动绑定,进行结果展示。这样可以实现不用刷新页面即可进行测试的效果,使得使用体验与桌面应用无异。

    2.5.2 服务器端为了能使用训练好的模型进行测试,我利用 flask 编写了服务端。当其接受到前端传回的语音信号后,就会构建模型,并载入训练好的模型参数,然后进行识别。完成识别后,再将结果传回到前端进行显示。
    3 总结在本项目中,我实现了一个识别效果较好的孤立词识别系统。在这一系列过程中,我编写了大量代码,即锻炼了自己的能力,又讲一学期学到的知识真正运用到了实践之中,加深了对知识的印象和理解。
    5 评论 104 下载 2019-04-18 11:28:25 下载需要12点积分
  • 基于JAVA和SQL SERVER数据库实现的人力资源管理系统

    一、系统开发平台1.1 介绍人力资源管理系统, 通过提高内部员工的满意度、忠诚度,从而提高员工贡献度,即绩效,帮助管理者通过有效组织管理降低成本和加速增长来创造价值链利润。随着企业的规模不断扩大,员工数量急剧增加,有关员工的各种信息量也成倍增长。面对庞大的信息量需要有人力资源管理系统来提高员工管理工作的效率。一个完善的人力资源信息管理系统能够极大地提高员工信息管理的效率。
    1.2 开发环境
    开发语言:Java

    用Java做设计流程清晰、结构合理,有良好的可扩充性和耦合性
    开发工具:Eclipse V4.5.0 JDK 1.8
    数据库:Microsoft SQL Sever 2012
    操作系统:Microsoft Windows 10

    二、数据库规划2.1 任务陈述人力资源管理系统是一个企业不可缺少的部分,它的内容对于企业的决策者和管理者来说都至关重要。随着企业的规模不断扩大,员工数量急剧增加,有关员工的各种信息量也成倍增长。面对庞大的信息量需要有人力资源管理系统来提高员工管理工作的效率。一个完善的人力资源信息管理系统能够极大地提高员工信息管理的效率,具有检索迅速、查找方便、可靠性高、存储量大、更新快、寿命长、成本低等优点。
    企业在正常的运营中需要对员工档案信息、部门资料、企业报表进行管理,利用人力资源管理系统及时了解各个环节中信息的变更,有利于提高管理效率。
    2.2 任务目标本系统主要可以实现以下任务目标:

    系统在员工进入公司时为员工建立人事档案,人事档案应该包括:

    员工基本信息:编号、姓名、性别、邮箱、电话、员工进入公司的时间、员工级别、员工所在部门和员工级别等员工技能情况:员工接受的培训、具备的技能等
    员工的工资应该包括基本工资和奖金两个部分:

    基本工资根据员工的级别划分(试用员工、普通员工、组长、部门经理、总经理)奖金应根据员工的业绩由其直接或更高级领导确定
    员工在来到公司上班时应该首先登录公司系统签到,离开公司时登录系统签离。如果办事外出或者出差应由上级领导确认考勤情况。缺勤或者迟到按一定数额罚款,迟到2小时以上算缺勤
    员工离职应保留员工的历史信息,以备日后查询
    系统还应该提供强大数据统计、查询、报表生成以及打印等功能
    用户权限管理
    异常处理

    三、需求分析3.1 用户需求说明3.1.1 数据需求公司有一名总经理,多名试用员工、普通员工、组长、部门经理。总经理负责公司的管理,部门经理与组长负责按级别管理员工,分配工作,管理员负责更新信息。
    职工号在公司内唯一。

    员工基本信息:职工号、密码、姓名、性别、邮箱、电话、员工进入公司的时间、员工职位级别(FK)、员工所属部门(FK)、是否离职
    公司部门:部门号、部门名字、部门经理
    公司职位:职位号、职位名、职位级别、部门号(FK)
    员工工资:职工号、职位级别、基本工资、业绩等级、奖金
    培训表:培训号、培训名、培训描述
    技能表:技能号、技能名、技能描述
    培训联系:员工号、培训号、培训名、成绩
    技能联系:员工号、技能号、技能名、熟练度

    员工在来到公司上班时应该首先登录公司系统签到。缺勤或者迟到按一定数额罚款,迟到2小时以上算缺勤。由管理员定时统计签到情况。

    签到表:职工号、年份、月份、日期、时刻、是否迟到
    考勤表:职工号、迟到次数、缺勤次数、罚款数

    3.1.2 事务需求
    管理员

    数据录入

    录入新员工基本信息录入公司部门信息录入职位信息录入员工业绩工资信息录入员工受培训信息录入员工技能信息录入员工考勤情况
    数据更新

    更新/删除员工基本信息更新/删除公司部门信息更新/删除职位信息更新/删除员工业绩工资信息更新/删除员工受培训信息更新/删除员工技能信息更新/删除员工考勤情况
    数据查询

    查询员工基本信息查询公司部门信息查询职位信息查询员工业绩工资信息查询员工受培训信息查询员工技能信息查询员工考勤情况查询员工签到情况

    员工

    查询员工基本信息查询公司部门信息查询职位信息查询员工业绩工资信息查询员工受培训信息查询员工技能信息查询员工考勤情况查询员工签到情况进行签到修改下级员工的工资

    3.2 系统需求说明3.2.1 初始数据库大小
    大约有1000名员工,分属于约20个部门中,每个部门有5个以下的职位
    公司提供10余种培训,员工最多可选择5种
    员工技能10余种,每人最多5种
    很多考勤条目

    3.2.2 网络和共享需求
    所有部门必须安全的和总部中央数据库网络互连
    必须能够支持至少100名成员同时访问.需要考虑大数量并发访问的许可需求
    3.2.3 性能单个记录查询时间少于1秒,高峰期少于5秒
    多个记录查询时间少于5秒,高峰期少于10秒
    更新/保存记录时间少于1秒,高峰期少于5秒

    3.2.4 安全性
    数据库必须有口令保护
    每个用户分配特定的用户视图所应有的访问权限
    用户只能在适合他们完成工作的需要的窗口中看到需要的数据

    3.2.5 备份和恢复
    每天24点备份
    用户界面

    菜单驱动联机帮助
    法律问题

    对员工信息管理,遵守法律

    四、数据库逻辑设计4.1 ER图
    该ER图包括员工、部门、职位、工资、培训、技能、考勤七个实体和工作于、包含、属于、得到、选择、拥有、进行七个关系。
    4.2 数据字典4.2.1 系统实体描述员工表



    属性
    描述
    数据类型和长度
    是否允许空值




    Employee_id
    职工号
    Varchar 50



    Password
    密码
    Varchar 50



    Sex
    性别
    Varchar 2



    Name
    姓名
    Varchar 50



    Position_rank
    职位级别
    Int 4



    Branch_id
    部门号 (外码)
    Varchar 32



    Position_id
    职位号 (外码)
    Varchar 32



    Email
    邮箱
    Varchar 50



    Phone
    电话
    Varchar 50



    Hiredate
    入职时间
    Varchar 50



    Service_state
    是否离职
    Varchar 2




    部门表



    属性
    描述
    数据类型和长度
    是否允许空值




    Branch_id
    部门号
    Varchar 50



    Branch_name
    部门名
    Varchar 50



    Manager_id
    经理职工号 (外码)
    Varchar 50




    职位表



    属性
    描述
    数据类型和长度
    是否允许空值




    Position_id
    职位号
    Varchar 50



    Position_rank
    职位级别
    Int 4



    Position_name
    职位名
    Varchar 50



    Branch_id
    部门号 (外码)
    Varchar 50




    培训表



    属性
    描述
    数据类型和长度
    是否允许空值




    Course_id
    培训课程号
    Varchar 50



    Course_name
    培训课程名
    Varchar 50



    Course_detail
    培训描述
    Varchar 128




    技能表



    属性
    描述
    数据类型和长度
    是否允许空值




    Skill_id
    技能号
    Varchar 50



    Skill_name
    技能名
    Varchar 50



    Skill_detail
    技能描述
    Varchar 128




    工资表



    属性
    描述
    数据类型和长度
    是否允许空值




    Employee_id
    职工号
    Varchar 50



    Position_rank
    职位级别
    Int 4



    Base_salary
    基本工资
    Int 4



    Achievement
    业绩级别
    Varchar 50



    Bonus
    奖金
    Int 4




    考勤表



    属性
    描述
    数据类型和长度
    是否允许空值




    Employee_id
    职工号
    Varchar 50



    Late
    迟到次数
    Int 4



    Absence
    缺勤次数
    Int 4



    Fine
    罚款数额
    Int 4




    签到表



    属性
    描述
    数据类型和长度
    是否允许空值




    Employee_id
    职工号
    Varchar 50



    Year

    Varchar 50



    Month

    Varchar 50



    Day

    Varchar 50



    Time
    时间
    Varchar 50



    Late
    是否迟到
    Varchar 50




    4.2.2 从数据字典中抽取出来的联系的描述:


    实体
    多样性
    联系
    多样性
    实体




    员工
    m
    工作于
    1
    部门


    员工
    m
    属于
    1
    职位


    员工
    m
    选择
    n
    培训


    员工
    m
    拥有
    n
    技能


    部门
    1
    包含
    m
    职位



    4.3 关系表
    五、应用程序设计5.1 功能模块5.1.1 管理员
    登录系统
    查询员工基本信息、公司部门职位、员工技能培训、员工工资、签到考勤信息
    添加以上信息的新条目
    修改以上数据
    定时查询签到表并对员工迟到缺勤情况进行更新

    5.1.2 员工
    登录系统
    查询以上信息
    签到并查询签到和考勤情况
    根据职位级别赋予修改下级员工奖金的权限

    5.2 界面设计5.2.1 登录根据职位等级,管理员与用户账号进入的界面不同,操作权限也不同。

    若用户名或密码为空。

    若用户名不存在。

    若密码错误。

    5.2.2 用户界面填写上方条件进行查询。

    不填写条件则默认为查询整个表。


    只能修改下级员工的奖金。

    每天签到一次,第二次不再更新时间。

    5.2.3 2.管理员界面管理员可以添加修改信息。



    管理员定时进行员工迟到缺勤情况的考勤并罚款。

    六、总结6.1 经验体会本次课程设计使我深切体会到了知识面狭窄的弊端,痛心地吸取了教训。由于对网页程序的编写一窍不通,此前也没有学习过任何有关html、css等的相关知识,我对开发网页数据库界面的信心不足,导致我最终只编写出一个连接了数据库的Java程序,采用了Java自带的图形界面功能,既不美观也不方便用户使用,我对此感到十分惭愧难过。
    但在为期两周的设计过程中,我也学习到了不少技巧。例如,设计数据库应该实事求是,与时俱进,妄想一次性将理论设计完成、写完文档再去实现功能代码是不正确的,应该一边编写一边修改,逐渐将程序和文档都完善起来。但是一味地进行实践而不去分析理论也是不可行的,最基本的要做到按照老师给的设计提纲,先进行目标明确,任务分析,再是需求分析,ER图,关系表,然后才是数据库逻辑设计,数据库物理设计,最后是应用的实现与完善。把握好用户需求,并不断地修改完善,才能设计开发出优秀的软件。
    6.2 系统特色本程序基本实现了人力资源管理中所应用的大体功能。对于用户来说可以查询本公司各部门各职位各个职员的基本信息、工资情况、签到考勤等,上级职位等级还可以决定下级员工的奖金情况。对于管理员具有各种查询修改添加信息的权限,并进行签到考勤评测。
    主要倾向于统计和展示人力资源的基本信息,界面简洁清晰,操作简便明了。
    6.3 系统完善系统除了展示添加修改信息与签到考勤外没有其他的功能,用作公司的人力资源管理系统尚显不足。如果需要完善,应添加信息注销删除、工资发放、出差安排、职位部门调动、报表生成以及打印、权限管理及异常处理等功能。
    7 评论 377 下载 2018-11-26 21:51:34 下载需要11点积分
  • 基于C#和SQL SERVER的汉字词典的设计与实现

    摘 要汉字的发展历史悠久,从甲骨文到到象形文字,再到简体中文。经历了不少变革。汉字词典不仅做为学习的工具,也是记录历史的史册。从《康熙字典》到《现在汉语字典》,短短百年收录的内容就已经发生了巨大的变化。不仅字典的内容有增删调整。汉字词典的形式也发展到多种多样。在互联网世界的今天衍生出Web版的汉字词典。
    基于Web的汉字词典是可通过互联网访问,根据用户输入的内容给出查询结果的程序。是一个让用户便于认识、学习和查找汉字词的工具。目的是让认识,学习汉字的人能在忘记汉字一些信息的时候方便快速的查找出想要的结果。
    用户通过输入要查询的汉字或词语,系统自动识别是查询汉字,还是查询词语。有助于加快查找速度。支持汉字词,成语,拼音以及汉字拼音的混合查询,同时支持部首的查询。输入汉字给出的查询结果包括但也未必包括:汉字书写笔顺GIF动态图,拼音,拼音读音MP3,部首,笔画,释义,相关词语。输入词语给出的查询结果包括但也未必包括:拼音,读音MP3,解释,相关词语。同时拥有管理员功能,管理员通过入口,输入自己的口令登录之后,可对汉字词语进行修改编辑操作,查看近期查找的热词的数量变化,也可对当年新生的流行词语进行收录。
    基于微软.NET Core框架开发,使用C#编程语言,SQL Server数据库,Visual Studio 2015集成开发环境。使用Entity Framework Core,结合仓储模式,创建数据库访问层。利用分词及汉语拼音识别算法自动分解出可能的汉字或词语。后端管理系统采用Vue.js框架结合Web API创建单页面应用程序。实现对汉字词语的基本操作。基于MathJax支持对LaTex语法的识别,实现对汉字词语解释更加丰富的展示。
    关键词:汉字;拼音;词典;Web
    AbstractThe development of Chinesecharacters has a long history, from oracle bones to hieroglyphics, and tosimplified Chinese characters. It has undergone many changes. The Chinesecharacter dictionary is not only a tool for learning, but also a record of theannals of history. From the “Kangxi dictionary” to “the presentChinese Dictionary”, the content that has been changed in just a fewhundred years has undergone tremendous changes. Not only the content of thedictionary is added and deleted. The form of the Chinese character dictionaryhas also developed into many kinds. In the Internet, the Web version of theChinese character dictionary is derived.
    A Chinese characterdictionary based on Web is a program that can be accessed through the Internetand given query results according to the input content of the user. It is atool for users to understand, learn and search Chinese characters. The purposeis to let people who know and learn Chinese characters can quickly and easilyfind the desired results when they forget some information about Chinesecharacters.
    By inputting Chinese charactersor words, the system automatically identifies whether to query Chinesecharacters or query words. Helps to speed up the search. Support Chinesecharacters words, idioms, Pinyin and Pinyin mixed query Chinese characters,while supporting the radical query. The search results include input Chinesecharacters but also does not necessarily include: Chinese characters writingGIF dynamic map, Pinyin, Pinyin pronunciation MP3, radicals, strokes,interpretation of related words. The input words include, but may not include,Pinyin, pronunciation, MP3, interpretation, and related words. At the same timehave administrator function, the administrator through the entrance, then enteryour password login, modify the edit operations of Chinese characters words,changes in the number of view the recent hot words search, can also be popularwords to the new year are included. Based on Microsoft.NET Core framework development, the use of C#programming language, SQL Server database, Visual Studio 2015 integrateddevelopment environment. Create a database access layer using Entity,Framework, Core, and warehouse mode. The Chinese characters or words can beautomatically decomposed by using the word segmentation and the Chinesephonetic recognition algorithm. The back end management system uses the Vue.jsframework and combines Web API to create a single page application. Realize thebasic operation of Chinese words and phrases. MathJax based support for theidentification of LaTex syntax, to achieve more rich interpretation of Chinesewords and expressions.
    Key Words: Chinese character; Pinyin; Dictionary; Web
    第1章 绪论1.1 背景汉字,是世界上历史最悠久的著作之一。即使是在3000年前的商代,甲骨文的碑文,一个发达的书写系统,已经存在于中国。专家学者的调查及研究表明:6000 年前仰韶文化出土的大量陶器铭文是已发现的中国最古老的文字。
    在远古时代,中国有一个非常流行的神话叫做 “仓颉造字”。根据这个神话,在5000年前,黄帝的历史编年史家,被动物的足迹启发,并理解不同的版画可以看作是区分不同对象的标记,所以他发明了许多不同的符号分别来代表不同的事物,它们是最古老的汉字。当然,这只是一个有趣的神话。任何形式文字的出现和形成,都需要一个漫长的过程,不能由个人发明。从科学的角度看,汉字是中华民族的人们在长久的生活中积聚创造出来的。
    在悠久的历史长河中,汉字经历了几次进化,才演变到现在的形式。
    人类对于汉字的学习离不开字典,《康熙字典》是18世纪至19世纪的标准汉语词典。清朝康熙皇帝在1710年下令编纂,1716年出版。
    虽然字典包含超过47,000个汉字,但现在这些汉字中不到四分之一是常用的。《康熙字典》的编辑,包括张玉书,陈廷敬,部分基于两个明代词典:梅应作在1615年编纂的《字汇》,以及在1627年由张自烈编纂的《正字通》。由于康熙皇帝要求五年内编制完成《康熙字典》,所以错误是不可避免的。道光皇帝时期成立了审查委员会,他们的1831年“字典考证”纠正了2,588个错误,其中大部分是引文。
    补充字典共包含47,035个汉字条目,加上1,995个图形变体,共有49,030个不同的字符。它们按部首分为214组,并按汉字中的附加笔画数排列。虽然这214个部首在《字汇》中首次使用,由于康熙字典的普及,它们被称为康熙部首,并保持在现代使用,作为一种方法来分类传统汉字。
    康熙字典有许多形式,从清代封印版到转载中国书籍,到西式精装书的现代修订版,到数字化的互联网版。
    在互联网时代,基于Web端的汉字词典也是必不可少。因为字典一般被当作工具书使用,除了专业工作者,很少有人会在触手可及的地方放置一本汉字词典。为了满足人们在不经意间遇到生字生词的时候能够快速查阅。能够在奋笔疾书的时候不至于因想不出合适的词汇而打断思路。基于Web的汉字词典应运而生。
    1.2 现状基于Web的汉字词典在国内的发展可以说种类繁多,各式各样的都有。但大多界面繁杂,广告肆意摆放,充满商业气息。也难怪,此类工具性的网站,做出来之后也全当公益性服务了。从这里面获取利益的机会是渺小的。也只有百度汉语做的最为出色。一部分原因应该就是公司规模庞大,做出百度汉语一方面算是回报社会,另一方面向自己公司的其他产品导流。百度作为目前国内最大的搜索引擎,有用庞大的中文资源以及中文信息处理的技术。将百度汉语结合其搜索引擎以及百度百科,使搜索结果更为丰富。
    随着中国国际地位的提升,“汉语热”也早已遍布全球各个国家和地区。国外的汉语词典类网站大多是便于用户结合当地语言来学习和认识汉语。因此作为常规使用的汉字词典也能满足基本需求。
    1.3 主要内容基于Web的汉字词典分为前台汉字词典查询系统和后台管理系统两大部分,其中前台部分主要提供给普通查询汉字词的用户使用,后台系统为管理员修改词库所用。
    前台系统主要用户查询汉字词,给出查询结果,其中查询方式支持汉字查询,词语或成语查询,纯拼音查询,汉字拼音混合查询以及语义化部首查询。
    汉字查询:只针对单个汉字进行查询,查询结果显示汉字的信息,若无匹配的结果,则显示推荐结果。
    词语或成语查询:对两个汉字以上的词语或成语进行查询,查询结果显示词语或成语的信息,若无正确结果,则显示推荐结果。
    纯拼音的查询:对使用英文字母代替的拼音进行查询,例如:“women”。自动查找可能匹配的汉字或词语,给出推荐结果。
    汉字拼音混合的查询:对与只会写部分汉字的词语进行插叙 ,例如:“严jin”。自动查找可能匹配的词语,给出推荐结果。
    语义化部首查询:对于键盘难以输入的部首,直接通过输入部首读音进行查询,例如:“所有提手旁的汉字”,就会给出能识别的偏旁部首的所有汉字。
    1.4 组织结构本设计主要包括正文,参考文献,致谢,外文原文及翻译,任务书,开题报告,程序源代码等部分。

    第1章,绪论:介绍了此系统的开发背景,国内外开发现状,主要内容以及组织结构等。第2章,.NETCore相关技术:说明了此系统开发时使用的主要技术点。第3章,可行性与需求分析:从各方面分析了此系统开发的可行性,以及功能等需求的分析。第4章,数据模型的分析与创建以及数据抓取的研究与实现:建立了系统的数据模型,抓取数据,为系统提供数据基础。第5章,汉字词典的设计与实现:主要介绍了此系统前台部分的实现,以及各个查询方式的实现描述。第6章,汉字词典后台管理系统的设计与实现:介绍了面向管理员开发的对词库的管理系统。第7章,主要对系统进行功能测试及修复。通过测试用例发现并解决问题。
    1.5 本章小结本章描述了汉字的发展,及汉字词典在汉字的发展过程中起到的巨大作用。结合国内外发展情况确定了本设计的实现目标,开发出人人可用的基于Web的汉字词典。
    第2章 .NET Core相关技术2.1 .NET Core自.NET框架的第一个版本发布以来已经有16年多了。 尽管开发者社区得到广泛的采用,今天“移动为先,云为先”需要轻量级的跨平台技术来构建应用程序。 .NET Core是Microsoft的.NET技术演进到一个模块化,跨平台,开源和云就绪平台,运行在Windows,macOS,Android,IoT和Linux上。 轻量级的.NET Core框架提供比某些竞争技术更快的性能。 .NET核心的目的是为所有类型的应用程序(包括Windows,跨平台和移动应用程序)提供统一的平台。 .NET标准库通过提供每个应用程序模型所需的共享基本API,并排除任何应用程序模型特定的API来实现此目的。

    .NET Core和.NET平台之间有相似之处和差异。 两者都实现.NET标准库,并支持ASP.Net Core和EF Core。 .NET框架将继续成为开发Windows应用程序的平台。 实际上,您可以将.NETFramework和.NET Core代码和谐地融合在同一解决方案中,例如WinForms应用程序消耗.NET Core上编写的服务。



    处处运行
    在Windows,Linux和macOS上运行




    完全开源
    在GitHub开放库,编译器,语言和工具。 授权模式:源代码(MIT),二进制(Microsoft EULA)


    模快化部署模式
    通过NuGet以较小的以功能为中心的软件包发布,而不是一个包含大部分核心功能的大型组件。 只需要使用应用程序所需的模块


    中间件管道是完全可插拔和可更换的
    依赖注入是从基础到框架构建的。 日志记录基础设施可从基础插入,即启动到API级别。 消息传递基础设施允许您使用内置消息传递或插入其他开源解决方案(如RabbitMQ)


    更快更安全的应用程序
    具有较小的应用程序表面积可实现更严格的安全性和改进的性能。 TechEmpower执行的基准测试表明,.NET内核的性能比其他某些竞争技术要快的多



    目前,.NET Core支持Console,ASP.Net Core,类库,通用Windows应用程序(UWP)和XamarinForms等等。随着Microsoft增加对更多应用程序模型的支持,此列表将继续增长。
    工具支持。命令行接口,.NET Core命令行界面(CLI)是开发.NETCore应用程序的新型基础跨平台工具。 该基础层可用于创建更高级别的工具和IDE。 CLI在所有支持的平台中提供相同的功能,以提供统一的体验。Visual Studio 2017:.NET Core工具集成到Windows和macOS版本的VisualStudio 2017中。 Visual Studio 2017提供了许多内置的模板,用于创建支持的应用程序模型,包括ASP.Net Core,类库,UWA和控制台应用程序。ASP.Net核心模板还提供了选择.NET Core framework 1.0或1.1的选项。 当您在Visual Studio中打开使用旧版本创建的.NETCore项目(即具有project.json的项目)时,它会自动检测更改,并提供单向迁移到较新的.csproj基础结构。
    .NETCore提供了灵活的部署模式。框架相关部署(FDD):在依赖于框架的部署中,仅安装了应用程序和第三方依赖关系。 该应用程序取决于系统范围的.NET Core版本。自包含部署(SCD):在自包含部署中,用于构建应用程序的.NETCore版本也与应用程序和第三方依赖关系一起部署,并可与其他版本并行运行。
    .NETCore支持容器技术,即将.NET Core运行在某一隔离的环境中。并与Docker镜像配合使用。 DockerHub可以轻松获得三个Docker镜像。 开发环境镜像是通过代码更改快速迭代并调试更改的理想选择。构建镜像旨在用于连续集成/构建环境中,包括编译器和任何其他依赖关系,以优化二进制文件。 生产环境是快速部署和启动时间的小镜像。 Visual Studio集成了Docker的支持,用户可以右键单击项目并添加Docker支持。
    .NETCore是Microsoft .NET平台的未来,采用该技术可以帮助您创建云就绪的跨平台应用程序。 新应用程序开发的一般指导是使用.NET Core,如果存在应用程序模型。 对于现有应用程序,.NET便携式分析工具将会方便地确定程序集到目标平台的可移植性,并帮助您完成迁移决定。
    2.1.1 依赖注入依赖注入(DI)是实现对象与其协作者或依赖关系之间松散耦合的技术。 为了执行其操作,类需要的对象不是直接实例化协作者,或使用静态引用,而是以某种方式提供给类。 大多数情况下,类将通过它们的构造函数来声明它们的依赖关系,允许它们遵循显式依赖原则。 这种方法被称为“构造器注入”。
    ASP.NETCore包括一个简单的内置容器(由IServiceProvider接口表示),默认情况下支持构造函数注入,ASP.NET通过DI提供某些服务。 ASP.NET的容器是指它作为服务管理的类型。 在本文的其余部分中,服务将引用由ASP.NET Core的IoC容器管理的类型。 您可以在应用程序的启动类中的ConfigureServices方法中配置内置容器的服务。
    2.2 Entity Framework CoreEntity Framewotk(EF)是一个对象/关系映射(O/RM)框架,是开发与数据交互的应用程序的一套技术。 .NET开发人员花费大量时间跟上数据库更改。Entity Framework提供从关系数据库模式到对象的映射,并提供抽象。在Entity Framework中,可以定义独立于数据库结构的实体类,然后将其映射到数据库的表和关联。 由于我们现在正在使用具有自己的架构的实体,所以我们可以避免数据库的变化。 对象上下文保留对已更改实体的标签。Entity Framework提供从面向数据库(DataReader,DataSet)到面向模型开发的转变。 因此,开发人员专注于代表应用程序业务模型的实体,而不是专注于数据库。
    EF Core是EF的主要演变,从EF6转向EF Core不是“升级”,它是一种“移植”。EF Core运行无处不在,EF Core支持每个平台的默认提供程序(即SQL Server for Windows,SQLitefor devices,Postgres / MySQL for macOS / Linux)。EF Core支持新的数据存储(关系和非关系)EF是最流行的ORM,目前包括使用WPF,WinForms和ASP.NET等技术构建的应用程序。 在未来,微软决定支持.NET开发常见的剩余平台。 这包括Windows Store,Windows Phone和Cloud Optimized.NET。 实EntityFramework与关系数据存储显然相关。 现在,EF还为非关系数据存储提供了很大的支持。 关系和非关系,如Azure表存储。EF Core是轻量级和可组合的,EF Core将考虑到内存和CPU使用。 而不是使用现有的Entity Framework 6 API,团队决定从头开始。 您只能使用对您的项目有用的扩展。使用Entity Framework的模式和概念保持不变。 你可以继续使用你当前正在使用的DbContext / DbSet。 可扩展的优点是可以替换和扩展它。EFCore增强了对单元测试的支持, EF Core支持内存供应商进行单元测试。
    2.3 C#编程语言2.3.1 基于任务的异步编程模型摩尔定律预言,每平方英寸集成电路的晶体管数量每两年就会提高一倍。戈登ž摩尔在20世纪60年代中期宣布和预测这一趋势将持续至少10年,但是摩尔定律实际上已经适用了将近50年。摩尔定律的预测常常被解释为处理器速度每隔几年就会翻一番。然而,摩尔定律的地基开始出现裂缝。开发人员现在必须找到满足客户需求的其他手段以实现更快的应用。并行编程是一种解决方案。这样,摩尔定律将在无限的未来继续有效[12]。
    线程代表程序中的行为,进程本身什么也不做。相反,它承载正在运行应用程序说消耗的资源,比如堆和栈。线程是应用程序中一种可能执行的执行路径。
    线程能够执行独立的任务或者配合相关任务的操作。并行应用程序也是并发的,然而,并不是所有的并发应用程序都是并行的。并发应用能够在单内核上运行,而并行执行需要多核。
    并行编程的目标是跨所有可用的处理器内核进行工作量的负载均衡以得到最大的CPU使用率,随着多核环境中处理器数量的增加,应用程序性能应该会提高。但是,因为其他因素可能会影响性能,所以增长比例小于内核数量的线性增长。
    ​ 在.NET Framework 4中,随着任务并行库的引入(TPL)的引入,微软已经将并行编程提升为一个核心技术。并行编程还被添加到LINQ,称为并行LINQ(PLINQ)。
    任务是并行编程的基本要素。任务并行是任务跨几个处理器的并行执行。并行任务通常有很多输入,在任务并行模式中,并行任务通常应用于相关数据集合。任务在线程上运行。线程是应用程序的引擎,代表正在运行的代码。Windows操作系统按照优先权调度线程。线程被分配一个可调整的优先权,一般而言,他们基于线程优先权,以一种轮转的方式调度。下面是线程优先的一些原因:

    线程已经超过其时间片或配额。
    较高优先级的线程启动。
    线程进入等待状态。
    有输入/输出操作发生。

    在.NET Framework中,Task类是任务的逻辑抽象。可以使用这个类来调度并最终执行并行任务。在默认情况下,线程池调度任务,将其放入线程池中的队列,最后在一个可用的线程上执行该任务。
    使用Parallel.Invoke方法:Paravalel.Invoke(newAction[] { MethodA, MethodB });Pavallel.Invoke对并行运行多个任务很方便,但是也有自己的不足:

    Parallel.Invoke新建但不返回Task对象。
    Action委托是有限制的,它无参数,也没有返回值。
    Parallel.Invoke并不像其他解决方案那么灵活,并且始终使用一个隐含的Task.WaitAll方法,直到所有的提供的任务执行完毕之后才返回。

    使用Task.Factory.StartNew方法:TaskFactory类是任务调度程序的一个抽象。在Task类中,Factory属性返回任务工厂的默认实现。任务工厂使用.NET Framework 4 线程池。
    var taskA = Task.Factory.StartNew(MethodA); var taskB =Task.Factork.StartNew(MethodB);
    使用Task.Wait方法明确的等待一个任务。Task.Wait是一个实例方法。等待任务的线程被认为是一个连接线程。如果任务已经完成,Task.Wait会立即返回。否则,该连接线程将会一直等待(阻塞),直到任务结束。
    taskA.Wait();
    使用Task.Start方法:通过新建一个Task对象并调用Task.Start方法。此方法的优点是,可以在启动任务前,在Task构造函数中配置该任务。
    具有返回值的任务:对于任务,可以使用Fun\<TResult\> 委托,其中Tresult是返回类型。当任务完成时,可以使用Task\<TResult\>.Result属性访问
    async/await是在C#的第5个版本添加的一对儿关键字,为开发并行程序提供了不少的方便。通常使用async修饰符声明的,可以包含await表达式的方法或匿名函数(匿名函数包括Lambda表达式或匿名方法)的方法被称为异步函数[1]。对于异步函数,如果表达式等待的值还不可用,那么异步函数将立即返回;当该值可用时,异步函数将(在适当的线程上)回到离开的地方继续执行。此前“在这条语句完成之前不要执行下一条语句”的流程依然不变。只是不再阻塞[1]。
    2.4 本章小结本章主要介绍了设计中运用到的框架及部分技术。其中.NET Core,Entity Framework Core为设计提供了实现基础。C#编程语言中的相关知识也是必须要掌握的。
    第3章 可行性研究与需求分析3.1 可行性研究1.经济可行性
    此系统采用微软公司的.NET Core框架进行开发,需要的环境以及工具包括:Windows操作系统,.NET Core SDK,Visual Studio 2015/2017,操作系统为电脑OEM厂商自带。.NET Core为微软开源框架,可以免费使用,Visual Studio 2015/2017为微软提供的免费社区版。因此经济上的开销可以忽略不计。此系统完成之后,需要部署到服务器,在云时代,自然是选择最方便快捷的云服务。因此购买一台云服务器会产生一定的开销。由于各大云服务器供应商均提供了学生优惠套餐,所以对于学生来说加个也是完全可以接受的。
    2.技术可行性
    虽然.NET Core是一个全新的框架,目前国内尚未出版广受好评的书籍。如果本身对.NET Framework技术栈比较了解,同时进行过常规的ASP.NET MVC开发,另一方面,微软的技术文档一直保持着业界最高水准,所以通过简单的熟悉文档,新手练习了.NET Core的新特性,所以能很快上手。反而是感觉比传统的ASP.NET MVC跟简单上手。
    开发一般的应用程序技术上没有问题。但一些不确定因素还是存在的,截止到目前为止,.NET Core还在不断完善当中。部分由于微软的决策,删去了部分ASP.NET MVC中拥有的API。还有.NET Core是跨平台的,所以可能之前在Windows中未遇到过的问题,在Linux或macOS中就会暴露出来。比如之前使用过一个解析Markdown的类库。在Windows中是没问题的,但是在Linux中就会出现解析失败。最终调试发现是因为Windows和Linux的换行符导致的。
    3.2 需求分析1.功能概述:
    基于Web的汉字词典包括两个模块。一个是面向广大普通使用者,另一个是面向系统运营这的后台管理系统。
    主要功能包括:

    单个汉字的查询:输入汉字之后,返回汉字的笔顺,笔画,拼音,读音,解释,相关组词等等信息。
    词语的查询:输入词语或成语,返回词语的拼音,读音,解释,相关词语等等。
    拼音的查询:数据一个汉字的拼音,或词语的拼音。多个词的拼音可连续输入,将自动识别。例如,wo men可直接输入women。但是对于有歧义的拼音要使用“’”(右单引号)分割,例如tiangao,要明确指定分割:chan’gao或者chang’ao。
    拼音和汉字的混合查询:例如:严谨,只知“严”,而不知“谨”如何写,可输入“严jin”查询。
    部首的查询:可任意输入一句有关查询部首的句子,或直接输入偏旁的读法,例如:“查找所有带提手旁的汉字”,“所有部首是三点水的汉字”。

    后端管理功能包括:

    汉字:浏览所有汉字,查找汉字,编辑汉字信息,删除汉字。
    词语:浏览所有词语和成语,查询词语,编辑词语信息,删除词语。
    热词查看:查看最近最高查询量走势。
    收录词汇:收录汉字,添加汉字,拼音,拼音MP3,部首,笔画数,笔顺GIF,释义以及释义的LaTeX语法支持。收录词语,拼音,拼音MP3,释义,以及释义的LaTeX语法支持。


    3.3 本章小结本章主要分析了设计从多方面实现的的可行性。在确实可行的前提下,进行需求分析,确定设计实现的主要功能。
    第4章 数据模型的分析与创建以及数据抓取的研究与实现4.1 数据模型的分析与创建通过分析基于Web的汉字词典,最终向使用者所展示的就是汉字的信息,和词语的信息。
    根据所取得的《现代汉语字典》的数据来看,汉字主要包括:汉字,拼音,解释。
    词语主要包括:词语,解释。但是如果只有这些数据是远远不能满足使用者的要求的。因此,通过搜索其他汉字词典网站。分析其他网站的数据信息之后,决定将《现代汉语字典》作为种子数据,从百度汉语上抓取汉字和词语的其他信息。以丰富此系统数据的完善性。百度汉语中的汉字包括:汉字,汉字拼音,读音MP3,部首,笔画,笔顺GIF图片,释义等。词语包括:词语,拼音,读音MP3,释义等。在数据可靠的前提下,分析百度汉语Web端HTML结构,确定抓取数据的可行性。好在并没有采用反爬虫措施,遂迅速建立数据模型如下:
    汉字数据模型



    属性名称
    数据类型
    说明




    CharacterID
    Int32
    ID


    Character
    String
    汉字


    Phonetic
    String
    拼音


    PhoneticURL
    String
    读音MP3链接


    Radical
    String
    部首


    Strokes
    Int32?
    笔画数


    OrderOfStrokesGIFURL
    String
    笔顺GIF图URL


    Explanation
    String
    释义


    ReferenceID
    Int32
    引用汉字ID


    ReferenceCharacter
    String
    引用汉字


    Remarks
    String
    备注



    词语数据模型



    属性名称
    数据类型
    说明




    WordID
    Int32
    词语ID


    CharacterID
    Int32
    开头汉字ID


    Word
    String
    词语


    Phonetic
    String
    拼音


    PhoneticURL
    String
    读音MP3链接


    Explanation
    String
    解释


    ReferenceID
    Int32?
    引用词语


    ReferenceWord
    String
    引用的词语



    因为从《现在汉语字典》和百度汉语中获取到的数据,其汉字和词语的拼音,均是带有声调的。所以在普通使用者查询汉字或词语的时候,去输入带有声调的拼音很是不方便。因此需要使用纯英文字母,表示拼音,将无声调的纯英文字母表示的拼音与带有声调的拼音关联起来,通过搜索查找找到在线汉语词典具有此类数据。通过分析其数据可靠性及HTML结构的可获取性,决定同样采用数据抓取的方式,获取其数据。
    拼音数据模型



    属性名称
    数据类型
    说明




    PhoneticID
    Int32
    拼音ID


    PhoneticRaw
    String
    使用英文字母代替拼音


    PhoneticTone
    String
    带有声调的拼音。



    历史记录数据模型



    属性名称
    数据类型
    说明




    ID
    Int32
    ID


    SearchWord
    String
    搜索的字词


    Count
    Int32
    搜索的次数


    SearchDateTime
    DateTime
    搜索日期



    4.2 数据库关系数据库关系图

    汉字结构E-R图

    词语结构E-R图

    拼音结构E-R图

    历史记录结构E-R图

    4.3 数据抓取技术的介绍与实现数据抓取的方式和数据的来源多种多样。互联网是开放的,因此通过互联网抓取数据是最常见的方式。实际上就是通过编写的一段自动化采集网站数据的程序。
    实现Web数据抓取需要掌握的技术包括:

    任意一门具备网络请求API的开发语言,如:C#,Java,Python,C++等。网页前端:HTML,JavaScript,CSS,浏览器开发工具。HTTP协议,正则表达式,数据库,代理切换等。多线程并发抓取,任务调度,消息队列,分布式爬虫,图像识别等等。
    对于基本的爬虫程序,只需要前三点即可。对于更高级的爬虫和更高效稳定的性能需要掌握第四点。
    爬虫程序通过模拟真是用户网络访问,同时也会有一些可识别的特征:

    获取个User-Agent:主要用来将我们的爬虫伪装成浏览器。Cookie:主要用来保存爬虫的登录状态。连接数:主要用来限制单台机器与服务器的链接数量。代理IP:主要用来伪装请求地址,提高单机并发数量。
    爬虫的工作方式可以归纳为两种:深度优先和广度优先。深度优先就是连接一个连接的像内爬。处理完毕之后再更换下一个连接。广度优先就是一层一层的处理,非常适合利用多线程并发技术来高效处理。
    爬虫的工作流程主要为:

    创建Request请求,访问目标地址,获取响应数据。解析数据,比如使用正则表达式,进行数据的过滤提取存储数据,将获取到的数据存储到磁盘或数据库。进行下一目标地址的爬取。直到爬取完所有目标地址结束。
    4.4 本章小结数据是一切程序运行的基础。由于此系统数据的特殊性,或者说,此系统的数据需要从外处获取。因此首先要确定我能获取到什么样的数据,之后设计数据模型,建立数据库。因此数据获取与数据模型的设计密不可分。
    第5章 汉字词典的设计与实现5.1 数据访问层数据访问对绝大部分程序来说是重中之重。无论是访问磁盘文件,访问数据库亦或是访问远程数据。拥有一套健全稳定快速的数据访问方式对程序的开发效率是有很大提高的。此系统的数据访问层,采用Entity Framework
    Core框架,封装常用方法。方法参数定义为Expression<T> 类型,在应用层通过传递Lambda表达式,提高了应用层使用的灵活性。因为参数类型为Expression<T>,因此可以利用C#表达式树的远程执行能力,在数据库中直接执行查询,之后返回到应用程序中。封装的方法中一般包含普通方法和异步方法两个版本。普通方法以同步的方式执行,可能因为数据库或者网络的原因,造成长时间阻塞。使用异步方法则可以避免此种情况。虽不能直接的加快程序运行的速度。但是总的来看提高了程序的流畅性,减轻了服务器的压力。
    实现上采用仓储模式,以接口的形式定义操作。之后可以有多个不同的实现。使用依赖注入方式,减轻程序的耦合度,提高程序的灵活性。
    接口及部分常用方法定义如下:
    public interface IRepository<T>{ #region 单模型操作 /// <summary> /// 添加 /// </summary> /// <param name="entity">实体</param> /// <param name="IsCommit">是否提交</param> /// <returns></returns> Task<bool> AddAsync(T entity,bool IsCommit = true); /// <summary> /// 更新 /// </summary> /// <param name="entity">实体</param> /// <param name="IsCommit">是否提交</param> /// <returns></returns> Task<bool> UpdateAsync(T entity,bool IsCommit = true); /// <summary> /// 获取 /// </summary> /// <param name="predicate">Lambda表达式</param> /// <returns></returns> Task<T> FindAsync(Expression<Func<T,bool>> predicate); /// <summary> /// 删除 /// </summary> /// <param name="predicate">Lambda表达式</param> /// <param name="IsCommit">是否提交</param> /// <returns></returns> Task<bool> DeleteAsync(Expression<Func<T,bool>> predicate,bool IsCommit = true); #endregion #region 分页查找 /// <summary> /// 分页查找 /// </summary> /// <param name="predicate">Lambda表达式</param> /// <param name="pagingModel">分页模型</param> /// <returns></returns> Task<PagingModel<T>> FindPagingAsync(Expression<Func<T,bool>> predicate,PagingModel<T> pagingModel); #endregion #region 连接查询 /// <summary> /// 内连接查询 /// </summary> /// <typeparam name="TInner">要联接的序列类型</typeparam> /// <typeparam name="TKey">联接键的类型</typeparam> /// <typeparam name="TResult">返回值类型</typeparam> /// <param name="inner">要联接的序列</param> /// <param name="outerKeySelector">用于从第一个序列的每个元素提取联接键的函数</param> /// <param name="innerKeySelector">用于从第二个序列的每个元素提取联接键的函数</param> /// <param name="resultSelector">用于从两个匹配元素创建结果元素的函数</param> /// <returns></returns> Task<IEnumerable<TResult>> JoinAsync<TInner, TKey, TResult>(IEnumerable<TInner> inner,Func<T,TKey> outerkeySelector,Func<TInner,TKey> innerkeySelector,Func<T,TInner,TResult> resultSelector); #endregion}
    5.2 基础系统实现此系统使用ASP.NETCore MVC实现,与传统的ASP.NET MVC框架极其类似。熟悉传统的ASP.NET MVC开发人员能无缝切换到ASP.NETCore MVC的开发。并且技术上更新很多,开发效率更高更快。
    ASP.NET Core的改进:

    建立在.NETCore上,支持真正的并行应用程序版本控制新的工具,简化了现代Web开发用于MVC和Web API的单一对齐的Web栈基于云的环境配置集成支持创建和使用NuGet软件包内置的依赖注入支持能够在自己的进程中托管在IIS或自主主机上
    使用ASP.NET Core 内置的依赖注入,添加数据访问层的依赖:
    public static class ServiceExtension { public static IServiceCollection AddRepository(this IServiceCollection services) { //添加依赖注入 services.AddScoped<IRepository<Character>,Repository<Character>>(); services.AddScoped<IRepository<ChineseWords>,Repository<ChineseWords>>(); services.AddScoped<IRepository<User>,Repository<User>>(); services.AddScoped<IRepository<SearchHistory>, Repository<SearchHistory>>(); services.AddScoped<IRepository<Phonetic>, Repository<Phonetic>>(); return services; } }
    在Startup.cs中添加:
    public void ConfigureServices(IServiceCollection services) { services.AddDbContext<MyContext>(options =>options.UseSqlServer(Configuration.GetConnectionString("SqlServerConnection"))); services.AddRepository(); services.AddMvc(); //允许跨域请求 services.AddCors(options => options.AddPolicy("CorsSample",p => p.AllowAnyOrigin() }
    在控制器的构造方法中,框架自动注入实现接口的实例:
    public class HomeController : Controller { public HomeController( MyContext context, IRepository<Character> repoCharacter, IRepository<ChineseWords> repoChineseWords, IRepository<SearchHistory> repoSearchHistory, IRepository<Phonetic> repoPhonetic ) { this._findWordService = new FindWordService(context, repoCharacter, repoChineseWords, repoSearchHistory, repoPhonetic); } }
    ASP.NET CoreMVC 的视图组件,是一个新特性。对于前端布局的解耦有很大的作用。同时也非常强大。视图组件,顾名思义,渲染的只是视图中的一个组件,并不是整个页面。同时包括在控制器和视图之间的关注点分离和可测试性等优点。像Action(动作)一样可以具有参数和复杂的业务逻辑。可以使用在任何重复的逻辑的地方,如果一个View考虑到需要用一个以上的视图模型,就可以将较小的那一块分解出来,使用视图组件进行调用。
    结合前端JavaScript的MVVM框架,返回Json数据进行数据交互,实现前后端分离:
    /// <summary> /// 查找历史 /// </summary> /// <param name="totalDay">最近天数的历史</param> /// <param name="totalSeries">排行最高的几条</param> /// <returns></returns> [EnableCors("CorsSample")] public JsonResult SearchHistory(Int32 totalDay = 10, Int32 totalSeries = 5) { //…… var result = hotSearch.Distinct(new Compare<SearchHistory>((x, y) => x.SearchWord == y.SearchWord)) .Select(p => new { name = p.SearchWord, type = "line", data = GetSearchWordCountPerDayArray(hotSearch, p) }); var legend = result.Select(p => p.name); return Json(new { xAxisArray = xAxisArray, legend = legend, series = result }); }
    读取JSON格式的配置文件,比传统ASP.NET MVC的XML格式配置文件更方便易读。
    生成不重复文件名方法:考虑到用户在上传文件时,可能会因为文件名相同而内容不同被覆盖,将会造成不可预估的损失。因此实现一个类似Windows资源管理器中批量重命名自动在文件名后追加数字,例如file(1).txt或者file(2).txt;
    /// <summary> /// 获取唯一的文件名 /// </summary> /// <param name="directory">文件夹</param> /// <param name="fileName">文件名称(不包括路径)</param> /// <returns></returns> private String GetSingleFileName(String directory,String fileName) { if (String.IsNullOrEmpty(directory)) throw new ArgumentNullException(nameof(directory)); if (String.IsNullOrEmpty(fileName)) throw new ArgumentNullException(nameof(fileName)); var allFileNames = Directory.EnumerateFiles(directory); var sameFileNameCount = allFileNames.Count(p => { var filePathSplit = p.Split(new Char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); var currentFileName = filePathSplit[filePathSplit.Length - 1]; return Regex.IsMatch(currentFileName, $@"\b{fileName.Split('.')[0]}(\(\d+\))?(?=\.)"); }); Func<String,Int32, String> GetCountFileName = (name,count) => { var regexFileName = new Regex(@"\w+(?=\.)"); return regexFileName.Replace(name, $"{regexFileName.Match(name)}({count})"); }; fileName = sameFileNameCount == 0 ? fileName : GetCountFileName(fileName, sameFileNameCount); return fileName; }
    5.3 纯汉字词的查询汉字词典的查询方式多种多样,此系统支持汉字、词语、成语,拼音,及汉字拼音混合的查询。
    首先要解决的问题就是如果识别用户所输入的类型。第一要判断的就是汉字和拼音。因为汉字和拼音的编码不同,所以可以直接采用正则表达式来识别。
    正则表达式都是关于文本。花一点时间,了解现代数字世界中的各种文字:电子邮件,新闻报道,短信,股票市场数据,电脑代码,通讯录中的联系人,照片中的人的标签 - 所有这些东西 是文字。 正则表达式是一种允许我们通过描述文本模式来处理这些文本的工具。
    因此,正则表达式是描述文本模式的一组符号。现在是单数。 当我们看到它是多重的,我们所说的是这些符号的正式语言,需要由正则表达式处理器来解释。
    此系统所支持输入类型的正则表达式如下:



    单个汉字
    \b[\u4e00-\u9fa5]\b




    词语(2个及2个以上的汉字)
    \b[\u4e00-\u9fa5 ]{2,}\b


    纯拼音
    \b[a-zA-Z ‘’]+\b


    汉字拼音混合
    [a-zA-Z\u4e00-\u9fa5]+



    对用户输入的数据进行正则匹配,返回能匹配到的字符串类型。
    在获取到用户输入类型之后,返回到控制器中,控制器根据结果调用不同的处理方法。在控制器中,创建一个方法字典,即一种返回类型对应一个方法,如果是返回类型与字典中的一个key相等,这调用此key的value去处理。这样可以有效减少因为不同的条件而产生的大量的if-else语句。
    var funDict = new Dictionary<WordType, Func<string, Task<IActionResult>>>(){ {WordType.Unknow, Unkonw}, {WordType.Character,Character }, {WordType.Word,Word }, {WordType.Phonetic,Phonetic }, {WordType.Mixture,PhoneticMixture }};return await funDict[this._findWordService.GetWordType(wd)](wd);
    如果判断为汉字或词语类型,则直接通过Service层,调用进行数据库查询。得到查询结果。一个汉字可能存在多音字的情况,所以查询之后返回一个IEnumerable\<Character\>类型结果。
    /// <summary> /// 查找汉字 /// </summary> /// <param name="wd">汉字</param> /// <returns>汉字</returns> public async Task<IEnumerable<Character>> FindCharacterAsync(string wd) { return await this._repoCharacter.FindAllAsync(p => p.Charater == wd); } /// <summary> /// 查找词语 /// </summary> /// <param name="wd">词语</param> /// <returns>词语</returns> public async Task<ChineseWords> FindWordAsync(string wd) { return await this._repoChineseWords.FindAsync(p => p.Words == wd); }
    5.4 纯拼音的查询此系统支持通过输入拼音查找汉字。不过因为汉字拼音一般是带有声调的,不能通过键盘直接输出。所以此系统支持以纯英文字母表示的拼音。例如:“women”,至于它的声调是多少,并不能直接输入。所以系统选择将所有的可用组合全部输出。
    例如用户输入的拼音字符串为:“tian’gaorenniaofei”。
    首先需要对字符串进行分割,分析出其中的拼音。根据《汉语拼音方案》可知:

    声母26个:”b”, “p”, “m”, “f”, “d”, “t”, “n”, “l”, “g”, “k”, “h”, “j”, “q”, “x”, “zh”, “ch”, “sh”, “r”, “z”, “c”, “s”, “y”, “w”韵母24个:”a”, “e”, “i”, “o”, “u”, “v”, “ai”, “ei”, “ui”, “ao”, “ou”, “iu”, “ie”, “ue”, “er”, “an”, “en”, “in”, “un”, “vn”, “ang”, “eng”, “ing”, “ong”; 其中单音节韵母6个拼音由声母和韵母组成。声、韵母的组成规则:

    一个韵母:例如:a,o,ang。一个声母和一个韵母:例如:ha,wa,wo。一个声母和两个韵母:例如:huang,zhuang
    其中只有单音节韵母之后可以再跟韵母。
    由上述规则,可设计出算法识别拼音,描述如下:
    首先创建拼音字典:

    遍历字符串中的每个字符。并获取以此字符开始的至整个字符串结尾的所有长度递增的子字符串列表。原理为超前搜索,确定子字符串的类型。遍历以字符开头的子字符串。如果是声母,将当前字符的索引作为key,当前子字符串和拼音类型枚举值作为Value。如果字典中已存在当前key。表明,超前搜索取得有效结果,将当前key的值直接覆盖。 如果是韵母同理。直到遍历完所有字符,返回创建的拼音字典。
    之后从拼音字典中提取,拼接可组成一个拼音的所有Value。

    创建一个字符串列表,做为最后组合成的拼音列表。创建字典Value列表,用于临时存放从字典中取出的值。遍历拼音字典。获取索引处的拼音类型枚举值,如果为声母,添加到字典Value列表中,index向前移动声母的长度个值。如果为韵母,首先获取韵母,并添加到字典Value列表中,index向前移动韵母长度个值。如果上一步获取到的韵母是单音节韵母,则其之后有可能再跟一个韵母。则继续重复第5步。上述第4,5,6步完成之后,一个拼音的识别已经完成。如果字典Value列表中的所有数据都是韵母,这将他们全部分开,分别作为单独的声母。遍历字典Value列表,拼接成一条拼音。重复第3步,直到全部遍历结束。
    /// <summary> /// 获取拼音字典 /// </summary> /// <returns></returns> private Dictionary<int,Tuple<CharType,string>> GetCharTypeDictionary() { //是否为声母 Func<string,bool> IsInitials = (s) => { return _initials.Any(p => p == s); }; //是否为韵母 Func<string,bool> IsVowels = (s) => { return _vowels.Any(p => p == s); }; //获取以i开始,至结尾长度递增的子字符串 Func<string,int,List<string>> GetSubString = (s,i) => { var _builder = new StringBuilder(); var _list = new List<string>(); var _length = s.Length - i; foreach(var l in Enumerable.Range(1,_length)) { _list.Add(s.Substring(i,l)); } return _list; }; var dict = new Dictionary<int,Tuple<CharType,string>>(); var splitArray = this.Phonetic.Split(new char[] { '\'','’' },StringSplitOptions.RemoveEmptyEntries); foreach(var s in splitArray) { var index = 0; var length = s.Length; var dictCount = dict.Count; for(; index < length; index++) { var currentIndex = dictCount + index; var allSubStrings = GetSubString(s,index); foreach(var subString in allSubStrings) { if(IsInitials(subString)) { if(dict.ContainsKey(currentIndex)) { dict[currentIndex] = new Tuple<CharType,string>(CharType.Initials,subString); } else { dict.Add(currentIndex,new Tuple<CharType,string>(CharType.Initials,subString)); } } else if(IsVowels(subString)) { if(dict.ContainsKey(currentIndex)) { dict[currentIndex] = new Tuple<CharType,string>(CharType.Vowels,subString); } else { dict.Add(currentIndex,new Tuple<CharType,string>(CharType.Vowels,subString)); } } } } } return dict; } /// <summary> /// 切分 /// </summary> /// <returns></returns> public List<string> Split() { /** * 过程描述: * 1.从StartIndex开始,取第一个,并且同索引中长度最长的。 * 2.从上个声母之后,如果不是韵母,退出,否则,取第一个韵母,同索引中取最长的。 * 3.从上个韵母之后,如果仍是韵母, * 如果上一个声母之后的韵母个数只有一个,则追加当前韵母,同索引中取最长的。 * 否则退出。 * 4.从上个韵母之后,是声母,退出。 */ //声母 initials //韵母 vowels var phoneticList = new List<string>(); var list = new List<Tuple<CharType,string>>(); var builder = new StringBuilder(); var index = 0; var dict = GetCharTypeDictionary(); while(index < dict.Count) { list.Clear(); builder.Clear(); if(index < dict.Count && dict[index].Item1 == CharType.Initials) { //获取声母 var initials = dict[index].Item2; list.Add(dict[index]); index += initials == null ? 0 : initials.Length; } if(index < dict.Count && dict[index].Item1 == CharType.Vowels) { //获取第一个韵母 var vowels1 = dict[index].Item2; list.Add(dict[index]); index += vowels1 == null ? 0 : vowels1.Length; if(_sigleVowels.Any(p => p == vowels1)) { if(index < dict.Count && dict[index].Item1 == CharType.Vowels) { //获取第二个韵母 var vowels2 = dict[index].Item2; list.Add(dict[index]); index += vowels2 == null ? 0 : vowels2.Length; } } } //如果都是韵母,拆开 if(list.All(p => p.Item1 == CharType.Vowels)) { foreach(var item in list) { phoneticList.Add(item.Item2); } } else { foreach(var item in list) { builder.Append(item.Item2); } phoneticList.Add(builder.ToString()); } } return phoneticList; }
    通过以上,如果获取到的拼音个数为1,查找汉字,大于1则为查找词语。
    选择对应的方法继续处理,如果查找汉字,首先从Pheonetic拼音表中查找出所有对应的带有声调的拼音。之后再到Character汉字表中查找Phonetic相等的汉字,查找词语同理。由于带有声调的拼音的编码问题。所以无法直接使用Entity Framework的Join查询。所以选择使用执行SQL的方式,SQL似乎可以忽略不同编码的问题:
    var phonetic = phonetics.ElementAt(0); var phoneticResult = (await this._repoPhonetic.FindAllAsync(p => p.PhoneticRaw == phonetic)).ToList(); #region /** * 由于汉字表和拼音表中拼音的字符编码不同,所以,无法使用此种方式查询 */ //var characters = await this._repoCharacter.JoinAsync(phoneticResult, c => c.Phonetic, p => p.PhoneticTone, (c, p) => c); #endregion//sql未进行参数化处理 var sql = $@"SELECT * FROM Character LEFT OUTER JOIN Phonetic ON (Character.Phonetic = Phonetic.PhoneticTone) WHERE PhoneticRaw = '{phonetic}'"; var characters = this._context.Set<Character>().FromSql(sql); return characters;
    5.5 汉字拼音混合的查询
    有时候并不是一个词所有的字都会写。用户可以输入会写的汉字,不会写的用拼音表示。例如:“严jin”。系统通过识别,将汉字转换为拼音。从而从汉字拼音的混合输入转换为纯拼音的输入。这里好像是将拼音转换为汉字更符合常识。实际上无论是哪种总是,最终都是,要根据一个拼音,查找出对应的所有汉字。如果将汉字全部转换为拼音,则将解决方法转换为了纯拼音的查询,可重用上一节论述的方法。
    过程描述:

    首先使用正则表达式提取出汉字。根据汉字,从拼音表中查找出对应的使用英文字母代替的拼音。遍历所有的汉字。如果当前汉字有n个读音,这source自身复制到n份。遍历source.count / n次,每一次遍历,要对序列进行交换次序。之后执行替换。
    序列自身复制到N份:
    Func<IEnumerable<string>, int, IEnumerable<string>> Copy = (source, count) => { if (s == null) return source;if (s.Count() == 0) return source; var _s = source; for (var i = 0; i < count - 1; i++) { source = source.Concat(_s); } return source; };
    字符串的替换,不同与.NET提供的string.Replace方法,此方法仅会替换指定索引位置的字符:
    //字符的替换,index,为需要被替换位置的开始索引 Func<string, string, string, string> Replace = (source, character, replacement) => { var index = source.IndexOf(character); source = source.Insert(index + 1, replacement); source = source.Remove(index, 1); return source; };
    交换索引中item的位置,index索引的排在最前面,其前一个item紧跟其后:
    //交换索引中item的位置,index排到最前面,其前面的紧跟其后 Func<IEnumerable<string>, int, IEnumerable<string>> Exch = (source, index) => { if (index == 0) return source; var list = source.ToList(); var sourceArray = source.ToArray(); for (var i = 1; i < index + 1; i++) { list.Remove(sourceArray[i]); list.Insert(0, sourceArray[i]); } return list; };
    替换汉字:
    //替换汉字 Func<IEnumerable<string>, Tuple<string, IEnumerable<string>>, IEnumerable<string>> Combin = (source, character) => { /** * 过程说明: * 1.如果当前汉字有n个读音,source自身复制n份 * 2.执行替换 * 3.遍历source.count / n 次,第一次顺序,则第二次倒序 */ var sourceArray = source.ToArray(); //当前汉字 var currentChar = character.Item1; //当前汉字读音个数 var n = character.Item2.Count(); sourceArray = Copy(sourceArray, n).ToArray(); //source的count var count = sourceArray.Count(); var index = 0; foreach (var order in Enumerable.Range(0, count / n)) { var phoneticArray = Exch(character.Item2, order); foreach (var p in phoneticArray) { var current = sourceArray[index]; sourceArray[index] = Replace(current, character.Item1, p); index++; } } return sourceArray; };
    5.6 句子通过分割得到词组的查询如果用户输入一条短句,短句是由单个汉字和词语组成的。因此在无法解析的句子情况下,最短句进行分割,得到多个单字和词语。也是帮助用户理解句子的一种方式。句子的分割可以利用数据库来实现:

    遍历句子中的每一个字符,得到以此字符开始的,长度递增的直至句子结尾的子字符串列表。逐个遍历子字符串列表,查询数据库,如果子字符串在词库中不存在,则不能只能作为词语。继续查找下一个子字符串,如果存在在词库中,则表明当前子字符串可作为一个词语。若之后的字符串仍然在词库中可查找到,则取最长的子字符串作为结果。若所有子字符串均不存在于词库中,表明当前字符只能作为一个单字。遍历完毕字符串中所有字符结束。
    对于短句分割出词语,已经有了很多相关研究,其中包括流行的结巴分词。此系统拥有一个词典,包括20000条数据。包含了每个词语的词频,和词性。通过创建前缀树结构,实现快速扫描,生成句子所有可能组合形成词语的情况,构造出有向无环图。前缀树就是将多个具有相同开头的词语存储起来。有助于加快查找速度。其中有向无环图(DAG)就是用生成一个句子中所有汉字能组成词语的所有情况构成的,记录了句子中一个词的开始位置,作为字典的Key,所有词语可能结束的位置作为list存放在value中。如果一个有向无环图为:{4:[4,6,9]},表示从位置4开始,到4,6,9组成的子字符串都是词语。根据字典生成前缀树,之后生成有向无环图。换句话说就是对待要分割的句子,生成几种可能的词语组合。切分之后组成短语列表,并对每个短语生成有向无环图,得到最大概率路径。
    生成有向无环图:

    遍历短句,获取当前索引字符。判断前缀树中是否存在当前字符。如果存在并且概率大于0,添加到列表中。继续从当前字符开始,继续从句子获取长度比当前字符大1的子字符串。直至遍历完句子中的所有字符结束。
    /// <summary> /// 生成有向无环图 /// </summary> /// <param name="sentence">短句</param> /// <returns></returns> private Dictionary<int, List<int>> GetDAG(string sentence) { if (string.IsNullOrWhiteSpace(sentence)) throw new ArgumentNullException("sentence"); var dag = new Dictionary<int, List<int>>(); var trie = WordDictionary.Trie; var length = sentence.Length; List<int> temp; for (var i = 0; i < length; i++) {//从当前汉字,向后遍历,直到短句终点 temp = new List<int>(); var current = sentence.Substring(i, 1); int j = i; while (j < length && trie.ContainsKey(current)) { //如果字典中存在当前汉字,并且概率大于0 if (trie[current] > 0) { temp.Add(j); } j++; if (j < length) { current = sentence.Substring(i, j + 1 - i); } } if (temp.Count == 0) { temp.Add(i); } dag[i] = temp; } return dag; }
    5.7 本章小结本章主要介绍了系统的详细设计,包括数据访问层,ASP.NET Core的相关技术及实现。汉字词典的查询方式的实现。其中汉字词及拼音的查询是系统的核心部分。
    第6章 汉字词典后台管理系统的设计与实现6.1 以WebAPI形式与前端MVVM框架的结合应用自计算机软件发展以来,计算机软件的形式已经发生了数次变革。从传统的PC端桌面程序到B/S架构的浏览器与服务端结合的程序。再到WebAPI与前端MVVM框架,软件开发方式与技术有了很大的变化,不论技术优劣,都是时代的产物。
    MVVM模式,最早是由微软提出来的。MVVM模式自然地适用于XAML应用程序平台,如WPF。 这是因为MVVM模式利用了WPF一些特性,比如DataBinding,Command和Behaviour。 MVVM类似于许多其他模式,将UI的外观和布局的责任与演示逻辑的责任分开;例如,如果您熟悉模型 - 视图 - 控制器(MVC)模式,您会发现MVVM有许多类似的概念。Model-View-ViewModel模式几乎可以在使用在XAML的任一平台上。 其目的是提供用户界面控件与其逻辑之间的清晰分离。
    MVVM模式具备有三个组件:Model,View和ViewModel。 每个都有独特和独立的作用。

    它提供了分离问题。紧密耦合,耐变形,脆弱的代码导致各种长期维护问题,最终导致客户对交付的软件的满意度差。应用程序逻辑和UI之间的干净分离将使应用程序更容易进行测试,维护和发展。它可以提高代码重用的机会,并支持开发者设计者的工作流程。它是XAML平台的一种自然模式。 MVVM模式的关键推动因素是Silverlight平台的丰富数据绑定堆栈以及依赖关系属性。这些组合提供了将UI连接到视图模型的手段。它支持开发人员设计工作流程。当UI XAML与代码隐藏没有紧密耦合时,设计师很容易行使自己需要创造的自由,并制作出一个好的产品。它提高了应用程序的可测试性。将UI逻辑移动到可以独立于UI技术实例化的单独类中,使得单元测试更容易。
    6.2 基于MathJax的对LaTeX语法支持的应用LaTeX是一种用于高质量排版的文件制作系统,它被发音为“Lah-tech”或“Lay-tech”(与“blech”或“Bertolt Brecht”))。 它最常用于中等到大型的技术或科学文件,但它可以用于几乎任何形式的出版。
    LaTeX不是一个文字处理器 相反,LaTeX鼓励作者不要太担心他们的文档的外观,而是专注于获取正确的内容。LaTeX基于这样的想法,最好是将文档设计留给文档设计者,并让作者继续撰写文档。

    描述:

    这篇文章是一篇文章。它的标题是笛卡尔的封闭类别和鸡蛋的价格。它的作者是Jane Doe。它是在1994年9月写的。该文件包含一个标题,后跟文本Hello world!
    此系统后台管理中,通过使用MathJax插件,时间对LaTex的解析:

    通过访问:http://latex.codecogs.com/eqneditor/editor.php?lang=zh-cn,进行编辑,编辑完毕之后将字符复制释义文本框中,并选择使用“$”或“$$”将公式包裹。

    选择预览就会看到由MathJax解析出来的结果

    6.3 本章小结本章主要介绍了系统的后端管理部分。后端管理系统采用Vue.js框架,结合ASP.NET Core实现单页面应用程序。主要包括对词库的管理操作。
    第7章 测试7.1 功能测试1.查询汉字测试:
    在输入一个汉字之后,能正确的显示所查询的汉字。在有信息前提下,能正确显示汉字的信息。其中汉字的读音在有效的前提下,能正常发音。相关组词能直接连接到其查询结果。

    2.查询词语测试:
    在用户输入两个及两个以上的汉字时,将被判定为查询词语。将会搜索词语库,在有效的前提下,能正常显示词语的各个信息。其中词语的读音能正确发音。特别的,在词语的释义中有形如“参看〖咱们〗”的字样,能连接到查询结果。

    3.纯拼音查询测试:
    在输入纯拼音的情况下,能识别拼音,并根据拼音查询出所有匹配的结果。查询结果能连接到查询。

    4.汉字拼音混合查询测试:
    汉字拼音的混合查询是用户混合输入汉字和拼音,能正确解析出用户想要查询的结果。

    5.语义化部首查询测试:
    由于汉字偏旁部首的特殊性,在一般的键盘上无法直接输入,所以可以直接通过语义描述的方式,表达用户所要搜索的偏旁部首相关的汉字,比如输入:“请给出所有偏旁为三点水的汉字”,也可直接输入偏旁部首的名称,比如:“提手旁”。系统会自动识别出偏旁部首关键字。

    6.后台管理-汉字的管理测试:

    7.后台管理-词语的管理测试:

    8.后台管理-热词查看测试:

    9.后台管理-收录词汇测试:

    7.2 本章小结本章主要对系统的所有功能进行了测试,验证各个功能模块是否能正常工作。在发现问题的情况下,及时修改调整。
    参考文献[1] Jon Skeet著姚琪琳译.深入理解C# 第三版 人名邮电出版社,2014, 406-452
    [2] Jeffrey Richter著CLR via C# [M] 第四版
    [3] Christian Nagel,Morgan Skinner 著 李铭 译 C#高级编程 第七版 清华大学出版社 2010.11
    [4] Adam FreeMan著 Asp.Net MVC5高级编程 第五版
    [5] Shahed著 Asp.Net Core Essentials Packt出版社 2016.9
    [6] 竺洪平 著 网页数据抓取中的几个关键技术问题[C].宁波教育学院学报
    [7] 周福才, 张冠宇, 张军. 基于WebServices和XML签名技术的认证字典在分布式数据中的应用[C]// 2005中国计算机大会. 2005.
    [8] 张冠宇. 基于WebServices技术的认证字典的设计与实现[D]. 东北大学, 2004.
    [9] 吴力荣. 基于MathJax的在线公式编辑器的设计与实现[J]. 廊坊师范学院学报(自然科学版), 2014, 14(5):40-42.
    [10] 李幼平, 陈艳山. 基于Web的在线复杂公式编辑器的实现[J]. 武汉轻工大学学报, 2006, 25(4):53-56.
    [11] 孙连山, 李云倩. MVVM框架在Web前端的应用研究[J]. 电脑知识与技术:学术交流, 2016(2X):45-46.
    [12] Marshall著, 梁春艳译. Visual Studio 2010并行编程从入门到精通[M]. 2013年1月1版. 北京:清华大学出版社, 2013:1-39.
    [13] JonGalloway, K.Scott Allen等著:孙远帅译.ASP.NET MVC5高级编程[M].北京:清华大学出版社,2015
    [14] 王珊,萨师煊.数据库系统概论[M].北京:高等教育出版社,2014.09
    [15] 许家珆.软件工程-方法与实践[M].北京:电子工业出版社,2007.09
    致 谢写到这里,我是兴奋的,也是失落的。漫漫求学路,也算是走到尽头了。其实更多的还是不舍。
    很多人都会回想起大一,到大四,这几年所度过的时光。我也是同样,只是早早的就意识到我也会有这一天。所以大部分的还是日子都过得很繁忙的样子。虽然成绩并不突出。但是非常非常害怕面对毕业之后的残酷生活。我怕毕业就是失业。我怕我会像新闻上,电视上报道的那些大学生一样,毕业之后不知所措。基于这个原因,我不停的学习,只想学会一个技能,能让我毕业之后能有个立足之地。
    其实,这个致谢辞我早就想感谢一个人。我们大一的时候学习了C语言,对于那时候练电脑都摸不顺溜的我,C语言简直噩梦般的存在。我也把期望寄托在每节课上面,认真听讲。但是最后还是无法搞懂程序的意义。在大一期末课程设计的时候,我们要求使用C语言编写一个读写TXT文本文件的程序。这个程序是我抄的,是我第一个抄的程序,也是我大学四年最后一个抄的程序。课设结束,验收我程序的就是,我的班导师。要说,老师也只是说了一两句我能力差,不知学习的话。然后从此就被我记在了心里。到大二,开始琢磨自学,因为感觉到如果只是跟着课堂走,是绝对不能再我毕业之时能掌握到一个能工作的技能的。在很长一段时间的艰难抉择中,确定了我的技术方向,以及之后想要做的职位。
    在大四上学期的时候,我还有一门专业任选课没有修。所以就选了老师的Java程序设计,那时我也已经找到了一家实习单位。因此老师的课就没有去听过。等到快要学期末的时候,按要求是要交结课报告的,在跟老师沟通之后,我快速了完成了毕设。老师本来说我因为考勤是拿不到好成绩的。最后老师看了我的结课报告之后破例给了我优秀。那天是我最开心的,一方面是终于不用再担心学分的问题,更重要的是得到了老师的肯定。老师就是这样,先是批评了我,经过3年之后,又肯定了我。我真的是从内心的感谢。
    当然也感谢我所有的老师,如今只后悔没有认认真真好好学习。只是再没机会了。我很喜欢这所学校。很喜欢这里的老师同学。
    3 评论 13 下载 2018-09-26 15:46:07 下载需要14点积分
  • 基于JSP和SQL Server 2012的音乐管理系统的设计与实现

    摘 要随着互联网和宽带上网的普及,网络传输以其特有的快速、高效、便捷的传输方式越来越被人们接受。在当今社会的影响下,人们因为快节奏的工作和生活产生了极大的压力,这时就需要一个放松的环境去释放这些压力,因此音乐网站也就应运而生了。与此同时,音乐网站也为广大音乐爱好者提供了一个音乐交流的平台,借此增加对音乐的了解。
    音乐网站系统以 Struts2 为框架进行开发,以 JSP 作为页面载体,后台数据库使用 Sqlserver ,在 Windows 环境下使用 MyEclipse 开发工具进行开发,采用 Ajax 和 Jqury 技术,使得系统更易维护。前台主要实现了用户的登陆注册、音乐的上传、试听点歌、发送短消息、音乐下载以及对音乐进行留言等功能;后台主要用于对数据库的管理,实现管理员对音乐的删除、对注册过的用户进行删除、 添加友情链接等功能。
    关键词:音乐网站;Struts2 框架;Sql Server 数据库
    1 绪论随着网络技术以及计算机的发展,人们也逐步进入到计算机网络这个范围中,人们通过Internet相互交流和沟通。因此不同的网站也应运而生了,例如音乐网站、娱乐网站、聊天网站等等,正因为在这样的一个信息化的网络时代,音乐更是随处可在。这就表明了,音乐网站要想有一个好的前景就必须用新的网络技术去支持,不断提升网络的宽带质量,更要提升音乐的试听、下载速度。
    1.1 设计背景因为宽带用户的增加,带动了音乐网站产业的蓬勃兴起。无论国内还是国外,音乐网站市场都呈现一派生气,近年来,全球数字娱乐业持续发展。网络传播以其特有的快速、高效、便捷的传输方式被人们所接受,越来越多的走进了大家。并且在当今音乐浪潮的影响下,随着音乐事业逐渐走向高峰,音乐已无处不在,音乐己与我们密不可分。全球数字娱乐业的迅猛发展、网络电视等,无不充斥着激烈的竞争。而现在许多音乐网站不能提供在线播放, 并且在技术支持上也不完善。于是设计和实现这样一个音乐网站就成为了必须,不仅仅满足用户的可以试听音乐的功能,而且还要保证在速度上不能慢,更要在功能和性能上满足用户更多的体验和需求。
    1.2 设计意义随着网络通信技术、多媒体技术及数据存储技术的快速发展,音乐网站作为一种大众的Web服务,给喜爱音乐的网络用户提供了极大的便利,增添了音乐用户的选择。但有一些音乐网站由于各种不同的原因遭到了社会的淘汰,其原因主要集中在页面设计、查询浏览的速度、功能模块等不同方面。因此,为了用户可以方便、快捷、简单、安全地实现音乐搜索去查找自己喜欢的音乐,并能实时地试听音乐、下载音乐、将音乐加入到自己的音乐盒中、点歌并将自己的建议写入到留言板以便网站的完善等,需要建立一个自由、安全的音乐网站。
    本音乐网站应用MVC模式进行设计开发。通过对网站有关音乐媒体发布事项的一番调查与分析, 在用户对音乐需求的基础上, 明确音乐网站系统需要实现的具体功能并实现其功能。
    1.3 开发工具和服务器介绍对于音乐网站所涉及到的开发工具和服务器进行简要的介绍。
    1.3.1 SqlServer 简介SQL Server 是由 Microsoft 开发和推广的关系数据库管理系统(DBMS),它最初是由 Microsoft、Sybase 和 Ashton-Tate 三家公司共同开发的。SQLServer 有图形化界面, 使系统管理和数据库管理更加直观、简单并且拥有丰富的编程接口工具,为用户进行程序设计提供了更大的选择余地等等,而 SQLServer2012 提高了服务器正常运行时间并且还加强了数据的保护,拥有了更高的安全性和高可用性,还拥有大量功能强大的免费工具,也拥有了更加快速的数据发现能力等等更多的加强和创新。
    1.3.2 MyEclipse 开发平台MyEclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。虽然大多数用户很乐于将 MyEclipse 当作 Java IDE 来使用,但 MyEclipse 的目标不仅限于此。MyEclipse 还包括插件开发环境(Plug-in Development Environment,PDE),这个组件主要针对希望扩展 MyEclipse 的软件开发人员,因为它允许他们构建与 MyEclipse 环境无缝集成的工具。由于 MyEclipse 中的每样东西都是插件,对于给MyEclipse 提供插件,以及给用户提供一致和统一的集成开发环境而言,所有工具开发人员都具有同等的发挥场所。
    MyEclipse 是一个开发源码项目,它其实是 Visual Age for Java 的替代品,其界面跟先前的 Visual Age for Java 差不多,但由于其开放源码,任何人都可以免费得到,并可以在此基础上开发各自的插件,因此越来越受人们关注。
    1.3.3 Tomcat 服务器Tomcat 是 Apache 软件基金会的一个核心项目,并且是由Apach 和 Sun 以及其他公司或个人共同开发而成的。因为有了Sun 公司的参与和合作,最新的 Servlet 以及 Jsp 规范总是能够在 Tomcat 中体现出来。 Tomcat 服务器是一种免费开源的 Web 应用服务器,是属于轻量级的服务器,技术先进以及性能稳定,普遍使用于中小型系统和并发访问量不是很多的情况,是调试Jsp 程序的法宝。Tomcat 具有处理静态 Html 页面的功能,同时又是 Servlet 和 Jsp 的容器,可以运行 Jsp 页面和 Servlet。Tomcat 很受广大编程爱好者的喜爱, 因为在运行它的时候占用的系统资源不大,扩展性很好,支持系统开发应用常用的功能,并处于不断的完善中, 程序员可以根据自己的需要去更改或在 Tomcat 中加入新的功能。运行程序只需要将所做的项目部署到 Tomcat 中,然后启动运行 Tomcat ,在浏览器上可以展示 Jsp。一般的我们在选择浏览器的时候用的是Chrome浏览器。
    1.4 开发技术介绍1.4.1 Java 编程语言简介Java 是 Sun 公司在 1995 年推出的一种编程语言, 被特意设计用于互联网的分布式环境。 Java 具有类似于C++的感觉,但相比C++而言,更易于使用。采用了以对象为导向的编程方式。使用 Java 编写的应用程序,既可以在一台独立的电脑上运行,也可以分布在一个网络的服务器端和客户端运行。另外,Java 还可以用来编写容量很小的应用程序模块或者 Applet,作为网页的一部分使用。applet 可使页面使用者和页面之间进行交互式操作[3][4] 。Java 推出之后马上给互联网的交互式应用带来了新面貌。目前,最常用的两种互联网浏览器软件中都包括一个Java 虚拟机 [5] 。并且几乎所有的操作系统中都增添了Java 编译程序。Java 语言比较于C 语言而言比较简单,具有跨平台、安全性以及面向对象等特点。跨平台指的是 Java 能运行于不同的平台,引进了虚拟机原理,实现了不同平台的接口并且在虚拟机上运行。安全性指的是 Java 程序运行的时候,内存由操作系统直接分配而不是像C++那样通过指针来对存储器地址操作,这样以来就可以避免了病毒通过指针入侵到系统中。面向对象指的是 Java 语言在编程的时候一般都是将属性私有封装在类中并提供公开的访问方法 [6] 。这样一来实现了程序的简洁和可维护的性能。封装继承的思想使得程序只需做一次编译,然后通过上述特性反复利用,程序开发者只需要将主要的精力投在类及接口的设计和实现上。
    1.4.2 JSP 技术JSP 是由 Sun Microsystems 公司倡导以及许多公司参与狗共同建立的一种 动态网页技术标准。JSP是最早的 Java EE 规范之一,也是最经典的 Java EE 技术之一,直到今天,JSP依然广泛地应用于各种 Java EE 应用中,充当 Java EE 应用的表现层角色。JSP 技术有点类似 ASP技术,它是在传统的网页HTML文件(*.htm,*.html)中插入 Java 程序段 (Scriptlet)和 JSP标记(tag),从而形成 JSP 文件(*.jsp) [7]。JSP技术使用Java 编程语言编写类XML 的 tags 和 scriptlets,来封装产生动态网页的处理逻辑 [8]。网页还能通过 tags 和 scriptlets 访问存在于服务端的资源的应用逻辑。JSP将网页逻辑与网页设计和显示分离,支持可重用的基于组件的设计,使基于 Web的应用程序的开发变得迅速和容易。Web服务器在遇到访问JSP网页的请求时, 首先执行其中的程序段,然后将执行结果连同JSP 文件中的HTML代码一起返回给客户[9][10]。插入的Java 程序段可以操作数据库、重新定向网页等,以实现建立动态网页所需要的功能。JSP通过在标准的HTML页面中嵌入 Java 代码片段,或使用各种JSP 标签包括使用用户自定义标签,从而可以动态的提供页面内容。也就是说 JSP页面的内容由两部分组成:静态部分(标准的HTML标签、静态的页面内容,这些内容与 静态 HTML页面相同)和动态部分(受 Java 程序控制的内容,这些内容由 Java 程序来动态生成 [11]。JSP和 Servlet 是 Java EE规范的两个基本成员,它们是 Java Web开发的重点知识,也是Java EE 开发的基础知识。JSP 和 Servlet的本质是一样的,因此 JSP 最终必须编译成Servlet才能运行,或者说 JSP 只是生成Servlet的“草稿”文件 [12] 。
    1.4.3 Struts2 框架技术Struts是全世界最早的MVC框架,它通过采用Java Servlet/JSP技术,实现了基于Java EEWeb应用的 MVC设计模式的应用框架,Struts 也确实是 Java EE应用中使用最广泛的 MVC框架[13] ,拥有广泛的市场支持。此外,Struts 具有页面导航功能,使系统的脉络更加清晰。通过一个配置文件,即可把握整个系统各部分之间的联系,这对于后期的维护有着莫大的好处。Struts2由传统的struts 1和WebWork两个经典的 MVC框架发展起来的,Struts2是一个非常优秀的MVC的框架。与传统的Struts1 相比,Struts2 允许使用普通的、传统的 Java 对象作为Action;Action 的 execute()方法不再与ServletAPI 耦合,因而更易测试;支持更多的视图技术;基于 AOP思想的拦截器机制,提供了极好的可扩展性;更强大、更易用的输入校验;整合的 Ajax 支持等,这些都是 Struts2 的巨大吸引力 [14] 。
    Struts2 框架工作的原理可以通过以下几个步骤来分析:首先客户端发出一个请求指向 Servlet 容器,这个请求经过几个过滤器后会到达 Struts2 框架的心脏 FilterDispatcher过滤器,在处理用户请求时,会和请求一起相互配合访问Strurs2 的底层框架结构 [15]。在 Web容器启动时,Struts2 框架会自动加载配置文件里面 的相关参数,并转换成相应的类。如:ConfigurationManager 、ActionMapper 和 ObjectFactory 。ConfigurationManager 存有配置文件的一些基本信息, ActionMapper 存有 action 的配置信息。在请求过程中所有的对象( Action,Results,Interceptors,等)都是通过ObjectFactory 来创建的。过滤器会通过询问 ActionMapper 类来查找到请求中需要用到的 Action 。过滤器会把请求的处理交给ActionProxy。ActionProxy 作为 Action 的代理对象找到需要调用的 Action 类并创建一个实例。然后执行所对应的 Action,返回的结果一般是需要去展示的 Jsp 页面或者是其他的标签。
    1.4.4 MVC 分层结构概括来说, MVC思想将一个应用分成了 Model、View、Control 三个部分,三个部分以最少的耦合协同工作,从而大大提高了应用的可扩展性和可维护性。
    MVC结构具有以下特点:多个视图对应一个模型;模型返回的数据与显示逻辑分离;三层架构导致的低耦合性和易维护性[16] 。那么在 Struts2 中,Model 对应业务逻辑组件,它通常用于实现业务逻辑方法以及与底层数据库的交互等;View 对应视图组件, 通常是指 Jsp 页面,但也适用于其他视图显示技术,如 Velocity 或者 Excel 文档;Control 对应系统核心控制器和业务逻辑控制器,系统核心控制器为 Struts2 框架提供的FilterDispatcher,它根据请求自动调用相应的Action。而业务逻辑控制器是指开发人员自行定义的一系列 Action,在 Action中负责调用相应的业务逻辑组件来完成处理。
    1.4.5 Ajax 和 Jquery 技术Ajax 全称是基于 XML的异步 JavaScript,是与服务器交换数据并更新部分网页的技术。(即在无需重新加载整个网页的情况下,能够更新部分网页的技术。) 传统的 Web应用允许用户填写表单,当提交表单的时候向服务器发送一个请求,服务器接收并处理接收的表单,然后返回一个新的网页。这种做法会浪费很多的带宽,因为前后两个页面中的大部分Html代码都是相同的。而与此不同的 Ajax 应用可以很好的解决这个问题,Ajax 应用可以向服务器发送并取回必需的数据,它使用 Soap或其他一些Web Service 接口,并且在客户端采用了js来处理来自服务器的响应 [17][18]。由于在浏览器和服务器之间交换的数据大量减少,所以应用响应会变得更快。综上所述,可以发现 Ajax 应用程序具有如下优势:

    通过异步刷新,减少用户等待时间,很好的提升了用户的体验度
    Ajax 引擎在客户端运行,承担了一部分本来有服务器承担的工作,从而大大减轻服务器的负担
    Ajax 优化了服务器和浏览器之间的传输,减少了不必要的数据往返,减少了带宽占用

    Jquery 是一个 JavaScript库,它通过封装原生的JavaScript 函数得到一整套定义好的方法。具有以下功能:

    链式操作方式 ( 对发生在同一个Jquery 对象上的一组动作,可以直接连接写而无需重复获取对象。)
    许多成熟的插件可供选择
    可靠的事件处理机制
    实现动画效果更方便[19][20] ,并且为网站提供 Ajax 交互

    Jquery 已经集成了 js 、CSS、DOM和 Ajax 于一体的强大功能,可以利用很少的代码,完成更多复杂的功能。Jquery 作为封装的库,其目的在于简化开发者使用js 。
    2 需求分析系统分析就是对系统从技术可行性、经济可行性和操作可行性进行分析。对软件开发中将要面临的问题及其解决方案进行初步设计及合理安排,明确开发目标。本系统就是以一个超级管理员和可由超级管理员增加减少的普通管理员共同管理的音乐管理系统。
    2.1 功能模块分析音乐网站系统主要由两部分组成:前台管理模块和后台管理模块。注册过的用户在进入该网站后,不仅可以查看音乐、上传音乐、并将自己喜欢的音乐添加到音乐盒,还可以进行留言。管理员登录后,不仅可以查看用户状态,还可以管理音乐、用户的信息。管理员还可以根据情况添加一些管理员以维护该音乐网站的环境及安全。

    登录与注销:每个用户必须用自己的注册的帐号登录到系统才可以访问网站。用户操作完成后退出系统,注销后可以重新登录系统
    系统管理员:实现管理员对音乐的删除、对注册过的用户进行删除、添加友情、修改密码链接等功能
    普通用户:普通用户可以浏览该网站的主页,包括试听、下载音乐,也可以进行留言;但不能查看音乐网站中的其他信息;必须要先注册之后才能登陆到系统中进行查看
    登陆用户:不但可以浏览该网站的信息,也可以进行留言、下载音乐;还可以通过网站给其他注册过的用户点歌,并将自己喜欢的音乐加入到音乐盒

    2.2 用例建模音乐网站分前台管理和后台管理两个大模块,其中前台管理又分为:首页、音乐盒、短信息、分享音乐、播放列表五大模块;后台管理又分为:后台首页、音乐管理、友情链接、用户管理、添加管理员、修改密码。根据以上功能,设计出了网站的总体架构模型,涵盖了整个网站的应用。逻辑模型如图2.1:

    3 系统设计本网站是一个免费、开放的音乐交流平台,对于网站,都必须有固定的服务器让用户进行访问,用户的访问在本系统中会记录相关信息。音乐网站有后台管理员,管理员可以对在网站内上传的音乐进行删除操作,也可以删除注册过的用户,还可以根据一些情况来增加其他管理员对音乐网站进行管理。
    对于只有注册过的用户,才可以对本网站内容进行浏览,进行音乐上传、试听及收藏和留言等。注册过的用户可以修改自己的密码,可以查询自己的账户信息,上传自己的喜欢的音乐及留言别人上传的音乐,还可以将别人上传的并且自己还喜欢的音乐添加到音乐盒。
    在功能实现方面,注册过的用户可以根据音乐了解其隶属于哪张专辑;根据上传的音乐可以查询到该音乐的信息(包括上传人的信息);根据上传时间查询最新上传的作品;可试听音乐,试听后如果喜欢也可下载音乐;并且可以对音乐进行留言。
    3.1 数据库的分析与设计数据库是计算机信息系统的基础。信息的收集、整理、存储、检索、更新、加工、统计和传播等操作必须在数据库管理系统的的支持下才能进行。目前,电脑系统的关键与核心部分就是数据库。数据库开发的优劣对整个系统的质量和速度有着直接影响。
    3.1.1 数据库的逻辑结构设计我们知道,数据库概念模型独立于任何特定的数据库管理系统,因此,需要根据具体使用的数据库管理系统的特点进行转换。即转化为按计算机观点处理的逻辑关系模型,E-R 模型向关系数据库模型转换应遵循下列原则:

    每一个实体要转换成一个关系
    所有的主键必须定义非空(NOT NULL)
    对于二元联系应按照一对多、弱对实、一对一、多对多等联系来定义外键

    管理员信息表主要是记录了管理员的基本信息。用户信息表(userTable)结构如表 3.1所示。



    列名
    数据类型
    长度
    允许空
    是否主键
    说明




    id
    int
    1


    序号


    username
    varchar
    20


    账号


    password
    varchar
    50


    密码


    email
    varchar
    20


    邮箱


    birthday
    date



    生日


    idnumber
    varchar
    20


    身份证


    sex
    varchar
    10


    性别


    qualify
    varchar
    50


    学历



    物件类别信息表主要是记录了物件类别的基本信息,歌曲信息表(musicTable)结构如表 3.2 所示。



    列名
    数据类型
    长度
    允许空
    是否主键
    说明




    id
    int
    1


    序号


    uploader
    varchar
    20


    更新者


    songtitle
    varchar
    30


    歌名


    singer
    varchar
    30


    歌手


    songimg
    varchar
    20


    封面图


    audiolength
    varchar
    20


    时长


    songarea
    varchar
    20


    地区



    3.1.2 数据库的连接原理对于不同的.NET 数据提供者,ADO.NET 采用不同的 Connection 对象连接数据库。这些 Connection 对象为我们屏蔽了具体的实现细节,并提供了一种统一的实现方法。在此处,因为我使用的数据库是 sql server 2012,所以我使用 vs 自带的 Connection 类自带的 SqlConnection 来连接数据库,代码如下:
    <?xml version='1.0' encoding='UTF-8'?><!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><!-- Generated by MyEclipse Hibernate Tools. --><hibernate-configuration> <session-factory> <property name="dialect"> org.hibernate.dialect.SQLServerDialect </property> <property name="connection.url"> jdbc:sqlserver://localhost:1433;databaseName=Music </property> <property name="connection.username">sa</property> <property name="connection.password">123456</property> <property name="connection.driver_class"> com.microsoft.sqlserver.jdbc.SQLServerDriver </property> <property name="myeclipse.connection.profile">Music</property> <mapping resource="bean/MusicTable.hbm.xml" /> <mapping resource="bean/UserTable.hbm.xml" /> </session-factory></hibernate-configuration>
    4 产品实现在管理信息系统的生命周期中,仅过了需求分析、系统设计等阶段之后,便开始了系统实施阶段。在系统分析和设计阶段,系统开发工作主要是集中在逻辑、功能和技术设计上,系统实施阶段要继承此前面各个阶段的工作成果,将技术设计转化为物理实现, 因此系统实施的成果是系统分析和设计阶段的结晶。
    4.1 用户管理模块实现为了保证系统的安全性,要使用本系统必须先登陆到系统中。仓库管理员登录采用后台数据库查询方式进行验证,先是在前台获取输入的管理中登录账号、密码, 点击登录后,通过数据库查询方式,后台进行验证,实现仓库管理员窗口登录。
    程序运行效果图如图 4.1 所示:

    4.1.2 功能实现角色管理 UserTableActio的主要代码:
    package action;import java.util.List;import java.util.Map;import javax.servlet.http.HttpSession;import org.apache.struts2.ServletActionContext;import org.hibernate.Query;import org.hibernate.Session;import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ActionSupport;import bean.UserTable;import config.HibernateSessionFactory;public class UserTableAction extends ActionSupport { private UserTable user; private List<UserTable> list2; private String checkCode; // 登录 public String login() { System.out.println("进入login成功!"); HttpSession session2 = ServletActionContext.getRequest().getSession(); boolean validated = false; String usr = user.getUsername(); String pwd = user.getPassword(); String checkCode2 = (String) session2.getAttribute("checkCode"); Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); String hql = "from UserTable WHERE username = ? AND password = ?"; try { System.out.println(checkCode2); List<UserTable> listx = session.createQuery(hql).setString(0, usr).setString(1, pwd).list(); if (usr.equals(listx.get(0)) && pwd.equals(listx.get(1)) && checkCode.equals(checkCode2)) validated = true; ActionContext actionContext = ActionContext.getContext(); Map<String, Object> map = actionContext.getSession(); map.put(usr, user); session.getTransaction().commit(); session.close(); return SUCCESS; } catch (Exception e) { return INPUT; } } // 注册 public String register() { System.out.println("进入register成功!"); Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Query query = session.createQuery("select id from UserTable"); UserTable user1 = new UserTable(); user1.setUsername(user.getUsername()); user1.setPassword(user.getPassword()); user1.setSex(user.getSex()); user1.setEmail(user.getEmail()); user1.setBirthday(user.getBirthday()); user1.setIdnumber(user.getIdnumber()); user1.setQualify(user.getQualify()); session.save(user1); session.getTransaction().commit(); session.close(); return SUCCESS; } //登出 public String logout(){ System.out.println("进入logout成功!"); ActionContext actionContext = ActionContext.getContext(); Map<String, Object> map = actionContext.getSession(); map.remove(user); return SUCCESS;} // getters and setters public UserTable getUser() { return user; } public void setUser(UserTable user) { this.user = user; } public List<UserTable> getList2() { return list2; } public void setList2(List<UserTable> list2) { this.list2 = list2; } public String getCheckCode() { return checkCode; } public void setCheckCode(String checkCode) { this.checkCode = checkCode; }}
    4.2 角色管理模块实现4.2.1 界面设计音乐管理列表界面

    音乐管理添加界面

    音乐管理修改界面

    4.2.2 功能实现音乐管理 MusicTableActio的主要代码:
    package action;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.sql.ResultSet;import java.sql.SQLException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Iterator;import java.util.List;import org.apache.struts2.ServletActionContext;import org.hibernate.Query;import org.hibernate.Session;import com.opensymphony.xwork2.ActionSupport;import bean.MusicTable;import config.HibernateSessionFactory;import method.CreateTxt;import method.ListToString;public class MusicTableAction extends ActionSupport { private MusicTable music; private List<MusicTable> list; private List<Object[]> list3; private char s = 's'; private int pageNum; private int totalpage; private int pageSize = 6; private int Amount; private InputStream fileInputStream; private String downloadfileName; private String tdfn;// truedownloadfilename private int pageNum1; private int totalpage1; private int pageSize1 = 6; private int Amount1; private int pageNum2; private int totalpage2; private int pageSize2 = 6; private int Amount2; private int pageNum3; private int totalpage3; private int pageSize3 = 6; private int Amount3; private int pageNum4; private int totalpage4; private int pageSize4 = 6; private int Amount4; private int pageNum5; private int totalpage5; private int pageSize5 = 6; private int Amount5; private int pageNum6; private int totalpage6; private int pageSize6 = 6; private int Amount6; private File upload; private String uploadFileName; private String truepath; private String name; private String keyString; // 对MusicTable的分页查询 public String find() { System.out.println("进入find成功!"); Amount = getAmount(); this.totalpage = Amount % pageSize == 0 ? (Amount / pageSize) : (Amount / pageSize + 1); if (pageNum <= 0) { this.pageNum = 1; } if (pageNum > totalpage) { this.pageNum = totalpage; } Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); String hql = "from MusicTable"; Query query = session.createQuery(hql); query.setFirstResult(((pageNum - 1) * pageSize)); query.setMaxResults(pageSize); list = query.list(); System.out.println(list); session.getTransaction().commit(); session.close(); return "success"; } // 查询按local public String local() { System.out.println("进入local成功!"); Amount1 = getAmount1(); this.totalpage1 = Amount1 % pageSize1 == 0 ? (Amount1 / pageSize1) : (Amount1 / pageSize1 + 1); if (pageNum1 <= 0) { this.pageNum1 = 1; } if (pageNum1 > totalpage1) { this.pageNum1 = totalpage1; } Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Query query = session.createQuery("from MusicTable where songarea = ?"); query.setFirstResult(((pageNum1 - 1) * pageSize1)); query.setMaxResults(pageSize1); query.setParameter(0, "内地"); list = query.list(); session.getTransaction().commit(); session.close(); return SUCCESS; } // 查询按hongkong public String hongkong() { System.out.println("进入hongkong成功!"); Amount2 = getAmount2(); this.totalpage2 = Amount2 % pageSize2 == 0 ? (Amount2 / pageSize2) : (Amount2 / pageSize2 + 1); if (pageNum2 <= 0) { this.pageNum2 = 1; } if (pageNum2 > totalpage2) { this.pageNum2 = totalpage2; } Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Query query = session.createQuery("from MusicTable where songarea = ?"); query.setFirstResult(((pageNum2 - 1) * pageSize2)); query.setMaxResults(pageSize2); query.setParameter(0, "港台"); list = query.list(); session.getTransaction().commit(); session.close(); return SUCCESS; } // 查询按usa public String usa() { System.out.println("进入usa成功!"); Amount3 = getAmount3(); this.totalpage3 = Amount3 % pageSize3 == 0 ? (Amount3 / pageSize3) : (Amount3 / pageSize3 + 1); if (pageNum3 <= 0) { this.pageNum3 = 1; } if (pageNum3 > totalpage3) { this.pageNum3 = totalpage3; } Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Query query = session.createQuery("from MusicTable where songarea = ?"); query.setFirstResult(((pageNum3 - 1) * pageSize3)); query.setMaxResults(pageSize3); query.setParameter(0, "欧美"); list = query.list(); session.getTransaction().commit(); session.close(); return SUCCESS; } // 查询按japan public String japan() { System.out.println("进入japan成功!"); Amount4 = getAmount4(); this.totalpage4 = Amount4 % pageSize4 == 0 ? (Amount4 / pageSize4) : (Amount4 / pageSize4 + 1); if (pageNum4 <= 0) { this.pageNum4 = 1; } if (pageNum4 > totalpage4) { this.pageNum4 = totalpage4; } Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Query query = session.createQuery("from MusicTable where songarea = ?"); query.setFirstResult(((pageNum4 - 1) * pageSize4)); query.setMaxResults(pageSize4); query.setParameter(0, "日本"); list = query.list(); session.getTransaction().commit(); session.close(); return SUCCESS; } // 查询按korea public String korea() { System.out.println("进入korea成功!"); Amount5 = getAmount5(); this.totalpage5 = Amount5 % pageSize5 == 0 ? (Amount5 / pageSize5) : (Amount5 / pageSize5 + 1); if (pageNum5 <= 0) { this.pageNum5 = 1; } if (pageNum5 > totalpage5) { this.pageNum5 = totalpage5; } Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Query query = session.createQuery("from MusicTable where songarea = ?"); query.setFirstResult(((pageNum5 - 1) * pageSize5)); query.setMaxResults(pageSize5); query.setParameter(0, "韩国"); list = query.list(); session.getTransaction().commit(); session.close(); return SUCCESS; } // 添加 public String upload() throws Exception { System.out.println("进入upload成功!"); String path = ServletActionContext.getServletContext().getRealPath("/"); InputStream is = new FileInputStream(upload); String ext = uploadFileName.substring(uploadFileName.lastIndexOf(".")); name = System.currentTimeMillis() + ext; OutputStream os = new FileOutputStream(path + "img/" + name); byte buffer[] = new byte[1024]; int count = 0; while ((count = is.read(buffer)) > 0) { os.write(buffer, 0, count); } os.close(); is.close(); Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Query query = session.createQuery("select id from MusicTable"); MusicTable music1 = new MusicTable(); music1.setUploader(music.getUploader()); music1.setSongtitle(music.getSongtitle()); music1.setSinger(music.getSinger()); music1.setSongimg(name); music1.setAudiolength(music.getAudiolength()); music1.setSongarea(music.getSongarea()); session.save(music1); session.getTransaction().commit(); session.close(); return SUCCESS; } // 下载歌单 public String download() { System.out.println("进入download成功!"); String pathdw = ServletActionContext.getServletContext().getRealPath("/"); File file = new File(pathdw + "/text/" + getTdfn()); downloadfileName = file.getName();// 获取文件名 try { fileInputStream = new FileInputStream(file); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return SUCCESS; } // 对musicTable的投影查询根据id public String createMusicList() { System.out.println("进入createMusicList成功!"); Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Query query = session.createQuery( "select new List(id,songtitle,singer,uploader,audiolength,songarea) from MusicTable music"); list3 = query.list(); CreateTxt createTxt = new CreateTxt(); ListToString listToString = new ListToString(); Date d = new Date(); System.out.println(d); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); String dateNowStr = sdf.format(d); System.out.println(dateNowStr); try { createTxt.creatTxtFile(dateNowStr + "SongList"); tdfn = dateNowStr + "SongList.txt"; createTxt.writeTxtFile(listToString.listToString(list3, s)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } session.getTransaction().commit(); session.close(); return "success"; } // 删除前 public String predel() { return SUCCESS; } // 删除 public String del() { System.out.println("进入del成功!"); Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); MusicTable music2 = (MusicTable) session.load(MusicTable.class, music.getId()); session.delete(music2); session.getTransaction().commit(); session.close(); return SUCCESS; } // 修改前 public String preupdate() { Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); String hql = "select songtitle,singer,songimg,songarea from MusicTable where id=" + music.getId(); Query query = session.createQuery(hql); list = query.list(); for (Iterator iter = list.iterator(); iter.hasNext();) { Object[] obj = (Object[]) iter.next(); music.setSongtitle((String) obj[0]); music.setSinger((String) obj[1]); music.setSongarea((String) obj[3]); } session.getTransaction().commit(); session.close(); return SUCCESS; } // 修改 public String update() { System.out.println("进入update成功!"); Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); MusicTable music3 = (MusicTable) session.load(MusicTable.class, music.getId()); music3.setSongtitle(music.getSongtitle()); music3.setSinger(music.getSinger()); music3.setSongarea(music.getSongarea()); session.update(music3); session.getTransaction().commit(); session.close(); return SUCCESS; } // 按查询关键字 public String search() { System.out.println("进入search成功!"); Amount6 = getAmount6(); this.totalpage6 = Amount6 % pageSize6 == 0 ? (Amount6 / pageSize6) : (Amount6 / pageSize6 + 1); if (pageNum6 <= 0) { this.pageNum6 = 1; } if (pageNum6 > totalpage6) { this.pageNum6 = totalpage6; } Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Query query = session.createQuery("from MusicTable where songtitle like ?"); query.setFirstResult(((pageNum6 - 1) * pageSize6)); query.setMaxResults(pageSize6); query.setParameter(0, "%" + getKeyString() + "%"); list = query.list(); session.getTransaction().commit(); session.close(); return SUCCESS; } // getters and setters public MusicTable getMusic() { return music; } public void setMusic(MusicTable music) { this.music = music; } public List<MusicTable> getList() { return list; } public void setList(List<MusicTable> list) { this.list = list; } public int getPageNum() { return pageNum; } public void setPageNum(int pageNum) { this.pageNum = pageNum; } public int getTotalpage() { return totalpage; } public void setTotalpage(int totalpage) { this.totalpage = totalpage; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getAmount() { int i = 0; Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); String hql = "select count(*) from MusicTable"; Query query = session.createQuery(hql); // 2、获取结果(结果为long类型) Object obj = query.uniqueResult(); // 3、转化为long(类型为long,转为int会报错) Long long1 = (Long) obj; i = long1.intValue(); session.getTransaction().commit(); session.close(); return i; } public int getAmount1() { int i = 0; Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); String hql = "select count(*) from MusicTable where songarea = '内地'"; Query query = session.createQuery(hql); // 2、获取结果(结果为long类型) Object obj = query.uniqueResult(); // 3、转化为long(类型为long,转为int会报错) Long long1 = (Long) obj; i = long1.intValue(); session.getTransaction().commit(); session.close(); return i; } public int getAmount2() { int i = 0; Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); String hql = "select count(*) from MusicTable where songarea = '港台'"; Query query = session.createQuery(hql); // 2、获取结果(结果为long类型) Object obj = query.uniqueResult(); // 3、转化为long(类型为long,转为int会报错) Long long1 = (Long) obj; i = long1.intValue(); session.getTransaction().commit(); session.close(); return i; } public int getAmount3() { int i = 0; Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); String hql = "select count(*) from MusicTable where songarea = '欧美'"; Query query = session.createQuery(hql); // 2、获取结果(结果为long类型) Object obj = query.uniqueResult(); // 3、转化为long(类型为long,转为int会报错) Long long1 = (Long) obj; i = long1.intValue(); session.getTransaction().commit(); session.close(); return i; } public int getAmount4() { int i = 0; Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); String hql = "select count(*) from MusicTable where songarea = '日本'"; Query query = session.createQuery(hql); // 2、获取结果(结果为long类型) Object obj = query.uniqueResult(); // 3、转化为long(类型为long,转为int会报错) Long long1 = (Long) obj; i = long1.intValue(); session.getTransaction().commit(); session.close(); return i; } public int getAmount5() { int i = 0; Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); String hql = "select count(*) from MusicTable where songarea = '韩国'"; Query query = session.createQuery(hql); // 2、获取结果(结果为long类型) Object obj = query.uniqueResult(); // 3、转化为long(类型为long,转为int会报错) Long long1 = (Long) obj; i = long1.intValue(); session.getTransaction().commit(); session.close(); return i; } public void setAmount(int amount) { Amount = amount; } public int getPageNum1() { return pageNum1; } public void setPageNum1(int pageNum1) { this.pageNum1 = pageNum1; } public int getTotalpage1() { return totalpage1; } public void setTotalpage1(int totalpage1) { this.totalpage1 = totalpage1; } public int getPageSize1() { return pageSize1; } public void setPageSize1(int pageSize1) { this.pageSize1 = pageSize1; } public int getPageNum2() { return pageNum2; } public void setPageNum2(int pageNum2) { this.pageNum2 = pageNum2; } public int getTotalpage2() { return totalpage2; } public void setTotalpage2(int totalpage2) { this.totalpage2 = totalpage2; } public int getPageSize2() { return pageSize2; } public void setPageSize2(int pageSize2) { this.pageSize2 = pageSize2; } public int getPageNum3() { return pageNum3; } public void setPageNum3(int pageNum3) { this.pageNum3 = pageNum3; } public int getTotalpage3() { return totalpage3; } public void setTotalpage3(int totalpage3) { this.totalpage3 = totalpage3; } public int getPageSize3() { return pageSize3; } public void setPageSize3(int pageSize3) { this.pageSize3 = pageSize3; } public int getPageNum4() { return pageNum4; } public void setPageNum4(int pageNum4) { this.pageNum4 = pageNum4; } public int getTotalpage4() { return totalpage4; } public void setTotalpage4(int totalpage4) { this.totalpage4 = totalpage4; } public int getPageSize4() { return pageSize4; } public void setPageSize4(int pageSize4) { this.pageSize4 = pageSize4; } public int getPageNum5() { return pageNum5; } public void setPageNum5(int pageNum5) { this.pageNum5 = pageNum5; } public int getTotalpage5() { return totalpage5; } public void setTotalpage5(int totalpage5) { this.totalpage5 = totalpage5; } public int getPageSize5() { return pageSize5; } public void setPageSize5(int pageSize5) { this.pageSize5 = pageSize5; } public void setAmount1(int amount1) { Amount1 = amount1; } public void setAmount2(int amount2) { Amount2 = amount2; } public void setAmount3(int amount3) { Amount3 = amount3; } public void setAmount4(int amount4) { Amount4 = amount4; } public void setAmount5(int amount5) { Amount5 = amount5; } public String getKeyString() { return keyString; } public void setKeyString(String keyString) { this.keyString = keyString; } public int getAmount6() { int i = 0; Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); String hql = "select count(*) from MusicTable where songtitle like ?"; Query query = session.createQuery(hql); query.setParameter(0, "%" + getKeyString() + "%"); // 2、获取结果(结果为long类型) Object obj = query.uniqueResult(); // 3、转化为long(类型为long,转为int会报错) Long long1 = (Long) obj; i = long1.intValue(); session.getTransaction().commit(); session.close(); return i; } public int getPageNum6() { return pageNum6; } public void setPageNum6(int pageNum6) { this.pageNum6 = pageNum6; } public int getTotalpage6() { return totalpage6; } public void setTotalpage6(int totalpage6) { this.totalpage6 = totalpage6; } public int getPageSize6() { return pageSize6; } public void setPageSize6(int pageSize6) { this.pageSize6 = pageSize6; } public void setAmount6(int amount6) { Amount6 = amount6; } public File getUpload() { return upload; } public void setUpload(File upload) { this.upload = upload; } public String getUploadFileName() { return uploadFileName; } public void setUploadFileName(String uploadFileName) { this.uploadFileName = uploadFileName; } public String getTruepath() { return truepath; } public void setTruepath(String truepath) { this.truepath = truepath; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Object[]> getList3() { return list3; } public void setList3(List<Object[]> list3) { this.list3 = list3; } public char getS() { return s; } public void setS(char s) { this.s = s; } public InputStream getFileInputStream() { return fileInputStream; } public void setFileInputStream(InputStream fileInputStream) { this.fileInputStream = fileInputStream; } public String getDownloadfileName() { return downloadfileName; } public void setDownloadfileName(String downloadfileName) { this.downloadfileName = downloadfileName; } public String getTdfn() { return tdfn; } public void setTdfn(String tdfn) { this.tdfn = tdfn; }}
    5 产品测试5.1 测试方法与策略系统测试的任务是尽可能彻底的检查出程序中的问题,提高软件系统的可靠性,其目的是检验系统是不是合格。系统测试是正对整个仓库管理系统进行的测试,目的是验证系统是否满足了需求规格的定义,找出需求规格不符合或与之矛盾的地方。
    5.2 用户管理模块测试测试流程

    打开登录界面,输入错误的登录信息
    点击登录按钮
    输入正确的登录信息
    点击登录按钮登录
    测试结果




    模块名称
    测试用例
    预期结果
    实际结果
    是否通过




    登录模块
    用 户 名 : null 密码:null
    弹出错误提示, 请输入正确的 账号密码
    登陆失败,提示请输入正确的 账号密码
    通过


    登录模块
    用户名:a 密码:null
    弹出错误提示, 请输入正确的 账号密码
    失败,提示请输入正确的账号 密码
    通过


    登录模块
    用户名:a 密码:1
    弹出错误提示, 用户名或者密 码错误
    登陆失败,提示用户名或者密 码错误
    通过


    登录模块
    用户名:zhangsan 密码:123
    提示成功登录
    提示成功登录
    通过



    5.3 音乐管理模块测试


    模块名称
    测试用例
    预期结果
    实际结果
    是否通过




    增加模块
    增加一首十年
    添加成功
    添加成功
    通过


    删除模块
    删除一首易燃易爆炸
    删除成功
    删除成功
    通过


    修改模块
    修改绒花的封面图
    修改成功
    修改成功
    通过


    查询模块
    查询我在未来等你
    查询成功
    查询成功
    通过



    6 结论本人将大学期间所了解到的计算机工程理论知识运用到了本次的毕业来发中来。即对基础学问进行了加强,同时也增加了动手能力。在这段时期里,我在各大开源网站查找了大量关于仓库管理系统以及管理系统方面相关的资料,查阅了很多 windowform 平台技术的相关文献以及学习资料,结合自己在公司学习项目的经验,对仓库管理系统的运作程序以及仓库管理的内容进行了详细调查,设计了这个仓库管理系统,即使在学校里面,每个学期的期末的时候,虽然学校针对动手练习都会开始相应的课程设计和实训, 但是都是一些小模块和工程量相对适中,且有老师一带一路做的感觉,难度不大,但是这次在做毕业设计则截然不同,完全靠自己的资料查阅和心中所想来完成自己所想做的毕业设计,完完全全独立做了一个相对来说功能较多的项目,对于自我提升是十分巨大的,不仅提高了自身的解决问题的能力也提升了自我的编程能力,每当解决项目中发生的问题,对于自己来说是有很大的帮助,出现问题不可怕,只要自己能坚持找出错误, 并且完善改正,必定会有巨大的提高,做程序的过程中有些很小的问题,常常是困扰自身很久时间的东西,因为系统编译并不会报错,但是却让你难以寻找,所以我们编程的时候一定要专心、仔细地检查,可以避免一些本无必要的时间的浪费。
    在开发系统的过程中,本人运用到了 C#技术和平时学习中所了解的一些技术与辅助工具,通过实现这些技术和运用这些工具,大大提高了整个系统的性能以及开发项目的速度。本系统还存在很多缺点和不完善的地方,例如界面并不是很好看,在细节上还有很多方面做的还不够完善,有些模块的功能还是过于简单,还需要加强。希望在以后的学习工作中能够学到更多的东西,来完善自己。
    通过本次毕业设计增强了自身的解决问题的能力和自身的学习能力,也从中学到很多在课堂上老师所难以教授的知识。通过实践我也深深的认识到开发软件所需要的品质以及软件开发的流程,使我软件编程的思维问题的能力有了比较大的提高,同时也培养了我实际做项目的能力,为我在工作中做项目有了一定的基础帮助。 
    参考文献[1] 厉建欣.司青燕.论 MySQL 开源数据库在中小企业的应用 [J].商场现代化.2010:17-18.
    [2] 罗义斌.丁志强.用 JDBC 实现 Java 程序与数据库的连接 [J].中文信息.2011:87-88.
    [3] 孙建华.Java 语言的应用简述 [J].电子技术与软件工程.2015,01:257.
    [4] 贾俊奇.软件开发下的JAVA 语言 [J].中国科技信息.2014,13:133-134.
    [5] 刘京华.Java Web 整合开发王者归来 [M].北京:清华大学出版社.2010:112-113.
    [6] 冷巨冰.Java 语言的发展与 Java 技术 [J].硅谷.2011(03):87-88.
    [7] 唐溢.JSP 技术在 WEB 页面中的应用研究 [J] .信息技术与信息化.2014,12:151-153.
    [8] 王景.JSP 动态网站的技术开发分析[J].赤峰学院学报(自然科学版),2013,20:24-26.
    [9] 任智乾.JSP技术在 Web 数据库中的应用[J].信息与电脑(理论版),2011,06:161+163.
    [10] 张超.基于 JSP 的 MVC 设计模式探究 [J].电脑与信息技术.2013(4):92-96.
    [11] 叶洁.基于 JSP 和 Java组件的动态 Web 网页的设计与实现 [J].现代机械 ,2003,03:26-27.
    [12] 常红梅.JSP 与 Servlet 技术对比 [J].太原科技.2008,01:62-63.
    [13] 周会强.基于 Struts2 框架的 Java Web 应用开发研究 [J].科技通报.2012(6):123-126.
    [14] 邱 晓 荣.基于 MVC 模式的 Struts2 框架在 Web 应用开发中的实现 [J].黑龙江科技信息.2012,18:98.
    [15] 张志刚.Struts 2 框架技术开发与应用 [J].计算机光盘软件与应用,2013,23:119-120.
    [16 刘楠楠. MVC 框架在软件开发中的应用研究 [J].数字技术与应用,2012,04:70.
    [17] 文永胜.Web 中利用 Ajax 技术进行模型优化 [J].科技信息(科学教研).2011(23):102-104.
    [18] 徐英娟.Ajax 基本原理及其 Web 应用探讨[J].电脑知识与技术.2012(12):73-75.
    [19] 尹婷,赵思佳.基于 Jquery 框架的 AJAX 网站设计模式的研究[J].湖南环境生物职业技术学院学报.2010(03):90-91.
    [20] 王洪九.运用 Jquery 和 ajax 实现数据库数据的提取和分页 [J].信息与电脑(理论版) .2012(09):76-77.
    1 评论 2 下载 2020-08-25 11:27:57 下载需要13点积分
  • 基于C#和SQL SERVER数据库实现的餐饮收银系统

    1 需求分析分析思维导图

    2 部分原型设计图登录

    管理员主页面

    3 实际实现界面注册界面

    登录界面

    管理员主页面

    添加食物界面

    服务员订单界面

    修改食物详情界面

    未完成订单界面

    支付成功并找零界面

    已完成订单界面

    4 程序使用说明
    管理员账号和密码:admin, admin
    服务员账号和密码: test, test

    注:可自行注册账号并登录,但是只能注册服务员账号
    5 总结这次写C#作业还是挺累的。我按照正常的软件开发流程写这个作业。借用思维导图,花了大概两个小时进行需求分析和原型设计。当然,在分析的过程中,始终无法对整个项目进行细致入微地考虑,所以总有考虑不周的地方,比如进行原型设计的时候没有考虑到实现的难度,或者说考虑地不够,导致在项目进行时对原型进行了些许微调。
    整个分析的过程是非常有效的,尤其是数据库,在实施过程中只进行了很少的微调。由于C#语言基础知识掌握不够,只花一个小时看完教科书就上手干,其中走了不少弯路。比如在连接数据库的时候总是连接不上(花了一整天连接Sql Server,可还是不行),后来才知道是Visual Studio缺少组件,后来改用比较熟悉的MySQL才将数据库问题解决。
    另外一个需要值得反思的是把大把时间花在UI上是否值得。虽然项目写出来非常好看,但是功能模块并不多,只是够用。这次作业大概花了三天的时间才做完,是远超出预期的,但是在这过程中确实学到了很多,踩了很多坑,比如把项目写残了一次,不过幸好用版本控制工具git给回滚回来了。
    期间解决了很多问题,对C#的掌握更深了,总的来说还是比较满意的。
    4 评论 79 下载 2018-11-06 10:39:08 下载需要12点积分
  • 基于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
    2 评论 40 下载 2020-03-30 08:31:42 下载需要15点积分
  • 基于SSH和MySQL的保险业务管理系统的设计与实现

    摘 要历经二十余年的高速发展,我国保险行业的市场竞争已经达到白热化的程度,在同一个城市往往有数十家主体参与保险业务的竞争。保险企业的竞争异常激烈,想要在现在这复杂多变的市场环境中跳出来,必须好好的进行业务的管理。广大保户在享受着竞争带来的实惠同时也变得更加挑剔,哪家保险公司能提供更好的服务往往成为其最终决定的关键因素。在这种环境下,越来越多的保险公司使用管理系统来提供更好的服务。目前保险公司的业务和管理信息平台,大多依从原来的内部开发思路搭建。一旦有新的应用要求,新开发出的系统又要考虑和以前系统的单独集成。而老系统的升级又会引发大量的系统更新和检测工作。因此一个好的系统对于企业是很重要的。
    关键词:互联网;保险行业;Mysql;SSH ;B/S
    AbstractAfter more than twenty years of rapid development, China’s insurance industry market competition has reached a white hot degree, in the same city, there are often several main players compete in the insurance business. The majority of households in the enjoyment of the benefits brought by the competition has become more critical, which insurance companies can provide better service is often a key factor in the final decision. In this environment, more and more insurance companies use the management system to provide better service. At present, the insurance company’s business and management information platform, mostly with the original internal development ideas. Once a new application is required, the newly developed system will be considered separately from the previous system. The upgrading of the old system will lead to a large number of system updates and testing. So a good system is very important to the enterprise.
    Key words: Internet; Insurance Industry; Mysql; SSH; B/S
    一、研究背景及意义1.1 研究背景科技增长的日新月异,由于不断进步的科学技术以及社会生产化的趋向扩大使得人类的科技水平大大增强,人类文明思想的富裕堪称越来越加强,思维的灵活加强速率呈超速加速。市场争抢日益严厉的趋势,使得人们对新闻的观念产生了根本性的变革。使新闻成为了继物资、动力后,文字被摆为与其并发的人类社会发育的第三大物资。
    在计算机基本普及的今天,网络科技的发展使得在家办公变得不再陌生,几乎家家户户都有一台以上的网络设备。最新数据截至到2016年9月,中国网民规模达7.4亿,互联网普及率超过50%,由此可见因特网的传播率之高。显然,互联网已经渐渐地成为了我们生涯的一个区域,上网环节的日益美满,以及越来越增长的变换因特网技术,终于使得各类互联网应用技术根据需求被逐渐的开发。
    到了如今社会,在面临损失和灾难的时候人们通常希望能够保证自己财产的安全,而且他们也想尽各种办法来避免生活中的一些损失,因此保险业务得以派上用场,从古至今,人们都拥有保险意识,人类社会一直以来就面临着自然灾害和意外的事件的困扰,人们在与大自然抗衡的时候,就萌生了对付意外事故和伤害的保险。我国的历任王朝都十分重视粮食的储存,被称为孔圣人的孔子就提出过“耕三余一”的思想颇具代表性。在国外,古埃及的石匠之间就有一种互助基金组织,该组织向每一位会员收取会费,假使有个别会员死灭,收到的费用就用来领取故去成员的死亡赔偿金,还有古代落马中不对里面的兵士结构,会用收取来的会费来抚慰死去战士的家属,这就是原始的保险雏形。现代保险发源于意大利,14世纪中叶出现了世界最古老的保险,是海上保险的雏形,此后,安全的作法迅速传播尽欧洲各个康吹,到了十七时代,伦敦已经成为了全球保险行业的大旨。在上海创设了华安合群保寿单位,这是国内首家华人资产人保险单位。到了21世纪保险已成为人们生活不可或缺的一部分。各种各样的保险业务在现实生活中无处不在,已经成为人们正常生活不可或缺的一项业务。由于社会的发展、人们对保险意识增强因此保险业务的数量快速增加。但是保险公司为了确保公司业务可持续增长,公司因此来自己培养高效率和训练有素的销售队伍,并且在各个地区建立自己的分公司以用来扩展保险业务,以记录所有投保人的详细信息,但是直到目前为止,手工依然作为主要的纪录形式。
    随着保险市场的逐渐增加,保险主体的市场已经逐渐完成。在1988年以前,只有中国人民保险公司在我国保险市场上经营。1988年以来,随着安平保险企业、太平洋保险公司的接踵创设,安全局势私家操作的款式被冲破。截至二零一一年终,国内国有中资、外国保险企业共一百五十八家。另外,保险中介介于保险机构之间或保险机构与投保人之间,专门从事保险中介服务,并从中遵章夺取回佣的企业和个人。部门也一直增长,截至二零一零年十二月底,我们国家保险市场上职业保险代购单位、安全经济企业和安全公共估算企业已经达到2461家左右,保险中介布局市场首先产生。
    安全主要市场的多方位,有力地促进了保险企业管理意识的变化,使之逐步创立了服务思想、竞赛思想、利益思维和发育思维。安全市场的膨胀逐渐由量的转向质的升高。
    然而随着业务的扩展和参保人数的增多,所要记录的信息必然会越来越多,每天让员工从几千堆的以硬盘形式存储的数据文件中查找客户的信息,不但费时、低效而且枯燥乏味。由此,保险公司为了合理方便的管理处理客户信息、业务运 作信息,让客户、员工、管理员方便的拥有自己的权限并对自己的信息模块进行操作,借助一个现代化计算机技术建立一个高效的管理信息系统是关键。
    1.2 行业背景保险是指将通过约定模式集合起来的本钱,用来补充被保护人的金钱利润的行业。
    安全是指投资人根据合约,向客户领取安全金,客户对于合约的可能爆发的事项因其发生而造成的物业承担损失补偿赔偿金职责,或者当客户死灭、伤亡和达到合同约定的春秋、限期时经受支付安全费职责的行为。
    安全市级是生意安全即双方签订安全合约的场合。它可以是集中的市集,也可以是疏散的没有性的市场。
    按照保险标的的不同,保险可分为财产保险和人身保险两大类。
    安全金钱是指以物业及其有关职责为安全性的的安全,包括金钱丢失保险、职责保险、守信保险、确保保险、农民保险等。它是财产及其相关利益为保险标的的一项赔偿性保险。
    人身保险是用的生命和身段为安全性的的业务。当人们遭遇祸患或因生病、垂老以致遗失工作力气、残疾、死灭或年老下岗时,根据安全合约,客户对被保险人或得利者支付保险金钱或年终奖,以办理其因病、残、老、死所造成的金币缺失。
    按照与投资人有没有直接相关关系,安全可变为原保险和二次保险。发生在保险人和投保人之间的安全举动,被叫为原保险。发生在保险人与保险人之间的保险行为,称之为二次保险。
    1.3 国内外现状1.3.1 国内现状随着资产配置更加多元化,中国社会老龄化问题日益突出,巨大的保险需求仍是国内寿险保 费收入增长的原动力,因此预计未来一年国内寿险公司整体保费收入仍将增长,根据测算,预计 2017 年保费增速将达到 10%。保费的迅速增长也表明保险业务的快速增加,随之而来的管理问题以及工作效率的问题也被放大。
    我国在加入世界贸易组织后组织后,国外的保险也对我国的业务产生了重大的影响,我国的保险业务开始体现出了国际化的特征,对中国保险行业的扩展有着很大的帮助,新的公司发展形势,对传统的保险业发展产生了很大的影响,是的对公司的能力要求产生了很大的增加,所以对保险的管理的依赖性就加强了很多,一个好的管理系统可以帮助公司脱颖而出,成为保险行业中的佼佼者。信息系统的好坏讲直接的影响到公司的发展。信息管理系统的好坏是未来保险公司想要在竞争中大白竞争对手的关键。
    目前的通信结构已经无法越好地满足行业程序与处理措施高准侧的要求,不足国度衡量的准则以及领导指示各地根据地区的处境,创建自己的信息工程。有些地方的结构项目没有按照意图及标相关设计的要求,致使软件的多次开发;上网连接阻断;新闻系统搭建如今还没有准确的金钱源头,对于新闻系统的组建金钱明显不足;缺乏结构和精英上的能力确保。外界的安全中介组织在很多区域没有专业实际的外部经营部门。社会安全中介部门的计算器精英不足,这种情况严重约束着全部保险新闻体系的创建和发展。所以保险业务管理系统的设计的实现就显得十分重要了。
    1.3.2 国外现状由于临时的区域知识和新闻模板的沟通,及这些年的阐明、设计安全业务员软件经历的积聚,外国安全业务使用设施在数字模板的构建上有一定的优点,具体反映在这多个方面,首先,具有完美的数据词典。数据字典是整个应用系统的基础,它包括各种数据项 的分类和定义,是保险行业应用软件的基石。第二,数据取值标准化。全面的数据取值定义,是系统标准化的基础,保证了软件系统的整体性、一致性和可操作性。第三,数据实体及关系。在数据项的基础上,数据实体及关系是表达保险行业 知识的最有效方法,在信息系统模型中占有重要地位。
    国外的很多系统已有20—30年的使用历史,积累了各种成功和失败的经验,这些是非常宝贵的资料,从整个应用系统发展看,应当是教训多于经验,这对我国保险公司管理系统进一步的开发具有很强的借鉴作用。特别在组织管理经验方面。所以我们十分有必要学习外国公司的管理方法。常言道—取其精华,去其糟粕。向他们好的一方面学习,同时也要去掉其中一些不好的东西。一个好的东西是值得我们学习的。学习好国外优秀的保险管理机制,可以使我们国内的保险行业发展的更加的优秀。一个好的股息机制可以促进我们变得越好。国外的软件行业相对于国内来说得话,发展的比较早,所以说他们的系统相对的也就比较完善一些,所以我们需要借鉴他们的优秀管理系统,才能使我们的保险行业发展的更加壮大。
    1.4 研究意义众所周知,不论什么公司想要发展都在不同程度上依赖一定的技术和知识才能够更好的发展与生存。尤其是在如今这知识经济和信息经济的时代,现在企业之间的竞争更多的是在于知识获取和信息获取使用能力的竞争。所以对企业对信息资源的有效管理和及时获取是当今时代更似想要更好发展的前提。只有在信息处理方面采取了有效的措施,才能够使公司企业在激烈的竞争中长期处于不败之地。不论任何一个行业,对需要一个优秀的管理机制,这样的话才可以公司发展得更加的完善。古语云:工预善其事,必先利其器。这就是一个充分的代表,一个好的公司想要在负载的环境中脱颖而出,就必须拥有一个优秀的管理系统,而现在互联网技术已经得到了非常迅速的发展,于是就特别的有必要建立一个可以是现在web浏览器上的一个系统来进行公司保险业务的管理,由此我们的系统就应孕而生了。
    通过本系统可以使保险业务的管理更加方便,用户和管理人员通过管理系统可以更加方便的进行保险的买入和对业务的管理,比传统的手工管理方便了好多。为管理人员提供方便条件。且系统运行稳定,数据安全可靠。在现代化管理中,计算机系统已经成为企业管理不可缺少的帮手。它的广泛应用已经成为现代化管理的重要标志。面对越来越多的信息资源和复杂的企业环境,相信企业有必要创建高效率的、实用性强的信息管理系统。这是现代化管理的必然趋势。因此很有必要开发一个管理系统来进行企业的业务管理。
    保险管理系统的开发目的是使保险业务的管理模式从手工记录转变成信息管理,为管理人员提供方便条件。对保险业务的实际情况进行调研之后,进行详细的需求分析,对现有的管理模式进行改进,开发出一套新型的管理系统,从中领悟系统开发的思想,掌握系统开发的流程和方法。开发这个管理信息系统优势主要体现在,极大提高了保险公司工作人员的工作效率,大大减少了以往出入存流程繁琐,杂乱,周期长的弊端。借助计算机系统对数据处理的严密性等特有机制,在改善保险业务的数据管理方式,降低业务人员的劳动强度,提高劳动生产率等等方面,保险业务管理系统都起到了良好的效果。同时还能使得业务流程更加规范化,信息和数据的处理更加高效准确,能适应信息化的要求,能帮助工作人员利用计算机,快速方便的对信息和数据流进行管理、输入、输出、查找的所需操作,使杂乱的业务数据能够具体化,直观化、合理化等。
    保险业务系统的实施的现实意义:

    系统处理业务更高效 , 节约人力资源
    基本信息的全面设置、数据录入方便、快捷
    最大限度的实现了易维护性和易操作性
    系统运行稳定,数据安全可靠

    本系统主要是为了开发一个操作方便、使用快捷、处理高效的保险管理系统。因此,本系统是从人工操作容易产生错误、过程繁琐、工作效率不高,保密性差不足之处,对系统的可操作性、稳定性和实用性有一定的限制,并能安全地保存数据于数据库中来提高其系统的保密性。使其真正实现保险管理系统的安全化、规范化、科学化、信息化。最终使公司能够更好地管理保险业务。本系统是从人工操作容易产生错误、过程繁琐、工作效率不高,保密性差不足之处,对系统的可操作性、稳定性和实用性有一定的限制,并能安全地保存数据于数据库中来提高其系统的保密性。使其真正实现保险管理系统的安全化、规范化、科学化、信息化。
    二、系统开发技术2.1 系统开发工具2.1.1 Jsp技术JSP技术是开发Java Web应用程序的主要技术,全名为java server page,其根本是一个简化的Servlet设计。它是由Sun Microsystems在1996年开发的,和许多公司一起建立的一种动态网页技术标准。JSP是servlet技术的扩展,现在的版本是1.2(2.0版将很快定下来)。有人认为JSP是servlets的替代,但实际并不是这样的。Servlets和JSP是一起用于复杂的Web应用程序的。
    JSP技术有点类似ASP技术,它是在传统的网页HTML文件(*.htm,*.html)中插入Java程序段(Scriptlet)和JSP标记(tag),从而形成JSP文件(*.jsp),而构成的JSP网页的程序片段可以控制数据库、对网页重新定向和发送E-mail等,从而满足建立动态网站所需要的功能。 简单来说JSP可用等式表示为:HTML+Java=JSP。JSP技术的运行原理为所有JSP页面,在执行的时候都会被服务器端的JSP引擎转换为Servelet(.java),然后又由JSP引擎调用Java编译器,将Servelet(.java)编译为Class文件(.class),并由Java虚拟机(JVM)解释执行。主要采用JSP技术的原因在于它对客户浏览器的要求不高因为所有操作都是在服务器端执行,客户只接收传送结果,就算客户端的浏览器不支持Java,同样可以访问JSP网页。Web应用如果用JSP开发就能跨平台使用,在Linux和其他操作系统上都能运行。
    JSP技术通过Java语言来编写类的标签来进行对网页的处理逻辑的封装使用Java编程语言编写类XML的tags和scriptlets,来封装产生动态网页的处理逻辑。JSP将网页逻辑与设计的显示分离,支持可重用的基于组件的设计,使基于Web的程序开发变得简单容易。 JSP(Java Server Pages)技术支持的网页是动态的,将逻辑和servlet进行了分离。
    而本系统采用JSP技术的原因也是基于相比较于其他技术JSP有很多优势:

    JSP代码跨平台,即一次编写,处处运行 。众所周知,微软公司的产品都具有垄断性,产品的可移植性也很差,ASP也不例外,而相较而言,JSP就避免了这些问题,可以在很多平台上使用,更加平民化人性化
    JSP组件跨平台 ,JSP组件包括企业JavaBeans,JavaBeans或定制的JSP标签,跟代码一样都是可以跨平台可重用的。企业JavaBeans组件可以访问传统的数据库并能以分布式系统模式工作于Solaris,Linux,UNIX和Windows平台
    支持多种网页格式,目前, JSP技术支持的网页格式没有特定的标准。一般来说,JSP技术既可以支持HTML/DHTML的传统浏览器文件格式,又适用于于无线通信设备如移动电话、PDA等设备进行网页预览的WML文件格式,还可以支持其他一些B2B电子商务网站应用的XML格式
    JSP标签可扩充性,JSP标签技术与XML兼容,所以使得开发网页的制作者充分的利用此技术来降低了对脚本语言的依赖,使网页建设变得越发简单容易
    健壮性与安全性:Java语言的存储管理具有健壮性,并且安全性更高,而JSP制作网页是基于Java语言的,因此也囊括了Java语言的优势

    2.1.2 SSH技术概述 “SSH 组合框架”是Struts + Spring + Hibernate的缩写,“SSH组合框架”体现的是“强强联手、各司其职、协调互补”的团队协作精神。SSH框架的流程大致是:Jsp页面——Struts———Service(业务逻辑处理类)—-Hibernate(左到右)。而负责控制Service生命周期的Struts框架会加大层与层之间的依赖性,也就是通常所说的耦合。大型Java Web 应用程序的开发具有代码繁琐过多,难于维护和扩展的缺点,而“SSH 组合框架”能够很好的实现业务分层,为该问题提供了很好的解决平台。
    Struts最早的Java Web 程序全部使用JSP 实现, JSP 页面包含HTML 标签和Java 业务逻辑代码,使得整个JSP 页面显得过于繁琐复杂,并且难以维护,在系统出现问题时使得开发人员面对大批的代码束手无策。于是SUN 公司对Java Web 进行了规范,先推出模式1,在模式1中引入了JavaBean代码,以达到封装业务逻辑代码的目的,最终成功的将逻辑代码与JSP页面进行了分离,而模式1引入的JavaBean代码仍然存在对流程控制上的缺陷,由此在模式2中引入Servlet 技术,才将整个框架彻底分离为模型、视窗和控制器三部分,使得Java Web 应用开发更加规范化。之后推出模式2,Struts 2集结了组件的多重优点,同时也使得基于MVC 的Java Web应用程序的开发变的更加简单。Struts 2通过核心控制器Struts Prepare And Execute Filter(struts2.0.x到2.1.2版本的核心过滤器为FilterDispatcher,继2.1.3版本开始就改为truts Prepare And Execute Filter)和拦截器遵循一定模式更好的实现后台控制维护、前台表现和业务逻辑处理等多项功能。
    Struts是用来做应用层的,它负责调用业务逻辑serivce层,从而控制了Service的生命周期。
    Spring服务器厂商对于很多技术支持没有进行统一,因此J2EE的应用缺少平台无关性,并且应用开发的效率低下,而Struts对逻辑service的调用会导致层与层之间的依赖性增强,发生耦合问题。这时Spring框架作为开源的中间件就起到了承上启下的作用,它控制Action对象(Strus中的)和Service类,使得两者关系变得松散,降低了层与层之间的依赖性来达到松散耦合的目的,这就是Spring的Ioc机制(控制反转和依赖注入)所起的作用。
    Spring事实上充当了管理容器的角色,用来管理struts和hibernate之间的工作,作为管理者它在整个程序中充当了桥梁的角色,整个程序运行都需要通过这个桥梁,Spring致力于解决应用各层的方案,而不仅仅局限于一层。
    可以说Spring的“一站式”功能贯穿表现层、业务层及持久层。但是Spring并没有取代整个框架而是与之完美的契合,就像一个服务者而不是霸占整个领域的统领者。Spring的核心技术是控制反转IOC 与AOP 代理机制,现在Spring使用基本的JavaBean就可以解决以前只能由EJB完成的事情,Spring 的用途并不局限于服务器端。
    Hibernate现在对很多的多层体系结构的开发都有一个缺点就是单凭使用JDBC 对持久层进行分离非常困难,负责业务逻辑代码编写的程序员在与数据库交互时需要书写大量的SQL语句,并且必须密切关注数据库各表的结构关系,以确保其SQL 语句工作的正常。而引入Hibernate 这样的持久层中间件的话,就对JDBC做了一个良好的封装,业务逻辑层的开发人员面对的就是对象而不必关心数据表,这样有利于分工合作,并且降低了产品的不可移植性。任何使用JDBC 的场合都可引入Hibernate,既可以在Java Application中使用,也可以在Servlet/JSP 的Web 应用中使用。
    整合Struts 2 标签库处理视图层,Struts 2 的核心控制器与业务控制充当控制层,Hibernate 与各业务逻辑组件处理业务层事务,最后由Spring 统管Bean 资源,对整个应用的JavaBean实例资源进行统一管理与调度。三个开源框架相辅相成,对所有资源进行一个良好的运转,就像团队分工协作,任务明确,因此“SSH框架”的引入推动了J2EE的开发。
    2.1.3 B/S模式简介B/S(Browser/Server,浏览器/服务器)模式又称B/S结构。它是随着internet技术的兴起,对C/S模式应用的扩展。在这种结构下,用户工作界面是通过浏览器来实现的。B/S模式最大的好处是运行维护比较简便,能实现不同的人员,从不同的地点,以不同的接入方式(比如LAN, WAN, Internet/Intranet等)访问和操作共同的数据析。B/S模式如图2-1所示

    2.2 系统开发环境2.2.1 MySQL数据库任何程序的运行都需要数据库,这是网络开发过程中不可或缺的一部分,就像任何生物不管类别大小个头大小,它们生命的延续都需要心脏的跳动,同样的道理,无论程序大小,都需要数据库的支持。Web数据库一般为三层或多层体系结构,前端采用浏览器技术,通过中间件和服务器对数据库进行访问。
    MySQL软件目前属于Oracle公司,由瑞典MySQL AB公司开发。以往的数据库都将数据集中存储在一个空间,就像一个大型仓库,因此容易造成数据过多冗余繁杂并且难以管理,而MySQL是一个关系型数据库管理系统,将数据分块保存于不同的表中,提高了数据的灵活性并且也解决了因为数据冗长而造成的运行速度过慢的问题。
    MySQL软件由于其体积小、速度快、总体拥有成本低的,成为中小型网站开发的常用网络数据库,尤其是开放源码这一特点,用于访问数据库的SQL语言很普遍,使得很多企业更偏向于选择MySQL数据库。MySQL软件分为社区版和商业版,由于其社区版的性能卓越,搭配PHP和Apache可组成良好的开发环境。
    MySQL规模小、功能有限(MySQL Cluster的功能和效率都相对比较差)的缺陷无法与其他大型数据库例如Oracle、DB2、SQL Server等并驾齐驱,但也并不磨灭许多中小型网站对它的使用热情。“麻雀虽小,五脏俱全”,MySQL提供的功能已经足够满足一般的个人使用者和中小型企业,并且源码开放使得总拥有成本大大降低,使得它更加受到这些使用者的青睐。
    2.2.2 MyEclipse IDE工具MyEclipse企业级工作平台(MyEclipse Enterprise Workbench ,简称MyEclipse)是对EclipseIDE的扩展,利用它我们可以在数据库和JavaEE的开发、发布以及应用程序服务器的整合方面极大的提高工作效率。它是功能丰富的JavaEE集成开发环境,包括了完备的编码、调试、测试和发布功能,完整支持HTML、Struts、JSP、CSS、Javascript、Spring、SQL、Hibernate。
    MyEclipse 是一个十分优秀的用于开发Java, J2EE的 Eclipse 插件集合,MyEclipse的功能非常强大,支持也十分广泛,尤其是对各种开源产品的支持十分不错。MyEclipse目前支持Java Servlet,AJAX, JSP, JSF, Struts,Spring, Hibernate,EJB3,JDBC数据库链接工具等多项功能。可以说MyEclipse几乎囊括了目前所有主流开源产品的专属eclipse开发工具。
    三、系统分析3.1 可行性分析可行性分析是目前项目开发中必不可少的一项工作,具有决定性的意义。在一个项目开启之前,必须对项目进行全面科学的分析,从各个角度进行科学的研究,对自己的项目进行全面的分析。本项目主要是关于技术可行性、经济可行性、管理可行性和社会可行性进行研究。
    可行性分析是在制定某一建设或科研项目之前,对该项目实施的可能性、有效性、技术方案及技术政策进行具体、深入、细致的技术论证和经济评价,以求确定一个在技术上合理、经济上合算的最优方案和最佳时机而写的书面报告。
    可行性研究报告主要内容是要求以全面、系统的分析为主要方法,经济效益为核心,围绕影响项目的各种因素,运用大量的数据资料论证拟建项目是否可行。对整个可行性研究提出综合分析评价,指出优缺点和建议。
    3.1.1 技术可行性本管理软件的开发工具为Myeclipse,前台页面使用JSP技术,后台数据库为MySQL。
    软件系统的实现使用了SSH框架来实现,使用该框架有很多的优点,SSH是典型的J2EE三层架构体现MVC思想,即将一个应用分成三个基本部分:M(模型)、V(视图)和C(控制器)。那边与迅捷的开发出新的需求,降低开发成本。它还具有良好的可扩展性,而且SSH还具有良好的可维护性,使用该框架实现了视图、控制器与模型的彻底分离,并且可以使业务逻辑层与持久层的分离。
    可以极大的提高可复用性,这样的话,不管前端怎样的变化,模型层只需要小小的变化即可。而且前端也不会随着数据库变化。还因为不同的层之间耦合度小,可以方便工作,大大提高了效率。控制层依赖于业务逻辑层,只与接口耦合,但绝不与任何具体的业务逻辑组件耦合;同样,业务逻辑层依赖于DAO层,也不会与任何 具体的DAO组件耦合,而是面向接口编程。采用这种方式的软件实现,即使软件的部分发生改变,其他部分也不会改变。
    通过使用SSH框架,配合数据库的连接,使此系统里的每个模块都能很好的实现。因此在技术上是可行的。
    3.1.2 经济可行性从经济可行性的角度出发,软件系统在开发过程中主要应该考虑的是怎样最大限度的节约成本,缩短软件的开发周期,用最小的投入取得最大的回报。该软件的实现是基于B/S架构的,B/S 架构即浏览器和服务器结构,在此结构下,用户的工作界面是通过浏览器实现此管理软件的一切操作基于WEB浏览器,很少的事务逻辑在前端实现,基本上主要的事物都是在服务器端实现,这样就大大简化了客户端电脑载荷,降低了用户的总体成本,减轻了系统维护与升级的成本和工作量,并且开发使用的软件直接安装在本机上,所以成本低廉且效率高,没有太多的经济负担。因此在经济上也是可行的。
    3.1.3 管理可行性本系统有管理员、客户两种角色。客户可以进行登陆用户账号,来进行下订单,申请赔付或者修改自己的信息。然而管理员可以通过登录管理员用户然后进行直接管理客户信息,并可以查看所有订单信息和赔偿信息,发挥了监督审查的作用,起到了监督管理的左右。因此在管理上是可行的。管理可行性是非常有用的,拥有一个好的管理可行性,系统的运行时是非常好的,十分有助于系统的完成。
    3.1.4 社会可行性当前的中国保险市场,是一个急速发展与变革的市场。保险行业 IT服务必须满足这种现状的要求。因此,他们对于IT服务的响应速度和服务质量有了更高的要求。
    现阶段,我国经济环境诸多因素给保险业提出了新的要求。一方面,加入WTO后,外资保险公司的加盟对于我国保险业产生重大的影响 ,中国保险市场将呈现出国际化特征,有利于业务拓展;但是另一方面,新的市场发展形势 使得国内保险公司面临严峻考验,对于公司的经营运作能力提出了更高的要求。
    现在,保险行业的特征决定了企业管理信息对保险公司尤为重要,公司的经营策略、业务运作、财务管理、分析决策无一不 建立在高质量信息管理的基础上。各家保险公司对于新险种开发、业务管理、自身风险管控以及服务水准提升等方面的要求 越来越强烈,这就要求其核心业务系统不能仅是对业务的简单支持,更重要的是到达支持、分析、管理、决策的层面。换句话说,保险信息系统的好坏将从根本上影响到保险公司的核心竞争力。
    3.1.5 操作可行性伴随着社会的不断发展,计算机的不断普及,越来越多的人已经可以熟练地掌握计算机的基本操作,本系统采用基于Windows的图形用户界面,通过web浏览器即可进行操作,而该系统是大家熟悉的操作系统,对于那些有一般的计算机知识的人员就可以轻松上手。整个保单管理系统采用友好的交互界面,简洁明了,不需要对数据库进行深入的了解便能轻松使用,无需对使用系统的人员进行培训。这样既减少投入成本又简化了操作环节。
    3.2 需求分析软件需求分析是软件项目设计中非常重要的一部分。在软件工程的历史长河中,人们在很长一段时间里把需求分析当做是整个软件工程中的一个非常简单的步骤,但在过去十多年中越来越多的人逐渐认识到它是整个过程中最关键的一个过程。只有通过软件需求分析,才能把软件功能和性能的总体概念描述为具体的软件需求规格说明,从而奠定软件开发的基础。许多大型应用系统的失败,最后均归结到需求分析的失败:要么获取需求的方法不当,使得需求分析不到位或不彻底,导致开发者反复多次地进行需求分析,致使设计、编码、测试无法顺利进行;要么客户配合不好,导致客户对需求不确认,或客户需求不断变化,同样致使设计、编码、测试无法顺利进行。
    需求分析之所以重要,就因为他具有决策性,方向性,策略性的作用,他在软件开发的过程中具有举足轻重的地位.大家一定要对需求分析具有足够的重视.在一个大型软件系统的开发中,他的作用要远远大于程序设计。需求分析在一个项目中是非常重要的,一个好的项目是离不开需求分析的,需求分析的好坏是一个项目成功须否的重要保证。所以一个项目的完成务必要做好需求分析环节,只有了解了需求之后,才能更好的进行业务逻辑的设定。这是一个项目完成的重中之重。我们要好好地完成需求分析。需求的好坏是一个设计完成的重要保障。需求分析做不好,后续工作就会出现很多的问题,就需要返工,导致效率的下降,所以我们有必要完善需求。
    保险业务信息管理系统主要就是完成保险的下单,交费,申请赔偿,和对个人信息的管理等流程。其中可以分为客户部分和管理员部分。
    3.2.1 客户部分客户主要就是进行注册自己的用户之后,通过自己的用户账号的登录系统,然后进行查看各种保险信息,选择自己所要购买的保险类别,进行下订单操作,在发生了意外之后可以进行申请赔偿的操作,还可以进入自己的个人用户界面进行个人信息的修改。
    其中客户部分的需求总共可以分为以下四部分:

    查看/购买保险产品信息:客户在可以看到当前出售的保险信息:保险的名称、保险费用、发布时间、保险内容,选择合适的保险后,可以添加到订单中
    查看/确认订单信息:客户选择需要购买的保险后可以在订单列表中查看订单名称、订单金额订单时间、订单人、订单状态,决定后确认订单
    查看/申请赔偿信息:客户可以在个人赔偿信息管理界面管理个人申请赔偿列表。客户可以在购买保险后,在保险内容生效时申请赔偿
    管理个人信息:通过个人信息管理面板客户管理个人注册信息:账号名、密码、姓名、年龄、电话、联系地址,客户可以在个人信息中修改自己的信息

    3.2.2 管理员部分管理员在通过管理员用户登录之后,可以自己管理公司的保险列表下面的各类保险信息,其中包括增加和删除操作,还可以查看用户的订单选购情况,是否完成付款,另外还能够进行赔偿信息的管理,可以对用户申请的赔付选择同意或者不同意,最后还可以进行用户的管理操作,增加或者删除用户。管理员用户能够随意的管理用户,对用户的管理有着很大的帮助。
    管理员的需求主要可以分为以下四个部分:

    保险信息管理:管理员在登录自己的管理员用户后,通过后台对保险信息管理进行新增或删除,从而完成自己对保险信息的管理
    订单信息管理:管理员登录之后,进入订单管理界面之后,可以查看当前用户提交的所有的订单信息
    赔偿信息管理:管理员可以查看用户提交的赔偿申请,根据实际的情况同意或者不同意用户的赔偿申请
    用户信息管理:管理员可以在用户信息管理中维护所有客户的信息。包括增加删除用户,进行用户信息的管理

    四、系统总体设计4.1 系统的设计SSH是 struts+spring+hibernate的一个集成框架,是目前比较流行的一种Web应用程序开源框架。Ssh架构图,如图4-2所示:

    系统总共分为三层:表现层,业务层,持久层。

    在表示层中,首先通过JSP页面实现交互界面,负责接收请求(Request)和传送响应(Response),然后Struts根据配置文件(struts-config.xml)将ActionServlet接收到的Request委派给相应的Action处理
    在业务层中,管理服务组件的Spring IoC容器负责向Action提供业务模型(Model)组件和该组件的协作对象数据处理(DAO)组件完成业务逻辑,并提供事务处理、缓冲池等容器组件以提升系统性能和保证数据的完整性
    在持久层中,则依赖于Hibernate的对象化映射和数据库交互,处理DAO组件请求的数据,并返回处理结果

    Struts负责Web层:
    ActionFormBean接收网页中表单提交的数据,然后通过Action进行处理,再Forward到对应的网页,在Struts-config.xml中定义了<action-mapping>,ActionServlet会加载进来。
    Spring负责业务层管理,即Service:
    Service为Action提供统一的调用接口,封装持久层的DAO,并集成Hibernate,Spring可对JavaBean和事物进行统一管理。
    Hibernate负责持久层,完成数据库的CRUD操作:
    Hibernate有一组hbm.xml文件和PO,是与数据库中的表相对应的,然后定义DAO,这些是与数据库打交道的类。
    在Struts+Spring+Hibernate系统中,对象之间的调用流程如图4-2所示:


    Struts——>Spring——>Hibernate
    JSP——>Action——>Service——>DAO——>Hibernate

    4.2 系统结构设计关于对保险业务信息管理的调研,选择了利用SSH框架编写,mysql作为数据库来进行保险业务管理系统的设计本系统主要分为保险业务管理和后台管理两部分,其中保险业务管理可以进行查看/购买保险产品信息、查看/确认订单信息、查看/申请赔偿信息、管理个人信息。后台管理部分主要是管理员进行登录管理员用户,从而进行管理,而管理员的权限可分为保险信息管理、订单信息管理、赔偿信息管理、用户信息管理。具体的功能结构图如图4-3所示。

    4.3 数据库关系图E-R图也称实体-联系图(Entity Relationship Diagram),提供了表示实体类型、属性和联系的方法,用来描述现实世界的概念模型。对于任何数据库,都可以创建任意多个数据库关系图;每个数据库表都可以出现在任意数量的关系图中。这样,便可以创建不同的关系图使数据库的不同部分可视化,或强调设计的不同方面。例如,可以创建一个大型关系图来显示所有表和列,并且可以创建一个较小的关系图来显示所有表但不显示列。系统ER图如图4—3所示。

    通过数据库关系图我们可以看出表与表之间的联系,主要可以分为user_list,order_list和product_list,每个表所含项目如下图所示。
    4.4 系统用例图用例图是用来表现设计出来的某某系统可以用来干什么的图,用路途主要关注的是系统的外在表现,人与人之间的交互,以及人与系统的交互,系统和其它系统的交互。
    用例图里面有三个基本元素:用例、关系、角色。

    角色(Actor):是用来描述系统里面有那些角色,不同的角色占用的系统功能是不一样的,用例图里的一个个小人就是表示的角色
    用例:用例是对包括变量在内的一组动作序列的描述,系统执行这些动作,并产生传递特定参与者的价值的可观察结果。用例在用例图中用椭圆的圆圈来表示,在圆圈里用文字来描述该序列,一般用动词宾语来描述
    关系:就是用来用来描述角色与线条之间关系的,在用例图中用线条来表示

    线条是指角色与用例之间的线条,这些线条是用来联系角色(小人)和用例(圈圈)的,表示某某角色能“做”什么用例。
    4.5 管理员用例图管理员在整个管理系统中的权限主要包括保险信息管理,订单信息管理,赔偿信息管理,用户管理。其中保险信息管理主要包括查看新增保险信息和删除保险信息,订单信息管理包含查看订单信息,赔偿信息管理包含审批赔偿申请,用户管理主要包含查看新增用户和删除用户,管理员用例图如图4-4:

    4.6 客户的用例图客户是保险公司中最主要的资源。客户在登录自己的主业之后可以进行自己相关的权限操作,权限主要分为保险信息,订单信息,赔偿信息和个人信息管理四大模块,其中保险信息包括购买保险产品,订单信息包括确认取消订单信息,赔偿信息模块主要包括赔偿申请,个人信息管理模块用户可以修改和保存自己的个人信息。客户参与整个系统的用例图如图所示:

    五、系统详细设计与实现5.1 系统详细设计保险业务管理系统设计共有3个数据字典,分别为:用户信息表(user_list),反馈评价信息表(product_list),软件信息表(order_list)。三个表底下分别有着不同的结构。
    在普通用户的角度看起来,数据的逻辑关系模型就是一张简单的二维表,每一个表里面都保存着保险企业中涉及总体的业务的逻辑。该管理系统涉及到的主要实体及其属性如下:
    5.1.1 数据库结构设计
    用户信息表:user_list(主键、帐号、密码、姓名、性别、年龄、电话、地址、类型)
    反馈评价信息表:product_list(主键、产品名称、产品内容、产品费用、发布时间)
    软件信息表:order_list(主键、订单名称、订单金额、下单时间、下单人、下单人ID、订单状态、产品ID)

    5.1.2 数据字典数据字典是对于数据模型中的数据对象或者项目的描述的集合,这样做有利于程序员和其他需要参考的人。分析一个用户交换的对象系统的第一步就是去辨别每一个对象,以及它与其他对象之间的关系。这个过程称为数据建模,结果产生一个对象关系图。当每个数据对象和项目都给出了一个描述性的名字之后,它的关系再进行描述(或者是成为潜在描述关系的结构中的一部分),然后再描述数据的类型(例如文本还是图像,或者是二进制数值),列出所有可能预先定义的数值,以及提供简单的文字性描述。
    保险业务管理系统设计共有3个数据字典,分别为:
    user_list表



    属性名
    存储代码
    数据类型
    长度
    备注




    主键
    user_id
    int
    11
    主键,唯一性


    用户名
    username
    varchar
    45



    密码
    password
    varchar
    45



    姓名
    name
    varchar
    45



    性别
    sex
    varchar
    45



    年龄
    age
    varchar
    45



    电话
    phone
    varchar
    45



    地址
    address
    varchar
    45



    类型
    type
    varchar
    45



    用户信息表主要包括用户的个人信息,其中包含用户名(username),密码(password),姓名(name),性别(sex),年龄(age),电话(phone),地址(address)和类型(type)几大部分。
    product_list表



    属性名
    存储代码
    数据类型
    长度
    备注




    主键
    product_id
    int
    11
    主键,唯一性


    产品名称
    product_name
    varchar
    100



    产品内容
    product_desc
    varchar
    2000



    产品费用
    product_cost
    varchar
    45



    发布时间
    product_time
    varchar
    45



    反馈评价信息表包含了险种的详细描述信息,主要是保险单号。其中产品名称(product_name),产品内容(product_desc),产品费用(product_cost),发布时间(product_time)。主要是用来反馈产品的信息。这个表里包含的是所有的保险业务的信息,是用来保存保险产品的。里面所含的各项信息是保险产品的各个内容。
    order_list表



    属性名
    存储代码
    数据类型
    长度
    备注




    主键
    order_id
    int
    11
    主键,唯一性


    订单名称
    order_name
    varchar
    100



    订单金额
    order_cost
    varchar
    45



    下单时间
    order_time
    varchar
    45



    下单人
    order_uname
    varchar
    45



    下单人ID
    order_uid
    varchar
    45



    订单状态
    order_state
    varchar
    45



    产品ID
    product_id
    varchar
    45



    软件信息表主要是包括用户的订单信息,其中包含了订单名称(order_name),订单金额(order_cost),下单时间(order_time),下单人(order_uname),下单人ID(order_uid),订单状态(order_state),产品ID(product_id)。这些信息都是和用户有着紧要关系的。用户下了订单之后的状态都是显示在这个表里。这个表示整个系统的核心,所有的业务实现基本都在这个表里面,所以这个表很重要。
    5.2 模块实现5.2.1 登录模块所有用户输入帐号、密码后,即可凭正确的信息登录系统。如图5-1所示:

    如通过管理员账号进入管理员界面,如图5-2所示:

    由用户账号登录进入用户界面,如图5-3所示:

    不同身份,功能的权限也不同。
    登录所需代码:
    public String login(){ UserList ul = userListService.login(userlist.getUsername(), userlist.getPassword(), ""); if (ul.getUser_id() != 0) { session.put("login", ul); return SUCCESS; }else{ response.setContentType("text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8");//防止弹出的信息出现乱码 try { PrintWriter out = response.getWriter(); out.print("<script>alert('用户名或密码错误!')</script>"); out.print("<script>window.location.href='http://localhost:8080/InsuranceBusiness/Login.jsp'</script>"); out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } return null; } }
    5.2.2 保险信息模块管理员登录进去所显示的界面,如图5-4所示:

    管理员可以在保险信息管理中查询、新增或者删除保险产品信息。如图5-5所示:

    客户可以在保险列表中查看所有保险产品。如图5-6所示:

    客户选择需要购买的保险后,加入订单信息中,用户可以在订单中确认或取消订单。如图5-7所示:

    public List<ProductList> selProductList() { Session session = sessionFactory.openSession(); String sql="select * from product_list"; Transaction tran = session.beginTransaction(); SQLQuery sq = session.createSQLQuery(sql); List<Object[]> list = sq.list(); List<ProductList> plist = new ArrayList<ProductList>(); for(Object[] obj : list){ ProductList pl = new ProductList(); pl.setProduct_id((Integer)obj[0]); pl.setProduct_name((String)obj[1]); pl.setProduct_desc((String)obj[2]); pl.setProduct_cost((String)obj[3]); pl.setProduct_time((String)obj[4]); plist.add(pl); } tran.commit(); session.close(); return plist; }}
    5.2.3 赔偿模块客户确认购买保险后,可以申请赔偿。如图5-8所示:

    管理员可以根据实际情况同意或者否决用户的赔偿申请,如图5-9所示:

    public List<OrderList> selOrderList(String uid, String state) { Session session = sessionFactory.openSession(); String sql="select * from order_list where order_uid = '"+uid+"' and order_state in ("+state+")"; Transaction tran = session.beginTransaction(); SQLQuery sq = session.createSQLQuery(sql); List<Object[]> list = sq.list(); List<OrderList> olist = new ArrayList<OrderList>(); for(Object[] obj : list){ OrderList ol = new OrderList(); ol.setOrder_id((Integer)obj[0]); ol.setOrder_name((String)obj[1]); ol.setOrder_cost((String)obj[2]); ol.setOrder_time((String)obj[3]); ol.setOrder_uname((String)obj[4]); ol.setOrder_uid((String)obj[5]); ol.setOrder_state((String)obj[6]); ol.setProduct_id((String)obj[7]); olist.add(ol); } tran.commit(); session.close(); return olist; } public String selCompensateListByMe(){ UserList ul = (UserList)session.get("login"); List<OrderList> clist = orderListService.selOrderList(String.valueOf(ul.getUser_id()), "'1','2','n','9'"); session.put("clist", clist); return SUCCESS; }
    5.2.4 用户信息模块管理员登录管理员账号后,用户管理界面,如图5-10所示:

    管理员可以修改用户的个人信息,如图5-11所示:

    客户可以在个人信息管理中修改自己的信息,如图5-12所示:

    增加更新用户:
    public UserList selUser(String uid) { Session session = sessionFactory.openSession(); String sql="select * from user_list where user_id = '"+uid+"'"; Transaction tran = session.beginTransaction(); SQLQuery sq = session.createSQLQuery(sql); List<Object[]> list = sq.list(); UserList ul = new UserList(); for(Object[] obj : list){ ul.setUser_id((Integer)obj[0]); ul.setUsername((String)obj[1]); ul.setPassword((String)obj[2]); ul.setName((String)obj[3]); ul.setSex((String)obj[4]); ul.setAge((String)obj[5]); ul.setPhone((String)obj[6]); ul.setAddress((String)obj[7]); ul.setType((String)obj[8]); } tran.commit(); session.close(); return ul; } public void updateUser(UserList ul) { Session session = sessionFactory.openSession(); Transaction tran = session.beginTransaction(); String sql = "update user_list set password = '"+ul.getPassword()+"', name = '"+ul.getName()+"', sex = '"+ul.getSex()+"', age = '"+ul.getAge()+"', phone = '"+ul.getPhone()+"', address = '"+ul.getAddress()+"', type = '"+ul.getType()+"' where user_id = '"+ul.getUser_id()+"'"; session.createSQLQuery(sql).executeUpdate(); tran.commit(); session.close();
    六、系统测试经过分析、设计和编码等阶段的开发后,得到了源程序,开始进入到软件测试阶段。然而,在测试之前的各阶段中都可能遗留下许多错误和缺陷,如果不及时找出并改正,这个软件产品就可能会导致巨大的损失。目前,程序的正确性证明尚未得到根本的解决,因此软件测试仍是发现软件中错误和缺陷的主要手段。
    系统测试,就是将已经确认的软件、计算机硬件、外设、网络等其他元素结合在一起,进行信息系统的各种组装测试和确认测试。系统测试是针对整个产品系统进行的测试,目的是验证系统是否满足了需求规格的定义,找出与需求规格不符或与之矛盾的地方,从而提出更加完善的方案。系统测试发现问题之后要经过调试找出错误原因和位置,然后进行改正,是基于系统整体需求说明书的黑盒类测试,应复盖系统所有联合的部件。对象不仅仅包括需测试的软件,还要包含软件所依赖的硬件、外设甚至包括某些数据、某些支持软件及其接口等。比较常见的、典型的系统测试包括恢复测试、安全测试、压力测试。
    软件测试方法从测试人员角度看,可分为人工测试和机器测试。人工测试又称为代码复审。主要有三种方法:个人复查、走查、会审。机器测试分为黑盒测试(又称功能测试)和白盒测试(又称结构测试)两种。
    下面对本系统进行测试,以检查系统能否正确完成各种操作,是否能够实现预期具有的功能。
    登录测试,如图6-1所示:

    赔偿信息管理测试,如图6-2所示:

    赔付成功如图6-3所示:


    测试要点:新增用户
    测试路径:填写的用户信息是否完整
    测试结果:填写完整,系统增加新的用户信息;填写不完整,提示输入完整的用户信息。如图6-4所示:


    修改用户信息,如图6-5所示:

    删除用户,如图6-6所示:

    保险信息管理测试,如图6-7所示:

    新增保险,如图6-8所示:

    删除保险产品如图6-9所示:

    订单信息管理测试,如图6-10所示:

    保险信息管理测试,如图6-11所示:

    购买如图6-12测试:

    赔偿信息测试,如图6-13所示:

    个人信息测试,如图6-14所示:

    参考文献[1] 温涛.东软Java软件工程师实训项目教程;大连;东软电子出版社,2011.8
    [2] 2016-2017年中国保险行业发展现状、发展趋势、发展前景分析 http://www.chyxx.com/industry/201611/471965.html
    [3] 伍飞.冉文江.基于J2EE架构的SSH框架研究及应用[J];信息系统工程;2010.6
    [4] 单晓光.Java Web开发技术的教学方法研究[J];黑龙江教育学院学报;2011.7
    [5] 刘志成.Java程序设计实例教程;北京;人民邮电出版社;2010.8
    [6] 李刚.Struts2权威指南——基于WebWork核心的MVC开发[M].北京:电子工业出版社,2007.
    [7] 鲁霞.基于Struts_Spring_Hibernate架构的综合积分系统的研究与实现[D].成都:西南交通大学硕士学位论文,2008.
    [8] 赵少卡.基于Struts+Spring+Hibernate架构的信息交流平台的设计与实现[J].计算机与现代化,2009(2):62-66.
    [9] 黄志明.基于Spring+Struts+Hibernate的报备系统的设计与实现[J].电脑知识与技术,2008,4(Z2):40-41.
    [10] MySQL入门与精通教程 http://www.docin.com/p-167853642.html
    [11] 网络数据库Mysql介绍 http://www.docin.com/p-60867610.html
    [12] 曹大有.基于Struts和Spring框架技术的Web应用的开发过程[J].计算机应用与软件,2008,25(8):203-204.
    [13] 夏昕.曹晓钢.深入浅出Hibernate[M]. 北京:电子工业出版社,2005.
    [14] 夏昕.Spring开发指南[M].北京:电子工业出版社,2004.
    [15] O‘REILLY. Learning MySQL.2010
    [16] DEITEL Java How to Program, 2012
    [17] O‘REILLY JavaServer Pages (JSP) - From The O´Reilly Anthology, 2011
    [18] 陈潇.在SQL Server使用触发器实现数据完整性[J].电脑知识与技术,2013(35)
    [19] 姜锋.Web网站通信安全的优化方案[J].网络安全技术与应用,2015,(10):53,55.DOI:10.3969/j.issn.1009-6833.2015.10.035.
    [20] 杨荻.保险行业BS架构信息管理系统设计与应用[J].计算机仿真,2010,27(6):342-345.DOI:10.3969/j.issn.1006-9348.2010.06.082.
    [21] 马秀麟,衷克定,刘立超等.从大数据挖掘的视角分析学生评教的有效性[J].中国电化教育,2014,(10):78-84.DOI:10.3969/j.issn.1006-9860.2014.10.013.
    [22] 杨伟斌.tomcat安装配置在高校web课堂中的应用研究[J].速读(下旬),2015,(9):309-309.
    1 评论 2 下载 2020-07-31 16:55:44 下载需要13点积分
  • 基于Jsp和Mysql的百货中心供应链管理系统

    摘要近年来,随着计算机技术的发展,以及信息化时代下企业对效率的需求,计算机技术与通信技术已经被越来越多地应用到各行各业中去。百货中心作为物流产业链中重要的一环,为了应对新兴消费方式的冲击,从供货到销售的各个环节也迫切地需要实现信息化、自动化。而上面所提到的这些环节,在二十世纪中期后被称为“供应链”,也是在本世纪初才在中国受到关注的一门新兴科学。
    本文就百货中心供应链管理系统的设计与开发展开论述,按照软件工程开发的实际步骤,依次对该项目的可行性分析、需求分析、概要设计、详细设计、系统实现以及系统测试分别进行阐述。
    在查阅了各界媒体资料、分析了国内外供应链管理系统的基础上,经过认真学习与不懈探索,利用J2EE技术和Mysql数据库,最终完成了百货中心供应链管理系统的开发,并经过一系列测试及试用,达到了最初的设计目标。
    关键词: 供应链,软件工程,J2EE
    AbstractIn recent years, with the development of computer technology, and the enterprise is in great demand of efficiency in the information era, computer technology and information technology has been increasingly applied to all walks of life. Department store is an important part of logistics industry chain, in order to cope with the emerging consumer’s impact, from supplying marketing, every aspect needs to implement informatization and automation urgently. These aspects mentioned above came to be known as the “supply chain” in the middle of twentieth Century, which is a new science not attached attention from China until the beginning of this century.
    In this paper, the design and development of supply chain management system of department store is described and analyzed, according to the actual steps of software engineering, the project feasibility analysis, demand analysis, outline design, detailed design, system implementation and system test are described individually.
    Under the base of consulting the media data, analyzing the supply chain management system at home and abroad. After study and exploration, finally the development of supply chain management system of department store is completed using J2EE technology and Mysql database. With a series of tests, the system has met the original design goals.
    Key words: supply chain, software engineering,J2EE
    1 引言1.1 课题背景随着国内物流行业的迅速发展,越来越多的企业认识到了“供应链”一词的含义以及它对整个企业物流活动的重大意义,于是,“供应链管理”也逐渐受到了大家的重视。供应链管理主要涉及到四个领域:供应、生产计划、物流、需求[1]。职能领域主要包括产品工程、产品技术保证、采购、生产控制、库存控制、仓储管理、分销管理[2]。在供应链管理中涉及到如此广泛、复杂的物流活动,要对其进行统筹、控制绝非易事,这也是我国企业目前在供应链管理中亟待解决的难题。与此同时,互联网和网络技术的进步为我们解决这一问题提供了方案,借助互联网及互联网技术,企业各个物流阶段的大量数据可以得到及时传输,并通过日益成熟的算法或处理手段实现对这些数据的准确分析,从而指导企业的物流活动或对未来做出预测。百货中心作为现在物流以及商业中的重要一环,为了应对新兴消费方式的冲击,其供应链模式自然也有统筹优化的必要,同时,Internet和网络技术的飞速发展也为供应链的管理提供了新的手段。
    SCM(Supply Chain Management)系统即供应链管理系统,利用计算机和Internet的优点,将供应链中的信息流加以收集并控制,只需要少量的人工,便可实现对整个供应链进行监管[3]。
    国际上研究供应链主要是开始于二战后期的物流管理,主要从多级库存以及生产-分销的角度来研究供应链的优化问题。从最初的物流管理到供应链管理,再到如今把供应链增长到战略管理来研究,花费了半个多世纪的时间。国内对供应链的研究起步较晚,国内一些企业对于供应链管理的认识比较肤浅,直到1997年以后,随着各种有关供应链方面的研究和报道增多,人们对物流领域的这一新鲜事物的关注也逐渐升温,直到今天,许多国外的知名公司如IBM、SAP都能为企业的供应链管理提供一整套的解决方案,国内近些年也出现了许多解决企业供应链管理问题的公司和软件[1]。但总体来说,对于这一门相对还很年轻的科学,我们还有很长的路要走。
    随着我国经济结构调整的深入,对企业节能减排的要求更加严格,企业只有通过强化环境保护的自我约束机制,来降低产品和生产过程相关的环境污染所带来的生产经营风险。绿色供应链管理能使整个供应链的资源消耗和环境负作用最小,并能有效满足日益增长的绿色消费需求,从而提高供应链的竞争力。因此,实施绿色供应链管理是企业发展的必然趋势,这对我国供应链管理行业提出了更高的要求。
    1.2 目的和意义对于课题-百货中心供应链管理系统,在了解了传统SCM的基础上,结合了计算机及Internet技术的优点,旨在于简化操作,提高效率,提高数据、信息的安全程度,为企业及其员工提供一个更加便捷高效的工作环境。
    与传统仅仅利用表格、账目来实现对供应链的管理,基于Web的百货中心供应链管理系统具有如下优点:

    信息存放在数据库中,安全稳定,便于备份
    不同职位的员工都可以使用一套系统,节约成本、方便管理
    基于Web的办公系统,方便员工维护,无地域限制
    利用计算机将不同数据整合,方便企业管理、进行决策

    1.3 研究内容和组织结构本文主要通过对百货中心供应链管理系统进行需求分析,结合供应链管理的相关理论,设计出供应链管理系统的各个功能模块,并对其做出一定的说明指导,方便使用者进行操作。
    系统的主要研究内容包括:

    百货中心供应链管理系统的可行性分析:研究供应链管理相关方面的知识,了解百货中心供应链的运作模式及现状,分析确定开发本系统的必要性和可行性
    系统需求分析:确定业务流程,分析数据流向,完成数据流图和系统用例图的绘制,完成数据字典的制作
    系统概要/详细设计:根据需求分析阶段的结果,以提高百货中心各层员工的工作效率为目的,将整个系统分成若干个小模块,通过设计、编写代码实现不同功能,完成数据库的搭建,最后将整个系统进行整合
    系统测试:对完成的系统进行条件许可下的测试,对系统的安全性、稳定性、容错性进行评估

    本文组织结构:

    引言部分:阐述本系统的该项研究的目的和范围,以及该项研究工作在国民经济中的实用价值与理论意义;本文所要解决的问题;论文内容安排等
    开发工具及技术分析:对于本系统开发将要用到的开发工具及技术进行简单的说明,并分析其优势
    系统需求分析:分析系统业务流程,为整个系统的设计开发打下基础
    概要/详细设计:依据前文的分析进一步设计系统的各模块功能,为一些比较有难度的部分提供解决方案
    系统实现及测试:描述系统各模块的功能并展示部分关键代码,并且完成一些简单的数据录入测试

    2 开发工具及技术2.1 开发工具本设计主要利用MyEclipse和Tomcat服务器,加上Mysql数据库进行开发,同时使用Maven来辅助、简化开发。下面对使用到的开发工具进行简要的介绍。
    2.1.1 MyEclipseMyEclipse企业级工作平台(MyEclipse Enterprise Workbench,简称MyEclipse)是一个功能丰富的JavaEE开发环境,包括了完备的编码、调试、测试和发布功能,完整支持HTML, Struts, JSP, CSS, Javascript, SQL, Hibernate[4]。它是对EclipseIDE的扩展,是一个十分优秀的用于开发Java, J2EE的 Eclipse 插件集合,MyEclipse的功能非常强大,支持也十分广泛,尤其是对各种开源产品的支持都十分不错[5]。
    2.1.2 TomcatTomcat服务器是一个免费的开放源代码的Web应用服务器,它属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,十分符合本项目的需求[6]。Tomcat运行时占用的系统资源小,扩展性好,支持负载平衡与邮件服务等开发应用系统常用的功能,并且它仍在不断地改进和完善中,因此十分受程序员的青睐。
    2.1.3 MysqlMysql是最流行的关系型数据库管理系统,在WEB应用方面MySQL是最好的RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一[7]。MySQL所使用的SQL语言是用于访问数据库的最常用标准化语言。MySql使用C和C++编写,并使用了多种编译器进行测试,保证源代码的可移植性;支持多种操作系统;为多种编程语言提供了API;支持多线程,充分利用CPU资源;提供TCP/IP、ODBC和JDBC等多种数据库连接途径;可以处理拥有上千万条记录的大型数据库[8]。
    2.1.4 MavenMaven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具。Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。当你使用Maven的时候,你用一个明确定义的项目对象模型来描述你的项目,然后Maven可以应用横切的逻辑,这些逻辑来自一组共享的(或者自定义的)插件。
    2.2 使用技术2.2.1 JSPJSP, 全名为Java Server Pages,是由SunMicrosystems公司倡导、许多公司参与一起建立的一种动态技术标准[9]。在传统的网页HTML文件中加入Java程序片段和JSP标签,就构成了JSP网页java程序片段可以操纵数据库、重新定向网页以及发送E-mail等,实现建立动态网站所需要的功能。所有程序操作都在服务器端执行,网络上传送给客户端的仅是得到的结果,这样大大降低了对客户浏览器的要求,即使客户浏览器端不支持Java,也可以访问JSP网页。
    JSP的根本是一个简化的Servlet设计,他实现了Html语法中的java扩张(以 <%, %>形式)。JSP与Servlet一样,是在服务器端执行的。通常返回给客户端的就是一个HTML文本,因此客户端只要有浏览器就能浏览[10]。Web服务器在遇到访问JSP网页的请求时,首先执行其中的程序段,然后将执行结果连同JSP文件中的HTML代码一起返回给客户端。插入的Java程序段可以操作数据库、重新定向网页等,以实现建立动态网页所需要的功能。
    2.2.2 SSH框架SSH 为 struts + spring + hibernate的一个集成框架,是目前较流行的一种Web应用程序开源框架[11]。集成SSH框架的系统从职责上分为四层:表示层、业务逻辑层、数据持久层和域模块层,以帮助开发人员在短期内搭建结构清晰、可复用性好、维护方便的Web应用程序。其中使用Struts作为系统的整体基础架构,负责MVC的分离,在Struts框架的模型部分,控制业务跳转,利用Hibernate框架对持久层提供支持,Spring做管理,管理struts和hibernate。
    采用上述开发模型,不仅实现了视图、控制器与模型的彻底分离,而且还实现了业务逻辑层与持久层的分离[12]。这样无论前端如何变化,模型层只需很少的改动,并且数据库的变化也不会对前端有所影响,大大提高了系统的可复用性。而且由于不同层之间耦合度小,有利于团队成员并行工作,大大提高了开发效率。
    2.2.3 TilesTiles 是一种JSP布局框架,主要目的是为了将复数的jsp页面作为一个的页面的部分机能,然后用来组合成一个最终表示用页面用的,这样的话,便于对页面的各个机能的变更及维护。 Tiles使得struts在页面的处理方面多了一种选择。并且更容易实现代码的重用。
    2.2.4 JavaScriptJavaScript是一种基于对象和事件驱动并具有相对安全性的客户端脚本语言[13]。同时也是一种广泛用于客户端Web开发的脚本语言,常用来给HTML(标准通用标记语言的子集)网页添加动态功能,比如响应用户的各种操作, 是一种动态、弱类型、基于原型的语言,内置支持类。在HTML基础上,使用JavaScript可以开发交互式Web网页[14]。JavaScript的出现使得网页和用户之间实现了一种实时性的、动态的、交互性的关系,使网页包含更多活跃的元素和更加精彩的内容。JavaScript的一个重要功能就是面向对象的功能,通过基于对象的程序设计,可以用更直观、模块化和可重复使用的方式进行程序开发。
    3 可行性分析在进行系统开发时,会受到来自时间、资源等多方面的限制,因此,在每一个项目开发开始之前,首先进行系统的可行性分析就显得十分重要,它可以减少项目开发的风险,避免人力、物力、财力的浪费[15]。下面将就法律、经济和技术三方面对本项目进行讨论。
    3.1 法律的可行性百货中兴供应链管理系统是自主开发的管理系统,开发过程中使用的开发工具及技术都是免费的,开源的,不存在侵权的问题,所有的源代码都是亲自编写或直接由工具自动生成,没有使用他人的项目成果或方案,因此在法律上是可行的。
    3.2 经济的可行性本系统所使用的开发工具都是开源的,为开发软件节省了大量的金钱和时间,采用的技术也是完全开放的、免费的,达到了降低成本的目的。软件对企业的硬件需求也不高,市场上的中低档计算机也可以符合使用要求,同时由于利用了互联网,比一般的供应链管理系统更加经济、效率。
    3.3 技术的可行性系统使用的开发工具是MyEclipse、Maven和Mysql数据库,工具免费且小巧,安装方便,简单易学。并且采用了目前十分流行的J2EE技术,因而有很多途径找到相关的学习资料,在大学期间我也学习了许多相关的知识,包括对于数据库和编程思想的学习,使得在这个项目中更容易上手,能够迅速投入到系统的设计开发中去。
    4 需求分析4.1 系统功能分析经过对百货中心供销流程的了解和对供应链管理相关资料的分析,决定将系统用户分成五类不同的用例,系统应根据用例的不同职能实现不同的功能,经过分析,系统应具备人事管理、合作公司管理、采购订单管理、库存管理、销售管理、经营统计六大功能模块。具体用例图如下:
    4.1.1 经理用例图经理用例-经理应是百货中心的最高负责人之一,负责百货中心大部分的业务管理及监督工作,必要时也可以完成所有其他用例的操作,地位相当于系统管理员,具有最高权限。

    4.1.2 人事部员工用例图人事部员工用例-人事部员工主要操作系统的人事管理模块,同时也可以进入经营统计模块查看。

    4.1.3 采购部员工用例图采购部员工用例-采购部员工主要负责操作系统的合作公司管理模块和采购订单管理模块,同时也可以进入经营统计模块查看。

    4.1.4 物资部员工用例图物资部员工用例-物资部员工主要负责操作系统的库存管理模块,同时也可以进入经营统计模块查看。

    4.1.5 销售部员工用例图销售部员工用例-物资部员工主要负责操作系统的销售管理模块,同时也可以进入经营统计模块查看。

    4.2 功能模块需求分析考虑到用户可能对计算机操作不是十分熟悉,本系统应具备操作简便、界面友好的特点,再结合系统分析的结论,本系统还应增加一个登录模块以实现不同用例登录系统后可以进行不同的操作,具体分析如下:

    系统界面简洁大方,使用简便,有友好的操作提示信息
    系统具有一定的安全性,避免恶意操作对系统及数据造成损害
    贴近实际用户的工作情况,对一些关键数据提供打印、保存功能
    系统应具备登录、人事管理、合作公司管理、采购订单管理、库存管理、销售管理、经营统计七大功能

    4.3 数据流图根据之前的分析,绘制数据流图。
    4.3.1 顶层数据流图用户通过输入用户名和密码,来实现用户登录,登录失败时会给出相应的提示并留在登录页面,登录成功后可以顺利进入供应链管理系统。

    4.3.2 一层数据流图成功登录的用户可以进入不同的模块完成相应的操作,根据登录用户的身份不同,可以进行的操作也会不同。

    4.4 数据字典数据字典的作用是对数据流图中的各种成分进行详细说明,作为数据流图的细节补充,和数据流图一起构成完整的系统需求模型[16]。数据字典一般应包括对数据项,数据结构、数据存储和数据处理的说明。以下列出本系统的主要数据字典条目。
    4.4.1 数据项的描述用户信息数据项描述



    数据项
    类型
    长度
    值范围




    ID
    数字
    11
    00000000000至99999999999之间


    用户名
    文本
    255
    最多255个字符


    密码
    文本
    255
    最多255个字符



    合作公司数据项描述



    数据项
    类型
    长度
    值范围




    ID
    数字
    11
    00000000000至99999999999之间


    公司名
    文本
    255
    最多255个字符



    采购订单数据项描述



    数据项
    类型
    长度
    值范围




    ID
    数字
    11
    00000000000至99999999999之间


    商品名
    文本
    255
    最多255个字符


    数量
    数字
    11
    00000000000至99999999999之间


    价格
    数字

    双精度浮点型



    库存信息数据项描述



    数据项
    类型
    长度
    值范围




    ID
    数字
    11
    00000000000至99999999999之间


    产品名
    文本
    255
    最多255个字符


    数量
    数字
    11
    00000000000至99999999999之间



    销售信息数据项描述



    数据项
    类型
    长度
    值范围




    ID
    数字
    11
    00000000000至99999999999之间


    数量
    数字
    11
    00000000000至99999999999之间


    价格
    数字

    双精度浮点型



    4.4.2 数据流的描述
    数据流编号:F1数据流名:员工简要信息简述:判断用户输入的信息是否符合要求,登录成功后用户可根据自己的权限对系统进行操作组成:用户名+密码
    数据流编号:F2、F3、F4数据流名:员工登录信息简述:获得与员工权限相关的信息,根据不同权限在页面上显示不同的操作选项组成:ID+用户名+密码+真实姓名+所在部门
    数据流编号:F5、F6数据流名:员工信息简述:实现对员工信息的增、删、改、查操作组成:ID+用户名+密码+真实姓名+性别+年龄+所在部门+创建人+创建时间+修改人+修改时间
    数据流编号:F7、F8数据流名:合作公司信息简述:实现对合作公司信息的增、删、改、查操作组成:ID+公司名+负责人+公司地址+联系电话+创建人+创建时间+修改人+修改时间
    数据流编号:F9、F10数据流名:采购订单信息简述:实现对采购订单信息的增、删、改、查操作组成:ID+商品名+数量+价格+运输方式+货物状态+创建人+创建时间+修改人+修改时间
    数据流编号:F11、F12数据流名:库存信息简述:实现对库存信息的增、改、查操作组成:ID+产品名+数量+存放位置+存放状态+创建人+创建时间+修改人+修改时间
    数据流编号:F13、F14数据流名:销售信息简述:实现对库存信息的增、查操作组成:ID +数量+价格+创建人+创建时间+修改人+修改时间
    数据流编号:F15数据流名:销售人员信息简述:统计销售人员情况组成:姓名+销售金额
    数据流编号:F16数据流名:采购人员信息简述:统计采购人员情况组成:姓名+采购金额
    数据流编号:F17数据流名:销售商品信息简述:统计销售商品信息组成:产品名+销售总量

    4.4.3 描述外部实体
    外部实体名称:经理简述:系统管理员,具有最高权限输入的数据流:人事信息、合作公司信息、采购订单信息、库存信息、销售信息输出的数据流:人事信息、合作公司信息、采购订单信息、库存信息、销售信息、经营统计
    外部实体名称:人事部员工简述:负责百货中心的人事活动及管理输入的数据流:人事信息输出的数据流:人事信息、经营统计
    外部实体名称:采购部员工简述:负责百货中心与外部合作、采购的事物输入的数据流:合作公司信息、采购订单信息输出的数据流:合作公司信息、采购订单信息、经营统计
    外部实体名称:物资部员工简述:负责管理百货中心的仓库、完成商品的入库、出库工作输入的数据流:库存信息输出的数据流:库存信息、经营统计
    外部实体名称:销售部员工简述:负责百货中心的销售工作输入的数据流:销售信息输出的数据流:销售信息、经营统计

    5 系统设计5.1 系统结构设计按照需求分析阶段的结果,本系统的结构主要由两部分构成,首先是登录模块,之后会由登录模块中返回的结果给用户展示可以进行的操作,包括人事管理、合作公司管理、采购订单管理等六大类操作。系统结构图大致如下:

    5.2 系统子模块功能介绍
    登录模块:用户通过输入用户名和密码来登录系统,如果输入错误会返回登录界面,成功登录后用户的登录信息会存储在浏览器中,系统会根据这些信息判断该用户的操作权限
    人事管理模块:已经登录的符合权限的用户可以在此模块中查看公司员工信息,也可以根据需要添加、修改、删除员工信息
    合作公司管理模块:已经登录的符合权限的用户可以在此模块中查看合作公司信息,也可以根据需要添加、修改、删除合作公司信息
    采购订单管理模块:已经登录的符合权限的用户可以在此模块中查看采购订单信息,也可以根据需要添加、修改、删除采购订单信息
    库存管理模块:已经登录的符合权限的用户可以在此模块中查看商品库存信息,也可以根据需要添加、修改、商品库存信息
    销售管理模块:已经登录的符合权限的用户可以在此模块中查看商品销售信息,也可以根据需要添加商品销售信息
    经营统计模块:已经登录的用户可以在此模块中查看最佳销售、最佳采购、最佳商品的信息

    5.3 数据库设计5.3.1 数据库概念设计(E-R模型)本系统实体与其属性的关系用E-R模型表示如下:

    5.3.2 数据库表结构设计根据上述模型,在将其转化成关系模型后,在数据库(数据库名:chain)中创建如下5张表:
    用户表(表名:tb_chain_user)
    用来存储公司员工的表,主要用于系统的登录判断。包含用户id、用户名、密码、真实姓名、性别、年龄、就职日期、是否为管理员、照片、所在部门、创建人、创建日期、更新人、更新日期字段。

    **合作公司表(表名:tb_chain_cooperation)
    用来存储百货中心的合作公司的表,主要用于管理与百货中心合作的公司及公司的商品。主要包含合作公司id、公司名、负责人、公司地址、联系电话、创建人、创建日期、更新人、更新日期等字段。

    订单表(表名:tb_chain_purchase)
    用来存储采购订单的表,用于记录采购的商品在入库前的状态。包含订单id、商品名、数量、价格、运送方式、运送状态、商品公司(合作公司)、创建人、创建时间、更新人、更新时间字段。

    库存表(表名:tb_chain_stock)
    用来存储商品的表,用于显示百货中心仓库中的货物及其相关信息。包含商品id、商品名、数量、摆放位置、存储状态、创建人、创建时间、更新人、更新时间字段。

    销售单表(表名:tb_chain_sale)
    用来存储销售信息的表,用于存储百货中心商品的销售情况。包含销售单id、数量、价格、商品id、用户id、创建人、创建时间、更新人、更新时间字段。

    6 系统实现在经过了需求分析、概要设计和详细设计后,便开始了百货中心供应链管理系统的实现阶段,首先我利用Tiles结合JavaScript对页面进行布局,之后再利用Maven完成整个项目框架的搭建,利用Hibernate反向工程生成Java实体类,再使用Struts和Spring完成之前设计的业务逻辑。部分关键代码及最终程序的运行效果如下:
    登录模块关键代码

    增、删、改、查功能调用关键代码


    经营统计模块关键代码


    6.1 系统登录界面项目发布后,在浏览器地址栏输入 http://localhost:8080 ,页面会跳转到webapp目录下的index.jsp页面并发送index.action请求,未登录的用户会再发送一个login.action请求并跳转到login.jsp页面。

    如果未输入用户名/密码,或输入的用户名/密码不正确,点击登录按钮后会给出出错提示,提醒重新登录。

    6.2 登录成功界面成功登录的用户会进入系统欢迎界面,整个界面是借助Tiles的帮助完成的,它让系统可以在执行不同的请求后只让页面的主题部分跳转,而网页的头、导航栏、尾部不跳转,节省了大量重复书写代码带来的开销。
    根据用户的身份不同,登录后所能看到的操作选项也有所区别。
    经理登录界面
    在本系统中,经理被定义为具有最高权限的用例,可以使用系统的所有功能,能够看到系统所有的操作选项。

    人事部员工登录界面
    本系统中,人事部员工可以操作系统的人事管理模块,因此进入系统后只能看到人事管理的操作选项以及经营统计选项。

    其他部分员工登录成功界面相似,故不再附图。
    6.3 人事管理界面经理、人事部员工可以进入人事管理界面对百货中心的员工信息进行添加、删除、修改、查看功能。
    人事管理界面
    用户进入人事管理界面后,可以根据页面的文字提示对人事信息进行相应的操作,所有员工的主要信息被页面上的表格列出并实现分页功能。

    添加员工界面
    用户点击人事管理界面上的“添加员工”按钮进入添加员工界面,在本页面中输入要添加的员工的信息后,点击保存,即可将新的员工信息添加进数据库中,如果有关键的信息没有正确输入,页面会给出相应的提示。

    更新员工信息界面
    类似于添加员工信息,修改员工信息界面实现了对单个员工信息的修改,同样实现了出错提示功能。

    删除员工成功界面
    成功删除员工信息后会在页面上给出绿色的成功提示信息。

    删除员工信息失败界面
    当已经登录的用户想要删除自己的信息时,会给出删除失败的提示,因为已经登录的用户不能删除自己。

    6.4 合作公司管理界面经理、采购部员工可以登录合作公司管理界面对合作公司进行添加、删除、修改、查看操作。
    合作公司管理界面
    用户进入合作公司管理界面后,可以根据页面的文字提示对合作公司信息进行相应的操作,所有合作公司的主要信息被页面上的表格列出并实现分页功能。

    添加合作公司界面
    用户点击合作公司管理界面上的“添加合作公司”按钮进入添加合作公司界面,在本页面中输入要添加的合作公司信息后,点击保存,即可将新的合作公司信息添加进数据库中,如果有关键的信息没有正确输入,页面会给出相应的提示。

    修改合作公司信息界面
    类似于添加合作公司信息,修改合作公司信息界面实现了对单个合作公司信息的修改,同样实现了出错提示功能。

    删除合作公司成功界面
    成功删除合作公司信息后会在页面上给出绿色的成功提示信息。

    6.5 采购管理界面经理、采购部员工可以进入采购管理界面,对采购订单进行添加、删除、修改、查看操作。其中添加的采购商品必须来自已经有合作关系的公司。
    采购管理界面
    用户进入采购管理界面后,可以根据页面的文字提示对采购信息进行相应的操作,所有采购订单的主要信息被页面上的表格列出并实现分页功能。

    添加采购信息界面
    用户点击采购管理界面上的“添加采购信息”按钮进入添加采购信息界面,在本页面中输入要添加的采购信息后,点击保存,即可将新的采购信息添加进数据库中,如果有关键的信息没有正确输入,页面会给出相应的提示。

    修改采购信息界面
    类似于添加采购信息,修改采购信息界面实现了对单个采购信息的修改,同样实现了出错提示功能。

    删除采购信息成功界面
    成功删除采购信息后会在页面上给出绿色的成功提示信息。

    采购单明细界面
    在采购管理界面点击单个的采购信息链接,可以进入采购信息明细界面,在本页面中可以看到本采购订单的详细信息。

    打印采购信息明细界面
    在采购信息明细界面下方点击“打印”按钮,进入打印采购信息明细界面,可以将相应的采购订单详细信息保存或打印。

    6.6 库存管理界面经理、物资部员工可以进入库存管理界面,并添加、修改库存信息。
    库存管理界面
    用户进入库存管理界面后,可以根据页面的文字提示对库存信息进行相应的操作,所有库存的主要信息被页面上的表格列出并实现分页功能。

    添加库存信息界面
    用户点击库存管理界面上的“添加库存信息”按钮进入添加库存信息界面,在本页面中输入要添加的库存信息后,点击保存,即可将新的库存信息添加进数据库中,如果有关键的信息没有正确输入,页面会给出相应的提示。

    修改库存信息界面
    类似于添加库存信息,修改库存信息界面实现了对单个库存信息的修改,同样实现了出错提示功能。

    库存信息明细界面
    在库存管理界面点击单个的库存信息链接,可以进入库存信息明细界面,在本页面中可以看到本库存的详细信息。

    打印库存信息明细界面
    在库存信息明细界面下方点击“打印”按钮,进入打印库存信息明细界面,可以将相应的库存详细信息保存或打印。

    6.7 销售管理界面经理、销售部员工可以进入销售管理界面,并对销售信息进行添加、查看操作。
    销售管理界面
    用户进入销售管理界面后,可以根据页面的文字提示对库存信息进行相应的操作,所有销售情况被页面上的表格列出并实现分页功能。

    添加销售记录界面
    用户点击库存管理界面上的“添加销售记录”按钮进入添加销售信息界面,在本页面中输入要添加的销售信息后,点击保存,即可将新的销售信息添加进数据库中,如果有关键的信息没有正确输入,页面会给出相应的提示。

    6.8 经营统计界面所有权限的员工都可以查看百货中心的经营状况,其中统计了销售量前十的员工、采购额前十的员工和销售数目前十的商品,方便员工了解公司经营现状,帮助决策层找到公司可能存在的问题。

    7 系统测试7.1 测试目的软件测试(software testing),描述一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。在整个软件生命周期中,软件测试占了很大一部分比例,它是保证软件质量的关键环节,也是降低软件开发风险的必要手段,软件测试工作应该贯穿整个项目开发的始终。
    7.2 测试方法白盒测试
    白盒测试也称结构测试或逻辑驱动测试,它是按照程序内部的结构测试程序,通过测试来检测产品内部动作是否按照设计规格说明书的规定正常进行,检验程序中的每条通路是否都能按预定要求正确工作。在系统开发初期,由于参数设置的失误,我开发的系统经常出现如下的错误:

    经过耐心的调试、测试,已经基本解决了这些错误。
    黑盒测试
    黑盒测试也称功能测试,它是通过测试来检测每个功能是否都能正常使用。在系统功能实现后,我也对系统进行了一部分文本录入测试作为黑盒测试,解决了之前部分页面文字提示错误、页面跳转错误的bug,但由于用户测试的时间有限,还有一些有待改进的地方需要在实际使用中发现。
    7.3 测试结果实现了所有模块的功能,修正了已经发现的所有问题、错误。但系统还有许多不完善的地方,有待实践阶段的检验和提高。
    8 总结通过这次对百货中心供应链管理系统的设计与开发,让我进一步温习了大学课堂上学到了软件工程相关的知识,也使得书本上J2EE、数据库相关的知识得到了实践的机会,同时也对Jsp、JavaScript、Maven等有了进一步的了解,通过查询相关的资料并学习,我也发现了许多不足的地方,还有更多更新更实用的技术,等着我去学习去钻研。总之,经过不懈的学习与调试,我的编程能力有了很大的提高,更重要的是,我也看到了自己仍需努力的方向。
    参考文献[1]曹俊超,戴克商.物资管理理论与实务.北京:清华大学出版社,2006.
    [2]罗伯特·M·蒙兹卡.刘秉镰,李莉,刘洋译.采购与供应链管理.北京:中信出版社,2004.
    [3]肯尼斯·莱桑斯,迈克尔吉林厄姆,鞠磊等译.采购与供应链管理.北京:电子工业出版社,2004.
    [4] 刘京华等. Java Web整合开发王者归来(JSP+Servlet+Struts+Hibernate+Spring).北京:清华大学出版社,2010.
    [5] HUNT J,LFTUS C.精通J2EE-Java企业级应用[M].北京:清华大学出版社,2004.
    [6] LIANG Y D..Java语言程序设计[M].北京:机械工业出版社,2003.
    [7] Angela Yochem.J2EE应用与BEA WebLogic Server[M].北京:电子工业出版社,2005.
    [8]陈天河.Java数据库高级编程宝典[M].北京:电子工业出版社,2005.
    [9]泰勒.JDBC数据库编程与J2EE[M].北京:电子工业出版社,2004.
    [10]顾兵.XML实用技术教程[M].北京:清华大学出版社,2007.
    [11]丁宝康.数据库实用教程[M].北京:清华大学出版社,2003.
    [12]李刚. 轻量级Java+EE企业应用实战(第3版).北京:电子工业出版社,2012.
    [13] 陈亚辉,缪勇.Struts2+Spring+Hibernate框架技术与项目实战.北京:清华大学出版社,2012.
    [14] 刘勇军,王电钢. Java EE项目应用开发:基于Struts2,Spring,Hibernate.北京:电子工业出版社,2012.
    [15] 埃克尔. Java编程思想(第4版).北京:机械工业出版社,2007.
    [16] 张海藩.软件工程导论[M].北京:清华大学出版社,2003.
    1 评论 5 下载 2020-07-20 10:04:27 下载需要13点积分
  • 基于JAVA的俄罗斯方块游戏

    一、功能需求俄罗斯方块应有如下功能:

    在二维的平面里用各种随即产生的方块堆积木,每填满一行消去一行,当到达顶部时,游戏结束玩家能通过方向键来控制方块的转动,左移,右移和直落每种类型的方块都有颜色游戏能够在玩的过程中,给出玩家的分数,分数是由随即方块的类型决定的,每堆一个方块,就将分数累加到总分中游戏有暂停、开始和结束、游戏规则、游戏说明等控制

    二、分析与设计
    开发环境:Eclipse
    软件功能架构图:

    界面设计过程:
    游戏主类,继承自JFrame类,负责游戏的全局控制。 内含:

    一个GameCanvas画布类的实例对象(用于存放小方格)一个保存当前活动块(RussiaBlock)实例的对象一个保存当前控制面板(ControlPanel)实例的对象添加菜单栏,并设置窗口的布局管理器为BorderLayout,左边加上画布,右边加上控制面板,设置整个程序打开时居中放置
    创意:玩家可以直接从控制面板控制游戏的开始和暂停以及增减难度,而且可以在菜单栏中更改游戏界面的背景色和方块的颜色,更加提高了用户舒适度。菜单中帮助栏目的关于本游戏的按钮可以显示出本人的信息。
    游戏界面图如下:




    程序实现的关键:

    该小程序总共由5个主要的类构成:

    菜单栏功能图

    各个类的关系如下图所示


    三、程序截图












    4 评论 314 下载 2018-10-21 20:40:18 下载需要10点积分
  • 基于java的多人聊天程序课程设计

    一、设计内容及要求1.1 设计内容聊天工具大多数由客户端程序和服务器程序外加服务器端用于存放客户数据的数据库组成,本程序采用客户机/服务器架构模式。通过Java提供的Socket类来连接客户机和服务器并使客户机和服务器之间相互通信,由于聊天是多点对多点的而Java提供的多线程功能。用多线程可完成多点对多点的聊天。
    1.2 设计要求主要有两个应用程序,分别为服务器程序和客户端程序。服务器应用程序主要用于消息转发、客户登录信息的管理以及向所有用户发送系统消息等;客户端应用程序主要用于客户聊天记录的显示和信息输入。采用Client/Server(C/S)体系结构,即客户机/服务器体系结构。聊天服务器专门用于监控用户状态和转发消息,客户端负责接收消息的用户序列和消息文本发送到服务器。该聊天系统实现私聊,群聊,用户注册,登陆,退出聊天系统等功能。
    二、系统需求分析2.1 系统介绍在当今信息时代,有许多的聊天工具,例如QQ、微信等。本程序就是利用Java网络编程的知识,采用客户机/服务器架构模式来实现客户端与客户端之间的通讯。
    2.2 开发背景在当今信息时代,越来越多的聊天工具被应用,Java语言是当今流行的网络编程语言,它具有面对对象、跨平台、安全、多线程等特点。使用Java语言不仅可以实现大型企业级的分布式系统应用,还能为小型的、嵌入式设备进行应用程序开发。面对对象的开发方法是当今最流行的开发方法,它不仅更贴近现实,而且有利于软件的维护和继承。为了进一步巩固课堂上所学到的知识,深刻把握Java语言的重要概念及面对对象的特性,锻炼我们熟练的应用面对对象的思想和设计方法解决实际问题的能力,所以我选择了开发Java多人聊天程序。
    三、系统总体设计3.1 系统功能结构图
    3.2 系统数据流程图
    四、系统详细设计4.1 本设计所涉及技术和知识点
    C/S体系结构:采用Client/Server(C/S)体系结构,即客户机/服务器体系结构。其中客户端用了发送和接受收显示聊天消息,服务器用来监听客户端的消息,并将接收到的数据转发到所用的客户端上,这样实现群聊功能。Socket套接字:作为多人聊天程序,网络编程的知识必不可少,其中用到了Socket套接字、IP地址、端口号等网络编程的知识。客户端与服务器的窗口用到Java Swing图形用户界面知识,其中包括界面的布局、组件的使用以及各种监听事件的使用。多线程:为了是客户端与客户端之间的消息、客户端发送与接收的消息不发生冲突,将每个客户端的发送和接收用不同的线程。IO流:聊天时客户端与服务器之间肯定有数据的输入输出,所以IO流的知识在这里也十分重要。
    4.2 功能模块详细设计
    客户端:运行客户端时,弹出登录客户端界面,这是需要设置用户名、IP地址和端口号,其中IP和端口号必须和服务器的对应,否则连接不上服务器。登录后进入客户端聊天界面窗口。这时可以与其他客户端之间在一个聊天室中聊天,若想私聊某人,只需在聊天内容前加上@该用户的姓名+:就可以了。点击右上角的下线按钮即退出该聊天室。
    发送消息:当点击发送按钮时,将消息通过DataOutputStream流中的writeUTF发送到服务端,服务端通过DataInputStream中的readUTF接受客户端的消息,紧接着服务端通过DataOutputStream中的writeUTF发送个所有客户端。
    私聊:当用户登录后,在没有点击发送按钮前,先将该客户端的姓名发送到服务器,服务器先接收到用户的姓名,然后在接收聊天消息。
    服务器:启动服务器,弹出设置服务器的窗口,填写服务器的IP地址和端口号,点击确定后,服务器启动,并不断监听客户端的连接和接收客户端发来的消息。

    五、编码与实现5.1 具体功能模块实现该多人聊天程序包括8个文件,功能如下:
    1. Client.java 包含Client类,其中有main、connectServer函数,是客户端启动的入口。在main函数中通过创建一个ClientLogin对象,来打开登陆窗口。 ClientLogin login = newClientLogin();
    2. ClientFrame.java
    包含ClientFrame类,该类继承于Jframe类,用来创建客户端的窗口。 其中包括窗口中的各个组件、布局以及组件的监听事件。
    sendButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { msg = msgText.getText().toString(); ClientSend.send(); msgText.setText(null); });
    发送按钮的监听事件,当点击发送时,将发送栏中的消息保存在字符串msg中,在,然后调用 ClientSend.send()函数,将该字符串发送到服务器。
    3. ClientLogin.java
    包含ClientLogin类,该类继承于Jframe类,用来创建客户端登录窗口,其中包括设置IP地址、端口号、用户姓名的各种组件,和登录按钮的监听事件:
    btn_login.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { name = jtf_userName.getText().toString(); ip = jtf_ip.getText().trim(); port = Integer.parseInt(jtf_port.getText().toString()); //点击登录后,客户端连接服务器 try { Client.connectServer(); } catch (UnknownHostException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } //隐藏当前窗口 dispose(); //关闭 //打开客户端 new ClientFrame(); } });
    点击登录按钮时,将窗口中用户姓名、IP地址和端口号分别赋值给字符串name、ip、port变量,然后调用Client.connctServer()来连接服务器,并且关闭该窗口,创建ClientFrame对象来打开客户端窗口。
    4. ClientReceive.java
    包含ClientReceive类,该类中有Runnable接口,用于创建一个用户接受服务器消息的客户端接受线程。
    线程体:
    public void run() { String msg = null; while(isRunning){ //将接受信息输出到客户端窗口中 msg = receive(); System.out.println(msg); ClientFrame.msgRecordText.append(msg+"\n"); } }
    该线程处于死循环中,其中receive()函数用来接收服务器的消息,并通过ClientFrame.msgReceordText.append(msg+”\n”)将消息显示在客户端的窗口聊天记录面板上。
    5. ClientSend.java
    包含ClientReceive类,该类中有Runnable接口,用于发送消息,该线程的线程体为空:
    public void run() { }
    当用户点击客户端窗口中的发送按钮时,会调用该类中的send函数,用于将消息发送到服务器。
    6. Server.java
    包含Server类,其中包含main、setServer方法和List<ServerForward>集合类。
    其中main函数是服务器的入口,用来打开服务器设置窗口。
    main函数:
    ServerFrame serverFrame = new ServerFrame();
    setServer函数:
    public static void setServer() throws IOException { //从服务器窗口获取ip和端口号 String ip = ServerFrame.ip; int port = ServerFrame.port; ServerSocket server = new ServerSocket(port, 0,InetAddress.getByName(ip)); while(true) { Socket client = server.accept(); System.out.println("连接成功"); ServerForward serverForward = new ServerForward(client); allClient.add(serverForward); Thread thread = new Thread(serverForward); thread.start(); } }
    启动服务器,不断的监听客户端的连接,当有客户端连接上时,在List<ServerForward>集合类中添加该线程,并启动该线程。
    7. ServerForward.java
    包含ServerForward类,服务器接受一个客户端得信息,再转发给其他客户端。该类中主要包括receive、send函数,用于转发客户端的消息。
    线程体:
    public void run() { //接受用户的昵称 while(isRunning) { if (name == null) name = getClientName(); else break; } while(isRunning) { sendToClient(receive()); } }
    因为服务器的工作不间断的,所以用无限循环。getClientName()从客户端中接受用户的姓名,并保存字符串name中。sendToClient(receive())接收一个客户端的消息,并转发给所有客户端。
    8. ServerFrame.java
    包含serverFrame类,该类继承于JFrame,用于创建服务器设置界面,其中包括设置IP地址、端口号,和确认按钮的监听事件:
    btn_set.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ip = jtf_ip.getText().trim(); port = Integer.parseInt(jtf_port.getText().toString()); //关闭窗口 dispose(); //点击确定后,设置服务器ip和端口号 try { Server.setServer(); } catch (UnknownHostException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } } });
    将服务器设置窗口中的IP地址和端口信息ip、port字符串中,并调用Server.setServer函数,开始启动服务器。
    5.2 演示界面5.2.1 服务器设置窗口
    5.2.2 客户端登录窗口
    5.2.3 客户端窗口
    5.2.4 群聊和私聊
    9 评论 347 下载 2018-10-21 14:43:22 下载需要13点积分
显示 60 到 75 ,共 15 条
eject