分类

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

资源列表

  • 基于C语言实现的超市管理系统

    1 需求分析超市随着市场经济和现代信息技术的的发展,不可必要的要卷入信息现代化的大潮,如何使用现代化的工具,使企业和经营者个人在最小的投入下获取最大的回报,成为每一个人的梦想。因此,在超市管理中引进现代化的办公软件,就成为时下最好的解决办法。使用软件办公,不仅能使经营者的劳力资本减少,同时能使超市的管理更规范更合理,解决了超市中用于管理进出货以及购买、库存等众多繁琐、工作量巨大从而导致耗费人员过多,超市经营紊乱等众多问题。
    1.1 主要功能
    超级管理员模块:(需帐号登录)

    添加管理员删除管理员
    管理员模块:(需帐号登录)

    商品信息录入(编号、名称、单价、库存)商品信息修改(修改商品的各种信息)商品信息查询(根据所输入的商品名字,编码查询库存信息)商品信息删除(从商品文件中删除商品信息)商品信息排序(按编号,单价,库存3种模式进行排序)输出商品全部库存信息删除普通用户功能(管理员有权限删除普通用户帐号)
    普通用户模块:(需帐号登录)

    新用户注册用户登录:
    商品查询商品排序输出商品全部库存信息购买商品(通过用户余额来进行购买)充值(通过输入充值卡卡号对用户余额充值)修改用户密码


    1.2 运行环境
    操作系统:Windows NT/2000/XP/VISTA/WIN7/WIN8/WIN10
    开发平台:Microsoft Visual Studio 2012

    1.3 文件说明
    程序源代码(超市管理系统.cpp)
    程序运行文件(超市管理系统.exe)
    管理员信息(管理员信息.txt)
    普通用户信息(普通用户信息.txt)
    商品信息(商品信息.txt)

    2 总体方案设计2.1 设计方案整个超市管理系统分为3个模块,超级管理员+管理员+普通用户,其中:

    管理员可以实现商品信息的录入,修改,查询等管理操作,同时还拥有对普通用户帐号的管理
    超级管理员是最高执行者,拥有对管理员帐号的操作权限,可以对管理员帐号进行添加或删除
    普通用户模块,由于考虑到该程序的真实性,所以实现了普通用户的注册和登录功能,用户要进行购物,必须使用帐号(可自行注册,无须经过管理员),其中普通用户具有商品查询等一部分功能。特色功能是具有帐号余额功能,同时购物可以进行充值功能(输入充值卡卡号,类似于购买充值卡来充值)

    2.2 主要结构
    超级管理员模块:(需帐号登录)

    添加管理员删除管理员
    管理员模块:(需帐号登录)

    商品信息录入(编号、名称、单价、库存)商品信息修改(修改商品的各种信息)商品信息查询(根据所输入的商品名字,编码查询库存信息)商品信息删除(从商品文件中删除商品信息)商品信息排序(按编号,单价,库存3种模式进行排序)输出商品全部库存信息删除普通用户功能(管理员有权限删除普通用户帐号)
    普通用户模块:(需帐号登录)

    新用户注册用户登录:
    商品查询商品排序输出商品全部库存信息购买商品(通过用户余额来进行购买)充值(通过输入充值卡卡号对用户余额充值)修改用户密码


    2.3 程序功能和流程图由于本程序模块功能较多,有超级管理员,管理员和普通用户,共3个模式的功能,流程图较大,因此分为3个子图。
    超级管理员模块

    管理员模块

    普通用户模块

    2.4 数据结构和算法的设计说明本程序有3个数据结构:管理员,普通用户,商品共3个结构体。其中程序拥有超级管理员、管理员和普通用户共3种身份,运用链表来存储和读取所保存的信息。
    2.4.1 结构体类型一开始选择模块,输入帐号和密码,进行验证,是否正确。正确就进入功能模块。
    typedef struct custom* cpointer;//结点指针类型struct custom{ string custom_ID;//帐号 string custom_name;//姓名 string custom_mima;//密码 double money;//账户余额 cpointer next;};typedef cpointer clklist;//单链表类型,即头指针类型
    其中,管理员、普通用户、商品都是定义结构体,而后进入系统,一开始便定义相对应的链表进行存储和获取已保存的信息。
    2.4.2 算法设计排序算法
    for(int i=0;i<Goodnum;i++){ for(int j=Goodnum;j>=i+1;j--){ if(Go.Good[j].Good_ID<Go.Good[j-1].Good_ID) {//比较编号大小,小的在前面,大的在后面 flag=1; p=Go.Good[j]; Go.Good[j]=Go.Good[j-1]; Go.Good[j-1]=p; } }
    通过对相邻2个商品的编号不断比较,排序,运用2个for循环,比较编号大小,小的在前面,大的在后面。不断变换,最终排序完成。
    2.5 程序关键源代码说明程序中拥有3个身份:超级管理员,管理员,普通用户。不同身份之间函数都差不多,因此将函数直接展示,不说明为哪个身份的权限功能。
    custom_ender函数:登录验证函数。对输入的帐号和密码进行验证检索,正确就进入对应的身份模块。先定义一个普通用户结构体类型cpointer对象p,把包含普通用户全部信息的单链表head赋值给p,而后对p进行检索,如果p链表中的用户信息与输入的用户信息(帐号+密码)相同,就返回1;不同就显示“用户帐号不存在”,同时返回0。
    int custom_ender(clklist &head,string ID,string mima){ cpointer p; p=head; while(p!=NULL) { if(p->custom_ID==ID&&p->custom_mima==mima) return 1; else p=p->next; } cout<<"用户帐号不存在!"<<endl; return 0;}
    custom_creat函数:注册函数。先定义一个普通用户结构体类型cpointer对象p,把包含普通用户全部信息的单链表head赋值给p,而后输入注册用户的各种信息(帐号,密码,姓名),如果输入的帐号ID与已保存的用户帐号相同,就显示已存在,提示重新输入。最后将输入的新注册用户信息运用头插法插入,保存到”普通用户信息.txt”文件中保存
    void custom_creat(clklist &head){ cpointer s,p; string ID,name,mima; int sign=1,flat=1; while(sign!=0){ flat=1; cout<<"请输入用户帐号"<<endl; cin>>ID; p=head->next; while(p!=NULL){ if(p->custom_ID==ID) flat=0; p=p->next; } if(flat==0) { cout<<"用户帐号已存在,请重新输入"<<endl; continue; } cout<<"请输入用户密码"<<endl; cin>>mima; cout<<"请输入用户姓名"<<endl; cin>>name; s=new custom; s->custom_ID=ID; s->custom_name=name; s->custom_mima=mima; s->money=0; s->next=head->next;//使用头插法建表 head->next=s; buyernum++;//输入一个用户信息,buyernum自加1 custom_save(head); cout<<"是否继续注册?<继续>请按1 <结束>请按0"<<endl; cin>>sign;//while循环判断条件,所以不需要用if }}
    custom_get函数:从文件获取用户信息函数。先定义一个普通用户结构体类型cpointer对象p,把包含普通用户全部信息的单链表head赋值给p, 而后运用一个for循环,将用户信息从“普通用户信息.txt“全部导入到p链表中,返回给系统。
    clklist custom_get(clklist &buyer){ cpointer s,p;//s用于存储用户信息,p用于buyer的连接 string numname; string ID,name,mima; double money; buyer->next=NULL; p=buyer; ifstream ifile("C:\\普通用户信息.txt",ios::in); if(!ifile){ cerr<<"用户信息查询出错"<<endl;return 0; } ifile>>numname; ifile>>buyernum;//从文件中提取用户个数,用于for循环 for(int i=1;i<=buyernum;i++){ ifile>>ID; ifile>>name; ifile>>mima; ifile>>money; s=new custom; s->custom_ID=ID; s->custom_name=name; s->custom_mima=mima; s->money=money; s->next=p->next; p->next=s; } buyer=p; ifile.close(); return buyer;}
    Good_add函数:商品信息录入函数。把包含商品信息的链表Goods传入该函数,输入商品编号,if(Good_ender1(Goods,ID)==0)进行检索是否商品已存在,存在就提示重新输入,不存在就继续录入商品信息,导入到Goods链表中,最后运用Good_save(Goods)保存全部信息到“商品信息.txt”文件中。
    void Good_add(sqlist &Goods){ string ID,name; double piece; int last,sign,flat=1;//last为商品库存,sign用于判断选择 fstream ifile("C:\\商品信息.txt",ios::in); for(;flat!=0;) { cout<<"请输入商品编号:"; cin>>ID; if(Good_ender1(Goods,ID)==0) { cout<<"请输入商品名称:"; cin>>name; if(Good_ender2(Goods,name)==0) { cout<<"请输入商品单价:"; cin>>piece; cout<<"请输入商品数量:"; cin>>last; Goods.Good[Goodnum].Good_ID=ID; Goods.Good[Goodnum].Good_name=name; Goods.Good[Goodnum].piece=piece; Goods.Good[Goodnum].last=last; Goodnum++;//添加完信息就自加1 Good_save(Goods);//添加完就保存至商品信息.txt cout<<"是否继续录入?<继续>请按1 <结束>请按0"<<endl; cin>>sign; if(sign==0) break; } else {cout<<"商品名称已存在!<重新输入>请按1 <结束>请按0"<<endl; cin>>flat;} } else {cout<<"商品编号已存在!<重新输入>请按1 <结束>请按0"<<endl; cin>>flat;} }}
    Good_change函数:商品信息修改函数。把包含商品信息的链表Goods传入该函数,考虑到用户可能只记得商品编号或者商品名称,因此编写了2种修改模式(按编号检索修改,还是按名称检索修改)。如果选择按编号检索修改,同样对编号进行检索,如果在Goods链表中找到该商品编号,就运用 sign=Good_locate1(Goods,ID);定位记录下该商品在文件中的位置,而后输入修改后的商品信息,保存至文件中;按名称检索修改类似。最后修改完后,会提示是否继续修改,如果不继续就返回用户功能界面,执行其他功能。
    void Good_change(sqlist &Goods){ string ID,name; int sign;//sign用于定位要修改商品的位置 int a,flat=1;//a用于switch for(;flat!=0;){ cout<<"<输入要修改的商品编号>请按1 <输入要修改的商品名称>请按2"<<endl; cin>>a; if(a!=1&&a!=2) {cout<<"选择有误,请重新输入"<<endl;continue;} switch(a){ case 1: { cout<<"请输入商品编号:"; cin>>ID; if(Good_ender1(Goods,ID)==1) { sign=Good_locate1(Goods,ID); cout<<"商品编号:"<<Goods.Good[sign].Good_ID<<endl; cout<<"商品名称:"<<Goods.Good[sign].Good_name<<endl; cout<<"商品单价:"<<Goods.Good[sign].piece<<endl; cout<<"商品库存:"<<Goods.Good[sign].last<<endl; cout<<"请输入修改后的信息:"<<endl; cout<<"商品编号:"; cin>>Goods.Good[sign].Good_ID; cout<<"商品名称:"; cin>>Goods.Good[sign].Good_name; cout<<"商品单价:"; cin>>Goods.Good[sign].piece; cout<<"商品库存:"; cin>>Goods.Good[sign].last; Good_save(Goods);//保存信息 cout<<"修改成功"<<endl; } else cout<<"商品不存在!"<<endl; break; } case 2: 大致与编号模式相同 else cout<<"商品不存在!"<<endl; break; } }//switch的 cout<<"<继续修改>请按1 <退出>请按0"<<endl; cin>>flat; }//for循环的}
    Good_inquire函数:商品信息查询函数。把包含商品信息的链表Goods传入该函数,考虑到用户可能只记得商品编号或者商品名称,因此编写了2种查询方式(按编号检索查询,还是按名称检索查询)。如果选择按编号检索查询,同样对编号进行检索,如果在Goods链表中找到该商品编号,就运用 sign=Good_locate1(Goods,ID);定位记录下该商品在文件中的位置,而后输出该商品信息的全部信息;按名称检索查询类似。最后查询完后,会提示是否继续查询,如果不继续就返回用户功能界面,执行其他功能。
    void Good_inquire(sqlist &Goods){ string ID,name; int a,sign,flat=1; for(;flat!=0;){ cout<<"<按商品编号查询>请按1 <按商品名称查询>请按2"<<endl; cin>>a; if(a!=1&&a!=2) {cout<<"选择有误,请重新输入"<<endl;continue;} switch(a){ case 1: { cout<<"请输入商品编号:"; cin>>ID; if(Good_ender1(Goods,ID)==1) { sign=Good_locate1(Goods,ID); cout<<"商品编号:"<<Goods.Good[sign].Good_ID<<endl; cout<<"商品名称:"<<Goods.Good[sign].Good_name<<endl; cout<<"商品单价:"<<Goods.Good[sign].piece<<endl; cout<<"商品库存:"<<Goods.Good[sign].last<<endl; } else cout<<"商品不存在!"<<endl; break; } case 2: 大致与编号模式相同 else cout<<"商品不存在!"<<endl; break; } }//switch的 cout<<"是否继续查询?<继续>请按1 <结束>请按0"<<endl; cin>>flat; if(flat==0) break; }//for循环的}
    Good_delete函数:商品信息删除函数。把包含商品信息的链表Goods传入该函数,考虑到用户可能只记得商品编号或者商品名称,因此编写了2种删除方式(按编号检索删除,还是按名称检索删除)。如果选择按编号检索删除,同样对编号进行检索,如果在Goods链表中找到该商品编号,就运用 sign=Good_locate1(Goods,ID);定位记录下该商品在文件中的位置,而后使用for(int i=sign; i\<Goodnum; i++)将该位置后的商品全部前移1位,覆盖掉该位置,最后保存删除后的商品信息至“商品信息.txt”中;按名称检索删除类似。最后删除完后,会提示是否继续删除,如果不继续就返回用户功能界面,执行其他功能。
    void Good_delete(sqlist &Goods){ int a,sign,flat=1; string ID,name; for(;flat!=0;){ cout<<"<输入要删除的商品编号>请按1 <输入要删除的商品名称>请按2"<<endl; cin>>a; if(a!=1&&a!=2) {cout<<"选择有误,请重新输入"<<endl;continue;} switch(a){ case 1: { cout<<"请输入要删除的商品编号:"; cin>>ID; if(Good_ender1(Goods,ID)==1){ sign=Good_locate1(Goods,ID); for(int i=sign;i<Goodnum;i++){ Goods.Good[i]=Goods.Good[i+1]; } Goodnum--; Good_save(Goods); cout<<"删除成功!"<<endl; } else cout<<"商品不存在!"<<endl; break; } case 2: 大致与编号模式相同 else cout<<"商品不存在!"<<endl; break; } }//switch的 cout<<"是否继续删除?<继续>请按1 <结束>请按0"<<endl; cin>>sign; if(sign==0) break; }//for循环的}
    Good_range函数:商品信息排序函数。把包含商品信息的链表Go传入该函数,选择排序模式(按编号,单价,库存进行排序),运用2层for循环,使用冒泡法进行排序,从尾部向头部进行对比检索,小的放前面,大的放后面,排序完之后就将排序后的商品信息显示给用户;3种模式大致相同。最后排序完后,会提示是否继续执行,如果不继续就返回用户功能界面,执行其他功能。
    void Good_range(sqlist Go){ Goods p; p.piece=0; p.last=0; int a,flag=0,flat=1; for(;flat!=0;){ cout<<"<按商品编号排序>请按1 <按商品单价排序>请按2 <按库存数量排序>请按3 <退出>请按0"<<endl; cin>>a; if(a!=0&&a!=1&&a!=2&&a!=3) {cout<<"选择有误,请重新输入"<<endl;continue;} switch(a){ case 1: { for(int i=0;i<Goodnum;i++){ for(int j=Goodnum;j>=i+1;j--){ if(Go.Good[j].Good_ID<Go.Good[j-1].Good_ID){//比较编号大小,小的在前面,大的在后面 flag=1; p=Go.Good[j]; Go.Good[j]=Go.Good[j-1]; Go.Good[j-1]=p; } }//jfor的 if(!flag) break; }//ifor的 cout<<"商品编号"<<setw(10)<<"商品名称"<<setw(10)<<"商品单价"<<setw(10)<<"商品库存"<<endl; for(int i=1;i<=Goodnum;i++){ cout<<Go.Good[i].Good_ID<<setw(13)<<Go.Good[i].Good_name<<setw(8)<<Go.Good[i].piece<<setw(10)<<Go.Good[i].last<<endl; } break; } case 2: 大致与编号模式相同 case 3: 大致与编号模式相同 case 0:return; }//switch的 }//最外层for的
    Good_buy函数:购买商品函数。把包含商品信息的链表Goods以及包含用户信息的链表head传入该函数,选择购买模式(输入编号或名称进行购买),如果输入的商品编号与Goods中的商品信息相同,就提示购买数量,这时如果购买数量超过库存数量会提示“库存不足”,然后重新输入;如果购买商品所支付的钱超过用户的余额,则提示“余额不足”,是否前往充值页面进行充值。充值模块下面会展示。购买完商品后,用户可以继续购买,也可以返回用户功能界面。
    void Good_buy(sqlist &Goods,clklist &head,string cID){//cID为用户帐号 string ID,name; int a,shu,sign,flat=1; cpointer p; p=custom_locate(head,cID); for(;flat!=0;){ cout<<"<输入商品编号购买>请按1 <输入商品名称购买>请按2"<<endl; cin>>a; if(a!=1&&a!=2) {cout<<"输入有误,请重新输入"<<endl;continue;} switch (a) { case 1: { cout<<"请输入商品编号:"; cin>>ID; if(Good_ender1(Goods,ID)==1) { sign=Good_locate1(Goods,ID); cout<<"请输入购买数量:"; cin>>shu; if(shu<=Goods.Good[sign].last){ if(p->money<Goods.Good[sign].piece*shu) {cout<<"余额不足,请充值!"<<endl; cout<<"是否前往充值?<充值>请按1 <否>请按0"<<endl; cin>>flat; if(flat==0) break; if(flat==1) return;} Goods.Good[sign].last=Goods.Good[sign].last-shu; cout<<"购买成功"<<endl; p->money=p->money-Goods.Good[sign].piece*shu;//账户余额减少,扣费成功 custom_save(head); cout<<"账户余额:"<<p->money<<endl; Good_save(Goods); } else cout<<"库存不足!"<<endl; } else cout<<"找不到相应商品,购买失败"<<endl; break; } case 2:与编号模式类似 }//switch的 cout<<"是否继续购物?<继续>请按1 <结束>请按0"<<endl; cin>>flat; if(flat==0) break; }//for的}
    custom_addmoney函数:余额充值函数。余额是用户帐号中的一个成员,初始为0,用户在购物的时候余额会减少,如果余额不足就无法进行购物,需要进行充值,充值是输入系统给定的充值卡卡号进行充值,这是本系统的一大亮点。把包含用户信息的链表head传入该函数,运用 p=custom_locate(head,ID);定位是哪个用户的帐号要进行充值,其中,系统设定了2种充值卡“asd500”和“asd1000”分别可以充值500和1000元,这类似与用户购买不同的充值卡给自己的账户进行充值。用户输入充值卡卡号,进行检索是否与系统设定的充值卡卡号相同,如果相同就充值相应的金额;如果不同,就提示“充值卡无效”。最后充值后,用户可以选择继续充值或者返回用户功能界面进行购物等其他操作。
    void custom_addmoney(clklist &head,string ID){ cpointer p; int sign=1; p=custom_locate(head,ID); string acard,card1="asd500",card2="asd1000"; while(sign!=0){ cout<<"请输入您获得的充值卡卡号:"; cin>>acard;//acard是用户获得的充值卡 if(acard!=card1&&acard!=card2) cout<<"充值卡无效"<<endl; if(acard==card1) { p->money+=500; cout<<"充值成功!"<<endl; cout<<"账户余额:"<<p->money<<endl; }; if(acard==card2) { p->money+=1000; cout<<"充值成功!"<<endl; cout<<"账户余额:"<<p->money<<endl; }; custom_save(head);//充值成功 cout<<"是否继续充值?<继续>请按1 <结束>请按0"<<endl; cin>>sign;//while循环判断条件,所以不需要用if }
    3 程序功能测试一开始进入系统,初次使用会提示文件打开失败,是正常的,不影响功能。由于原本的“管理员信息.txt”“普通用户信息.txt”“商品信息.txt”是空的,当录入信息就不会有提示了。进入身份选择(都要帐号和密码)

    选择1进入超级管理员,(帐号:asd,密码123),先添加管理员。

    选择1,添加管理员信息(帐号+密码+姓名),添加完后可以选择继续添加或返回

    选择2,输入要删除的管理员帐号,直接删除管理员

    添加完管理员后,可返回主菜单,进入管理员模式,输入刚刚添加的管理员帐号+密码,进入管理员模式

    功能1,进入商品录入功能,输入商品的信息(编号,名称,单价,库存),当录入成功之后,管理员可以选择继续录入或返回(该模块当录入编号和名称和已录入的信息相同会提示出错,重新录入)

    功能2,可进行商品修改,有2种模式进行选择,输入商品编号101后,显示“商品信息.txt“文件中的商品信息,而后管理员可以输入修改后的信息

    功能3,可以进行商品信息查询,可以查询到刚刚修改的联想笔记本

    功能4,可以进行删除已录入的商品信息,例如,删除刚录入的联想笔记本

    删除后,进入查询功能查看联想笔记本,不存在,表明删除成功~ ~

    功能5,进行已录入商品信息排序,可选择(编号,单价,库存)进行从小到大排序,编号也是可以的

    功能6,输出全部商品信息

    功能7,删除普通用户,如果已经有普通用户,只需要输入普通用户的帐号就可以直接删除
    进入普通用户模块,如果没有帐号是无法查看和购物的,因此消费者可以自行注册

    注册完,就可以登录进入用户模块进行购物了

    其中,商品查询,排序,库存是和管理员一样的,就不展示了
    功能4,购买商品,一开始,由于没充值时,用户余额为0,余额不足,无法购买,用户可以返回,进行充值后购买。如果充值后,余额充足就可以购买了,购买后,余额相应减少

    这里我先前往充值2000元,后购买如下,主机单价50,购买后余额为1950,扣费成功

    功能5,用户可以随时修改自己的账户密码,保护自己的财产
    功能6,就是充值了,输入系统给定的充值卡卡号,有(asd500和asd1000)

    由于刚余额1950,现在输入卡号asd1000,成功充值1000,剩余2950
    4 总结这次选择了做“超市管理系统”,在完成基本功能之后,觉得要真正实现成功的超市管理系统,必须要有个人的帐号,因此增加了普通用户注册和帐号模式,同时管理员和超级管理员也都是用帐号+密码进入。普通用户可以自行注册,拥有自己的私人帐号。同时,超市管理系统普通用户在进行购买之后,应该是要有余额的,因此添加了余额成员。拥有余额成员之后,就想到,用户需要购买东西,余额不足就需要进行充值,为了实现真实性,就选定,用户需要输入充值卡卡号进行充值。最终完美实现。
    这个系统,是使用链表实现的,由于之前的大作业是使用文件流,不是使用链表,因此这次的大作业就决定说要使用链表来实现。在编程过程中,也发现了很多的bug,最终还是一一解决。感觉自己的编程能力在不断的提高,无论是什么bug都可以自行调试解决。
    同时,在思考程序的框架功能时,也逐渐重视用户体验,人机交互。编写大作业,不再只是仅仅满足基本功能,在基本功能上,还添加其余用户体验好的功能(比如帐号登录,充值等等功能),感觉大作业让我学会了很多。
    6 评论 252 下载 2018-10-31 11:28:48 下载需要7点积分
  • 基于C++和OpenSSL实现的SSL网络通信

    一、实验内容
    安装openSSL
    编写一个服务器的程序,服务器端的功能是建立SSL网络服务,接受客户端的SSL连接,收发SSL消息
    编写一个客户端的程序,客户端的功能是通过SSL协议连接服务器,收发SSL消息
    生成SSL证书
    撰写试验报告,包括了服务器端和客户端运行结果截图,以及生成的SSL证书

    二、实验框架程序分为两部分,客户端和服务器端,我们的目的是利用SSL/TLS的特性保证通信双方能够互相验证对方身份(真实性),并保证数据的完整性, 私密性。
    服务器认证阶段

    客户端向服务器发送一个开始信息“Hello”以便开始一个新的会话连接
    服务器根据客户的信息确定是否需要生成新的主密钥,如需要则服务器在响应客户的“Hello”信息时将包含生成主密钥所需的信息
    客户根据收到的服务器响应信息,产生一个主密钥,并用服务器的公开密钥加密后传给服务器
    服务器恢复该主密钥,并返回给客户一个用主密钥认证的信息,以此让客户认证服务器

    用户认证阶段
    在此之前,服务器已经通过了客户认证,这一阶段主要完成对客户的认证。经认证的服务器发送一个提问给客户,客户则返回(数字)签名后的提问和其公开密钥,从而向服务器提供认证。
    流程图如下:

    客户端以及服务器端的框架如下:

    三、实验步骤3.1 安装openSSL下载openSSL的exe文件,在 https://slproweb.com/products/Win32OpenSSL.html 网站上下载合适的安装包。

    下载完后打开安装,选择安装位置,64位和32位不要安装在同一个目录下。

    选择把dll复制到OpenSSL目录下。

    安装完成后,如果有捐款意向的可以捐款,没有意向则取消掉钩,然后点“Finish” 。
    3.2 VS2017搭建openssl环境新建空项目,然后配置项目属性(包含目录添加进openssl的include文件夹;库目录添加openssl的lib文件夹)。

    将OpenSSL安装目录下bin文件夹中的“libeay32.dll”和“ssleay32.dll”(名字后面的版本号可能因更新而不同)复制到工程目录下。
    3.3 生成证书首先要生成服务器端的私钥(key文件)
    openssl genrsa -des3 -out server.key 1024运行时会提示输入密码,此密码用于加密key文件(参数des3便是指加密算法,当然也可以选用其他你认为安全的算法),以后每当需读取此文件(通过openssl提供的命令或API)都需输入口令。如果觉得不方便,也可以去除这个口令,但一定要采取其他的保护措施!
    去除key文件口令的命令:
    openssl rsa -in server.key -out server.key
    openssl req -new -key server.key -out server.csr生成Certificate Signing Request(CSR),生成的csr文件交给CA签名后形成服务端自己的证书。屏幕上将有提示,依照其指示一步一步输入要 求的个人信息即可。

    对客户端也作同样的命令生成key及csr文件。
    openssl genrsa -des3 -out client.key 1024openssl req -new -key client.key -out client.csr

    首先生成CA的key文件,再生成CA自签名的证书。
    首先生成CA的key文件:
    openssl genrsa-des3 -out ca.key 1024再生成CA自签名的证书:
    openssl req -new -x509 -key ca.key -out ca.crt

    用生成的CA的证书为刚才生成的server.csr,client.csr文件签名。
    openssl中还附带了一个叫CA.pl的文件,可用其生成文件。


    3.4 服务器和客户端程序编写3.4.1 客户端编写框架/*生成一个SSL结构*/meth = SSLv23_client_method();ctx = SSL_CTX_new (meth); ssl = SSL_new(ctx);/*下面是正常的socket过程*/fd = socket();connect();/*把建立好的socket和SSL结构联系起来*/SSL_set_fd(ssl,fd);/*SSL的握手过程*/SSL_connect(ssl);/*接下来用SSL_write(), SSL_read()代替原有的write(),read()即可*/SSL_write(ssl,"我是客户端",strlen("我是客户端"));
    3.4.2 服务器编写框架/*生成一个SSL结构*/meth = SSLv23_server_method();ctx = SSL_CTX_new (meth); ssl = SSL_new(ctx);/*下面是正常的socket过程*/fd = socket();bind();listen();accept();/*把建立好的socket和SSL结构联系起来*/SSL_set_fd(ssl,fd);/*SSL的握手过程*/SSL_connect(ssl);/*接下来用SSL_write(), SSL_read()代替原有的write(),read()即可*/SSL_read (ssl, buf, sizeof(buf));
    四、实验结果截图服务器(server)运行截图和客户端(client1)运行截图,证书信息也在截图中。
    经过三次握手,数据交互,服务器收到了客户端传来的“我是客户端消息”,客户端收到了服务器传来的“服务器收到了”数据。
    2 评论 50 下载 2019-03-20 19:47:35 下载需要13点积分
  • 基于C++的身份证管理程序

    一、目的与要求该课程设计是数据结构课程的重要实践教学环节,是一次全面的系统分析与设计能力的培养,是实现该专业学生总体培养目标的重要教学环节。使学生通过了解学科领域的发展动向,培养数据结构与程序设计的的基本思想,独立分析和解决实践问题的能力, 提高和锻炼学生动手能力。

    对所选题目,运用面向过程的分析与设计方法,给出系统分析与设计的结果,要求必须要运用数据结构课程中相关的基本知识
    选择熟悉的开发工具,完成系统实现和测试, 掌握系统实现和测试的方法, 必须要有详尽的程序注释
    撰写开发文档, 培养编写系统分析与设计文档的水平

    二、任务实现身份证管理程序,该程序应该具有下列功能:

    通过键盘可以输入身份证信息,大量信息可存放在文件中。身份证包含的信息请参看自己的身份证
    给定身份证号码,显示其身份证信息
    给定省份的编号,显示该省的人数
    给定某区的编号,显示该区的人数
    给定身份证号码,可以修改该身份证信息
    给定身份证号码,可以删除该身份证信息

    提供一些统计各类信息的功能。例如男女的人数、比例;以及哪年、哪月、哪日出生的人数等。界面要合理。
    三、总体设计根据需求分析结果确定程序的总体设计,首先在每个功能中都有输入和输出,所以设计时需要采用交互方式。通过编写一个主菜单功能来实现添加身份证信息、修改身份证信息、删除身份证信息、查询身份证信息等各个功能模块的调用,从而更好地协调各个功能模块之间的关系。
    四、详细设计说明4.1 涉及的知识点
    二叉平衡树的建立
    二叉平衡树的查找
    二叉平衡树的删除

    4.2 详细的设计思路4.2.1 采用的数据结点和存储结构身份证相关信息需要包括身份证号码、姓名、地址、性别和民族。
    二叉平衡树或者是一棵空树,或者是具有下列性质的二叉树:

    如果左子树不空,则左子树上所有结点的值均小于它的根结点的值
    如果右子树不空,则右子树上所有结点的值均大于它的根结点的值
    它的左、右子树也分别为二叉平衡树

    对于一个记录集合,可以用一棵二叉平衡树来表示,树中的一个结点对应于集合中的一个记录,整棵树表示记录集合。二叉平衡树每个结点所存储的记录,其关键字都大于它的左子树上所有结点存储的记录的关键字,而小于它的右子树上所有结点存储的记录的关键字。
    用二叉平衡树表示记录集合时,不但容易进行动态查找,而且对二叉平衡树进行中序遍历时还可以得到记录集合中各记录的有序排列。
    二叉平衡树的存储结构采用二叉链表存储方式。
    4.2.2 采用的算法查找算法:由于身份证号码的唯一性,查找算法以身份证号码为关键字进行。

    当二叉平衡树为空时,查找失败
    如果二叉平衡树根结点的关键字等于要查找的关键字时,则查找成功
    如果二叉平衡树根结点的关键字小于要查找的关键字,则用同样的方法继续在根结点的右子树上查找
    如果二叉平衡树根结点的关键字大于要查找的关键字,则用同样的方法继续在根结点的左子树上查找

    在根结点为p的二叉平衡树中,查找身份证号码为id的结点。
    对含有n个结点的二叉平衡树来说,在树上查找结点的关键字等于某个给定值的过程走的是一条从根结点到该结点的路径,所需要做的比较次数等于该结点所在的层数。二叉平衡树的形态和折半查找的判断树相同,所以在构造二叉平衡树时的输入顺序也很重要,一般来说,输入的顺序越无序,构造出的二叉平衡树越利于查找。
    插入算法:在二叉排序树插入新的结点时,必须要保证插入后的二叉树仍满足二叉平衡树的定义。因此,插入时必须首先找出合适的插入位置。实际上待插入结点的位置就是在查找过程中所查找的最后一个结点的左孩子或右孩子,新插入的结点一定是叶子结点。因此,仍可采用上述查找算法。当查找失败时,在二叉树中插入关键字等于给定值的结点。

    若二叉排序树为空树,则将新插入的结点作为根结点插入
    若二叉排序树的根结点关键字值等于要插入的结点的关键字,则返回
    若要插入结点的关键字小于根结点关键字,则要把插入的结点插入到左子树中
    若要插入结点的关键字大于根结点关键字,则要把插入的结点插入到右子树中

    在子树中插入的方法与在整棵中的插入方法相同的,如此下去,直到把要插入的结点插入到二叉排序树中或者发现树中已有有关关键字为止。同时,为了将二叉排序树,整形为二叉平衡树,在上述的4步操作后还要判断平衡因子是否为小于2大于-2的整数,然后相应地作出合适的调整(如LL,LR,RR,RL等)。在将全部家当的平衡置为大于-2小于2 的整数后,操作最终完成。
    删除算法:与在二叉平衡树上做插入操作的要求是相同的,从二叉平衡树中删除一个结点,要保证删除后的二叉树仍然是一棵二叉平衡树。根据二叉排序树的结构特征,可以分以下4种情况来考虑。

    待删除结点是叶结点。直接删除该结点
    待删除结点只有左子树而无右子树。根据二叉排序树的特点,在这种情况下,可以直接将其左子树的根结点放到被删除结点的位置
    待删除结点只有右子树而无左子树。可以直接将其右子树的根结点放到被删除结点的位置
    待删除结点同时有左、右子树。根据二叉排序树的特点,可以将其右子树放到被删除结点的位置上,再把删除结点的左子树链接到被删除结点右子树是最左子树的左孩子结点上;也可以直接将被删除结点的左子树代替被删除的结点,同时将被删除结点的右子树收为被删除结点左子树中序尾点的右孩子

    最后用旋转子树的算法将最新得到的子树变化为二叉平衡树。
    修改算法:先调用一次操作算法,再直接将查找到的结点的信息改为目标信息。
    4.2.3 关于二叉平衡树的说明若向二叉平衡树中插入一个新阶段后破坏了破坏性,首先从该新插入结点方向向根结点方向查找第一个失去平衡的结点,然后以该失衡结点和它相邻的刚查找过得两个结点构成调整子树,使之成为新的平衡子树。当失衡的最小子树被调整为平衡子树后,整个树又成为一棵平衡二叉树。
    失衡的最小子树是指以离插入结点最近,且平衡因子绝对值大于1的结点作为根的子树。假设用A表示失衡的最小子树的根结点,则调整该子树的操作可归纳为下列4 种情况:

    LL型调整:这是因为A结点的左孩子的左子树上插入结点,使得A结点的平衡因子由1变为2而引起的不平衡
    RR型调整:这是因为A结点的右孩子的右子树上插入结点,使得A结点的平衡因子由 - 1变为 - 2而引起的不平衡
    LR型调整:这是因在A结点的左孩子的右子树上插入结点,使得A结点的平衡因子由 1 变为 2 而引起的不平衡
    RL 型调整:这是因为A结点的右孩子的左子树上插入结点,使得A结点的平衡因子由 -1 变为 -2 而引起的不平衡

    五、调试与测试输入身份证信息

    给定身份证号码,显示其身份证信息

    给定身份证号码,修改该身份证信息

    给定身份证号码,删除该身份证信息

    将相关信息保存到文件中

    给定省份的编号,显示该省的人数

    给定某区的编号,显示该区的人数

    统计男女的人数

    统计哪年、哪月、哪日出生的人数

    遍历(将信息输出在控制台)

    六、总结复习了二叉平衡树、二叉排序树的相关知识,加深了对树的理解。更好地复习和学习了文件的读取和写入的相关知识。
    遇到的问题及解决:

    第一个问题是文件的写入,通过对课本的复习,我很好地解决了问题
    第二个问题是效率问题,由于要保证查找效率,我选择了二叉平衡树的做法
    第三个问题是数据的修改。由于对树的理解错误,因而将问题实现的更加复杂。但是,在参考了许多资料后,重新采用简单的方式达到了目的
    0 评论 4 下载 2020-08-28 10:34:52 下载需要9点积分
  • 基于Android Studio实现的2048游戏

    1 需求分析1.1 背景与意义1.1.1 手机应用市场发展现状随着4G越来越普及以及手机应用的日益丰富还有智能水平的不断提高,从便携性和随身性这两方面来考虑,电脑所带来的体验已经不能跟手机相提并论了,它已经完美的超越了电脑。
    现如今Android、苹果等各智能手机已经基本占领整个手机市场,从而使得更多应用的出现,而手机游戏应用在其中占领主要位置。
    随着Android智能手机的普及以及游戏种类的多元化,使得Android手机游戏用户规模保持着稳步增长之势。
    1.1.2 国内外现状目前国内外的Android开发还是主要以应用开发为主,主要分成三类:企业应用、通用应用及游戏应用。企业应用的开发主要是一些大公司为了自己的品牌而开发的;通用应用主要是一些创业型公司或者独立开发者为了自己盈利开发的应用;游戏应用目前和通用应用相同。
    2048小游戏是一款最近风靡全球的手机游戏,简单的游戏模式和趣味的玩法,几乎游戏下载排行榜的前20名都可以看到“它的身影”。
    1.1.3 此游戏的意义现如今,手机游戏已在我们的生活中占据一席之地,并在一步步的壮大。可以说,随着它的迅猛发展,现今的手机游戏已经不单单是一种缓解压力的工具,而是形成了一种文化现象。随着游戏软件在市场的一步步壮大,与其有关的文化也随之传播。
    2048游戏的制作属于电子游戏中益智类小游戏,它做到了娱乐性、趣味性、教育性相统一。益智类的游戏即是需要去开动大脑思考从而获得游戏的胜利。简单的益智类游戏可以使玩家在娱乐中不断地开发大脑。这样一来就实现了在娱乐中学习。
    1.2 系统需求分析1.2.1 系统功能需求分析系统主要实现以下的几个功能:呈现游戏界面、重新开始游戏、当前分数和最高分数、游戏帮助等功能。
    重新开始游戏是当玩家无法满足当前进度时点击此按钮就会重新开始游戏,如果玩家处于不同关卡时提示重新开始游戏还是停留在此关卡。游戏帮助是当新手玩此游戏时无法知道游戏玩法时给予相应的提示。呈现游戏界面是游戏开始时主界面在游戏区域会生成4x4的矩阵同时在矩阵里面随机生成两个2或4的游戏卡片。当前分数和最高分数是显示此局玩家所获得的分数和历史上最高的分数,如果当前的分数超过最高的分数,那么最高分数显示当前的分数。如下图所示:

    1.2.2 游戏的基本规则在开始游戏后玩家通过滑动屏幕来操控卡片的移动方向,当卡片滑动中如果有两张卡片相同且他们中间也没有其他卡片时,在滑动的过程中这两张卡片会合并,显示为这两张卡片之和。在滑动过程中有三张卡片相同时只会合并向滑动方向两张卡片。在滑动中如果有两张卡片一样同时又有一张卡片的值跟这两张卡片相加的值时,滑动只会使那两张相同的卡片合并而不会接着让合并后的卡片和另一张卡片合并。
    2 系统分析与设计2.1 系统流程设计游戏进入开始页面,能够进入游戏的主界面并开始普通开局,从主界面能够重新开始游戏、查看帮助和进入关卡选择界面。当玩家点击重新开始按钮会弹出相应的对话框让玩家选择,如果玩家选择“是”时则重新开始游戏,如果选择“否”则返回游戏界面不做任何处理。在开始界面按返回按钮时则会退出游戏。
    游戏流程如下图所示:

    2.2 系统模块设计从总体出发,将该系统划分为三大模块:“菜单设计”、“界面设计”和“算法设计”。
    2.2.1 菜单设计菜单的实现是在游戏界面,可进一步划分为三个模块,分别是:“重新开始”、“退出游戏”、“游戏帮助”,如图所示:

    2.2.2 界面设计


    开始界面
    游戏界面









    2.2.3 算法设计当有两张卡片相同时,向它们可以碰撞的方向滑屏,卡片会移动到最底边并生成其两倍数字的卡片,并且生成一个“2”或者“4”的卡片。如图所示:



    生成2
    生成4









    当有两张卡片相同时,且在它们相同的方向有张跟他们之和的卡片,向它们可以碰撞的方向滑屏,相同的卡片会移动到无法移动的位置并生成其两倍数字的卡片,但合成的方向不会跟那两张数字的卡片合并,并且生成一个“2”或者“4”的卡片。如图所示:



    生成2
    生成4









    当界面上没有空位并且两两相邻的卡片不相同时游戏结束。如图所示:

    2.3 本章小结本章主要对游戏所实现的功能进行需求分析,分析了图形的特点和实现的可行性。对系统的性能进行了详细的分析。对系统的流程,系统所需的图形文件,系统的总体架构和系统用例进行了设计。通过本章的分析、设计能更加具体的了解系统功能,对系统所要实现的功能和图形文件有了更深的认识。为下一章系统功能的具体实现提供了可靠的参考依据。
    3 系统实现3.1 开始界面的实现游戏的主界面是按钮,只是为了实现界面的跳转,当玩家点击开始游戏就会调用loginActivity.java,此函数让页面跳转到游戏界面开始游戏,代码及图片如下所示:
    public class loginActivity extends MainActivity { protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.login); }}

    3.2 游戏界面的实现游戏界面主要是在activity_main.xml中当前分数、最高分数、重新开始按钮、退出游戏按钮、游戏帮助按钮、帮助按钮,当跳转到游戏界面时就会调用并执行MainActivity.java函数来展示游戏界面,代码及图片如下所示:
    protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);}

    3.3 游戏滑动卡片移动的实现当玩家滑动屏幕时,主要通过GameView函数来监听玩家手指滑动的位置,先通过获取开始坐标和结束坐标,然后通过比较结束坐标跟开始坐标的差值来判断玩家是怎么滑动屏幕的。判断出玩家的滑动轨迹后,通过调用swipeLeft、swipeRight、swipeUp、swipeDown方法来实现卡片的移动,代码及图片如下所示:
    private void initGameView(){ setColumnCount(4); //将面板设置成4列 setBackgroundColor(0xffbbada0); System.out.println("initGameView"); setOnTouchListener(new View.OnTouchListener() { /* * startX:手机刚开始在屏幕上的X坐标 * startY:手机刚开始在屏幕上的Y坐标 * offsetX,offsetY,分别是手指在屏幕上的X,Y上的偏移量 */ private float startX,startY,offsetX,offsetY; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: startX = event.getX(); startY = event.getY(); break; case MotionEvent.ACTION_UP: offsetX = event.getX() - startX; offsetY = event.getY() - startY; if(Math.abs(offsetX) > Math.abs(offsetY)){ if(offsetX < -5){ swipeLeft(); System.out.println("Left"); }else if(offsetX > 5){ swipeRight(); System.out.println("Right"); } } else{ if(offsetY < -5){ swipeUp(); System.out.println("Up"); }else if(offsetY > 5){ swipeDown(); System.out.println("Down"); } } break; } return true; } });}//向左滑动public void swipeLeft(){ boolean meger = false; for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { for (int x1 = x+1; x1 < 4; x1++) { if(cardsMap[x1][y].getNum()>0){ if(cardsMap[x][y].getNum()<=0){ /* * 将下标为(x,y)所在位置的卡片上的数字 * 设置为,坐标为(x1,y)所在位置的卡片上的值; * 第二步,将坐标(x1,y)所在位置的卡片上的数字 * 设置为0 * (即:变成空卡片) */ cardsMap[x][y].setNum( cardsMap[x1][y].getNum()); cardsMap[x1][y].setNum(0); x--; meger =true; break; }else if(cardsMap[x][y].equals(cardsMap[x1][y])){ cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2); cardsMap[x1][y].setNum(0); MainActivity.getMainActivity(). addScore(cardsMap[x][y].getNum()); meger = true; } break; } } } } if(meger){ addRandomNum(); checkComplete(); }}//向右滑动public void swipeRight(){ boolean meger = false; for (int y = 0; y < 4; y++) { for (int x = 3; x >=0; x--) { for (int x1 = x-1; x1 >= 0; x1--) { if(cardsMap[x1][y].getNum()>0){ if(cardsMap[x][y].getNum()<=0){ /* * 将下标为(x,y)所在位置的卡片上的数字 * 设置为,坐标为(x1,y)所在位置的卡片上的值; * 第二步,将坐标(x1,y)所在位置的卡片上的数字 * 设置为0 * (即:变成空卡片) */ cardsMap[x][y].setNum( cardsMap[x1][y].getNum()); cardsMap[x1][y].setNum(0); x++; meger =true; break; }else if(cardsMap[x][y].equals(cardsMap[x1][y])){ cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2); cardsMap[x1][y].setNum(0); MainActivity.getMainActivity(). addScore(cardsMap[x][y].getNum()); meger =true; }break; } } } } if(meger){ addRandomNum(); checkComplete(); }}//向上滑动public void swipeUp(){ boolean meger = false; for (int x= 0; x< 4; x++) { for (int y = 0; y < 4; y++) { for (int y1 = y+1; y1 < 4; y1++) { if(cardsMap[x][y1].getNum()>0){ if(cardsMap[x][y].getNum()<=0){ /* * 将下标为(x,y)所在位置的卡片上的数字 * 设置为,坐标为(x1,y)所在位置的卡片上的值; * 第二步,将坐标(x1,y)所在位置的卡片上的数字 * 设置为0 * (即:变成空卡片) */ cardsMap[x][y].setNum( cardsMap[x][y1].getNum()); cardsMap[x][y1].setNum(0); y--; meger =true; break; }else if(cardsMap[x][y].equals(cardsMap[x][y1])){ cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2); cardsMap[x][y1].setNum(0); MainActivity.getMainActivity(). addScore(cardsMap[x][y].getNum()); meger =true; } break; } } } } if(meger){ addRandomNum(); checkComplete(); }}//向下滑动public void swipeDown(){ boolean meger = false; for (int x = 0; x< 4; x++) { for (int y = 3; y>= 0;y--) { for (int y1 = y-1; y1 >=0; y1--) { if(cardsMap[x][y1].getNum()>0){ if(cardsMap[x][y].getNum()<=0){ /* * 将下标为(x,y)所在位置的卡片上的数字 * 设置为,坐标为(x1,y)所在位置的卡片上的值; * 第二步,将坐标(x1,y)所在位置的卡片上的数字 * 设置为0 * (即:变成空卡片) */ cardsMap[x][y].setNum( cardsMap[x][y1].getNum()); cardsMap[x][y1].setNum(0); y++; meger =true; break; }else if(cardsMap[x][y].equals(cardsMap[x][y1])){ cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2); cardsMap[x][y1].setNum(0); MainActivity.getMainActivity(). addScore(cardsMap[x][y].getNum()); meger =true; } break; } } } } if(meger){ addRandomNum(); checkComplete(); }}



    效果1
    效果2









    3.4 重新开始游戏功能的实现当玩家点击游戏界面的重新开始游戏时,会弹出给玩家选择的对话框,让玩家选择“是”时游戏会重新开始,代码及图片如下所示:
    public void onClick(View view){ AlertDialog.Builder dialog3 = new AlertDialog.Builder(this); dialog3.setTitle("提示:"); dialog3.setMessage("你确定重新开始吗?"); dialog3.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); dialog3.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); dialog3.show(); }

    3.5 退出游戏功能的实现当玩家中途有事想退出游戏时会弹出给玩家选择的对话框,让玩家选择“是”时游戏会退出,代码及图片如下所示:
    public void onClick(View view){ AlertDialog.Builder dialog = new AlertDialog.Builder(this); dialog.setTitle("提示:"); dialog.setMessage("你确定要离开吗?"); dialog.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { System.exit(0); } }); dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); dialog.show(); }

    3.6 游戏帮助功能的实现当新玩家进入到游戏且不知道此游戏玩法时,玩家可以点击游戏帮助按钮来了解游戏玩法,点击按钮时游戏会弹出对话框显示游戏玩法,代码及图片如下所示:
    public void onClick(View view){ AlertDialog.Builder dialog2 = new AlertDialog.Builder(this); dialog2.setTitle("hey,guy!"); dialog2.setMessage("这么简单的游戏你确定需要帮助?"); dialog2.setNegativeButton("继续玩~", new DialogInterface.OnClickListener({ @Override public void onClick(DialogInterface dialog, int which) { } }); dialog2.show();}

    3.7 本章小结本章主要阐述本游戏相关功能的实现,详细的讲述了主界面的实现和各按钮功能的实现。
    4 测试本章主要对系统的功能进行测试,此次测试只是进行简单的调试,来确定游戏的各项功能是否能够正常运行。
    4.1 游戏流程测试该测试主要验证游戏能否实现场景的切换,当界面在开始界面时只显示按钮画面,当玩家点击此界面的开始按钮时跳转到游戏界面,如图所示:



    效果1
    效果2









    4.2 游戏模式该测试主要是测试游戏能否正常运行,当玩家滑动屏幕时能否正常的移动和当卡片相同时是否能够相加,还有就是测试游戏是否能正常结束。



    效果1
    效果2









    4.3 本章小结本章是对游戏系统进行简单的测试,通过测试可以看出此游戏可以正常的工作,同时一些功能也能够实现。
    5 总结本次课程设计的内容大部分都是参照课堂所讲以及一些网站给出的各种建议写的,在写的过程中遇到了很多问题,学到了很多东西。期间大概是因为基础不够好,只是找错误就花了很长时间。不过正因为这些错误,才能学到更多的知识,才能把知识点掌握的更牢靠,对于一些没有实现的功能,之后我一定会多花费些时间研究出来。我的课程设计优化的空间还相当大,希望老师能给出指导!
    12 评论 627 下载 2018-12-20 18:50:37 下载需要14点积分
  • 基于JSP实现的个人网站

    摘 要本报告是JSP程序设计的期末设计的课程设计报告。本网站基本满足了所有需要的内容和功能需求,包含了个人的简介,家乡的介绍,包括个人的信息,留言板等内容。
    也包含了数据库的增(用户注册,留言板的留言等),删(个人留言支持删除),改(个人信息的修改等),查(留言板的查看,个人信息的查看等)四个功能。数据库的3张表,包括用户登录信息表,用户个人信息表,留言板内容表。
    主题:JSP、增删改查、数据库、个人服务器
    1、系统设计背景意义1.1 开发背景随着WWW(World Wide Web)的普及,动态网页技术也急速发展。从原来的CGI(Common Gateway In-terface)到ASP(Active Server Page),都从某种程度上满足了网页开发人员对动态网页开发技术的需求。但是不管是CGI还是ASP都存在一定的局限性,如CGI对服务器资源的耗费,ASP只能同Microsoft IIS一起使用等,这些都限制了这些技术的使用范围,极大地阻碍了它们的推广。
    广大的页面开发人员都热切地盼望一种统一的页面开发技术,该技术应该具有的特点:

    与操作平台无关,能够在任何Web或应用程序服务器上运行
    将应用程序逻辑和页面显示分离
    提供代码重用,简化开发基于Web的交互式应用程序的过程

    JSP(Java Server Page)技术就是被设计用来满足这样的要求的。JSP是由Sun MicroSystem公司于1999年6月推出的新的网页开发技术,它是基于Java Serv-let以及整个Java体系的Web开发技术,是Servlet2.1API的扩展。利用这一技术,可以建立先进、安全和跨平台的动态网站。
    1.2 研究现状JSPJava语言以不依赖于平台、面向对象、安全等优良特性成为网络程序设计语言中的佼佼者。目前,许多与Java有关的技术得到了广泛的应用与认可,JSP(JavaServerPages)就是其中之一。JSP是基于Java语言的一种Web应用开发技术,可以建立安全、跨平台的先进动态网站。
    许多Web网站都使用了JSP技术。利用JSP技术创建的Web应用程序可以实现动态页面与静态页面分离,便于Web应用程序的扩展和维护。由于JSP是基于Java语言的Web技术,相对其他Web技术,JSP具有脱离硬件平台束缚、编译后运行等优点,已成为Internet上的主流Web技术之一。
    2 、需求分析2.1 系统需求分析设计一个个人网站,网站内容必须包括个人的基本信息(含个人照片),比如个人爱好,家乡特产、特色旅游等静态网页内容;必须调用数据库,且具备数据库的增删改查的功能,这是动态网页部分内容。
    2.2 数据需求需要一个数据库,包括三张数据表,分别记录用户的登录信息,记录用户每个人的用户信息,记录用户的留言内容。
    3 、系统设计3.1 系统原理
    3.2 数据库设计3.2.1 数据库概念结构设计数据库概念结构设计是在需求分析的基础上,设计出能够满足用户需求的各种实体,以及它们之间的关系,为后面的逻辑结构设计打下基础。用E-R图是描述数据实体关系的一种直观描述工具,所以本系统采用了E-R图的方法进行数据库概念结构设计。
    用户登陆E-R图

    用户实体E-R图

    留言板E-R图

    实体之间关系E-R图

    3.3.2 数据库逻辑结构设计概念结构是独立于实际数据模型的信息结构,必须将其转化为逻辑结构后才能进行数据库应用的设计。也就是要将概念上的结构转化为BP数据库系统所支持的实际数据模型。
    个人网站数据库中各个表格的设计结果如下面的四个表所示。每个表表示数据库中的一个表。
    用户登录表

    username:记录用户注册时的用户名
    password:记录用户注册时的密码

    且用户名和密码均不能为空值,所以在提交到数据库之前已经在网页中进行检查。


    用户留言板表

    username:记录留言的用户
    date:记录用户留言的时间,精确到秒。格式为“YYYY-MM-DD HH-MM-SS”
    message:记录用户留言的内容,格式为TEXT

    注:date的记录利用数据库自带的now()函数,方便网页的内容的传输。


    用户信息表

    username:记录个人信息的所有者
    gender:记录用户的性别
    age:记录用户的年龄
    phone_number:记录用户的联系方式
    school:记录用户的所在学校
    address:记录用户的地址



    3.4 系统模块设计
    4、系统实现4.1 欢迎页(index.jsp)本页是网站的第一页,可以选择用户登录(login.jsp)或者跳过登录直接进去主页(Home.jsp),如果没有注册,可以点击注册按钮,进入注册页面(register.jsp)。
    效果示意图:

    <%@ page language="java" contentType="text/html; charset=utf-8"%><!DOCTYPE html><html><head><style> body{ text-align:center; background: url("./img/bg.jpg") fixed center center no-repeat; background-size: cover; width: 100%; } #center{ margin:0 auto; border:1px soild #000; width:300px; height:100px } *{ padding: 0; margin: 0; } .black_half{ padding: 25px; background-color: rgba(0,0,0,0.5); } .black_half h1{ color: #FFFFFF; } .black_half a{ text-decoration:none; color: #FFFFFF; } .black_half a:hover{ text-decoration:underline; color: #FFFFFF; } .white h3{ color: #FFFFFF; }</style><title>欢迎——…的期末作业</title></head><body> <br><br> <div class="black_half"> <h1>W E L C O M E !</h1> </div> <div class="black_half"> <h2> <a href="login.jsp">用户登陆</a>   <a href="register.jsp" style="font-size:12px;">还没有账号?点此注册</a> </h2><br> <h2> <a href="Home.jsp">我是游客,跳过登录</a> </h2> </div> <br><br> <div class="white"> </div></body></html>
    4.2 主页(Home.jsp)本页面是网站的主页,内容比较简单。
    最上端的是导航栏,如果前面选择了登陆,则左上角会显示“您好,xxx”,可以选择退出登录,右边导航栏也会多一个“个人信息”按钮,可以进入个人信息页面(details.jsp)。
    如果未登录,会显示“您还未登陆,点击登录” ,可以选择登录按钮,进入(login.jsp)。
    右边导航栏的其他按钮还包括作者简介(profile.jsp)、家乡介绍(hometown.jsp)、留言板(board.jsp)、关于(about.jsp)、返回欢迎页(index.jsp)。
    效果示意图:

    <!DOCTYPE html><html><head> <title>主页</title><style> @import"home_style.css"</style></head><body style=" font-size: 16px; line-height: 1.4em; letter-spacing: 0.08em; padding: 0; margin: 0; background: url('./img/bg.jpg') fixed center center no-repeat; background-size: cover; width: 100%;"> <div class="ace-head-inner"> <div class="ace-head-container ace-container"> <div class="ace-head-row"> <div id="ace-head-col1" class="ace-head-col text-left"> <span> <% String username = (String)session.getAttribute("username"); if (username != null){ out.println("您好,"+username+" <a href='logout.jsp'>退出登陆</a>  "); } else{ out.println("您还未登陆 <a href='login.jsp'>点此登陆</a>  "); } %> </span> </div> <nav id="ace-main-nav"> <ul class="clear-list"> <% if (username != null){ out.println("<li><a href='details.jsp'>个人信息</a></li>"); } %> <li><a href="Home.jsp">主页</a></li> <li><a href="profile.jsp">作者简介</a></li> <li><a href="hometown.jsp">家乡介绍</a></li> <li><a href="board.jsp">留言板</a></li> <li><a href="about.jsp">关于</a></li> <li><a href="index.jsp">返回欢迎页</a></li> </ul> </nav> </div> </div></div><div class = white_box> <p style="font-size:200px;">你好。</p> <p style="font-size:200px;" align="right">欢迎。</p></div></body></html>
    4.3 注册(register.jsp/checkregister.jsp)本页面是网站的注册页面,包含两个jsp文件,register.jsp获取用户输入的表单,包括用户名和两次密码,在通过js函数判断(判断用户名、密码是否为空,两次密码是口相同)之后通过onsubmit的方法决定是否将表单传送给checkregister.jsp。
    如果通过判断,checkregister.jsp连接数据库并先用select查询是否存在用户名相同的用户,如果不存在用insert的sql语句把用户信息输入数据库,并返回注册成功或者失败的提示框,如果成功跳转到主页,如果失败跳转回注册页面。
    效果示意图:

    register.jsp
    <%@ page language="java" contentType="text/html; charset=utf-8"%><!DOCTYPE html><html><head><title>用户注册</title></head><style> @import"style.css"</style><script> function addCheck() { var username = document.regfrm.username.value; var password = document.regfrm.password.value; var double_times = document.regfrm.double_times.value; if (username == "") { alert("用户名不能为空!"); return false; } if (password == "") { alert("密码不能为空!"); return false; } if (password != double_times) { alert("两次输入密码不相同!"); return false; } } function validate() { var flag = addCheck(); if (flag == false) return false; return true; }</script><body> <div id = center> <form action="checkregister.jsp" method="post" name = "regfrm" onsubmit="return validate();"> <table class="hovertable"> <tr> <td colspan="5" align="center" style="font-size:30px;height:80px;width:300px;"><strong>注册</strong></td> </tr> <tr > <th>用户名:</th> <td><input type="text" name="username" value="输入16个字符以内" maxlength="16" onfocus="if(this.value == '输入16个字符以内') this.value =''"></td> </tr> <tr> <th>输入密码:</th> <td><input type="text" name="password" value="输入20个字符以内" maxlength="20" style="width:200px;" onfocus="if(this.value == '输入20个字符以内'){this.value =''; this.type='password'}"></td> </tr> <tr> <th>确认密码:</th> <td><input type="text" name="double_times" value="请再次输入密码" maxlength="20" style="width:200px;" onfocus="if(this.value == '请再次输入密码') {this.value =''; this.type='password'}"></td> </tr> <tr> <td colspan="2" align="center"> <input type="submit" value=" 注 册 "> <input type ="button" value=" 返回登陆 " onclick="location='login.jsp'"> </td> </tr> <tr> <td colspan="5" align="center"><a href="index.jsp"> 返 回 主 页 </a></td> </tr> </table> </form> </div></body></html>
    checkregister.jsp
    <%@ page language="java" contentType="text/html; charset=utf-8"%><%@ page import = "java.sql.*" %><!DOCTYPE html><html><body> <% String user = new String(request.getParameter("username").getBytes("ISO8859_1"),"utf-8"); String pwd = new String(request.getParameter("password").getBytes("ISO8859_1"),"utf-8"); Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://127.0.0.1:3306/user_data"; String um = "root"; String psw= "8876"; Connection conn = DriverManager.getConnection(url, um, psw); PreparedStatement pStmt = conn.prepareStatement("select * from user_data.user_info where username = '" + user + "'"); ResultSet rs = pStmt.executeQuery(); if(rs.next()){ out.println("<script language='javascript'>alert('该用户已存在,请直接登陆!');window.location.href='register.jsp';</script>"); } else{ PreparedStatement tmt = conn.prepareStatement("Insert into user_data.user_info values('" + user + "','" + pwd + "')"); int rst = tmt.executeUpdate(); if (rst != 0){ PreparedStatement tmt2 = conn.prepareStatement("Insert into user_data.details values('" + user + "',1,0,' ',' ',' ')"); tmt2.executeUpdate(); out.println("<script language='javascript'>alert('用户注册成功!');window.location.href='login.jsp';</script>"); } else{ out.println("<script language='javascript'>alert('用户注册失败!');window.location.href='register.jsp';</script>"); } } %></body></html>
    4.4 登陆(login.jsp/checklogin.jsp)本页面是网站的登陆页面,包含两个jsp文件,login.jsp获取用户输入的表单,包括用户名和两次密码,在通过js函数判断(判断用户名、密码是否为空)之后通过onsubmit的方法决定是否将表单传送给checklogin.jsp。
    如果通过判断,checklogin.jsp连接数据库并通过select的sql语句查询数据库中用户信息,如果成功显示登陆成功的消息框并跳转到主页,如果失败显示登陆失败的消息框跳转回登陆页面。
    效果示意图:

    login.jsp
    <%@ page language="java" contentType="text/html; charset=utf-8"%><!DOCTYPE html><html><head><title>用户登陆</title></head><style> @import"style.css"</style><script> function validateLogin() { var userName = document.frmLogin.username.value; var password = document.frmLogin.password.value; if ((userName == "") || (userName == "输入您的用户名")) { alert("请输入用户名!"); return false; } if ((password == "") || (password == "输入您的密码")) { alert("请输入密码!"); return false; } }</script><body> <div id = "center"> <form action="checklogin.jsp" method="post" name="frmLogin"> <table class="hovertable" > <tr> <td colspan="5" align="center" style="font-size:30px;height: 80px;width:300px;"><strong>登陆</strong></td> </tr> <tr> <th style="font-size:15px;">用户名:</th> <td style="font-size:15px;"><input type="text" name="username" value="输入您的用户名" maxlength="16" style="width:200px;" onfocus="if(this.value == '输入您的用户名') this.value =''"></td> </tr> <tr> <th style="font-size:15px;">密 码:</th> <td style="font-size:15px;"><input type="text" name="password" value="输入您的密码" maxlength="20" style="width:200px;" onfocus="if(this.value == '输入您的密码'){this.value =''; this.type='password'}"></td> </tr> <tr> <td colspan="5" align="center" style="font-size:15px;"> <input type="submit" value=" 登 录 " onclick="return validateLogin()"> <input type ="button" value=" 新用户注册 " onclick="location='register.jsp'"> </td> </tr> <tr> <td colspan="5" align="center"><a href="index.jsp"> 返 回 主 页 </a></td> </tr> </table> </form> </div></body></html>
    checklogin.jsp
    <%@ page language="java" contentType="text/html; charset=utf-8"%><%@ page import = "java.sql.*" %><!DOCTYPE html><html><body> <% String username = new String(request.getParameter("username").getBytes("ISO8859_1"),"utf-8"); String password = new String(request.getParameter("password").getBytes("ISO8859_1"),"utf-8"); Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://127.0.0.1:3306/user_data"; String um = "root"; String psw= "8876"; Connection conn = DriverManager.getConnection(url, um, psw); if(conn != null){ String sql = "select * from user_data.user_info where username='"+username+"' and password='"+ password + "'"; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); if(rs.next()){ session.setAttribute("username",username); out.println("<script language='javascript'>alert('登录成功!');window.location.href='Home.jsp';</script>"); } else{ out.println("<script language='javascript'>alert('登录失败!');window.location.href='login.jsp';</script>"); } } %></body></html>
    4.5 个人信息(details.jsp/setdetails.jsp/getdetails.tag)本页面是网站的个人信息页面,每次打开页面getdetails.tag都会从数据库中查询个人信息(每个新注册的用户默认都是空数据的),并显示在details.jsp中。并且可以修改表中的数据,点击修改按钮,表中的数据会以表单的形式以post的方式传递给setdetails.jsp,该setdetails可以连接数据库并通过update方式修改数据库。
    效果示意图:

    details.jsp
    <%@ page language="java" contentType="text/html; charset=utf-8"%><%@ taglib tagdir = "/WEB-INF/tags" prefix="getdetails" %><%@ page import = "java.sql.*" %><!DOCTYPE html><html><head> <title>个人信息</title> <style> @import"style.css" </style></head><body><getdetails:getdetails></getdetails:getdetails> <div id = center> <form action="setdetails.jsp" method="post" name="set_details"> <table class="hovertable"> <tr> <td colspan="5" align="center" style="font-size:30px;height: 80px;width:350px;"><strong>个人信息</strong></td> </tr> <tr> <th>性别:</th> <td> <label> <input type="radio" name="gd" id="" class="a-radio" value=1 <%= gender==1?"Checked":"" %> > <span class="b-radio"></span>男 </label> <label> <input type="radio" name="gd" id="" class="a-radio" value=0 <%= gender==0?"Checked":"" %> > <span class="b-radio"></span>女 </label> </td> </tr> <tr> <th>年龄:</th> <td> <label> <input type="text" type="text" name="age" value = <%=age %> style="width:200px;" maxlength="2"> </label> </td> </tr> <tr> <th>联系方式:</th> <td> <label> <input type="text" type="text" name="phone_number" style="width:200px;" maxlength="11" value = <%=phone_number %> > </label> </td> </tr> <tr> <th>所在学校:</th> <td> <label> <input type="text" type="text" name="school" style="width:200px;" maxlength="40" value = <%=school %> > </label> </td> </tr> <tr> <th>详细地址:</th> <td> <label> <input type="text" type="text" name="address" style="width:200px;" maxlength="40" value = <%=address %> > </label> </td> </tr> <tr> <td colspan="2"> <input type = "submit" value = " 修 改 "> <input type = "button" value = " 返 回 " onclick="location='Home.jsp'"> </td> </tr> </table> </form> </div></body></html>
    setdetails.jsp
    <%@ page language="java" contentType="text/html; charset=utf-8"%><%@ page import = "java.sql.*" %><!DOCTYPE html><html><body> <% String gender = new String(request.getParameter("gd").getBytes("ISO8859_1"),"utf-8"); String age = new String(request.getParameter("age").getBytes("ISO8859_1"),"utf-8"); String phone_number = new String(request.getParameter("phone_number").getBytes("ISO8859_1"),"utf-8"); String school = new String(request.getParameter("school").getBytes("ISO8859_1"),"utf-8"); String address = new String(request.getParameter("address").getBytes("ISO8859_1"),"utf-8"); String username = (String)session.getAttribute("username"); int _gender = Integer.parseInt(gender); int _age = Integer.parseInt(age); Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://127.0.0.1:3306/user_data"; String um = "root"; String psw= "8876"; Connection conn = DriverManager.getConnection(url, um, psw); if(conn != null){ PreparedStatement tmt2 = conn.prepareStatement("UPDATE user_data.details set gender="+ _gender +",age="+ _age +",phone_number='"+ phone_number +"',school='"+ school +"',address='"+ address +"' where username='"+username+"'"); int rst = tmt2.executeUpdate(); if(rst != 0){ out.println("<script language='javascript'>alert('修改成功!');window.location.href='details.jsp';</script>"); } else{ out.println("<script language='javascript'>alert('修改失败!');window.location.href='Home.jsp';</script>"); } } %></body></html>
    getdetails.tag
    <%@ tag language="java" pageEncoding="utf-8"%><%@ tag import="java.sql.*" %><%@ variable name-given="gender" variable-class="java.lang.Integer" scope="AT_END"%><%@ variable name-given="age" variable-class="java.lang.Integer" scope="AT_END"%><%@ variable name-given="phone_number" variable-class="java.lang.String" scope="AT_END"%><%@ variable name-given="school" variable-class="java.lang.String" scope="AT_END" %><%@ variable name-given="address" variable-class="java.lang.String" scope="AT_END"%><% String username = (String)session.getAttribute("username"); if (username != null){ Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://127.0.0.1:3306/user_data"; String um = "root"; String psw= "8876"; Connection conn = DriverManager.getConnection(url, um, psw); if(conn != null){ String sql = "select * from user_data.details where username='"+username+"'"; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); if(rs.next()){ String ss = rs.getString(1); int gender = rs.getInt(2); int age = rs.getInt(3); String phone_number = rs.getString(4); String school = rs.getString(5); String address = rs.getString(6); jspContext.setAttribute("gender", gender); jspContext.setAttribute("age", age); jspContext.setAttribute("phone_number", phone_number); jspContext.setAttribute("school", school); jspContext.setAttribute("address", address); } } } else{ out.println("<script language='javascript'>alert('请先登录!');window.location.href='login.jsp';</script>"); }%>
    4.6 作者简介(profile.jsp)本页面是本网站的个人简介页面,除了导航栏之外为静态网页,简单的自我介绍。
    效果示意图:

    profile.jsp
    <%@ page language="java" contentType="text/html; charset=utf-8"%><!DOCTYPE html><html><head> <title>作者简介</title><style> @import"home_style.css"</style></head><body> <div class="ace-head-inner"> <div class="ace-head-container ace-container"> <div class="ace-head-row"> <div id="ace-head-col1" class="ace-head-col text-left"> <span> <% String username = (String)session.getAttribute("username"); if (username != null){ out.println("您好,"+username+" <a href='logout.jsp'>退出登陆</a>  "); } else{ out.println("您还未登陆 <a href='login.jsp'>点此登陆</a>  "); } %> </span> </div> <nav id="ace-main-nav"> <ul class="clear-list"> <%if (username != null){out.println("<li><a href='details.jsp'>个人信息</a></li>"); } %> <li><a href="Home.jsp">主页</a></li> <li><a href="profile.jsp">作者简介</a></li> <li><a href="hometown.jsp">家乡介绍</a></li> <li><a href="board.jsp">留言板</a></li> <li><a href="about.jsp">关于</a></li> <li><a href="index.jsp">返回欢迎页</a></li> </ul> </nav> </div> </div></div><div class = white_box> <div style="text-align:center;"> <br> <h1><b>作者简介——我</b><br></h1> <br> <img src="./img/myphoto.jpg" style="display:block;max-height:200px;max-width:200px;margin:0 auto;"/><br> <br> <h2 style="display:inline;">name:</h2> <br><br> <h2 style="display:inline;">pingyin:</h2> <br><br> <h2 style="display:inline;">En-name:</h2>Ray8876 <br><br> <h2 style="display:inline;">birth:</h2>1998-08 <br><br> <h2 style="display:inline;">phone:</h2>158****2095 <br><br> <h2 style="display:inline;">e-mail:</h2> <br><br> <h2 style="display:inline;">school:</h2>中国计量大学现代科技学院 <br><br> <h2 style="display:inline;">major:</h2> <br><br> <h2 style="display:inline;">class:</h2> </div></div></body> </html>
    4.7 家乡介绍(hometown.jsp)本页面是本网站的家乡介绍页面,除了导航栏之外为静态网页,大部分内容摘自乌镇导游网。本页面源代码较长且为静态网页,这里省略
    效果示意图:

    4.8 留言板4.8.1 留言板(board.jsp/getboard.tag)本页面是网站的留言板网页,每次打开页面都会调用getboard.tag,从数据库中查询所有的留言内容(SELECT * FROM user_data.board order BY date DESC;),并且按照时间倒序排序,排在最上面的为最新留言。
    第一个白框是留言的模块,第二个白框是搜索模块(search.jsp)和我的留言的链接(myboard.jsp)。
    效果示意图:

    board.jsp
    <%@ page language="java" contentType="text/html; charset=utf-8"%><%@ taglib tagdir = "/WEB-INF/tags" prefix="getboard" %><!DOCTYPE html><html><head> <title>留言板</title><style> @import"home_style.css"</style></head><body style=" font-size: 16px; line-height: 1.4em; letter-spacing: 0.08em; padding: 0; margin: 0; background: url('./img/bg4.jpg') fixed center center no-repeat; background-size: cover; width: 100%;"><getboard:getboard></getboard:getboard> <div class="ace-head-inner"> <div class="ace-head-container ace-container"> <div class="ace-head-row"> <div id="ace-head-col1" class="ace-head-col text-left"> <span> <%String username = (String)session.getAttribute("username");if (username != null){out.println("您好,"+username+" <a href='logout.jsp'>退出登陆</a>  ");}else{out.println("您还未登陆 <a href='login.jsp'>点此登陆</a>  ");} %> </span> </div> <nav id="ace-main-nav"> <ul class="clear-list"> <%if (username != null){out.println("<li><a href='details.jsp'>个人信息</a></li>");} %> <li><a href="Home.jsp">主页</a></li> <li><a href="profile.jsp">作者简介</a></li> <li><a href="hometown.jsp">家乡介绍</a></li> <li><a href="board.jsp">留言板</a></li> <li><a href="about.jsp">关于</a></li> <li><a href="index.jsp">返回欢迎页</a></li> </ul> </nav> </div> </div></div><div class = white_box> <form action="checkboard.jsp" method="post"> <textarea rows="5" cols="" name="txt"></textarea> <br><br><br> <center> <input type="submit" value=" 留 言 " style="font-size:20px;" > </center> </form></div><div class = white_box> <form action="search.jsp" method="post"> <center> <input type="text" value=" 留 言 搜 索 " style="font-size:20px; display: inline;" onfocus="if(this.value == ' 留 言 搜 索 ') this.value =''" name="src"> <input type="submit" value=" 搜 索 " style="font-size:20px;" > <input type ="button" value=" 我的留言 " onclick="location='myboard.jsp'" style="font-size:20px;" > </center> </form></div><%=content %></body></html>
    4.8.2 搜索留言(search.jsp/searchboard.tag)搜索留言与留言栏内容相似,唯一的差别就是tag文件可以接收input框中的搜索的内容并且通过select语句查询包含查询内容的留言内容并返回内容。
    效果示意图:

    search.jsp
    <%@ page language="java" contentType="text/html; charset=utf-8"%><%@ taglib tagdir = "/WEB-INF/tags" prefix="searchboard" %><!DOCTYPE html><html><head> <title>留言板</title><style> @import"home_style.css"</style></head><body style=" font-size: 16px; line-height: 1.4em; letter-spacing: 0.08em; padding: 0; margin: 0; background: url('./img/bg4.jpg') fixed center center no-repeat; background-size: cover; width: 100%;"> <div class="ace-head-inner"> <div class="ace-head-container ace-container"> <div class="ace-head-row"> <div id="ace-head-col1" class="ace-head-col text-left"> <span> <%String username = (String)session.getAttribute("username");if (username != null){out.println("您好,"+username+" <a href='logout.jsp'>退出登陆</a>  ");}else{out.println("您还未登陆 <a href='login.jsp'>点此登陆</a>  ");} %> </span> </div> <nav id="ace-main-nav"> <ul class="clear-list"> <%if (username != null){out.println("<li><a href='details.jsp'>个人信息</a></li>");} %> <li><a href="Home.jsp">主页</a></li> <li><a href="profile.jsp">作者简介</a></li> <li><a href="hometown.jsp">家乡介绍</a></li> <li><a href="board.jsp">留言板</a></li> <li><a href="about.jsp">关于</a></li> <li><a href="index.jsp">返回欢迎页</a></li> </ul> </nav> </div> </div></div><% String search_message = new String(); try{ search_message = new String(request.getParameter("src").getBytes("ISO8859_1"),"utf-8"); } catch(Exception e){}%><div class = white_box> <form action="search.jsp" method="post"> <center> <input type="text" value=" 留 言 搜 索 " style="font-size:20px;display:inline;" onfocus="if(this.value == ' 留 言 搜 索 ') this.value =''" name="src"> <input type="submit" value=" 搜 索 " style="font-size:20px;" > </center> </form></div><searchboard:searchboard src="<%=search_message%>" /><%=content %></body></html>
    4.8.3 我的留言(myboard.jsp/myboard.tag/deleteboard.jsp)本页面是留言板内容中的我的留言网页,网页通过myborad.tag文件查询用户名为当前登录用户的数据库中的留言内容,并显示在网页上,并且显示删除按钮,点击就可以调取deleteboard.jsp来删除指定的留言内容。
    效果示意图:

    myboard.jsp
    <%@ page language="java" contentType="text/html; charset=utf-8"%><%@ taglib tagdir = "/WEB-INF/tags" prefix="myboard" %><!DOCTYPE html><html><head> <title>留言板</title><style> @import"home_style.css"</style></head><body style=" font-size: 16px; line-height: 1.4em; letter-spacing: 0.08em; padding: 0; margin: 0; background: url('./img/bg4.jpg') fixed center center no-repeat; background-size: cover; width: 100%;"> <div class="ace-head-inner"> <div class="ace-head-container ace-container"> <div class="ace-head-row"> <div id="ace-head-col1" class="ace-head-col text-left"> <span> <%String username = (String)session.getAttribute("username");if (username != null){out.println("您好,"+username+" <a href='logout.jsp'>退出登陆</a>  ");}else{out.println("您还未登陆 <a href='login.jsp'>点此登陆</a>  ");} %> </span> </div> <nav id="ace-main-nav"> <ul class="clear-list"> <%if (username != null){out.println("<li><a href='details.jsp'>个人信息</a></li>");} %> <li><a href="Home.jsp">主页</a></li> <li><a href="profile.jsp">作者简介</a></li> <li><a href="hometown.jsp">家乡介绍</a></li> <li><a href="board.jsp">留言板</a></li> <li><a href="about.jsp">关于</a></li> <li><a href="index.jsp">返回欢迎页</a></li> </ul> </nav> </div> </div></div><% String search_message = new String(); try{ search_message = new String(request.getParameter("src").getBytes("ISO8859_1"),"utf-8"); } catch(Exception e){}%><myboard:myboard></myboard:myboard><%=content%></body></html>
    5、总结本网站基本满足了所有需要的内容和功能需求。
    包含了个人的简介,家乡的介绍,包括个人的信息,留言板等内容。也包含了数据库的增(用户注册,留言板的留言等),删(个人留言支持删除),改(个人信息的修改等),查(留言板的查看,个人信息的查看等)四个功能。数据库的3张表,包括用户登录信息表,用户个人信息表,留言板内容表。
    6、参考文献[1]耿祥义,张跃平.JSP实用教程(第三版),清华大学出版社
    [2]刘长生,谢强,丁秋林,Java应用中的乱码问题分析[J] 计算机技术与发展,2006,25(5):77-80.
    [3]飞思科技产品研发中心。JSP应用开发详解(第二版)[M].北京:电子工业出版社,2004
    [4]萨师煊,王珊。数据库系统概论(第三版)[M].北京:高等教育出版社,2000
    [5]张红梅,王磊。在JSP中访问数据库的方法[J].农业图书情报学刊,2006,18(12):142-144
    6 评论 78 下载 2019-04-12 14:25:20 下载需要12点积分
  • 基于JAVA和MYSQL数据库实现的小型公司工资管理系统

    第一章 需求分析1.1 功能要求1.1.1 功能概况本次设计要求运用面向对象设计知识,利用 JAVA 语言设计实现一个“小型公司工资管理系统”。
    1.1.2 存储功能能够存储雇员的编号、姓名、性别、所在部门,级别,并进行工资的计算。 其中,雇员级别分为经理、技术人员、销售人员和销售经理。四类人员的月薪计算方法如下:经理拿固定月薪;技术人员按小时领取月薪;销售人员按其当月销售额的提成领取工资;销售经理既拿固定月薪也领取销售提成。由此要求,该项目需要利用数据库的关系表存储数据。
    1.1.3 添加功能程序能够任意添加上述四类人员的记录,可提供选择界面供用户选择所要添加的人员类别,要求员工的编号要唯一,如果添加了重复编号的记录时,则提示数据添加重复并取消添加。需要利用 Java 语言连接数据库,使用数据库添加语句。
    1.1.4 查询功能可根据编号、姓名等信息对已添加的记录进行查询,如果未找到,给出相应的提示信息,如果找到,则显示相应的记录信息。利用 Java Swing 控件进行展示。
    1.1.5 编辑功能可根据查询结果对相应的记录进行修改,修改时注意编号的唯一性。
    1.1.6 删除功能主要实现对已添加的人员记录进行删除。如果当前系统中没有相应的人员记录, 则提示“记录为空!”并返回操作;否则,输入要删除的人员的编号或姓名,根据所输入的信息删除该人员记录,如果没有找到该人员信息,则提示相应的记录不存。
    1.1.7 统计功能能根据多种参数进行人员的统计。例如,统计四类人员数量以及总数,或者统计男、女员工的数量,或者统计平均工资、最高工资、最低工资等信息。利用数据库语句完成统计。
    1.1.8 界面功能利用 java 的 GUI 功能设计系统的图形用户界面,要求界面美观,易用。
    第二章 概要设计2.1 系统分析2.1.1 架构设计本系统采用架构如下图所示,主要分为三个模块:用户操作界面、身份认证中心和用户数据库。其中,用户操作界面为最顶层功能,便于用户选择以添加、修改、 删除、查询统计公司信息;身份认证中心便于鉴别不同用户,以实现映射到不同的数据库(表);用户数据库中保存用户个人存储的信息,同时实现最底层功能,即各项功能的基本操作。

    2.1.2 实体设计登陆实体作为程序的进入窗口,用户登陆时,系统会要求用户输入账号和密码,并在数据库中进行匹配分析,若用户名存在且密码正确则通过身份认证,同时映射到用户 个人的数据表中,不同用户对应不同数据表存储相关信息。
    主界面实体登录成功后的功能选择界面,包含添加、查询、显示、统计四个功能,其中,对于查询或显示的信息可直接选择并完成修改删除功能。
    添加功能实体从主界面中选择进入,负责接收用户输入的员工信息,判断员工编号是否重复、录入的员工信息格式是否正确,并将符合要求的数据项其上传至数据库,完成添加员工信息的操作。
    查询功能实体从主界面中选择进入,按照用户选择的查找方式和具体查找要求,从数据库中筛选符合条件的信息并以表格形式显示,如果未查询到相关信息会给以提示。
    修改功能实体从查询功能实体进入。查询结果会以表格的形式显示在用户面前,用户可以双击某项查询结果进入编辑界面完成修改功能,同添加功能类似,系统会判断用户修改的编号是否已经重复、修改的信息是否格式正确,并将符合要求的信息在数据 库中完成更新修改操作。
    删除功能实体从查询功能实体进入。查询结果会以表格的形式显示在用户面前,用户可以双击某项查询结果进入编辑界面,在编辑界面中可选择删除此信息,删除完成后将会予以反馈。
    统计功能实体自动统计以下内容:公司整体信息(职位分布、部门人数分布等)、各部门详细信息(男女比例、工资情况、年龄情况、职位分部等),并可由用户自行选取具体部门、具体级别并显示统计结果,所有统计结果均自动绘图显示。

    2.1.3 分层设计数据库驱动层(数据层)数据库驱动层为最底层,主要以各种 JDBC 数据库驱动语句以及各种算法组成,完成添加、修改、删除、查询、统计分析的基本功能,并完成添加修改过程中的编号查重、格式判断等异常判断。各功能成功或失败情况将传递给上层,同时,异常情况也将分类传递给上层。
    异常处理层(功能层)主要分类处理数据库反馈的结果,例如查询成功失败、添加的编号重复、修改成功等操作的反馈结果。并处理来自底层抛出的异常,捕获后生成提示信息传递给上一层。
    用户界面层(表示层)接受来自异常处理层的处理结果:对于异常,采用消息框提示的方式展示给用户;对于查询结果,以表格的形式显示在界面上;对于统计结果,自动绘制图表显示给用户;其他提示信息同样采用消息框给用户反馈。同时用户可以直接在界面上选择相应功能,底层会自动实现相应操作并反馈给用户界面层。

    2.2 程序流程2.2.1 系统流程图
    2.2.2 调用关系运行程序后,首先进入用户登陆界面,用户名与密码不匹配则登陆失败,成功则进入用户操作主界面。
    在用户操作主界面中有四个按钮供用户选择,分别是:添加记录、查询记录、显示信息、统计整理,点击不同按钮跳转至不同功能实现界面。
    添加信息模块允许用户添加新信息,系统会判断编号是否重复、各式是否正确。若通过审核则将此信息添加至数据库中,询问用户是否继续添加。如果退出则重新返回主界面。
    查询信息模块允许用户按个人需求查询相关信息,如:职员编号、姓名、性别、级别、部门等。查询得到的信息会显示在表格中,用户可以点击表格中具体某一项选择编辑信息,在编辑模块中可以修改或删除选中的信息。
    显示信息模块与查询功能类似,显示的内容会自动放入表格中同时允许编辑修改。 统计整理模块会将统计得到的信息以图表形式显示给用户,同时允许用户自行查询想要统计的信息并自动绘制图表。
    第三章 详细设计3.1 功能类定义与实现3.1.1 常量与参数的定义(Parameter 类)JDBC 数据库连接所用参数与端口JDBC(Java Data Base Connectivity,java 数据库连接)是一种用于执行 SQL 语句的 Java API,可以为多种关系数据库提供统一访问,它由一组用 Java 语言编写的类和接口组成。JDBC 为数据库开发人员提供了一个标准的 API,据此可以构建更高级的工具和接口,使数据库开发人员能够用纯 Java API 编写数据库应用程序,并且可跨平台运行,并且不受数据库供应商的限制。
    本系统采用的是MySQL数据库,编程语言为Java语言,编译器为Eclipse Oxygen,Java连接数据库时需要用到JDBC驱动器、数据库URL以及数据库管理员账号密码等。
    根据数据库的 URL、用户名和密码,创建一个 JDBC Connection 对象。如: Connection connection = DriverManager.geiConnection(“连接数据库的 URL”, “ 用户名”, “密码”)。其中,URL=协议名+IP 地址(域名)+端口+数据库名称;用户名 和密码是指登录数据库时所使用的用户名和密码。示例创建 MySQL 的数据库连接代码如下:
    Connection connectMySQL = DriverManager.geiConnection("jdbc:mysql://localhost:3306/myuser","root" ,"root"); public static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; public static final String DB_URL = "jdbc:mysql://localhost:3306/java?useSSL=true&characterEncoding=UTF8"; public static final String ACC = "root"; public static final String PWD = "zxczxc";
    职员级别对应代号本系统中将职员级别分为四种:经理、技术人员、销售人员、销售经理,其中经理拿固定月薪;技术人员按小时领取月薪;销售人员按其当月销售额的提成领取工资;销售经理既拿固定月薪也领取销售提成。若想方便统计需要将对应职位转换成相应的代号。此处经理对应 int 型数字 1,技术人员对应 2,销售人员对应 3,销售经理对应 4.具体如下:
    public static final int Manager = 1; //经理 public static final int Engineer = 2; //技术人员 public static final int Salesman = 3; //销售人员 public static final int SalesManager = 4; //销售经理
    工资自动计算所需常量由于经理拿固定月薪;技术人员按小时领取月薪;销售人员按其当月销售额的提成领取工资;销售经理既拿固定月薪也领取销售提成。若想方便计算工资,必须提前订好各种常量,如:固定的月薪、工作每小时的工资、销售额提成比例等,具体如下:
    public static final int BASE = 5000; //底薪 public static final int HOUR = 80; //每小时工资 public static final double Parameter = 0.015; //提成比例
    3.1.2 职工个人信息的定义(Person 类)职工个人信息职工个人信息包括:职工编号(唯一)、姓名、性别、年龄、电话号码、所属部 门、工作级别、月工作时间、月销售总额、月工资。其中月工资不可显式输入,自动由程序结算得到。通过构造函数直接创建对象,具体如下:
    public Person(String ID,String name,String sex,int age,String phone, String department,int kind,int hours,double sells) { this.ID = ID; this.name = name; this.sex = sex; this.age = age; this.phone = phone;this.department = department; this.kind = kind; this.hours = hours; this.sells = sells;}
    通过此方法得到私有成员变量:
    public String getID() { return ID; }
    职工工资计算方法经理拿固定月薪;技术人员按小时领取月薪;销售人员按其当月销售额的提成领取工资;销售经理既拿固定月薪也领取销售提成。具体计算方法如下:
    switch (kind) { case 1: this.salary = Parameter.BASE; break; case 2: this.salary = Parameter.HOUR*hours; break; case 3: this.salary = Parameter.Parameter*sells; break; case 4: this.salary = Parameter.BASE + Parameter.Parameter*sells; break; default: return; }
    3.1.3 数据库查询与底层算法(JDBC 类)JDBC 连接数据库在开发环境中加载指定数据库的驱动程序。使用的数据库是MySQL,所以需要下载MySQL支持JDBC的驱动程序(mysql-connector-java-5.1.18-bin.jar);而开发环境是Eclipse,将下载得到的驱动程序加载进开发环境中。
    在Java程序中加载驱动程序。在Java程序中,可以通过 “Class.forName(“指定数据库的驱动程序”)” 方式来加载添加到开发环境中的驱动程序,例如加载MySQL的数据驱动程序的代码为:
    Class.forName(“com.mysql.jdbc.Driver”);
    创建数据连接对象:通过DriverManager类创建数据库连接对象Connection。DriverManager类作用于Java程序和JDBC驱动程序之间,用于检查所加载的驱动程序是否可以建立连接,然后通过它的getConnection方法,根据数据库的URL、用户名和密码,创建一个JDBC Connection 对象。如:
    Connection connection = DriverManager.geiConnection(“连接数据库的URL", "用户名", "密码”)
    其中,URL=协议名+IP地址(域名)+端口+数据库名称;用户名和密码是指登录数据库时所使用的用户名和密码。
    创建Statement对象:Statement 类的主要是用于执行静态 SQL 语句并返 回它所生成结果的对象。通过Connection 对象的 createStatement()方法可以创建一个Statement对象。例如:
    Statement statament = connection.createStatement();
    具体示例创建Statement对象代码如下:
    Statement statamentMySQL =connectMySQL.createStatement();
    调用Statement对象的相关方法执行相对应的 SQL 语句:通过execuUpdate() 方法用来数据的更新,包括插入和删除等操作,例如向staff表中插入一条数据的代码:
    statement.excuteUpdate("INSERT INTO staff(name, age, sex,address, depart, worklen,wage)" + " VALUES ('Tom1', 321, 'M', 'china','Personnel','3','3000' ) ");
    通过调用Statement对象的executeQuery()方法进行数据的查询,而查询结果会得到 ResulSet对象,ResulSet表示执行查询数据库后返回的数据的集合,ResulSet对象 具有可以指向当前数据行的指针。通过该对象的next()方法,使得指针指向下一行,然后将数据以列号或者字段名取出。如果当next()方法返回null,则表示下一行中没有数据存在。使用示例代码如下:
    ResultSet resultSel = statement.executeQuery( "select * from staff" );
    关闭数据库连接:使用完数据库或者不需要访问数据库时,通过Connection的 close() 方法及时关闭数据连接。
    身份认证对于用户,需要先要求输入账号密码,并将账号密码传入数据库身份鉴别表进行匹配,若用户名密码均匹配成功,则映射到用户创建的表中。传入参数为账号和密码,返回判断情况:返回1为账号不存在、返回2为密码不正确、返回3为出现数据库连接异常、返回0则认证成功。
    public static int LoginCharge(String acc,String pwd) { try { Class.forName(Parameter.JDBC_DRIVER); Connection conn = DriverManager.getConnection(Parameter.DB_URL, Parameter.ACC, Parameter.PWD); Statement stat = conn.createStatement(); String query = "select * from `" + Parameter.COMPANY + "` where acc=\"" + acc + "\""; ResultSet rs = stat.executeQuery(query); if (!rs.next()) return 1;//账号不存在 String pwd2 = rs.getString("pwd"); if(!pwd2.equals(pwd)) return 2;//密码不正确 String table = rs.getString("table"); Parameter.TABLE = table; return 0; }catch (Exception e) { e.printStackTrace(); return 3; }
    插入信息模块中,需要判断插入的编号是否重复,如果重复则不允许插入,函数 rs.next()如果返回结果不为空,则说明已经存在此编号。输入信息为Person对象,返回判断结果:返回1为编号已存在,返回2为数据库连接异常,返回0为插入成功,具体如下:
    public static int insertIntoSql(Person p) { try { Class.forName(Parameter.JDBC_DRIVER); Connection conn = DriverManager.getConnection(Parameter.DB_URL, Parameter.ACC, Parameter.PWD); Statement stat = conn.createStatement(); // 判断是否已经存在编号 String query1 = "select * from `" + Parameter.TABLE + "` where no=\"" + p.getID() + "\""; ResultSet rs = stat.executeQuery(query1); if (rs.next()) { return 1; } String query = "INSERT INTO `" + Parameter.TABLE + "` VALUES (\"" + p.getID() + "\",\"" + p.getName() + "\",\"" + p.getSex() + "\",\"" + p.getAge() + "\",\"" + p.getPhone() + "\",\"" + p.getDep() + "\",\"" + p.getKind() + "\",\"" + p.getHours() + "\",\"" + p.getSells() + "\",\"" + p.getSalary() + "\")"; stat.executeUpdate(query); return 0; } catch (Exception expt) { return 2; } }
    从数据库中删除信息删除信息模块中,需要删除的编号是否存在,如果不存在则不允许删除,函数 rs.next()如果返回结果为空,则说明此编号对应的职员不存在。输入信息为职员的 编号ID,返回判断结果:返回1为编号不存在,返回2为数据库连接异常,返回0为插 入成功,具体如下:
    public static int deleteFromsql(String id) { try { Class.forName(Parameter.JDBC_DRIVER); Connection conn = DriverManager.getConnection(Parameter.DB_URL, Parameter.ACC, Parameter.PWD); Statement stat = conn.createStatement(); String query1 = "select * from `" + Parameter.TABLE + "` where no=\"" + id + "\""; ResultSet rs = stat.executeQuery(query1); if (!rs.next()) { return 1; } String query2 = "delete from `" + Parameter.TABLE + "` where no=\"" + id + "\""; stat.executeUpdate(query2); return 0; } catch (Exception expt) { return 2; } }
    从数据库中查询信息查询信息模块中,具体分为按照ID查询和按照其他条件查询,具体差别为ID唯一,至多只能查找到一条信息,而按照其他条件查询可能会返回多条信息,因此需要区 别处理,输入信息为职员的信息,返回值为查询结果,为空则查询失败具体如下:
    public static String searchByID(String id) {//按照ID查询 try { Class.forName(Parameter.JDBC_DRIVER); Connection conn = DriverManager.getConnection(Parameter.DB_URL, Parameter.ACC, Parameter.PWD); Statement stat = conn.createStatement(); String query1 = "select * from `" + Parameter.TABLE + "` where no=\"" + id + "\""; ResultSet rs = stat.executeQuery(query1); if (!rs.next()) { return null; } String name = rs.getString("name"); String sex = rs.getString("sex"); int age = rs.getInt("age"); String phone = rs.getString("phone"); String department = rs.getString("department"); int kind = rs.getInt("kind"); int hours = rs.getInt("hours"); double sells = rs.getDouble("sales"); double salary = rs.getDouble("salary"); String result = id + "@" + name + "@" + sex + "@" + age + "@" + phone + "@" + department + "@" + kind + "@" + hours + "@" + sells + "@" + salary; // 生成日志 File f = new File("log.txt"); if (!f.exists()) f.createNewFile(); PrintStream ps = new PrintStream(new FileOutputStream(f)); ps.println(result); ps.close(); return result; } catch (Exception expt) { return "Fail"; } } public static String searchByOthers(String chosen, String others) { //按照其他条件查询,chosen为条件,others为具体筛选内容 try { Class.forName(Parameter.JDBC_DRIVER); Connection conn = DriverManager.getConnection(Parameter.DB_URL, Parameter.ACC, Parameter.PWD); Statement stat = conn.createStatement(); String query; if (chosen.equals("age") || chosen.equals("kind")) query = "select * from `" + Parameter.TABLE + "` where " + chosen + "=\"" + Integer.parseInt(others) + "\""; else query = "select * from `" + Parameter.TABLE + "` where " + chosen + "=\"" + others + "\""; ResultSet rs = stat.executeQuery(query); if (!rs.next()) { return null; } String id = rs.getString("no"); String name = rs.getString("name"); String sex = rs.getString("sex"); int age = rs.getInt("age"); String phone = rs.getString("phone"); String department = rs.getString("department"); int kind = rs.getInt("kind"); int hours = rs.getInt("hours"); double sells = rs.getDouble("sales"); double salary = rs.getDouble("salary"); String result = id + "@" + name + "@" + sex + "@" + age + "@" + phone + "@" + department + "@" + kind + "@" + hours + "@" + sells + "@" + salary; while (rs.next()) { id = rs.getString("no"); sex = rs.getString("sex"); name = rs.getString("name"); age = rs.getInt("age"); phone = rs.getString("phone"); department = rs.getString("department"); kind = rs.getInt("kind"); hours = rs.getInt("hours"); sells = rs.getDouble("sales"); salary = rs.getDouble("salary"); result += "#" + id + "@" + name + "@" + sex + "@" + age + "@" + phone + "@" + department + "@" + kind + "@" + hours + "@" + sells + "@" + salary; } } catch (Exception expt) { expt.printStackTrace(); return "Fail"; } }
    从数据库中更新信息编辑信息模块中,如果需要修改信息,则需要启用更新操作:先判断是否修改了编号,如果修改编号则需要判断修改后的编号是否重复,如果重复则不允许修改为此编号。输入修改前的Person对象和修改后的Person对象,如果修改失败则回退操作,即把原来的Person对象恢复,具体实现如下:
    public static int UpdateFromsql(Person newP, Person oldP) { try { Class.forName(Parameter.JDBC_DRIVER); Connection conn = DriverManager.getConnection(Parameter.DB_URL, Parameter.ACC, Parameter.PWD); Statement stat = conn.createStatement(); if (deleteFromsql(oldP.getID()) != 0) { return 1; } String query1 = "select * from `" + Parameter.TABLE + "` where no=\"" + newP.getID() + "\""; ResultSet rs = stat.executeQuery(query1); if (rs.next()) { if (insertIntoSql(oldP) != 0) JOptionPane.showMessageDialog(null, "发生未知错误"); return 2; } if (insertIntoSql(newP) != 0) { if (insertIntoSql(oldP) != 0) JOptionPane.showMessageDialog(null, "发生未知错误"); return 3; } return 0; } catch (Exception expt) { if (insertIntoSql(oldP) != 0) JOptionPane.showMessageDialog(null, "发生未知错误"); return 4; } }
    从数据库中统计整理信息统计整理模块功能较为复杂,但实现方法大体类似,根据具体的查询条件和查询内容查询相关的信息,并返回结果,具体实现如下:
    统计数量
    public static int statisticCount(String option) { try { Class.forName(Parameter.JDBC_DRIVER); Connection conn = DriverManager.getConnection(Parameter.DB_URL, Parameter.ACC, Parameter.PWD); Statement stat = conn.createStatement(); String query = "select count(*) from `" + Parameter.TABLE + "` "+option; ResultSet rs = stat.executeQuery(query); if (!rs.next()||rs.getString(1)==null) { return 0; } int result = Integer.parseInt(rs.getString(1)); return result; } catch (Exception expt) { JOptionPane.showMessageDialog(null, "发生未知错误"); return 0; } }
    统计不同职位的人数
    public static int statisticKindCount(int kind, String option1, String option2)
    统计不同性别的人数
    public static int statisticSexCount(String sex, String option1, String option2)
    统计最高、最低、平均工资
    public static double statisticAvgSalary(String option1, String option2) public static double statisticMaxSalary(String option1, String option2) public static double statisticMinSalary(String option1, String option2)
    统计最大、最小、平均年龄
    public static double statisticAvgAge(String option1, String option2) public static int statisticMaxAge(String option1, String option2) public static int statisticMinAge(String option1, String option2)
    3.2 图形界面类定义与实现3.2.1 JFreeChart 制图(JFreeChart 类)柱形图制作传入图表的名称(标题)、Dataset 容器(存放图形参数)、以及所要绘制图形的颜色,返回绘制的 Chart 图形。
    public class CategoryChart { public static JFreeChart createChart(String name, CategoryDataset dataset,Color color) { JFreeChart chart = ChartFactory.createBarChart3D(name, null, null, dataset, PlotOrientation.VERTICAL, true, false, false); CategoryPlot plot = chart.getCategoryPlot();// 设置图的高级 属性 BarRenderer3D renderer = new BarRenderer3D();// 3D 属性修改 plot.setNoDataMessage("无 信 息"); renderer.setSeriesPaint(0,color); //设置柱的颜色 // 设置网格竖线颜色 plot.setDomainGridlinePaint(Color.gray); plot.setDomainGridlinesVisible(true); // 设置网格横线颜色 plot.setRangeGridlinePaint(Color.gray); plot.setRangeGridlinesVisible(true); // 图片背景色 plot.setBackgroundPaint(Color.LIGHT_GRAY); plot.setOutlineVisible(true); // 设置墙体颜色 renderer.setWallPaint(Color.gray); // 对 X 轴做操作 CategoryAxis domainAxis = plot.getDomainAxis(); // 对 Y 轴做操作 ValueAxis rAxis = plot.getRangeAxis(); renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator()); renderer.setBaseItemLabelsVisible(true); renderer.setBaseItemLabelFont(new Font("黑体", Font.CENTER_BASELINE, 12), true); renderer.setBasePositiveItemLabelPosition( new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.CENTER_LEFT)); renderer.setItemLabelAnchorOffset(15); //设置距离图片左端距离 domainAxis.setUpperMargin(0.2); //设置距离图片右端距离 domainAxis.setLowerMargin(0.2); //设置柱的透明度 plot.setForegroundAlpha(0.6f); // 最后还得将 renderer 放到 plot 中 plot.setRenderer(renderer);// 将修改后的属性值保存到图中 return chart; } }
    饼图制作传入图表的名称(标题)、Dataset 容器(存放图形参数),饼图颜色自动分配,返回绘制的 Chart 图形。
    public class PieChart { public static JFreeChart createChart(String name,PieDataset piedataset) { JFreeChart jfreechart = ChartFactory.createPieChart3D(name, piedataset, true, true, false); PiePlot3D pieplot3d = (PiePlot3D) jfreechart.getPlot(); pieplot3d.setNoDataMessage("无 信 息"); pieplot3d.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}:{1}({2})"));//设置标签显示的格式 pieplot3d.setSectionOutlinesVisible(false); pieplot3d.setLabelBackgroundPaint(new Color(220, 220, 220));//设置标签的背景颜色。 //设置旋转角度 pieplot3d.setStartAngle(180.0); //设置旋转方向,Rotation.CLOCKWISE)为顺时针 pieplot3d.setDirection(Rotation.CLOCKWISE); //设置图表透明图 0.0~1.0 范围。0.0 为完全透明,1.0 为完全不透明 pieplot3d.setForegroundAlpha(0.9F); return jfreechart; } }
    3.2.2 Dataset 容器(JFreeChart 制图所需容器)柱形图数据集主要包括年龄统计的数据集和工资统计的数据集,对于年龄和工资,本系统统计最大值、平均值和最小值,对于这三项数据,采用柱形图绘制比较合适。代码见附录。

    饼图数据集主要包括性别比例统计的数据集和不同部门、级别人数分布统计的数据集,对于年龄比例和人数比例,本系统绘制饼图直观的展现不同种类人数所占比例的大小。代码见附录

    3.2.3 界面设计与制作(JFrame 继承子类)主要包括登陆界面、主界面、插入信息界面、查询信息界面、编辑界面(修 改删除查询详情)、显示信息界面(表格显示)、统计整理界面(自动制作柱形图、 饼图),详情见第五章。 设计界面主要使用 Java Swing 和 Java AWT,采用框架 Java BeautyEye,同 时采用事件处理等接口完成图形界面设计,做到良好的美观性以及实用性、易用性。便于用户操作。
    3.3 函数调用关系图
    程序由 LoginFrame()进入,登陆成功进入 MainFrame(),Mainframe 可以选择进入 InsertFrame、QueryFrame 和 StatisticFrame,其中 QueryFrame 调用 Delete 和 Update 函数,Statistic 调用 HandleDate、JFreeChart 和 JDBC 函数完成统计并自动将数据可视化。
    第四章 测试结果4.1 登陆界面


    4.2 程序主界面如果登陆失败,如账号不存在或密码错误,则会给以相应提示,登陆成功则跳转至程序主界面。

    4.3 添加信息界面
    如果编号重复、添加内容格式不正确,则会有一定提示:


    4.4 查询信息界面查询界面打开后默认显示全部记录,以表格形式显示

    共有五种查询方式可选择:

    在此处我们选择查询部门为技术部的所有职员,其他类似不做重复测试。可以看到表格刷新,显示出符合条件的所有记录:

    4.5 编辑信息界面在查询界面点击每条查询结果的最右侧按钮可进入编辑界面,可以修改、删除、查询详细信息

    4.6 统计整理界面



    13 评论 382 下载 2018-11-05 11:25:51 下载需要15点积分
  • 基于spring+struts2+hibernate实现的Java web论坛

    1、绪论这次的实训项目是开发一个java论坛系统,而开发java论坛系统的目的是提供一个供java学习交流的平台,为Java程序员提供交流经验、探讨问题的社区。
    2、需求分析java论坛系统最基本的功能首先是发表主题,其次是其他人员根据主题发表自己的看法。此外,为了记录主题的发表者和主题的回复者信息,系统还需要提供用户注册和登录的功能。只有注册的用户登录后才能够发表和回复主题,浏览者(游客)只能浏览主题信息。根据用户的需求及以上的分析,java论坛需要具备前台功能和后台功能。
    对于一个用户,使用论坛进行交流时,首先要注册一个 账户,然后登录后才能进行对帖子的回复,如果不登录,就只能查看帖子而不能进行回复和发表帖子。用户使用论坛系统的需求是发表某一个主题相关的帖子,但用户不可以删除发表的的帖子和评论,目的是为了维持论坛的秩序,一旦用户发表违规内容,管理员将会对其删除用户操作。对于论坛管理人员来说,需要完成对用户发表的帖子的管理,包括:设置精华帖、置顶 帖子、删除帖子等操作。
    开发java论坛系统的目的是提供一个供java学习交流的平台,为Java程序员提供交流经验、探讨问题的社区。。因此, java论坛系统最基本的功能首先是发表主题,其次是其他人员根据主题发表自己的看法。此外,为了记录主题的发表者和主题的回复者信息,系统还需要提供用户注册和登录的功能。只有注册的用户登录后才能够发表和回复主题,浏览者(游客)只能浏览主题信息。根据用户的需求及以上的分析, 校园论坛需要具备前台功能和后台功能。
    系统前台功能:显示用户发表的帖子,查看帖子的内容、发表对帖子的回复、发表对回复的回复、显示用户的头像、用户信息的显示、用户新信息的提醒。
    系统后台功能:进入后台、帖子管理、用户管理、添加删除用户、系统设置、退出系统、返回首页。
    3、设计为了方便学习者的交流,我们决定要做这么一个java论坛,而对于论坛这样的数据流量特别大的网络管理系统,必须要满足使用方便、操作灵活等设计需求。所以本系统在设计时应满足以下几个目标:

    临时用户进入,可浏览帖子但不可发帖
    一个版面能显示所有的帖子
    具有登录模块,有用户的个人信息
    用户随时都可以查看自己发表的帖子
    管理员权限可删除任意帖子,具有最大权限的管理功能
    对用户输入的数据,系统进行严格的数据检验,尽可能 排除人为的错误
    系统最大限度地实现了易维护性和易操作性
    系统运行稳定安全可靠

    3.1 业务功能分析功能模块图

    E-R图

    论坛系统前台流程图

    论坛后台管理流程图

    论坛系统基本用例图

    管理员操作删除帖子用例时序图

    3.2 数据库搭建3.2.1 数据库设计帖子表(t_announce)

    时间表(t_new)

    版块表(t_category)

    评论表(t_comment)

    大版块表(t_grade)

    帮助帖子表(t_help)

    主题表(t_topic)

    类型表(t_type)

    用户表(t_user)

    3.2.2 数据库实现
    4、编码4.1 后台功能实现上传本地文件方法

    帖子评论操作的Service层

    换页Dao类的创建

    登陆拦截器

    采用session的方法对账户表单信息进行验证

    获取用户列表

    4.2 前端页面实现4.2.1 用户登录页面实现
    4.2.2 管理员登录页面实现
    4.2.3 主页面
    4.2.4 管理员管理页面
    5、测试5.1 登陆测试
    5.2 前台界面测试5.2.1 评论帖子
    5.2.2 主页
    5.2.3 注册页面测试
    5.2.4 修改个人资料页面测试
    5.2.5 管理员页面测试
    5.2.6 管理员操作测试
    5.2.7 用户信息管理操作
    5.3 帖子管理测试
    1 评论 4 下载 2020-07-19 18:01:41 下载需要13点积分
  • 基于Java的连连看游戏设计与实现

    摘 要连连看是一种消除类益智游戏,核心要求是在规定的时间内,消除游戏界面中选中的两张相同的图案,直至完全消除所有图案。这款游戏操作简单(只需单击鼠标左键操作)、面向人群广泛,在限时操作的游戏要求下,吸引玩家自发地锻炼观察能力、判断能力和反应能力,故从推出至今颇受欢迎。消除类游戏如今也有很多类型,但连连看游戏因其操作简单依旧广受好评,该游戏不仅能调节精神状态,还能在游戏中锻炼我们的眼力视野和集中力,开发思维能力的同时培养面对困难时具备攻克困难的信心。
    此次设计所使用的语言为Java语言,开发环境为JDK Version1.7.0,开发工具为Eclipse。主要应用Swing组件,Java小程序,事件及接口等。本系统主要是运用Swing组件和事件处理技术,进行界面的绘制,鼠标的操作,以及积分的显示和沙漏的计时的显示等功能。
    关键词:游戏;连连看;二维游戏
    AbstractLink-Game is a kind of tile-matching puzzle games,the core requirement is that within the prescribed period eliminating two selected pictures which clicked on the before and after and had the same pattern until completely eliminating all of the same two.There are numerous reasons why this game is popular since launch as follow.The operation of the game is simple (just need clicking the mouse left key)and facing the crowd is widespread.But also in the limited time,game players have to victory attracts people exercise spontaneously observation ability,judgment ability and the ability to respond to.Now this kind of puzzle games also has a lot of types,but Link-Game because of its simple operation is still popular,not only can the game adjust the mental state,but also exercise our eyesight and concentrated force by enjoying the game.Furthermore,it develops the thinking ability.Meanwhile,it cultivates the confidence to overcome difficulties when we face the difficulties.
    This design uses Java language,and it’s development environment is the Version 1.7.0 JDK on eclipse,the development tool.This system mainly use Swing components,Java applet,event and interface.By using event handling technology and Swing technology realizes the GUI,the mouse operation,showing the game credits as well as the function that timing as the hourglass.
    Keywords: Games; Link-game; Two-dimensional Game
    1. 绪论以互联网产业为代表的中国信息产业蓬勃发展,并已成为国民经济和社会发展的重要组成部分。电子游戏产业作为电子技术的产物,涉及到电子游戏的开发、市场营销和销售等方方面面的经济领域,并且很快在全世界的娱乐领域占据主流位置。在社交网络飞速发展的影响下,电子游戏社交化助力推动电子游戏各个方面的发展,带来的经济效益也愈发庞大。网页游戏、单机游戏、网络游戏形形色色数量庞大,涌现出一批批颇具新意的游戏,为疲惫的生活带来轻松和愉悦,满足玩家的娱乐休闲要求。
    1.1 课题背景连连看游戏顾名思义就是找出具有关联关系的事物并进行相应处理,经历了从桌面游戏、在线游戏再到社交游戏三个过程,形式多种多样。游戏的核心要求是将两个能用三根以内的直线连接的关联事物(相同事物)消除(或进行其他处理)。一般的连连看小游戏规则和操作都简单明了易上手,但也有很多新版本的连连看游戏加入了各类道具和游戏模式来丰富游戏内容,很好地增强了游戏的娱乐性,也带给玩家长期的挑战性和新鲜感。
    对于90后大部分玩家来说,一定对网页游戏有很深刻的印象。最早,玩家们会在电脑课上接触到基于Flash的网页游戏。在线Flash游戏大都界面优良,操作简单,基本靠鼠标点击或者键盘方向键控制即可完成游戏。虽然当时网络游戏发展也很迅猛,但网页游戏仍旧依靠自身特点很快地吸引了一大批玩家。随着网络更多地服务于社交活动以及更多开放平台的兴起,很多游戏慢慢走向“社交化”,就是将游戏与个人空间结合,在社交网络和平台上主动或被动的通过玩家的“分享”快速地传播,应运而生出社交游戏。
    无论是网页游戏还是网络小游戏,都拥有很多玩家受众,经典游戏也有很多,其中不乏有应用Java语言开发的经典游戏,比如俄罗斯方块、超级泡泡龙、贪吃蛇以及任天堂的超级马里奥等等,兼具游戏趣味和休闲益智的连连看便是这其中的佼佼者。
    1.2 Java游戏开发的现状提到游戏开发,更多地会提到C和C++,这两个语言在游戏开发中有稳定和高效的表现。作为主流开发语言的Java是否也能在游戏开发方面展现良好的一面呢?从理论上讲,Java语言当然能被用来开发游戏,随着Java技术不断的更新发展,Jogl、Java3D等技术的出现,Java程序在显卡愈发强大的硬件加速基础上运行效果显著提升,开发出了许多基于Java的2D、3D游戏和大型的在线游戏。但Java作为开发语言开发游戏仍然被诟病,可以开发游戏不等同于适合开发游戏,因此,要讨论Java开发游戏的优势和意义。
    1.2.1 Java日益趋向成熟Java语言从面世至今已过20载,它的发展也越来越符合人们对它的要求和需要。企业级应用的实践在某些方面可以看出该语言在大型软件开发方面颇为适用。当Java语言运行效率不再成为诟病时,相信Java语言跨平台、安全性、高抽象的优势在开发的大型游戏软件方面会有很好的表现。
    1.2.2 Java极大的方便了游戏脚本的使用开发的过程往往是一个需要不断改进的过程,过程中会涉及许多方面的问题,游戏开发也不例外。所以改进的过程是否容易实现对于开发者来说也很重要,而游戏脚本就是为了改进的过程更容易实现。
    如果将全部文件和数据写入程序,出现问题后要将整个程序重写编译发布,游戏是会不断地修改的,程序会越变越复杂。如果我们将可重复的数据写入外部文件,游戏引擎开发完毕通过读取外部文件运行的话,这样,当游戏出现问题时,修改外部文件就能解决问题,这样做极大地便利了游戏开发过程。Java本身就可以用来编写游戏脚本,目前也有例如groovy、beanshell等脚本语言可以无缝交互于Java语言,极大的方便了Java游戏编程。
    1.2.3 Java平台无关特性提起Java语言特性,不得不提它的平台无关性。跨平台一直都是游戏开发面对的一个实际问题,Java在这方面做的相对于其他语言要好一些。当然,跨平台的特性可以使程序员减少工作量,公司减少投资,然而有些时候,“write once run everywhere”也需要付出一定的代价。在现实中,往往会出现这样的情况:对于Java applet来说,即使电脑在硬件上满足程序的要求,可能也无法让程序以同样良好的状态运行在每一台电脑上,除非使用者都是专业人士。利用Java跨平台特性开发软件在实现过程中有利也有弊,但Java在解决跨平台问题上比起其他技术要做的好一些。
    1.2.4 Java在手机游戏开发方面的优势目前来看,游戏功能在手机功能中占据比重越来越大,手机游戏开发也将占据游戏开发市场更大的份额。手机搭载了各类操作系统也使Java语言因其跨平台的特性在游戏开发中颇受青睐。例如,安卓系统基于Java语言开发,安卓市场在手机市场所占比重很大,所以Java应用还是有一定的需求和不错的前景的。
    1.2.5 Java在网络方面的良好表现Java在解决网络方面的问题上有不错的优势,体现在两个方面。一方面,基于applet和Java Web Start的游戏很容易更新,不需要用户手动下载新版本。另一方面,Java在网络交互的API相对友好。
    在大型网络游戏开发中,分布式系统尤为重要,为了更好的推出硬件产品,Sun公司大力开发了用于网络服务器的Project DarkStar,DarkStar项目系统基础结构的设计方便了大型多玩家在线游戏的开发,并且有健壮的游戏运作能力,能动态的分配可用的服务器资源,还拥有性能改善功能,可以说,Project DarkStar的出现提高了Java在开发网络服务器方面的可能性。
    1.2.6 游戏速度基于Java的游戏执行效率方面一直颇受争议,在大型游戏应用方面的实例不多,更适用于中小型游戏开发。Java开发的游戏执行速度被很多程序员争议的地方在于Java程序运行时要启动Java虚拟机,具体表现如何,取决于开发项目的大小和软、硬件各方面的表现。与常用来开发游戏的C++语言相比,Java开发出的游戏速度更慢,但Java开发的成本也相对较低。
    1.3 项目开发的目标游戏软件的最直观的评判是它的操作界面,界面的好坏直接影响游戏玩家对这款游戏的接受程度和喜爱程度。对游戏评判的要求其次是功能齐全与否,功能越丰富,游戏体验的层次越丰富。在游戏操作简单的基础上丰富游戏内容,会使游戏变得更易普及。
    针对连连看这款小游戏,本项目的开发目标是:游戏界面整洁美观,实现游戏的可操作性,使游戏操作简单易上手,并且在基础功能实现后增添一些理解简单、操作简单的功能用以丰富游戏内容。
    实现连连看游戏具体要做到以下几点:游戏界面美观大方:通过有些界面要能对游戏操作过程有一定的理解;游戏具有一定的可玩性和吸引力:有一定内容,不局限于普通功能;游戏运行稳定可靠。
    在设计与实现的过程中,力求对Java语言有新的认识和理解,对面向对象的概念和方法熟练应用和实践。在编写过程中,养成良好的编程习惯和良好的编程风格。在应用所学知识时,巩固理解Java程序设计的基本过程以及线程、网络、界面布局等编程技术。旨在培养分析问题的能力和解决问题的能力,着重培养设计分析、设计方法、设计操作与测试、观察设计过程和理解归纳问题的能力。
    通过对游戏的开发,实现游戏的可操作性及美观性,进一步深化面向对象的程序设计思想,以及熟练运用Swing进行编程的能力,为将来的实际工作打下坚实的基础。
    1.4 项目开发的意义项目开发的意义有两个层面。一方面,在项目开发过程中,开发人员通过将所学所感融入实际应用中,非常有利于学习和掌握开发过程,有利于进一步掌握Java面向对象的程序设计语言的基础知识和技能,有利于更直观地感受到面向过程的开发和面向对象的开发之间的不同点。
    另一方面,项目开发往往能够很好地培养和锻炼个人专业技术能力和个人综合素质能力。本次项目开发,是开发人员和所有先辈们共同努力的结晶。在开发过程中,查阅资料,解读国内外优秀学子和老师的智慧结晶,扩展了开发人员解决问题的思路和看待问题的眼界,在实践过程中,感受开发的乐趣,可以更好的验证优秀的结论,也可以在前人的基础上提出新看法新角度,并在实践中证明。
    项目开发的过程大大有利于锻炼开发人员对于目标问题的发现、分析以及解决过程中必不可少的沟通能力、分析能力、理解归纳能力、设计实现能力以及观察测试能力等各项能力。
    通过此次毕业设计,能充分的展现项目开发的意义:

    进一步巩固、加深本科四年专业所学所感,掌握基本理论知识,结合理论完成实践,提高综合分析问题,解决问题的能力
    开发小型应用系统,掌握运用Java语言编写调试应用程序,训练独立开发应用系统,进行数据处理的综合能力
    掌握面向对象程序设计的方法
    熟练掌握Java语言的基本语法,灵活运用各种数据类型,对面向对象的程序设计语言的学习有更好的理解
    进一步掌握在集成环境下如何调试程序和修改程序。

    1.5 本文章节安排本文共分七章,具体章节安排如下:

    第一章概述了选题背景、项目目标及意义,介绍了Java游戏开发现状,指明连连看游戏设计及实现的基本方向
    第二章概述了开发环境和相关技术,简述了Java和Eclipse,重点介绍了Java在游戏开发中的应用,包括GUI开发、绘图技术、事件处理机制等
    第三章介绍了可行性分析和系统需求分析。首先从技术、经济、社会三方面进行了可行性分析,然后简述了连连看游戏的一般游戏规则。最后,从业务需求、用户需求、功能需求和非功能需求四个方面进行了需求分析
    第四章进行了系统概要设计,主要将系统划分出界面模块和处理模块两大模块,确定了游戏风格和素材
    第五章介绍了详细设计和实现,包括界面、处理模块和游戏连接算法的设计及实现
    第六章进行了系统测试。简述了系统测试相关内容,给出了测试用例和测试结果
    第七章进行了全文总结,一方面总结了在完成过程中学习到的内容,另一方面说明了现存问题,展望了进一步工作

    1.6 本章小结本章通过对选题背景、项目目标和意义以及Java游戏开发现状的介绍,阐述了选题原因,指明了连连看设计和实现的基本方向,描述了项目开发意义。
    2. 开发环境和相关技术简介Eclipse 是一款优秀的跨平台的自由的集成开发环境(IDE),除了可作为Java的集成开发环境外,还可以作为编写其他语言(如C++和Ruby)。Java是一种可以撰写跨越平台的应用软件的面向对象的程序设计语言,具有优越的通用性、高效性、安全性和平台移植性,广泛应用于PC、科学超级计算机、游戏控制台、数据中心、移动电话和互联网等各个领域。本章将围绕Eclipse和Java介绍项目开发环境和相关技术。
    2.1 开发环境软件开发环境(Software Development Environment,SDE)指在基本硬件和数字软件的基础上,为支持系统软件和应用软件的工程化开发和维护而使用的一组软件。系统的软件环境主要由开发系统所用的开发工具和环境集成机制等几部分构成。良好的开发环境对于稳定项目组人员以及提高生产效率都有不可忽视的作用。本次开发环境的具体内容如表2-1开发环境表所示。
    开发环境表




    名称
    版本
    语种




    操作系统
    Windows
    Windows 8.1
    简体中文


    开发环境
    Java
    JDKVersion1.7.0
    简体中文


    开发工具
    Eclipse
    Eclipse-jee-mars
    简体中文



    开发工具 Eclipse Eclipse-jee-mars简体中文
    2.1.1 EclipseEclipse 是一款优秀的跨平台的自由的集成开发环境(IDE),从其功能上来讲是一个基于Java的、开放源代码的可扩展开发平台,就其本身而论,它是一个用于通过插件组件构建开发环境的框架、服务,并且附带一个标准的插件集,包括Java开发工具(Java Development Kit)。
    Eclipse的目标不仅仅为提供一个IDE,它还包括了插件开发环境(Plug-in Development Environment,PDE),该环境使得开发人员可以根据所需添加新插件,使得Eclipse不断扩充越来越强大。整个Eclipse体系结构像一个拼图,可添加插件,还可以在已有插件上再添加插件,所以Eclipse的架构基本上是“内核+核心插件+定制插件”。
    如图2-1所示,其中,Platform Runtime(平台运行库)是 Eclipse 平台核心,它是一个微内核,负责管理插件注册表和插件,其他所有的功能如 WorkSpace(工作空间)和 WorkBench(工作台)等都是以插件的形式提供。工作空间是负责管理用户资源的插件。工作台是提供用户界面的插件。SWT(Standard Widget Toolkit,标准小窗口工具箱)是Eclipse 平台自己开发的图形API包,作用和Java的AWT/Swing GUI API 一样,用来构建图形界面。

    2.1.2 Java体系Java根据应用范围可以分为三个体系:Java SE、JavaEE、Java ME。
    Java SE(J2SE,Java2 Platform Standard Edition,标准版)主要用于桌面应用软件的编程;JavaEE(J2EE,Java 2 Platform, Enterprise Edition,企业版)主要用于开发分布式的网络程序,例如电子商务网站和ERP系统;Java ME(J2ME,Java 2 Platform Micro Edition,微型版)主要用于嵌入式系统开发,例如手机和PDA的编程。
    工作原理Java由四方面组成:Java编程语言,即语法;Java文件格式,即各种文件夹、文件的后缀;Java虚拟机(JVM),即处理*.class文件的解释器和Java应用程序接口(Java API)。当编辑运行一个Java程序时,需要同时涉及这四个组成。

    使用文字编辑软件(例如记事本、写字板、UltraEdit等)或集成开发环境(Eclipse、MyEclipse等)在Java源文件中定义不同的类,通过调用类(这些类实现了Java API)中的方法来访问资源系统,把源文件编译生成一种二进制中间码,存储在class文件中,然后再通过运行与操作系统平台环境相对应的Java虚拟机来运行class文件,执行编译产生的字节码,调用class文件中实现的方法来满足程序的Java API调用。
    特性
    第一,Java语言是简单的。一方面,语法与C语言和C++语言接近,易学习易使用。另一方面,Java丢弃了C++中很少使用的、不易理解的特性。 Java语言中不使用指针使用引用并且提供了自动的垃圾回收机制,这使得程序员不必为内存管理而担忧
    第二,Java是面向对象的语言。Java提供类、接口和集成等原语,并只支持类之间的单继承,但支持接口之间的多继承,支持类与接口之间的实现机制(关键字 implements)。Java语言还全面支持动态绑定。Java程序使用类(class)来组织的,另外它还包括一个类的扩展集合,分别组成各种程序包(Package),用户可以在自己的程序中使用。例如,Java提供产生图形用户接口部件的类(java.awt包),这里awt是抽象窗口工具集(abstract windowing toolkit)的缩写,处理输入输出的类(java.io包)和支持网络功能的类(java.net包)
    第三,Java语言是分布式的。Java设计成支持在网络上应用,它是分布式语言。Java既支持各种层次的网络连接,又以Socket类支持可靠的流(stream)网络连接,所以用户可以产生分布式的客户机和服务器。
    第四,Java语言具有健壮性和安全性。Java允许扩展编译时检查潜在类型不匹配问题,不支持隐式声明,不支持指针。它的强类型机制、异常处理以及垃圾回收机制保证了Java程序的健壮性。并且Java还提供了Null指针检测、数组边界检测、异常出口、Byte code校验等功能。Java通常被用在网络环境中,具有许多安全特性。
    第五,Java语言具有多线程性。Java的lang包提供一个Thread类,而线程必须由Thread类或其子(孙)类来创建。通常使用以下俩种方法创建线程:其一,使用Thread(Runnable)的构造将一个实现了Runnable接口的对象包装成一个线程。其二,从Thread类派生出子类并重写run方法。Java语言支持多个线程同时执行,并提供多线程之间的同步机制(关键字synchronized)。
    第六,Java语言是可解释的。C、C++语言都是针对CPU芯片进行编译,生成机器代码。而Java程序在Java平台上被编译为字节码格式的“中间代码”,可以在有Java虚拟机(JVM)的人和系统上被解释执行
    第七,Java语言是动态的。Java语言的设计目标之一是适应于动态变化的环境。Java程序需要的类能够动态地被载入到运行环境,也可以通过网络来载入所需要的类。这也有利于软件的升级。另外,Java中的类有一个运行时刻的表示,能进行运行时刻的类型检查

    2.2 相关技术简介本次项目开发基于成熟的Java语言,开发环境是Eclipse。Eclipse是一个开放源代码的软件开发项目,专注于为高度集成的工具开发提供一个全功能的、具有商业品质的工业平台,它使用简单,且占用电脑资源也比较少,便于系统的学习Java。Java语言具有良好的特性,是一种应用广泛的面向对象的程序设计语言。
    2.2.1 Eclipse的图形界面开发Eclipse拥有漂亮的开发界面,基于标准部件库(Standard Widget Toolkit,SWT)开发。SWT是基于Java环境下的新类库,它提供了Java环境下的图形编程接口,SWT中的图形库和工具包取代了AWT和Swing。SWT直接调用操作系统的图形库,这使得Java程序的运行速度得到了保证,但是SWT的缺点是支持的平台太少。Eclipse也可以开发基于Swing的程序。
    2.2.2 Java技术在游戏开发中的应用图形用户界面(Graphical User Interface,GUI)图形用户界面(Graphical User Interface,GUI)与早期命令行界面相比,在视觉上对于用户来说更易于接受。但是,通过在显示屏的特定位置,以各种美观而不单调的视觉消息提示用户状态的改变,势必得比简单的消息呈现花上更多的计算能力。
    在Java语言中,所有的组件都以类的形式给出,AWT组件放在java.awt包中,Swing组件放在java.swing包中。如图2-3所示,java.awt包中控件类的体系结构。

    Java.awt是Java内置的包,属于Java基本库(JFC)一部分,要使用到该包中的类,必须显式声明import java.awt.*。Component是所有组件的父类,Component类或之类创建的对象叫组件。Button、Scrollbar、Canvas、List、Checkbox、TextField、TextArea、Label是包java.awt中的类,并且是包中Component的子类。容器也是组件,可以嵌套。上图中,Applet不是java.awt中的类。
    Javax.swing包包含了一系列Swing控件,如果要使用该包中的类,则必须显式声明import javax.swing.*。Javax.swing包中类有:Japplet、JFrame、JDialog、Jcomponent。Swing组件类的设计原理建立在MVC(Model-view-Controller)结构基础上。MVC模式由图2-4所示。

    抽象窗口工具包(Abstract Window Toolkit,AWT)是SUN专门针对Java GUI编程提供的最早的也是最初的开发工具包,用来建立和设置Java图形用户界面,这个工具包提供了一套与本地图形界面交互的接口。AWT使用的技术是对等设计模式即(AWT 中的图形函数与操作系统所提供的图形函数之间有着一一对应的关系)。所以它建立图形用户界面时,是利用操作系统所提供的图形库,这使得不同操作系统上显示不同的界面,因此AWT组件集遵循最大公约数原则,即AWT只拥有所有平台上都存在的组件的交集。AWT具有两面性,不被Sun推荐使用,只是为了确保向下兼容和支持Swing。
    Swing是在AWT的基础上构建的图形界面系统,它最初是为解决AWT不能满足用户需求的发展。Swing提供了AWT能提供的所有功能,并且用纯粹的Java代码对AWT的功能进行了扩充。Swing遵从组件按照某种布局摆放在容器里的原理。当界面完成之后,必须能进行事件处理,AWT和Swing之间的事件处理基本是一致的。Swing组件是用Java实现的轻量级( light-weight)组件,没有本地代码,不依赖操作系统的支持,这是它与AWT组件的最大区别。Swing采用了一种MVC的设计范式,即“模型-视图-控制”。 Swing构建界面包括以下几个步骤:导入Swing包;选择界面风格;设置顶层容器;设置按钮和标签;将组件放到容器上;为组件增加边框;处理事件;辅助技术支持。Swing组件的层次结构图如图2-5所示。

    SWT是Standard Widget Toolkit的缩写,是IBM为尝试解决AWT和Swing带来的诸多问题而构建的一个开源的GUI编程框架,它提供了比AWT更为丰富的组件集。与 AWT 的概念相比,SWT 是一个低级的 GUI 工具包,在构建SWT的过程中,构建者从 AWT 和 Swing 实现中学习了很多经验,他们试图构建一个集二者优点于一体而没有二者的缺点的系统。因此SWT可以说是AWT与swing的融合体。
    绘图技术由Sun公司与Adobe系统公司合作推出的Java 2D API,提供了一个功能强大而且非常灵活的二维图形框架。Java 2D API扩展了java.awt包中定义的Graphics类和Image类,提供了高性能的二维图形、图像和文字,同时又维持了对现有AWT应用的兼容。
    Java 2D API是JFC(Java Fundation Classes)的一员,加强了传统AWT的描绘功能。在 JDK1.2中已经支援 Java 2D 的使用。透过Java 2D API ,程序员可以轻松地描绘出任意的几何图形、运用不同的填色效果、对图形做旋转( rotate)、缩放( scale)、扭曲( shear)等。
    Applet程序中所采用的AWT的绘图机制主要涉及三个方法:paint()方法、update()方法和repaint()方法,update()方法和paint()方法都有一个Graphics类参数。Graphics是画图的关键,它可以支持两种绘图:一种是基本的绘图,如:画线、矩形、圆等;另一种是画图像,主要用于动画制作。处理图形则包括两个步骤:创建Graphics对象和使用Graphics对象绘制线条和形状、呈现文本或显示与操作图像。
    Graphics中提供的图形绘制方法有:

    paint( ):进行绘图的具体操作,必须有程序员重写,系统自动调用
    update( ):用于更新图形,先清除背景、前景,再调用paint();因为update()方法和paint()方法所传递的参数是Graphics类的对象,所以通常用于在动画程序中通过重载进行绘画
    repaint( ):用于重绘图形,在组件外形发生变化,即大小改变或位置移动repaint( )方法立即被系统自动调用,而实际上repaint()方法是自动调用update()方法

    事件处理机制除了友好的图形用户界面,流畅的人机交互也是必不可少的要素。在游戏过程中,正确且及时的对用户操作做出响应会给用户带来很好的游戏体验。所以说,游戏开发中的交互与其他技术有着相同的地位,是一个游戏必备的核心。Java的事件处理机制能够提供良好的交互。
    Java的事件处理机制中,有以下几个概念:

    事件Event:一个状态的改变或者一个活动的发生。Java中的事件主要有两种:组件类事件、动作类事件
    事件源Event Source:产生事件的对象
    事件监听器Event Listener:监听事件源的对象,包含事件处理器,并负责检查事件是否发生,若发生就激活事件处理器进行处理的类叫做事件监听器类。其实例就是事件监听器对象。事件监听器类必须实现事件监听器接口或继承事件监听器适配器类。事件源通过调用相应的方法将某个对象作为自己的监听器。在事件发生时,事件源负责给予通知的一种对象。接收到事件通知的监听器进行处理。事件监听器接口和事件监听器适配器类也都包含在java.awt.event和javax.swing.event包中
    事件处理器Event Handler:事件处理方法,接收事件并处理事件的方法。事件处理器包含在一个类中,这个类的对象负责检查事件是否发生,若发生就激活事件处理器进行处理

    事件处理机制图详见图2-6。当事情发生时,由事件源委托给事件监听器进行处理,继而执行事件处理代码,产生执行效果。

    多线程的应用在Java中,线程有两个指代含义:其一是指java.lang.Thread类的一个实例;其二是指线程的执行。如图2-7所示,Java线程有五种基本状态:新建状态(New)、就绪状态(Runnable)、运行状态(Running)、阻塞状态(Blocked)和死亡状态(Dead)。

    在Java中,线程的创建常见的有以下三种形式。

    第一种,继承Thread类,重写该类的run()方法。其中,run()方法的方法体也称之为线程执行体,是线程需要完成的任务。当创建此线程类对象时会创建一个新的线程,并且使得线程进入新建状态。通过调用线程对象引用的start()方法,使得该线程进入到就绪状态,此时此线程并不一定会马上得以执行,这取决于CPU调度时机
    第二种,实现Runnable接口,并重写该接口的run()方法,该run()方法同样是线程执行体,创建Runnable实现类的实例,并以此实例作为Thread类的target来创建Thread对象,该Thread对象才是真正的线程对象
    第三种,使用Callable和Future接口创建线程。具体是创建Callable接口的实现类,并实现clall()方法。并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建线程

    对于线程的启动而言,三种方法都是调用线程对象的start()方法,需要特别注意的是:不能对同一线程对象两次调用start()方法。在Java中,一旦创建一个新的线程,就产生一个新的调用栈,每个线程都有一个调用栈,即使不在程序中创建任何新的线程,线程也在后台运行着。一个Java应用总是从main()方法开始运行,mian()方法运行在一个线程内,它被称为主线程。
    JDK1.6之后增加了线程池的概念,使用线程池对线程的操作性能更优于传统的线程操作,线程操作更加灵活、安全。
    2.3 本章小结本章主要介绍了Eclipse和Java的相关内容和本次项目涉及到的相关技术,通过对比GUI三种工作集:AWT、SWT、Swing,加深对图形用户界面开发的理解和对于AWT、Swing组件层次结构的掌握。通过学习总结Java的事件处理机制的概念和过程,为项目的设计和实现打下理论基础。
    3. 需求分析软件需求分析就是通过调查研究和有效的沟通以及建立系统的数据模型、功能模型和行为模型,使用户和开发人员就“系统必须做什么”这个问题达成一致意见,最后生成软件需求规格说明的过程。软件需求分析的过程就是对用户或企业意图不断揭示的过程,需要对系统进行可行性研究之后,对系统目标做出分为详细的描述。
    3.1 可行性分析可行性研究的结果是清楚的回答:该系统是否值得开发。
    下面将分别从技术、经济、社会、操作四个方面对基于Java的连连看游戏的设计与实现进行可行性分析和研究。
    3.1.1 技术可行性技术可行性分析一般可以理解为项目开发涉及到的技术、环境是否符合开发标准,能够达到预期效果;它是项目成功运行的一个必不可少的条件;因此,对技术可行性分析需要进行全面化的评估。
    本次连连看游戏采用的开发工具是功能强大的Eclipse,它具有十分强大的可扩展功能,只要下载安装所需要的相关插件,就能支持我们用纯Java实现此次的桌面游戏程序。使用Eclipse开发应用程序可按需下载插件,不过分依赖于硬件,不论是升级产品方面还是扩展功能方面都有很好的发挥空间。
    本次项目使用Java的GUI开发技术。Java本身可提供类库,完善的类库和AWT包对桌面游戏开发提供了强大完整的技术支持,完全可以满足我们连连看小游戏的开发,在开发过程中,可以创建满足本次开发项目任务的直接的、简明的图形用户界面。
    Eclipse在开发Java项目方面应用多而广,是一个成熟可行的开发平台。Java语言也是成熟的开发语言,能够满足此次要求。在开发方面,无论是开发平台,还是开发语言,对于开发人员来说都是熟悉且能易掌握的。在从硬件方面来看,时下的硬件容量不断扩大,可靠性日益渐涨,性价比越来越高,对于本项目开发而言,足够满足需求。
    由以上分析可知,本软件在技术上是可行的。
    3.1.2 经济可行性经济可行性是指对项目的成本和收益进行分析,具体内容包括两个部分:新系统所能带来的经济效益和该经济效益是否超过系统开发和系统维护所需要的费用。
    对于本项目而言,在系统开发和系统维护方面的开销很小,没有过多的硬件投入,调试方便,开发过程中,Eclipse是开源免费的,本游戏在此开发环境下,不需要太复杂的工具和服务器支持,在完成过程中,也仅需要一台个人电脑以及在完成过程中上网查询所用到的人力资源以及文献资源。
    综上所述,本项目在经济上是可行的。
    3.1.3 社会可行性社会可行性广义上可分为三大部分:道德方面、法律方面、社会方面。接下来将就这几个方面,对此次项目进行分析。
    从道德方面来看,本次开发无论从过程中还是最终完成的产品上看均不涉及传播低级黄色内容、社会负能量。本次开发目的主要是借毕业设计巩固所学专业知识,一切皆以个人为单位,不涉及广泛传播及使用,对社会基本不造成任何不良影响。
    从法律方面来讲,本次开发过程和最终产品因开发目的不涉及版权、社会安全等法律问题。在开发过程中,参考的所有文献会列明,尊重知识产权,尊重专利版权,不会将产品投入社会使用。
    从社会方面来谈,本次开发是对已有成果的一次学习和开发体验,虽不能带来很大的社会价值,但不同程度上实现了开发者个人价值。因不涉及产品推广,所以不涉及产品带来的社会经济效益和社会影响力。
    由以上分析可知,本软件具有社会可行性。
    3.1.4 操作可行性操作可行性主要分析系统操作难度问题。本游戏界面以窗口形式给出,可视化强,整体风格简洁大气,各个功能键布局合理使得游戏功能一目了然。整个游戏过程操作简单易上手,完全依靠鼠标点击操作,在简单说明或培训下,操作上基本没有难度。
    综上所述,本游戏具有技术可行性、经济可行性、操作可行性和社会可行性值得开发。
    3.2 连连看游戏需求描述及规则描述游戏规则是模仿网络上普通的连连看游戏,即解决鼠标两次点击的图片能否消去的问题。当然,前提是点击两张相同的图片,若点击的是同一张图片或者两张不同的图片,则不予以处理。在两张相同图片所能连通的所有路径中,如果存在一条转弯点不多于两个的路径,就可以消去;如果没有,则不予以处理。
    开始制作游戏时,主要需要解决的问题有以下几个方面:第一,如何设置整个游戏的界面。第二,如何控制连连看游戏中随机图片的生成且每种图片生成个数必须为偶数。第三,游戏开始后,需要判断鼠标两次点击的图片能否消去,即判断图片是否相同且片之间路径是否满足判断要求等。第四,如何实现游戏计时功能、刷新功能、重新开始新一局游戏功能。第五,相关游戏情况展示。
    游戏往往会涉及游戏胜利或失败条件。对于连连看游戏来说,胜利条件是在规定时间内将游戏界面上所有图片全部依照一定规则消除掉。失败条件则相反,指未能或无法在规定时间内将棋盘上面的图片全部消除掉。
    3.3 系统需求分析软件需求分为四个层次,分别是:业务需求、用户需求、功能需求和非功能需求。 
    业务需求主要反映了组织结构或客户对系统、产品高层次的目标要求,通常在项目定义与范围文档中予以说明;用户需求描述了用户使用产品必须要完成的任务,这在实例或方案脚本中予以说明;功能需求定义了开发人员必须实现的软件功能,使用户利用系统能够完成他们的任务,从而满足业务需求;非功能性的需求描述了系统展现给用户的行为和执行的操作等,它包括产品必须遵从的标准、规范和约束,操作界面的具体细节和构造上的限制。
    3.3.1 业务需求业务需求针对的是项目组或者公司,描述是公司想如何解决用户的问题,如何满足用户的欲望,并将利益最大化。
    本项目课题是连连看游戏的设计与实现,在业务需求方面,第一,具备连连看基本游戏功能。选择两个图形,判断是否满足一定条件,条件即两个图形一致且二者之间存在转弯少于3的路径。当判定满足这一条件后,两张图片被消除。第二,具备附加功能:计时功能、重新开始功能、刷新当前界面功能等。
    3.3.2 用户需求本项目面向的用户是游戏玩家,对于用户而言,需求有两个方面,一方面,要求游戏界面整齐美观,长时间使用也应尽可能的减小对游戏的审美疲劳。另一方面,要求游戏体验良好。在运行游戏的过程中,能保证数据安全,游戏能稳定、高速地运行。对于游戏本身,用户往往要求游戏功能相对完善,游戏具备可娱乐性,并且游戏规则易理解,游戏操作既要简单同时也应有难度,在保证游戏操作顺滑、响应快速的情况下,游戏能具有一定的挑战性。
    通过用例图能更清晰的分析用户需求,如图3-1连连看游戏的用例图。用户在连连看游戏中,能开始游戏、重新开始游戏、重排列游戏、结束游戏、退出游戏、消除图片、查看得分和闯关数等。

    以“重排列游戏”用例为例,其活动图如下图3-2所示。

    3.3.3 功能需求根据上文游戏规则描述以及需求描述,游戏规则是模仿网络上普通的连连看游戏,主要需求是解决鼠标两次点击的图片能否消去的问题。当然,前提是点击两张相同的图片,若点击的是同一张图片或者两张不同的图片,则不予以处理。在两张相同图片所能连通的所有路径中,如果存在一条转弯点不多于两个的路径,就可以消去;如果没有,则不予以处理。这也是游戏的基本功能,给定任意具有相同图形的两个格子,我们需要寻找这两个格子之间在转弯最少的情况下,经过格子数目最少的路径。如果这个最优路径的转弯数目少于3 ,则这两个格子可以消去。
    根据难度的不同该游戏由4、8、12、15种不同的图片组成,游戏开始将会出现64张随机组合的图片,在规则下点击两张相同的图片后,图片将会消失。图片全部消完为游戏成功,将进入下一关。游戏还将设置刷新功能,重新开始功能的按钮,并实现该功能,方便用户进行操作。游戏的主要功能将通过程序中的线程、布局功能、事件监听进行有效实现。
    本系统将划分为以下几个模块,如图3-3系统功能模块图。将连连看游戏按照功能划分为:

    消除模块:完成连连看游戏消除动作的模块
    重新开始模块:完成连连看游戏中重新开始新一局游戏功能的模块
    刷新模块:完成连连看游戏中,将游戏中未消除的图片个数记录并重新随机放置等数量图片的功能模块
    选择难度模块:完成游戏中切换游戏难度并开始新一局游戏的模块
    计时模块:完成游戏中倒计时并显示提示信息的模块
    状态显示模块:完成游戏中对游戏得分、闯关数记录的模块


    为更好的实现该游戏,结合系统流程图可进一步将上述功能细化如下:

    第一,图片的选择:选中的图片应该区别于其他图片
    第二,图片的排列:在开始新一局的游戏时,图片的排列要清晰,满足随机的同时,要保证成对出现
    第三,记分功能:在游戏界面上要有明确标识,直观的显示当前游戏状态,包括游戏得分情况和闯关关数情况
    第四,沙漏计时功能:沙漏状计时能将时间地流逝直观形象的表达,增加游戏难度的同时很好地刺激了游戏玩家的胜负欲
    第五,游戏的开始和重新开始:在游戏开始前,应对玩家有所提示。重新开始游戏要中断当前游戏,开始一局新的游戏,同样要有所提示
    第六,游戏关闭和结束:游戏关闭和结束是两个概念,游戏关闭相当于关闭程序,游戏结束是指游戏时间到,此处应该对玩家有所提示,游戏结束后游戏依旧在运行,可以开始新一局游戏,也可以结束游戏
    第七,游戏难度:游戏难度不要仅仅局限于一个难度,提升难度有利于激发玩家运行游戏,提高游戏对玩家的吸引力和游戏本身的可玩性。游戏难度应可选。游戏默认开始时游戏难度应该较低。现设置游戏难度为4个等级,每个等级显示总体个数相同但不同种类的图片,难度越高,种类越多,整体界面看起来越复杂
    第八,游戏闯关: 每一个难度下可以有很多关卡,每一个关游戏过关后可以直接进入下一关,最好能实现每一关较上一关略有难度
    第九,游戏提示功能(刷新功能):在游戏过程中可以使用一次刷新功能,重新排列当前游戏未消除的图片个数的图片
    第十,游戏必要的提示:包括前面叙述的关卡数提示、得分提示、游戏开始和结束提示、倒计时提示
    第十一,游戏要最大限度地实现了易维护性和易操作性,游戏运行稳定、安全可靠

    3.3.4 非功能需求非功能需求包括产品必须遵从的标准、规范和约束,操作界面的具体细节和构造上的限制。
    首先,软件制作为了设计、实现和后期维护的方便,以及软件用户使用的便利,所以必须采取一定的设计原则。其主要设计原则有:

    简单性:这里指游戏操作简单易懂,结合上文,可以通过游戏界面实现部分要求,游戏整体要尽量操作简单易懂,这对于我们这款注重交互体验的游戏软件至关重要
    针对性:本软件设计是基于java的连连看的需求定向开发设计,所以具有专业突出和很强的针对性
    实用性:要求本软件能够满足基于java的连连看游戏的需要,因此具有良好的实用性
    一致性:界面风格及命名规则一致性(整体界面的布局、地图样式和贴图保持风格一致;变量、类名和其他元素的命名规则保持一致)具体的来说:元素风格一致性是指界面元素的美观风格、摆放位置在同一个界面和不同界面之间都应该是一致的。变量命名规则的一致性具体是指变量用英文单词及英文词组进行命名,做到任意变量均能从上下文推断其义

    其次,游戏界面的具体细节也不可忽略。游戏一经推出,能否第一时间被喜欢、被欢迎,除了游戏本身操作方面的表现,更多时候取决于游戏界面的优美表现。时下,大型网络游戏、flash网页游戏、桌面小游戏,款式多、样式多,不乏有一些亮眼表现的好游戏、经典游戏。玩家在审美疲劳的同时练就了一双苛刻的眼力,对游戏界面的要求也越来越高。
    本游戏主要针对广大游戏玩家的娱乐时间,在结束一段紧张的工作学习时间之后,通过玩游戏放松心情。结合连连游戏一般以图片形式给出,本次游戏界面也将采用图形用户界面设计准则。
    在游戏界面中,将通过一个二维界面采用图片的形式给出一些可点击可选择的方块,在选中图片后应该能明显区分。整体布局合理,用户使用应以方便、灵活、快捷、准确为准。
    游戏界面总体风格要简洁明了,对各个功能按钮、功能部件一目了然,通过简单的图片和组件,直观的“摆出”游戏规则和使用方法。方便游戏玩家接受和掌握游戏方法,达到舒缓压力的基本要求。
    3.4 本章小结首先,本章对连连看游戏项目从技术、经济、社会三个方面进行可行性研究,研究证明项目可行。其次,从业务需求、用户需求、功能需求和非功能需求四个层次借助用例图和活动图描述了连连看游戏系统的需求。
    4. 概要设计概要设计的主要任务是把需求分析得到的系统扩展用例图转换为软件结构和数据结构。设计软件结构的具体任务是:将一个复杂系统按功能进行模块划分、建立模块的层次结构及调用关系、确定模块间的接口及人机界面等。数据结构设计包括数据特征的描述、确定数据的结构特性、以及数据库的设计。显然,概要设计建立的是目标系统的逻辑模型,与计算机无关。
    4.1 模块设计由于Swing组件类的设计原理建立在MVC(Model-View-Controller)结构基础上,MVC是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。所以根据此架构模式划分连连看游戏总体结构,设计各模块概要内容,进而划分出此次项目中的类,绘制类图。
    4.1.1 连连看系统总体结构此次设计连连看的主体构成为连连看图片以及一些功能键。从界面布局来看,面板的右面有重新开始、刷新按钮,难度选择选项卡(4种难度),得分、关卡状态显示栏,以及沙漏状的时间倒计时装置。面板左面是一块主要操作区域,用来显示待消除的图片排列情况。本连连看系统应该包括以下两大结构:游戏界面模块;处理模块。游戏界面模块下分两个模块:功能键模块和操作模块。如图4-1:

    图4-1所示的游戏模块图中,连连看游戏系统主要分成两个部分。第一部分是显示部分即游戏界面模块,该模块根据布局又分为功能键模块和操作间模块。第二部分是处理部分即处理模块,在该模块中,需要完成需求分析中的用户需求和功能需求。
    4.1.3 游戏界面模块游戏界面模块根据布局细分为操作模块和功能键模块。

    操作模块:在游戏过程中,需要使用鼠标与游戏系统交互的主要模块。模块主要有排列的JButton构成,每个JButton上显示图片。所有JButton随机出现,且成对出现。借按钮组件及其事件处理机制,模拟游戏中选中图片并消除。当点击按钮组件时,这个外界刺激会触发事件监听器,事件监听器会接收事件并作出处理,就有了对这一操作的响应
    功能键模块:在游戏过程中,需要使用鼠标与游戏系统交互的次要模块。模块主要有JButton组件、下拉列表、JLabel等组件,构成完成游戏功能的控制部分,在此布局内,除了使用这些组件外,还要绘制一个沙漏状的动画,用以实现倒计时功能。同样,在此模块中所有组件除沙漏,均需要用鼠标操作,每个组件都应该有对应的响应事件和事件监听器

    为更好的区分开显示和实现,游戏界面模块将以布局为主要内容,具体的处理和响应将划分到处理模块。
    4.1.4 处理模块针对游戏的主要功能划分出一个模块:处理模块。这个模块中将实现一些功能,包括操作功能、计时功能、提示功能等。现将设计一下几个模块:

    图像处理模块:程序运行后,这个模块将把资源文件中提供的图片进行排列。这个模块在初始化游戏布局和重新开始游戏以及刷新游戏时会用到
    响应模块:响应模块分两大类,一类是对操作模块中JButton的响应(即消除功能),一类是对功能键模块中各个组件的响应(每个响应都实现其对应功能)
    更改提示模块:这个模块主要负责记分、记录关数
    倒计时模块:倒计时模块是对沙漏动画的绘制,并在倒计时五秒处显示提示JLable,在倒计时结束后弹出提示框
    消除模块:判断选中的两个图片是否满足被消除的条件,此模块中,将实现判断

    4.2 确定类在图形用户界面GUI设计中,会使用到javax.swing中的JButton、JDialog、JFrame 、JLabel、JPanel等组件。将这些组件放在JFrame容器中,构成LianLianKan类继承于JFrame类。如图4-2所示。在LianLianKan类中声明内部类LianLianKanJPanel类,继承于JPanel类。如图4-3所示,在LianLianKanJPanel类中声明了若干JButton、Choice、ImageIcon类对象。
    连连看类图

    LianLianKanJPanel类图

    在LianLianKanJPanel类中再声明一个内部类loudou类。loudou类同样继承于JPanel类,在该类中创建Thread类、JLabel、JDialog类对象,漏斗形状的绘制通过调用paintComponent(Graphics g)方法完成。loudou类图如图4-4所示。Thread类图如图4-5所示。
    loudou类图

    Thread类图

    4.3 游戏素材本课题游戏显示将采用图片连连看的模式,界面要满足需求分析中提出的简洁明了、友好大方,保证数据存储安全可靠。游戏素材则包括两类图片,一类是背景图片,一类是游戏操作模块中显示用的游戏图片。
    4.3.1 背景图片在背景图片的选择中,考虑到游戏界面的简洁性,选定采用纯色背景图片。为了更加清晰的衬托出游戏图片以及功能键模块中的组件,选定纯黑色游戏背景图片,此处选择图片是为了方便以后便利地更换背景图片或者扩充其他游戏设置功能等。背景图片见图4-6。

    4.3.2 游戏图片前文提到,根据游戏难度的不同将选择显示不同种类的图片,现将按照难度区分,依次展示简单模式、中等模式、困难模式和变态模式下游戏界面将出现的游戏图片素材。除简单模式,每一难度模式将新增几种图片并包含上一难度模式下的图片种类。
    简单模式下将出现四种简单的游戏图片,是四种颜色不同的球体,详见图4-7。

    中等模式下将包括八种图片,图4-8将展示新增图片。

    困难模式将包括十二种图片,图4-9将显示新增四种图片。

    变态模式将包括十五种图片,图4-10将展示新增的三种图片。

    4.4 本章小结本章划分了连连看游戏总体结构。游戏界面方面确定了游戏界面中的素材和风格。处理模块下根据其功能,设计并描述了各个小模块的概要内容,进而划分出此次项目中的类,绘制了类图。
    5. 详细设计和实现详细设计是在概要设计的基础上进行细化的过程。详细设计的主要任务是设计每个模块的实现算法即实现游戏界面、组件的事件处理等。在详细设计阶段,除了要注意具体模块的功能分解,还要绘制活动图、状态图、顺序图等动态模型,丰富静态结构图。
    5.1 界面设计游戏主界面以窗口形式给出,用户操作的游戏功能部分由各个组件构成,通过弹出的提示框开始游戏活动,用户通过点击窗口上的各个组件完成操作。游戏界面设计如下图5-1所示。

    5.1.1 界面实现在游戏运行开始时,将弹出一个提示框以提示用户即将开始游戏,提示框如图5-2。此处弹出提示框一方面是提示作用,一方面是为便利扩展游戏功能,可将游戏扩展成多用户模式,在提示框实现处更改为用户登录模块,并联接数据库。鉴于本次任务时间有限此处未能实现。

    部分代码如下:
    if (remainTimes == 0) { JOptionPane.showMessageDialog(null, "游戏开始?");
    单击确定按钮进入游戏主界面,默认进入简单模式下的游戏主界面,如图5-3。

    如上图所示,游戏主界面展示了本次连连看小游戏的主体布局界面。在界面的左侧是游戏主要操作和显示被操作图片的区域,界面的右侧展示了功能模块中几个功能组件。界面的右侧由上至下展示了“重新开始”按钮、“刷新”按钮、难度模式选择列表(默认是简单模式)、两个标签文本、一个沙漏状的倒计时动画(包括一个隐形的标签文本,当时间还剩五秒的时候,会显示倒计时信息)。
    不同难度的游戏模式下,主要游戏界面展示略有不同,四种难度模式下的游戏界面图如图5-3、5-4、5-5、5-6。
    中等模式下的游戏界面图

    困难模式下的游戏界面图

    变态模式下的游戏界面图

    如上图所示,对游戏主界面没有任何操作时,四种难度模式下的游戏主界面最大的区别就是操作模块部分的图片排列,可以看出,难度越大图片种类越多,看起来越复杂,实现了前文对于难度变化提到的要求。每一种困难模式下的图片均是成对出现的,满足前文对于图片排列的要求。
    整体界面以黑色为主,简洁大方,整体布局合理工整。左侧图片素材清晰、可爱,图片素材之间留有空隙,视觉上更舒服更易于区分,右侧功能键排列整齐,文字描述清晰。
    布局部分核心代码如下:
    Random random = new Random();int temp = 0;for (int i = 0; i < 32 - Kinds; i++) { temp = random.nextInt(Kinds) + 1; numbers.add(temp); numbers.add(temp);}for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { BlockButton[i][j] = new JButton(); add(BlockButton[i][j]); BlockButton[i][j].addActionListener(this); BlockButton[i][j].setBounds(30 + j * 40, 30 + i * 40, 31,34); }}
    5.1.2 倒计时沙漏的设计在游戏的界面上,还有一个特殊的面板,漏斗面板,漏斗面板上绘制了一个沙漏状的倒计时装置,该装置通过线程控制,时间变量每更新一次,漏斗面上重新绘制一次,每次绘制的线条通过判断条件设置摆放位置,随着时间的递增,沙漏状的倒计时装置就动态的开始倒计时,直至最后五秒,显示提示信息,倒计时结束后,弹出游戏失败提示框。沙漏示意图如下图5-7。

    此处沙漏使用Graphics类的paintComponet()方法,游戏开始自动调用,在线程中,当剩余时间参数改变时调用repaint(),重载paintComponet(),通过判断剩余时间,绘制线条,这样随着每一秒时间的流逝,上方的绿色线条会在视觉上像是流动到下方。当属于时间不足5秒时,JLabel显示提示信息。部分代码如下:
    super.paintComponent(g);g.setColor(Color.green);for (int i = 0; i < 56; i++) { g.drawLine(x1 + i / 2 + 2, y1 + i, x2 - i / 2 - 2, y1 + i);}if (remainTimes < 55) { for (int i = 0; i < remainTimes; i++) { g.drawLine(x1+i/2+2, y2-i-1,x2-i/2-2, y2-i-1); } g.drawLine((x1 + x2) / 2, (y1 + y2) / 2, (x1 + x2) / 2, y2 - 2); g.drawLine((x1+x2)/2+1, (y1+y2)/2+1, (x1+x2)/2+1, y2-2); g.setColor(getBackground()); for (int i = 0; i < remainTimes; i++) { g.drawLine(x1 + i / 2 + 2, y1 + i, x2 - i / 2 - 2, y1 + i); }}if (remainTimes >= 50 && remainTimes <= 55) overJLabel.setText((55-remainTimes) + "second"); if (remainTimes == 56) overJLabel.setText("OVER"); remainTimes++;repaint();
    倒计时结束时,意味着在规定时间内未完成游戏,判定游戏失败,此时应该有提示框,如图5-8。

    部分代码如下:
    if (remainTimes == 56) { JOptionPane.showMessageDialog(null, "时间到!游戏结束!");}
    5.2 游戏执行的实现因为每一次选择难度模式后、每通过一关游戏后都将开始一局新游戏,故一次游戏活动图如图5-9所示。最终状态有两种,游戏失败和游戏结束。

    一次游戏活动的顺序图如图5-10所示,一次游戏过程中,“点击图片”、“点击‘重新开始’按钮”、“点击‘刷新’按钮”操作上可不分时间先后顺序。每一次游戏结束后可以开始新一局游戏直至用户退出游戏。

    5.2.1 点击图片的实现及其部分代码前文提到,每选中一个图片应该区别于其他未被选中的图片。具体实现方式:当点击第一图片时,图片会变成激活状态,颜色变暗(用到了JButton的SetEnable方法)。当点击第二张图片时如果符合游戏规则,则两张图片消除,否则第一张图片变回默认状态,第二张图片变为激活状态;按钮状态图如图5-11所示,系统截图如图5-12。
    按钮状态图

    系统截图

    此功能实现代码:
    BlockButton[j][i].setEnabled(false);
    5.2.2 记分、记关数的实现在游戏过程中,需要对游戏当前状态进行记录,一次得分记录的过程活动图如图5-13,记录实例系统截图如下图5-14。
    记录活动图

    系统截图

    游戏过程中,每消除一对相同图片,得分10,8×8格式的二维图片集,一共64张图片,共计32对,所以没过一关得分是320分,图5-9显示的是,消除34对后的得分。在每一难度下的每一关通过后,记分不清0,继续记分。但切换到不同难度时,得分会清0。
    5.2.3 刷新功能的实现游戏中每一关只有一次使用刷新功能的机会,此功能键触发的响应事件,会调用chongzai()方法,按照当前状态未消除的图片个数重新在二维按钮排列的其他位置排放其他图片。点“刷新”按钮的流程图如图5-15所示,前后变化如下图5-16、5-17所示。
    “刷新”流程图

    刷新前系统截图

    刷新后系统截图

    刷新功能一关游戏只能使用一次,不论是那一个难度下,一关内刷新功能只能使用一次,只有通过这一关,下一关中刷新功能才能使用。使用一次之后,按钮将不能点击,状态图如图5-18,系统截图如下图5-19所示。
    刷新按钮状态图

    点击一次之后系统截图

    刷新功能部分代码如下:
    if (e.getSource() == reLoad) { chongzai();reLoad.setEnabled(false);
    chongzai()中部分代码如下:
    for (int i = 0; i < jishushengyu / 2; i++) { kind = random.nextInt(Kinds) + 1; do { randomx1 = random.nextInt(8);//0-8随机数 randomy1 = random.nextInt(8); } while (map[randomy1][randomx1] > 0); map[randomy1][randomx1] = kind; do { randomx = random.nextInt(8); randomy = random.nextInt(8); } while (map[randomy][randomx] > 0); map[randomy][randomx] = kind;}
    5.2.4 重新开始游戏功能的实现重新开始游戏功能实际也是开始新游戏功能,重新开始布局的过程。将图片成对的显示在场景中,并打乱调用的是newMap()方法。在该方法中,用了一个数组以数字标记的形式来记录加载的图片是哪种图片,在每次加载图片的时候是一张图片连续加载两次,以保证加载图片成对。然后用数组的随机方法将数组打乱。
    5.3 游戏的连接算法连连看游戏中对于用户来说最简单的呈现,就是单击两个连在一起的相同的图像时,这两个图像就会消去,但是在Java代码中是如何实现的呢?连连看游戏的联通算法一般包括回溯法和堆栈实现的迷宫算法。
    根据游戏规则能知道,即使不是紧邻的两个相同的图像块消去时也不能超过两次转弯。在本次开发的连连看中两个图像块可以消去的情况大致可以分为以下几种情况。
    5.3.1 连连看连接方式的类型连连看游戏的连接方式就是指两个图片之间连接的方式,一共可以分为以下这几种方法:
    两点直线法示例如图5-20。

    三点直角折线法示例如图5-21。

    四点方形折线法示例如图5-22。

    四点方形折线法示例如图5-22。

    下面对上面四种类型进行细致划分讲解:

    两点直线法的连接类型包括:上下,左右
    三点直角折线法包括:上左,上右,下左,下右,左上,右上,左下,右下
    四点方形折线法包括:上左下,上右下,下左上,下右上,左上右,右上左,左下右,右下左
    四点梯形折线法包括:上左上,下左下,上右上,下左下,左上左,右上右,左下左,右下右

    5.3.2 连连看连接方式的分析满足上述要求是第一步,即两个图片满足上次相连方式。第二步是满足图片相同。换言之,检验两个方块能否消掉,要让两个方块同时满足两个条件才行,就是两者配对并且连线成功,此处可分三种情况。从下面的这三种情况,我们可以知道,需要三个检测,这三个检测分别检测一条直路径。这样就会有三条路径。若这三条路径上都是空按钮,那么就刚好是三种直线(两个转弯点)把两个按钮连接起来了。

    第一种情况:相邻。这种情况最简单
    第二种情况:不相邻。若不相邻,第一步在选中的第一个按钮的同行找到一个空按钮,此时分为两种情况:

    情况A:找到空按钮后,再看选中的第二个按钮的横向到这个空按钮所在的列交叉处是否有按钮,若交叉处没有按钮,再从与第一个按钮到与它同行的那个空按钮之间是否有按钮,此时也没有按钮的话,路径通,反之则否情况B:第一步在选中的第一个按钮的同行找不到一个空按钮,此时在选中的第一个按钮的同列找一个空按钮。找到空按钮后,查看选中的第二个按钮竖向到这个空按钮所在行的交叉处是否有按钮。没有按钮的话,再查看选中的第一个按钮到与它同列的那个空按钮之间是否有按钮。没按钮的话,再判断与选中的第一个按钮同列的这个空按钮横向到与选中的第二个按钮同列有否有按钮,没有的话,路径通

    若满足以上情况的分析,也即路径通,选中的两个图片可消除。若以上情况分析均不满足,说明这两个按钮不可以消去。
    具体判断流程图如图5-24。

    代码中定义的方法有:

    判断在一列之内两图片之间是否全部是空白或直接相邻
    判断在一行之内两图片之间是否全部是空白或直接相邻
    是否可以一条直线相连
    是否可以两条直线相连
    是否可以三条直线相连
    是否可以三条直线相连,似U形
    是否可以三条直线相连,似之字形N
    是否处于游戏区域的四条边的同一边上

    5.3.3 部分核心代码// 判断在一列之内两图片之间是否全部是空白或直接相邻// 直接相连,因而不包含空白if (Math.abs(posY1 - posY2) == 0) { return true;}int a = posY1 < posY2 ? posY1 : posY2;int b = posY1 < posY2 ? posY2 : posY1;for (int j = a + 1; j < b; j++) { if (map[posX1][j] != 0) { return false; }}// 是否可以一直线相连if (posX1 != posX2 && posY1 != posY2) { return false;}if (posX1 == posX2) { if (containsAllOrNoneZeroInColumn(posX1, posY1, posX2, posY2)) { return true; }}if (posY1 == posY2) { if (containsAllOrNoneZeroInRow(posX1, posY1, posX2, posY2)) { return true; }}// 是否可以三直线相连,似之字形Nif (isOnZigzagWith1Row2Cols(posX1, posY1, posX2, posY2)) { return true;}if (isOnZigzagWith2Rows1Col(posX1, posY1, posX2, posY2)) { return true;}// 是否处于游戏区域的4条边的同一边上if ((posY1 == posY2 && posY2 == 0) || (posY1 == posY2 && posY2 == 8 - 1) || (posX1 == posX2 && posX2 == 0) || (posX1 == posX2 && posX2 == 8 - 1)) { return true;} // 是否可以三直线相连,似之字形, 两行一列 Zint moreX = posX1 < posX2 ? posX2 : posX1;int lessX = posX1 < posX2 ? posX1 : posX2;for (int i = lessX + 1; i < moreX; i++) { if (containsAllOrNoneZeroInColumn(i, posY1, i, posY2) && containsAllOrNoneZeroInRow(i, posY1, posX1, posY1) && containsAllOrNoneZeroInRow(i, posY2, posX2, posY2) && map[i][posY1] == 0 && map[i][posY2] == 0) { return true; }}
    6. 系统测试软件测试是保证软件质量的一种重要手段。
    软件测试就是在正常条件与非正常条件下,分别对软件、应用程序进行操作或者设计出测试用例并执行测试用例,最后评价操作结果的过程。换言之,软件测试就是利用测试工具按照测试方案和流程对产品进行功能和性能测试,或者根据需要编写不同的测试用例,人为地设计和测试系统,对提出的测试方案中所有可能出现的问题进行分析和评估。
    软件测试过程中应该故意地去促使错误的发生,也就是事情在不该出现的时候出现或者在应该出现的时候没有出现。从本质上说,软件测试是”找错”,在”找错”中发现软件的毛病。这也揭示了软件测试的真正意义。
    6.1 软件测试目的及意义软件测试是指使用人工,或者自动的手段,来运行或测定某个软件产品系统的过程,其目的是检验是否满足规定的需求或者弄清预期的结果与实际结果之间的区别。测试包括找出破绽,但不包括跟踪错误和修正。
    当然,软件测试也存在测试误区,在测试过程中,应尽量规避以下误区:

    第一,测试并不仅仅是为了找出错误。通过分析错误产生的原因和错误的发生趋势,可以帮助项目管理者发现当前软件开发过程中的缺陷,以便及时改进;这种分析也有助于测试人员设计出有针对性的测试方法,改善测试的效率和有效性
    第二,没有发现错误的测试也是有价值的,完整的测试是评定软件质量的一种方法,应当把“尽早地和不断地进行软件测试”作为软件测试者的座右铭
    第三,完全测试是不可能的,测试需要终止,测试无法显示软件潜在的缺陷

    6.1.1 测试目的Grenford J.Myers曾对软件测试的目的提出过以下观点:

    第一,测试是为了发现程序中的错误而执行程序的过程
    第二,好的测试方案是极可能发现迄今为止尚未发现的错误的测试方案
    第三,成功的测试是发现了至今为止尚未发现的错误的测试

    软件测试的目的决定了如何去组织测试。如果测试的目的是为了尽可能多地找出错误,那么测试就应该直接针对软件比较复杂的部分或是以前出错比较多的位置。如果测试目的是为了给最终用户提供具有一定可信度的质量评价,那么测试就应该直接针对在实际应用中会经常用到的商业假设。
    在软件测试的实际应用中,我们对于系统性能方面的测试要多加重视。
    系统在上线之后会有很多不能预知的性能问题,需要在上线之前实现进行模拟,以规避风险,包括大数据量访问,高并发数等等。当然也有很多应对手段,没有哪种手段可称为最完美,只有最合适的,需要灵活掌握,综合运用以达到最优程度,这是个很值得研究的领域。
    针对连连看游戏的测试,分为两个方面,第一是游戏功能方面的测试,主要从界面布局、游戏响应两个方面进行。在游戏性能方面,从用户对本系统的满意度、易用性、稳定性着手,主要测试游戏过程的流畅程度。
    界面布局方面,首先是在初始化游戏时,游戏界面的合理布局以及游戏所用到的图片是否能按要求完全显现。游戏开始后,玩家是否能对界面中的组件进行操作,其次,在响应事件结束后,界面能否按照要求反应变化。最后,游戏的开始和结束能否合理控制。
    游戏响应方面,主要要求对用户操作组件的事件按需求正确处理,比如点击按钮时,应该怎样处理事件对象,选择游戏功能时,是否能完成游戏功能。
    6.1.2 测试意义软件测试的真正意义在于发现错误,而不在于验证软件是正确的,软件测试是发现软件中错误和缺陷的主要手段。在一般情况下,软件测试的过程与整个软件开发过程基本上是平行进行的。当然,测试计划应该在需求分析阶段就已经开始制定了。随后工作则是伴随着软件的开发过程逐步展开。由于缺陷在开发与维护的任何阶段都有可能发生,并有此产生一个或多个bug,包括错误、误解和冗余,有时候甚至会误导开发者。所以软件测试是发现并指出软件系统缺陷的过程。
    软件测试是软件开发过程中的很重要的一项内容,是用来确认一个程序的品质或性能是否符合开发之前所提出的要求的过程。它不仅是软件开发阶段的有机组成部分,而且在整个软件工程(即软件定义、设计和开发过程)中占据相当大的比重。
    6.2 测试方法分类从是否关心软件内部结构和具体实现的角度划分,可分为以下三类:

    白盒测试:白盒测试又称结构测试、透明盒测试、逻辑驱动测试或基于代码的测试。它是知道产品内部工作过程,可通过测试来检测产品内部动作是否按照规格说明书的规定正常进行,按照程序内部的结构测试程序,检测程序中的每条通路是否都有能按预定要求正确工作,而不顾它的功能,白盒测试的主要方法有逻辑驱动、基路测试等,主要用于软件验证
    黑盒测试:黑盒测试也称功能测试或数据驱动测试,它是在已知产品所应具有的功能的前提下,通过测试来检测每一个功能是否都能正常使用。在测试中,把程序看作一个不能打开的黑盒子,在完全不考虑程序内部结构和内部特性的情况下,在程序接口进行测试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数据而产生正确的输出信息。黑盒测试着眼于程序外部结构,不考虑内部逻辑结构,主要针对软件界面和软件功能进行测试。黑盒测试方法主要有等价类划分、边值分析、因果图、错误推测等,主要用于软件确认测试
    灰盒测试:灰盒测试关注输出对于输入的正确性,同时也关注内部表现,但这种关注不像白盒那样详细、完整,只是通过一些表征性的现象、事件、标志来判断内部的运行状态,有时候输出是正确的,但内部其实已经错误了,这种情况非常多,如果每次都通过白盒测试来操作,效率会很低,因此需要采取这样的一种灰盒的方法

    从是否执行程序的角度,可以划分为两类:

    静态测试:静态方法是指不运行被测程序本身,仅通过分析或检查源程序的语法、结构、过程、接口等来检查程序的正确性。对需求规格说明书、软件设计说明书、源程序做结构分析、流程图分析、符号执行来找错。静态方法通过程序静态特性的分析,找出欠缺和可疑之处,例如不匹配的参数、不适当的循环嵌套和分支嵌套、不允许的递归、未使用过的变量、空指针的引用和可疑的计算等
    动态测试:动态测试方法是指通过运行被测程序,检查运行结果与预期结果的差异,并分析运行效率、正确性和健壮性等性能。这种方法由三部分组成:构造测试用例、执行程序、分析程序的输出结果

    从软件开发的过程按阶段划分,可以划分为:单元测试、集成测试、确认系统、系统测试、验收测试、回归测试、Alpha测试、Beta测试
    6.3 测试步骤此次测试过程按4个步骤来进行,即:单元测试、集成测试、确认测试和系统测试。

    首先,进行的单元测试:单元测试就是对源代码实现的每一个程序单元的进行测试,检查每个程序模块是否能够正确地实现规定的功能
    之后,进行了集成测试:主要是根据软件体系结构,把已经测试过的单元模块组装起来,在组装过程中,检查程序结构组织是否正确
    接下来,进行确认测试:确认测试则是检查目前已实现的软件是否符合需求分析确定了的各种需求,以及软件配置是否完善、正确
    最后,是进行系统的测试:系统测试是把已经经过确认的软件放入实际运行环境中,通过与其他系统的成分组合在一起进行的测试。严格地说,系统测试已经超过了软件工程的范围。但在实际工作中这几个阶段却是相互交叉的。如图6-1所示



    单元测试:在代码级别上,针对构成软件的最小组件即单元进行测试,是测试过程中粒度最小的测试。其测试目的在于验证单元功能的正确性,与设计的符合程度
    集成测试:在单元测试的基础上,将所有经过单元测试的模块按照设计要求组装成子系统或者系统进行测试。其测试目的是为了关注各个模块之间的交互是否正确
    确认与系统测试:将已经集成好的软件系统,作为整个基于计算机系统的一个元素,与计算机硬件、外设、某些支持软件、数据和人员等其他系统元素结合在一起。在实际运行(使用)环境下,对计算机系统进行一系列的组装测试和确认测试。其目的在于发现与系统定义不符或矛盾的地方以及系统各个部分是否可以协调工作

    6.4 测试用例游戏测试相当于是软件测试的子类,它继承了软件测试的特性,同时也衍生出了自己的特殊属性。测试的目的是发现软件中存在的缺陷。游戏测试主要有游戏情节的测试、游戏世界的平衡测试、游戏文化的测试三个内容。
    由于游戏的特殊性,所以游戏测试则主要分为两部分组成,一是传统的软件测试,二游戏本身的测试,同时它又是游戏所以还涉及到娱乐性,可玩性等独有特性,所以测试的面相当的广。
    要了解如何测试游戏必需了解如何做游戏,了解它的开发过程,才能真正的测好游戏。游戏要成功,其基本的必要条件有三。分别为Vision(设计)、technology(技术)和Process(过程)。 现针对游戏功能,设计如下几个测试用例,见表6-1测试用例表。

    6.5 测试结果本系统在测试和运行过程中,有以下几方面优点:界面友好,操作方便。系统界面简单,功能较完善,易上手,可以激发玩家的乐趣;通用性好,扩展性强。本系统可以适用于各种人群,具有优越的通用性能。但部分系统功能需完善,由于时间和技术因素,交互入口等方面还有待拓展。

    第一,连连看基本游戏功能表现不错(即选择两个图形,判断是否满足一定条件,条件即两个图形一致且二者之间存在转弯少于3的路径。当判定满足这一条件后,两张图片被消除),在运行一次游戏过程中,点击两个不同的图片时,不会消除两个图片,在点击第一个图片时图片变暗,点击第二个图片时因为图片不匹配,第二个图片变暗,两张图片没有消失。在运行一次游戏过程中,点击满足存在多欲三个连接路径的两张图片,同样也不能消除
    第二,图片的排列正确。在开始新一局的游戏时,图片的排列清晰明了,满足随机的同时,成对出现
    第三,记分功能正确。没消除一对图片得分10。得分数在游戏界面上能明确标识,直观的显示出当前的游戏状态,包括游戏得分情况和闯关关数情况
    第四,沙漏计时功能有缺陷。沙漏状计时能正确,倒计时五秒时,提示问字有误,该显示的内容显示不全
    第五,游戏的开始和重新开始表现正确。在游戏开始前,弹出的提示框根据指示点击确定后,能够开始新游戏,即开始记分、计时。重新开始游戏功能也表现正确,能中断当前游戏,开始一局新的游戏,同样开始记分、计时,并且可以多次开始新游戏
    第六,游戏关闭和结束有缺陷。窗口游戏在关闭时,可以直接点击窗口的关闭按钮。游戏结束时,弹出的提速框表现正常,但是沙漏上方的JLabel表现异常,文字显示不全
    第七,游戏难度选择功能正常。游戏难度有4个等级,每个等级选择后,操作模块的界面能显示总体个数相同但不同种类的图片,难度越高,种类越多。在选择了一个难度模式之后,同时也开始一局新游戏
    第八,每一个难度下可以有很多关卡,每一个关游戏过关后可以直接进入下一关
    第九,刷新功能(游戏提示功能)正常。在游戏过程中只可以使用一次刷新功能,重新排列当前游戏未消除的图片个数的图片
    第十,游戏要最大限度地实现了易维护性和易操作性,游戏运行稳定、安全可靠

    6.6 本章小结本章主要明确了测试的目的和测试的重要性,通过设计测试用例得出,游戏中的消除功能、计时功能、记录得分和关数功能、重新开始功能、刷新功能基本实现。
    1 评论 4 下载 2020-07-25 11:31:14 下载需要15点积分
  • 基于QT的网络五子棋游戏程序的设计与实现

    摘 要在现在如此发达并且得到广泛应用的现代网络技术下,集趣味性,娱乐性,益智性,并且包含网络功能的休闲类游戏以及成为了人们选择网络休闲游戏的要求。
    系统采用当今广为流行的五子棋游戏为模版,利用C++的第三方GUI设计工具Qt为程序设计界面,并结合软件工程的思想开发一款基于网络的五子棋游戏对弈软件。本软件采用P2P的模式,利用一个服务端来辅助各个客户端之间的查找和链接,服务端用于记录当前各个客户端的游戏状态,并将实时更新的各个客户端的状态发送到其他客户端,方便客户端加入其他客户端建立的游戏主机,并建立P2P链接,进行游戏。客户端是玩家用于建立游戏主机或者加入游戏进行五子棋对弈的主程序,具有当今五子棋游戏常见的聊天功能、悔棋功能、认输功能、计分功能、玩家断网处理等。
    玩家只需运行客户端,连接到指定的服务端,就可以加入其他的游戏主机进行游戏,或者建立游戏主机,等待其他客户端的加入进行游戏对弈。
    关键字: 多线程,Qt,socket
    ABSTRACTWith the development and widely usage of computernetwork, it has been a requirement for a casual online game to be interesting,entertaining and intelligence-improving.
    This paper implements a online Gobang game based onthe popular Gobang, used third-party C++ GUI library Qt and combined softwareengineering model. The software uses P2P model, which uses a sever end to helpclients find and connect with each other and help record the status of everyclient and send it to other clients in order to make it convenient to join thehost and establish the P2P connection between clients to start the game. Clientis the main program for user to create or join the Gobang game and have thefunctionalities of chatting, regretting, yielding, scoring and connectionproblems handling.
    All user needs to do is run a client, connect to thespecific server, then he can join a host or create a host himself and wait forother clients to join and have a game.
    Key words:multithreading, Qt, socket
    1 绪论1.1 课题研究意义五子棋[1]是起源于中国古代的传统黑白棋种之一。现代五子棋日文称之为“连珠”,英文称之为“Renju”、“Gobang”或“FIR”(Five in a Row 的缩写),亦有“ 连五子”、“五子连”、“串珠” 、“五目”、“五目碰”、“五格”等多种称谓。
    五子棋不仅能增强思维能力,提高智力,而且富含哲理,有助于修身养性。五子棋既有现代休闲的明显特征“短、平、快”,又有古典哲学的高深学问“阴阳易理”;它既有简单易学的特性,为广大人民群众所喜闻乐见,又有深奥的技巧和高水平的国际性比赛;它的棋文化源渊流长,具有东方的神秘和西方的直观;既有“场”的概念,亦有“点”的连接。它是中西文化的交流点,是古今哲理的结晶。
    五子棋起源于古代中国,发展于日本,风靡于欧洲。对于它与围棋的关系有两种说法,一说早于围棋,早在“尧造围棋”之前,民间就已有五子棋游戏;一说源于围棋,是围棋发展的一个分支。在中国的文化里,倍受人们的青睐。古代的五子棋的棋具与围棋相同。五子棋大约随围棋一起在我国南北朝时先后传入朝鲜、日本等地。从此,五子棋经过了不断的改良,例如棋盘由原来的纵横各十七道改为现行的纵横各十五道的五子棋专用棋盘等等。二十世纪初,五子棋传入欧洲并迅速风靡了全欧洲。通过一系列的变化,使五子棋这一简单的游戏系统化、规范化,最终成为今天的职业连珠五子棋,同时也成为一种国际比赛棋。
    在网络发达的今天,对于二人对弈的五子棋,开发一款带有网络功能的五子棋游戏,能够更加方便身在异地的玩家进行游戏。
    1.2 课题研究目的五子棋在我国的历史可谓是源远流长,喜爱它的玩家也是大有人在。但目前的五子棋软件一般都是单机版的,游戏无法在异地的玩家之间进行,因此为了方便异地的玩家在一起进行五子棋游戏,设计出一款基于网络版的五子棋游戏,玩家可以通过网络挑选自己喜爱的对手并同其进行比赛,比赛过程中可以进行聊天,达到相互交流经验的作用,同时能让身处各地的玩家连接到服务器进行五子棋对弈。
    1.3 研究现状分析目前常见的单机类五子棋游戏可分为“人机模式”与“双人模式”。“人机模式”指人与按照事先编写好的五子棋落子算法程序来进行游戏的计算机进行对弈,“双人模式”指两个人通过使用同一台计算机,交替落子来进行游戏。这两种方式,都需要玩家双方在同一台计算机面前进行完成,因此局限性很大,玩家不能再异地的不同的计算机上来进行游戏。
    随着现代计算机网络的迅速发展,网络上的计算机之间的通信已经变得十分便捷。这也为身在异地间的用户利用网络来进行游戏提供了途径。
    网络版的五子棋软件利用网络连接协议TCP/IP,在不同地方的玩家之间建立一个TCP连接,并用这个连接来交换数据,进行通信。因此,网络版的五子棋软件在游戏之前必须确定对网络参数设置的正确性,设置正确之后,才能进行玩家双方的TCP成功连接。连接成功后,双方轮流下棋,同时将每一步落子的信息通过网络连接传送给对方,使双方棋盘上的状态保持一致。
    与单机版的五子棋软件相比,网络版的五子棋软件也提供了所有单机版的五子棋软件所具有的功能,例如:倒计时器、“认输”、“和棋”和“悔棋”等。但对于网络版的五子棋来说,这些功能的同步都是通过网络信息交互来实现的,因此,网络版的五子棋游戏实现过程较单机版要复杂一些。
    在胜负判断方面,单机版的五子棋软件与网络版的五子棋软件可以采用完全相同的算法(如果不考虑先手禁手等)。一方玩家下完一步棋后,系统会自动判断当前落子之后,玩家是否胜利,如果没有胜利,再将落子的信息传送给对方,如果判断结果为胜利,则直接发送胜利消息给对方。每次落子之后,都要进行这样一次胜负判断定的过程。另外,由于网络版的五子棋的游戏双方可能不在同一个地点,因此,提供聊天功能很有必要。
    目前常见的网络五子棋的游戏形式又可分为两种,一种是以QQ五子棋(如图1.1)为代表的桌面应用程序的游戏形式,一种是网页flash(如图1.2)的游戏形式。

    系统结构方面,QQ五子棋游戏采用了C/S结构,而网页flash的五子棋采用的是B/S结构。
    功能方面,二者均提供了常见的悔棋、计分、计时、聊天、认输等功能。均未设计五子棋中“先手禁手”等规则。不同之处在于,常见的网页五子棋对于一方断网的情况不能及时发现,发现后也只是做出提醒另外一方的操作。而QQ五子棋能够对一方断网的情况及时发现,并且采用电脑托管或者直接结束比赛并计算相应分数的操作。
    游戏流畅度方面,网页flash的游戏形式受限于浏览器解析网页代码的速度限制,游戏载入时间明显过长。而QQ五子棋只需要基本的Windows操作系统即可,运行环境要求较低,运行流畅。
    1.4 各章内容简介本文第一章介绍了课题的研究背景,第二章简单介绍了实现程序所用到的技术介绍,第三章对程序需求进行了分析,第四章为系统的设计思想以及详细设计,第五章介绍了系统的实现过程,第六章展示了系统的效果,最后第七章总结了系统已完成的工作和下一步待完成的工作。
    2 实现技术2.1 P2P模式2.1.1 P2P模式介绍P2P[2](peer-to-peer, 简称P2P)又称对等互联网络技术,是一种网络新技术,依赖网络中参与者的计算能力和带宽,而不是把依赖都聚集在较少的几台服务器上。请注意与point-to-point之间的区别,peer-to-peer一般译为端对端或者群对群,指对等网中的节点;point-to-point一般译为点对点,对应于普通网络节点。P2P网络通常用于通过Ad Hoc连接来连接节点。这类网络可以用于多种用途,各种文件共享软件已经得到了广泛的使用。P2P技术也被使用在类似VoIP等实时媒体业务的数据通信中。
    纯点对点网络没有客户端或服务器的概念,只有平等的同级节点,同时对网络上的其它节点充当客户端和服务器。这种网络设计模型不同于客户端-服务器模型,在客户端-服务器模型中通信通常来往于一个中央服务器。
    2.1.2 P2P模式的优势P2P网络的一个重要的目标就是让所有的客户端都能提供资源,包括带宽,存储空间和计算能力。因此,当有节点加入且对系统请求增多,整个系统的容量也增大。这是具有一组固定服务器的Client-Server结构不能实现的,因为在上述这种结构中,客户端的增加意味着所有用户更慢的数据传输。
    P2P网络的分布特性通过在多节点上复制数据,也增加了防故障的健壮性,并且在纯P2P网络中,节点不需要依靠一个中心索引服务器来发现数据。在后一种情况下,系统也不会出现单点崩溃。
    当用P2P来描述Napster 网络时,对等协议被认为是重要的,但是,实际中,Napster 网络取得的成就是对等节点(就像网络的末枝)联合一个中心索引来实现。这可以使它能快速并且高效的定位可用的内容。对等协议只是一种通用的方法来实现这一点。
    2.1.3 P2P模式的应用点对点技术有许多应用。共享包含各种格式音频,视频,数据等的文件是非常普遍的,实时数据(如IP电话通信)也可以使用P2P技术来传送。
    有些网络和通信渠道,像Napster,OpenNAP,和IRC@find,一方面使用了主从式架构结构来处理一些任务(如搜索功能),另一方面又同时使用P2P结构来处理其他任务。而有些网络,如Gnutella和Freenet,使用P2P结构来处理所有的任务,有时被认为是真正的P2P网络。尽管Gnutella也使用了目录服务器来方便节点得到其它节点的网络地址。
    2.2 Qt2.2.1 Qt介绍
    UI(User Interface)也可以称之为用户接口或使用者接口,是系统和用户之间进行交互和信息交换的媒介,它实现信息的内部形式与人类可以接受形式之间的转换。
    Qt[3]是由挪威TrollTech公司于1995年底出品,之后被诺基亚公司收购并维护的一个跨平台的C++图形用户界面应用程序框架。广泛用于开发GUI程序,这种情况下又被称为部件工具箱。也可用于开发非GUI程序,比如控制台工具和服务器。自从1996年早些时候,Qt进入商业领域,它已经成为全世界范围类数千种成功的应用程序的基础,被GoogleEarth、KDE、西门子公司等使用。它是诺基亚(Nokia)的Qt Development Frameworks部门的产品。
    经过多年发展,Qt不但拥有了完善的C++图形库,而且近年来的版本逐渐集成了数据库、OpenGL库、多媒体库、网络、脚本库、XML库、WebKit库等等,其核心库也加入了进程间通信、多线程等模块,极大的丰富了Qt开发大规模复杂跨平台应用程序的能力,真正意义上实现了其研发宗旨“Code Less; Create More; Deploy Anywhere.”。
    2.2.2 Qt模块模块化 QtC++ 类库提供一套丰富的应用程序生成块 (block),包含了构建高级跨平台应用程序所需的全部功能。Qt模块结构图如图2.1:

    其中本系统设计到更多的Qt的消息响应机制和多线程如下:
    1.Qt的消息响应机制:信号与槽:
    Qt利用信号与槽(signals/slots)机制取代传统的callback来进行对象之间的沟通。当操作事件发生的时候,对象会发提交一个信号(signal);而槽(slot)则是一个函数接受特定信号并且运行槽本身设置的动作。信号与槽之间,则通过QObject的静态方法connect来连结。
    信号在任何运行点上皆可发射,甚至可以在槽里再发射另一个信号,信号与槽的连结不限定为一对一的连结,一个信号可以连结到多个槽或多个信号连结到同一个槽,甚至信号也可连接到信号。
    以往的callback缺乏类型安全,在调用处理函数时,无法确定是传递正确型态的参数。但信号和其接受的槽之间传递的数据型态必须要相符合,否则编译器会提出警告。信号和槽可接受任何数量、任何型态的参数,所以信号与槽机制是完全类型安全。
    信号与槽机制也确保了低耦合性,发送信号的类并不知道是哪个槽会接受,也就是说一个信号可以调用所有可用的槽。此机制会确保当在”连接”信号和槽时,槽会接受信号的参数并且正确运行。
    2.多线程
    Qt的运行绪支持是独立于平台的运行绪类,采用信号与槽机制,实现类型安全的运行绪间通讯。这使得它易于开发具可移植性的多线程Qt应用程序。并能充分利用多核架构,获得最佳运行性能,还能根据可用的处理器内核数自动调整使用的运行绪数。多线程程序设计也是一个执行耗时操作而不会冻结用户界面的有效典范。
    2.2.3 Qt的优势1.面向对象
    Qt的良好封装机制使得Qt的模块化程度非常高,可重用性较好,对于用户开发来说是非常方便的。Qt提供了一种称为signals/slots的安全类型来替代callback,这使得各个元件之间的协同工作变得十分简单。
    2.丰富的API
    Qt包括多达250个以上的C++类,还提供基于模板的collections,serialization,file,I/Odevice,directorymanagement,date/time类。甚至还包括正则表达式的处理功能。
    3.优秀的跨平台能力
    使用Qt开发的软件,相同的代码可以在任何支持的平台上编译与运行,而不需要修改源代码。会自动依平台的不同,表现平台特有的图形界面风格。

    Linux/X11:用于X Window System(如Solaris、AIX、HP-UX、Linux、BSD)。支持KDevelop和EclipseIDE集成Mac:用于Apple Mac OS X。基于Cocoa框架。支持Universal Binary。支持以Xcode编辑、编译和测试。Windows:用于Microsoft Windows。支持Visual Studio集成Embedded Linux:用于嵌入式Linux。可以通过编译移除不常使用的组件与功能。通过自己的视窗系统QWS,不需依赖X Window System,直接写入Linux帧缓冲。可以减少存储器消耗。并提供虚拟帧缓冲QVFb,方便在桌面系统上进行嵌入式测试。Windows CE / Mobile :用于Windows CESymbian:用于Symbian platformMaemo:用于Maemo
    4.大量的开发文档
    对于Qt的各个模块,都有对应的帮助文档和编写好的例子供开发人员参考。
    3 系统需求分析服务端程序运行流程图如图3.1:

    打开服务端后,用户首先设置服务参数,然后等待客户端连接。
    当收到客户端的连接时,将目前已经连接到服务端的所有客户端的状态(正在游戏中,建立了主机并等待玩家加入)发送到刚刚连接进来的客户端。
    如果收到客户端请求:请求建立游戏主机、请求加入别人的游戏主机进行游戏,则服务端更新此客户端的状态,然后将最新的状态发送给各个客户端。
    客户端程序运行流程图如图3.2:

    打开客户端后,用户首先设置服务器参数,然后连接服务端。连接成功后,客户端会收到来自服务端的其他客户端的当前状态,用户可以选择是建立游戏主机,还是加入别人的游戏主机进行游戏。
    1.功能需求
    程序主要核心功能如图3.3:


    服务器开始、退出
    服务端程序能够开启、关闭五子棋游戏的服务。关闭服务时,能够给当前已连接的客户端发送关闭服务消息。
    玩家开始、退出
    玩家进入游戏主机之后,需要点击准备才能开始游戏,若玩家在游戏时退出游戏,需要向对手发送退出游戏的信息。
    聊天功能
    玩家在对弈过程中可以发送信息进行交流。
    悔棋
    玩家在对弈过程中,能够进行悔棋请求,如果对方答应悔棋请求,则系统撤销双方玩家最近一次的落子;若对方不答应悔棋请求,则游戏继续。
    认输
    玩家在对弈过程中,可以直接选择认输,不需要经过对方同意。
    计分
    程序能保存当前两个玩家从开始第一句对弈,到其中一方离开游戏这期间的战绩情况。
    断网处理
    当其中一方玩家意外断网时,程序能通过超时相应判断出对方丢失了网络连接并作出处理。

    2.环境需求

    装有windows或者linux的操作系统的计算机两台计算机的CPU不低于P4,内存不小于64M10/10Mbps自适应网卡每台计算机各一块每台计算机都应配置有TCP/IP协议
    3.用户界面需求

    界面友好、美观界面简洁操作界面方便、易懂
    4.异常处理需求

    处理端口号冲突时的异常当出现错误落子位置时,此次操作无效如果网络非正常断开,则终止此局游戏
    4 系统设计4.1系统设计思想本系统的能够实现一个在网络上供玩家进行对战的网络版的五子棋游戏,玩家只要登陆到服务器上,然后选择其它已创建好的游戏主机,进行五子棋对战游戏。或者自己建立一个游戏主机,等待对方的加入。
    在C/S 模式游戏中,服务端一般提供所有用户的全局信息,并能提供客户之间的信息转发,客户之间的通讯必须通过服务端进行。因为在多个客户能够连接到同一台服务端上,所以服务端必须用线程负责每个用户的通讯和消息处理。
    但是考虑到如果采用这种思路,当客户端达到一定的数量之后,会增加服务端的负荷,而且当两个玩家开始游戏之后,服务端只需知道玩家双方是否退出游戏以及双方的游戏结果即可,而玩家之间的对弈信息、聊天等信息大可不必经过服务端。
    基于以上考虑的原因,决定采用P2P的网络模式:服务端程序开启服务后,通过一个线程监听客户端的连接,一旦有客户端连接,服务端便为该客户端建立连接并启动一个特定的线程,利用该连接不断获取客户端操作请求,从而更新游戏大厅信息,让其他玩家及时了解到哪些客户端建立了游戏主机,哪些客户端之间正在进行游戏对弈。而当客户端加入了另外一个客户端建立的游戏主机时,二者便建立起P2P连接,用于传送二者之间的对弈信息,操作请求(悔棋,认输等),聊天信息等。设计思想的结构拓扑图如图4.1:

    4.2 系统总体设计系统使用Socket技术与Qt多线程机制结合,使用C/S模式与P2P模式结合,在进行客户与服务端以及各个客户端之间进行信息的交互。
    其中,对客户端进行的各个操作请求产生的数据包发送的对象如表4.1:



    客户端操作类型
    数据包发送对象




    用户登录请求
    服务器


    用户建立主机请求
    服务器


    用户加入游戏请求
    服务器


    网络丢失确认
    服务器


    对方网络丢失信息通知
    服务器


    发送认输通知
    客户端


    发送落子信息
    客户端


    发送聊天内容
    客户端


    发送悔棋请求
    客户端



    用户程序之间进行交互的协议如图4.2:

    其中,“数据类型”字段如表4.2:



    消息类型
    说明




    COMM_SERVER_CONN_FAILED
    连接服务器失败


    COMM_SERVER_CONN_SUCCESSFUL
    连接服务器成功


    COMM_SERVER_CLOSE
    服务器关闭


    COMM_SERVER_GAMEINFO
    服务器发送大厅信息


    COMM_CLIENT_QUITGAME
    客户端退出游戏


    COMM_CLIENT_DISCONN
    客户端请求断开服务器


    COMM_CLIENT_CONN
    客户端请求连接服务器


    COMM_CLIENT_CREATE
    客户端请求创建主机


    COMM_CLIENT_JOIN
    客户端请求加入游戏


    COMM_CLIENT_GAMESTART
    双方准备完毕,游戏开始


    COMM_CLIENT_GAMEOVER
    某方玩家胜利,游戏结束


    COMM_CLIENT_GAMEOP
    玩家游戏操作:落子


    COMM_CLIENT_CHAT
    玩家游戏操作:发送聊天信息


    COMM_CLIENT_UNDO
    玩家游戏操作:悔棋


    COMM_CLIENT_UNDO_YES
    玩家游戏操作:悔棋回复yes


    COMM_CLIENT_UNDO_NO
    玩家游戏操作:悔棋回复no


    COMM_CLIENT_LOSE
    玩家游戏操作:认输


    COMM_CLIENT_LOSTCONN
    玩家发送消息:对手超时,判定为掉线



    请求方需要发出请求时,便把消息类型设置为如上对应的消息类型(例如:服务器连接请求),并设置请求相关的数据(例如:需要连接的服务器的IP以及端口),最后发送此数据包。
    数据字段根据第一个字段的不同设置不同的数据,有可能为包含五子棋落子位置的信息;有可能为空数据(例如:连接服务器成功则数据字段为空,连接服务器失败则数据字段为连接服务器失败的原因)。
    接收方在接受到此数据包之后,首先判断出数据包的类型什么,然后利用接受到的数据(例如:服务器的IP以及端口)以及数据包类型(例如:服务器连接请求)来处理数据(例如:是否接受此客户端的连接),处理完毕之后,设置响应数据包类型为具体的响应类型(例如:连接成功),并且设置响应相关的数据(例如:连接成功则没有数据,连接失败则数据为连接失败的原因),最后发送此数据包。
    例如某个客户端在连接服务器时,详细流程如图4.2:

    客户端想服务端发送连接请求,数据包设置如图中“数据包(1)”,服务端收到连接请求之后,判断出此时已达服务端最大的连接数,然后将数据包设置如图中“数据包(2)”,然后将此数据包发送给刚刚的客户端,通知客户端此次连接因为服务器已经达到了最大连接数,拒绝客户端的连接。
    4.3 系统工作流程4.3.1 服务端工作流程基于以上设计,服务端只负责本地游戏服务的开启,以及各个客户端的连接,建立主机,加入游戏等请求,因此服务端的工作流程如图4.3:

    服务端首先设置服务参数,然后开启本地服务,等待客户端的连接。
    当接受到客户端的连接之后,建立一个新线程,用于接受客户端的操作请求,父线程则继续等待客户端的连接。
    当子线程收到客户端发来的操作请求时,则根据对应的请求类型做相应的处理。
    4.3.2 客户端工作流程基于以上设计,客户在与服务端交互时采用C/S模式,与其他玩家对弈时,采用P2P模式,因此客户端的工作流程如图4.4:

    客户端连接到服务端之后,首先获取到服务端发送来的各个客户端的状态,然后选择是自己建立游戏主机,还是加入别人的游戏。
    游戏中,客户端与客户端之间会建立P2P连接,传递各种游戏操作信息。
    4.4 五子连珠算法设计五子棋游戏中,如果一方胜利,则胜利时的五子连珠必定与玩家最后落下的那颗棋子相关。因此每当用户落下一颗棋子时,程序便判断包括这颗棋子在内的纵向、横向、斜向的五颗棋子有没有五子相连的情况,若有,则此方胜利,反之,继续比赛。
    五子棋程序中,采用一个二维数组保存棋盘的每个位置的当前状况(白色棋子,黑色棋子,没有落子)。当其中一方胜利时,在棋盘记录中,五子相连的方向的当前状态应同为白子或同为黑子。
    以斜向为例,胜利时的可能情况如图4.5所示:(所有圆均表示同一个玩家落下的棋子,填充色的圆表示最后落下的子):

















    每次落下一颗棋子时,程序判断斜向这5种情况以及其他几个方向类似情况是否为同色,若是,则胜利,反之,继续比赛。
    程序伪代码:
    curPosX,curPosY : 当前落子的横纵坐标count : 棋盘格数(19)winColor : 当前落子玩家所持有的棋子的颜色chessboardRecord[count][count] : 记录棋盘各个位置的落子的颜色的二维数组for I from 4 to 1 step 1 if curPosX<0 or curPosY<0 then continue; end if for J from 0 to 5 step 1 if curPosX>count-1 or curPosY>count-1 then break end if if chessboardRecord[curPosX][curPosY]<>winColor break end if else if j=4 return true end if end forend for
    5 系统实现5.1 主要的数据结构// 用于记录某个棋子是主机落下的还是对手落下的enum playerRole enum playerRole{ HOST, GUEST};
    // 记录当前游戏状态是playingGame(正在游戏)还是readyToPlayingGame(等待对方按下准备按钮,然后开始游戏)enum playerStatus enum playerStatus{ playingGame, readyToPlayingGame};
    // 用户程序之间交互协议enum comm_request_typeenum comm_request_type{ //连接服务器失败 COMM_SERVER_CONN_FAILED, //连接服务器成功 COMM_SERVER_CONN_SUCCESSFUL, //服务器关闭 COMM_SERVER_CLOSE, //服务器发送大厅信息 COMM_SERVER_GAMEINFO, //退出游戏 COMM_CLIENT_QUITGAME, //请求断开服务器 COMM_CLIENT_DISCONN, //客户端请求连接服务器 COMM_CLIENT_CONN, //客户端请求创建主机 COMM_CLIENT_CREATE, //客户端请求加入游戏 COMM_CLIENT_JOIN, //双方准备完毕,游戏开始 COMM_CLIENT_GAMESTART, //某方玩家胜利,游戏结束 COMM_CLIENT_GAMEOVER, //玩家游戏操作:落子 COMM_CLIENT_GAMEOP, //玩家游戏操作:发送聊天信息 COMM_CLIENT_CHAT, //玩家游戏操作:悔棋 COMM_CLIENT_UNDO, //玩家游戏操作:悔棋回复yes COMM_CLIENT_UNDO_YES, //玩家游戏操作:悔棋回复no COMM_CLIENT_UNDO_NO, //玩家游戏操作:认输 COMM_CLIENT_LOSE, //玩家发来消息,对方掉线 COMM_CLIENT_LOSTCONN};
    // 用户程序之间交互数据包的格式struct msg_request_structstruct msg_request_struct{ //请求类型 qint8 request; //数据 QString data;};
    5.2 服务端的实现5.2.1 界面实现服务端能够开启本地服务,以及实时查看游戏大厅信息:哪些玩家正在对弈,哪些玩家在等待其他玩家加入等。因此服务端应具有两个界面,分别用来配置本地服务以及显示游戏大厅信息。如图5.1和图5.2:

    5.2.2 主要的成员变量// 用户程序之间交互的数据结构msg_request_struct* msg_req_struct;
    // 记录对弈双方的IP信息,若主机在等待其他玩家加入,则其对手IP地址置为“-”QList<QPair<QString, QString> >playerFightInfo;
    // 保存服务端本地开启的服务套接字QTcpServer *tcpServer_player;
    5.2.3 功能实现1.客户端连接限制功能
    考虑到服务端运行环境不同,所能承受的负荷也不同,因此加入“客户端连接限制”功能,防止过多的客户端连接导致服务端的负荷过大。
    在服务端的服务配置界面,可以设定服务端允许的最大连接数,当客户端的连接数达到了服务端设置的最大连接数的时候,服务端便不允许其他客户端连接。
    核心代码:
    QTcpSocket *tcpSocket_player = tcpServer_player->nextPendingConnection();DataClass::curConnCount++; if(DataClass::curConnCount > DataClass::maxConnectionLimit){ DataClass::curConnCount--; tcpSocket_player->close(); tcpSocket_player = NULL; return ;}
    2.广播游戏大厅信息(建立主机,加入游戏,退出游戏等)
    服务端与客户端之间的信息交互采用C/S模式,因此当有客户端更新并向服务端发送信息(例如建立主机,加入游戏,退出游戏等)之后,服务端应及时将更新之后的信息广播出去,使得其他客户端及时更新大厅信息。
    核心代码:
    QString qsNull = "-";playerFightInfo.push_back(qMakePair(clientAddr, qsNull));updateGameInfo();QList<QTcpSocket* > allTcpSocket = tcpServer_player->findChildren<QTcpSocket *>(); QString data; for(int i=0; i<playerFightInfo.size(); i++)data += playerFightInfo[i].first + " " + playerFightInfo[i].second + "_";for(int i=0; i<allTcpSocket.size(); i++){DataClass::sendMsg(COMM_SERVER_GAMEINFO, data, tcpSocket);}
    客户端收到服务端发送过来的data之后,用正则表达式分析出对弈双方的信息,然后更新本地显示。
    5.3 客户端的实现5.3.1 界面实现客户端具有一个配置连接服务器的界面,用于输入连接服务器信息,如图5.3:

    登陆服务器成功之后,会显示从服务器接受到得玩家对弈信息,用户这时可以选择建立游戏主机等待别人加入,或者是加入别人的主机进行对弈,如图5.4:

    玩家选择了建立游戏主机或者加入游戏后,会弹出游戏界面等待开始游戏,如图5.5:

    5.3.2 主要的成员变量// 记录超时时间的定时器QTimer timer;
    // 记录当前棋盘的落子信息int chessboardRecord[19][19];
    // 用户程序之间交互的数据结构msg_request_struct* msg_req_struct;
    // 当前玩家的身份(参考5.1的playerRole数据结构)playerRole plyRole;
    // 当前游戏状态(参考5.1的playerStatus数据结构)playerStatus plyStatus;
    // 下一步该谁落子(参考5.1的playerRole数据结构)playerRole whosTurn;
    // 记录对战成绩int win, lose;
    // 记录当前已经落下的棋子的信息:落子的位置,谁落的这颗子QList<QPair<QPoint, enum playerRole> > pieceRecord;
    5.3.3 功能实现1.玩家开始、退出
    开始时输入玩家的姓名,同时下方会显示出相应的IP地址。在输入相关的信息后就会弹出游戏界面,而游戏设置的对话框随即会自动隐藏,释放。这时就开始等待对方的加入,等有人加入后就可以开始游戏了。或者直接加入别人建立的主机。如果不想玩了就可以按退出按钮,一方退出游戏后,另一方就会显示尚未连线,然后等待下一个玩家的进入。功能详细流程如图5.6:

    核心代码:
    // 建立游戏主机DataClass::sendMsg(COMM_CLIENT_CREATE, "", tcpSocket_server); GameStatus gameStatus;gameStatus.setPara(tcpSocket_server);connect(tcpSocket_server, SIGNAL(readyRead()), &gameStatus, SLOT(getNewDataFromServer()));gameStatus.setPlayerRole(HOST);gameStatus.exec();
    // 加入游戏int row = ui.clientStatus_client_TBW->currentRow();if(ui.clientStatus_client_TBW->item(row,1)->text() != "-"){ QMessageBox::information(this,"错误","此主机正在对战中..."); return ;}DataClass::sendMsg(COMM_CLIENT_JOIN,ui.clientStatus_client_TBW->item(row, 0)->text(), tcpSocket_server); GameStatus gameStatus;gameStatus.setPara(tcpSocket_server);connect(tcpSocket_server, SIGNAL(readyRead()), &gameStatus, SLOT(getNewDataFromServer()));gameStatus.setPlayerInfo(ui.clientStatus_client_TBW->item(row,0)->text());gameStatus.setPlayerRole(GUEST);gameStatus.exec();
    // 退出游戏if(plyRole == HOST){ plyStatus = readyToPlayingGame; ui.chatLog_client_TE->clear(); ui.record_me_client_LE->setText("胜利:" + QString::number(win) + "场,失败:" + QString::number(lose) + "场!"); ui.record_rivar_client_LE->setText(""); ui.addr_rivar_client_LE->setText(""); QMessageBox::information(NULL,"提示","对方退出游戏!");}else if(plyRole == GUEST){ ui.gameReady_client_BTN->setDisabled(false); closeByServer = true; this->close();}
    2.用户之间聊天
    在下棋的同时可以通过聊天窗口和对方进行聊天会话,写完信息之后点击发送,就可以在公共的显示栏中看到自己发出的信息和对方回应的信息。进而开始用户之间的交流,同时所用的组合框的下拉菜单中会有一些简便的备用的语句,可以点击随即发送,这样就能省去部分打字的时间。
    核心代码:
    if(ui.sendwords_client_LE->text() == ""){ QMessageBox::information(NULL,"错误","请先输入文字!"); return ;}ui.chatLog_client_TE->append("自己: " + ui.sendwords_client_LE->text());DataClass::sendMsg(COMM_CLIENT_CHAT,ui.sendwords_client_LE->text(),tcpSocket_player);ui.sendwords_client_LE->setText("");
    3.悔棋、认输
    在游戏中,玩家可以发出悔棋请求,如果对方同意悔棋,则程序自动回退一步;若对方不同意悔棋,则请求无效。玩家也可以发出认输请求,程序自动结束本轮游戏并计分,认输请求不需要对方同意。悔棋功能详细流程如图5.7:

    核心代码:
    // 悔棋 if(whosTurn != plyRole) { QMessageBox::information(NULL,"错误","轮到你下棋的时候你才能发出悔棋请求!"); return ; } if(!(DataClass::checkDialog("确认","确认悔棋?"))) return ; whosTurn = (plyRole == HOST ? GUEST : HOST); DataClass::sendMsg(COMM_CLIENT_UNDO,"",tcpSocket_player);
    // 收到悔棋响应(同意悔棋)QMessageBox::information(NULL,"提示","对方同意悔棋!");whosTurn = plyRole;if(pieceRecord.size() > 0){ chessboardRecord[pieceRecord[pieceRecord.size() - 1].first.x()-1][pieceRecord[pieceRecord.size() - 1].first.y()-1] = 0; pieceRecord.removeAt(pieceRecord.size() - 1);}if(pieceRecord.size() > 0){ chessboardRecord[pieceRecord[pieceRecord.size() - 1].first.x()-1][pieceRecord[pieceRecord.size() - 1].first.y()-1] = 0; pieceRecord.removeAt(pieceRecord.size() - 1);}update();
    // 收到悔棋响应(不同意悔棋)whosTurn = plyRole;QMessageBox::information(NULL,"错误","对方不同意悔棋请求!");
    // 认输if(!(DataClass::checkDialog("确认","确认认输?"))) return ;DataClass::sendMsg(COMM_CLIENT_LOSE,"",tcpSocket_player); if(plyRole == GUEST) ui.gameReady_client_BTN->setDisabled(false);ui.undo_client_BTN->setDisabled(true);ui.lose_client_BTN->setDisabled(true);plyStatus = readyToPlayingGame;lose += 1;ui.record_me_client_LE->setText("胜利:" + QString::number(win) + "场,失败:" + QString::number(lose) + "场!");ui.record_rivar_client_LE->setText("胜利:" + QString::number(lose) + "场,失败:" + QString::number(win) + "场!");
    4.计分
    游戏开始的时候双方的战绩均为零,当一轮过后战绩就会被刷新一次,各自几胜几败很清晰的出现在界面上,由于最先下棋的玩家胜利的几率会很大,所以根据各自的胜负情况会交替双方先手的顺序,达到公平的目的。
    5.断网处理
    当客户端在等待对方操作时超时,则测试是否能连接服务器。若能连接,则向服务器发送对方以断网的相关信息并结束比赛计算分数;若不能连接,则提示用户已丢失与服务器和对方的连接。断网处理的详细流程如图5.8:

    核心代码:
    QTimer timer;connect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));timer.start(30000); if(tcpSocket_player->isValid()) return ;QMessageBox::information(NULL,"提示","对方超时!");dataInit();ui.undo_client_BTN->setDisabled(true);ui.lose_client_BTN->setDisabled(true);ui.send_client_BTN->setDisabled(true); if(plyRole == GUEST){ DataClass::sendMsg(COMM_CLIENT_LOSTCONN,"HOST " +ui.addr_rivar_client_LE->text(),tcpSocket_server); if(tcpSocket_player) { tcpSocket_player->close(); tcpSocket_player = NULL; } this->close();}else if(plyRole == HOST){ DataClass::sendMsg(COMM_CLIENT_LOSTCONN,"GUEST " + ui.addr_rivar_client_LE->text(),tcpSocket_server); plyStatus = readyToPlayingGame; ui.chatLog_client_TE->clear(); ui.record_me_client_LE->setText("胜利:" + QString::number(win) + "场,失败:" + QString::number(lose) + "场!"); ui.record_rivar_client_LE->setText(""); ui.addr_rivar_client_LE->setText(""); if(tcpSocket_player) { tcpSocket_player->close(); tcpSocket_player = NULL; } if(tcpServer_player) { tcpServer_player->close(); tcpServer_player = NULL; }}
    5.3.4 五子连珠算法核心代码(4个方向中,以斜向为例):
    checkWinLURD(int last_x, int last_y, int winColor)函数:for(int j=4; j>-1; j--){ if(last_x - j <0 || last_y - j < 0) continue; for(int z=0; z<5; z++) { if(last_x - j + z > 18 || last_y - j + z > 18) break; if(chessboardRecord[last_x - j + z][last_y - j + z] != winColor) break; else if(z == 4) return true; }}return false;
    6 系统效果展示6.1 服务端效果展示服务端配置页面(默认为监听端口为45454端口,默认连接上限为50),如图6.1:

    开启服务有,当有客户端连接时,左下角会实时更新当前连接数。当客户端建立游戏主机之,服务端也会及时显示,如图6.2:

    当有玩家加入游戏时,服务端也能及时更新,如图6.3:

    6.2 客户端效果展示
    客户端连接服务器配置页面,如图6.4:

    客户端登陆后,会实时显示当前连接到服务端的游戏主机信息,如图6.5:

    玩家此时可以选择加入别人的游戏主机(双击主机列表),游戏界面如图6.6:

    点击“准备”按钮之后,即可开始游戏,如图6.7:

    游戏过程中,玩家可以聊天,如图6.8:

    游戏过程中,玩家可以点击“悔棋”、“认输”、“退出”按钮达到相应功能。
    7 结论7.1 已完成的工作目前本软件已完成的工作如下:

    了解五子棋游戏的落子规则,并设计相应的判断胜利算法。
    通过查阅相关资料,对于本软件设计了一个比较简单且快速有效的五子连珠算法。
    学习网络编程技术,掌握C/S模式网络程序的基本编程方法。
    经分析,本软件最终采用了P2P的网络模式,相比于C/S模式,P2P模式使得本软件效率更高。
    学习GUI程序设计,设计五子棋游戏的程序界面。
    本软件已实现一个操作方便,界面美观的五子棋游戏程序。
    设计并实现网络五子棋的服务器和客户端程序。
    本软件已实现服务器和客户端程序,服务端用于收集客户端的游戏状态信息,客户端用于玩家之间的对弈。
    设计并实现悔棋、认输、计分、聊天等游戏辅助功能。
    本软件已实现常见的游戏功能:悔棋,认输,计分,聊天等功能。

    另外,程序还实现了断网处理:当对方玩家1分钟之内没用做任何操作,则系统认为此玩家已丢失网络连接,结束此局比赛,并且让丢失连接的玩家退出此游戏主机。
    7.2 下一步待完成的工作本系统和其它的网络五子棋软件相比,功能上还存在着一定的差距,例如:本系统必须要知道主机的IP地址以及端口号才能建立连接、第三方观看的玩家不能加入棋局等等。
    要想设计出更完善的网络五子棋软件,仍然需要做大量的工作:
    1.服务器的设置
    在网络中将其中一台计算机设置成为固定的服务器,其IP地址和端口号是固定不变的,客户端可以直接连接到此服务器上,然后通过服务器上的信息选择对手或者创建游戏主机,这样就省去了玩家必须知道游戏主机的IP地址和端口号的麻烦了。
    2.界面需要进一步美化
    界面可以适当进行美化,提高游戏的娱乐性。
    3.提高通信的可靠性
    在采用同TCP连接的一般情况下,网络五子棋软件都可以正常稳定的工作,但是仍不能保证其任何情况下都能正常稳定,一旦由于某种原因使得网络传输过程中的数据丢失,将使双方的游戏数据不一致,游戏便无法继续进行。因此,可以考虑一方断网之后,计算机智能代替下棋的功能。
    4.扩充功能。
    增加记录当前棋谱的功能,以供五子棋残局爱好者能在日后研究。
    致谢从论文选题到搜集资料,从程序的设计到反复调试,从论文的成型到反复修改,期间经历了太多的喜悦、痛苦和彷徨。如今,伴随着这篇毕业论文的最终成稿,自己甚至还有一点成就感。
    我要感谢我的导师。他为人随和热情,治学严谨细心。在闲聊中她总是能像知心朋友一样鼓励你,在论文的写作和措辞等方面她也总会以“专业标准”严格要求你,从选题、定题开始,一直到最后论文的反复修改、润色,老师始终认真负责地给予我深刻而细致地指导,帮助我开拓研究思路,精心点拨、热忱鼓励。正是老师的无私帮助与热忱鼓励,我的毕业论文才能够得以顺利完成,谢谢老师。
    我要感谢班里的同学们,在百忙之中抽出时间帮助我搜集文献资料,帮助我理清论文写作思路,对我的论文提出了诸多宝贵的意见和建议。
    参考文献[1] Wikipedia.五子棋[EB/OL].[2011-04-07]. http://zh.wikipedia.org/zh/五子棋
    [2] Wikipedia.点对点技术[EB/OL].[2011-04-02].http://zh.wikipedia.org/wiki/点对点技术
    [3] Wikipedia.Qt[EB/OL].[2011-04-03].http://zh.wikipedia.org/wiki/Qt
    [4] Bruce Eckel.Thinking in Java[M].北京:机械工业出版社, 2007.
    [5] Thomas H.Cormen,Charles E.Leiserson,Ronald L.Rivest,CliffordStein.Introduction to Algorithms[M].北京:机械工业出版社, 2006.
    [6] Jasmin Blanchette,Mark Summerfield.C++ GUI Qt 4[M].北京:机械工业出版社, 2009.
    [7] 蔡志明.精通Qt4编程(第二版)[M].北京:机械工业出版社, 2011.
    [8] 严蔚敏,吴伟民.数据结构(C语言版)[M].北京:清华大学出版社, 2007.
    [9] 张银犬. 基于P2P技术的信息资源共享模式研究[EB/OL].[2005-11-25]. http://epub.cnki.net/grid2008/detail.aspx?filename=TSGJ200505012&dbname=CJFD2005
    [10] 顾军,王恒莉,徐丽. P2P网络模型的分析与探讨[EB/OL].[2005-10-01]. http://epub.cnki.net/grid2008/detail.aspx?filename=JISJ200510015&dbname=CJFD2005
    [11] 马睿. 基于Qt的TCP网络编程研究与应用[EB/OL].[2011-01-12]. http://epub.cnki.net/grid2008/detail.aspx?filename=FJDN201011067&dbname=CJFD2010
    4 评论 181 下载 2018-09-27 23:33:59 下载需要16点积分
  • 基于C#实现的电影网站数据爬虫和电影网站

    1 简介1.1 背景随着网络的发展,网购也越来越流行,人们可以在去各大电影院的网站方便的购票并选择自己喜欢的时间去影院观看。但电影院网站众多,人们可能为了寻找一个电影而奔波与各大网站,导致浪费大量时间在寻找电影资源上。本网站提供有效的电影信息聚合,方便用户筛选自己喜欢的电影和电影院,节省时间。
    1.2 目标该文档描述好看的电影网的详细功能定义,并对模块划分、业务流程进行了定义。所有设计人员、开发人员、测试人员以及其他团队成员都应该以该文档作为产品的功能定义,并衍生出其他文档。
    2 功能描述我看电影网提供给用户各大电影院信息,新电影详情,并提供收藏与偏好功能,有效的聚合各类电影信息,帮助用户快速选择喜欢的电影并转入专业买票网站购票页。
    整个系统分为两大主要功能模块和后台数据库服务器模块:

    通过B/S(浏览器/服务器)结构实现的Web部分

    Web部分主要供用户使用。普通用户可以通过 Web 浏览自己的基本资料和收藏、查看电影、购票。看过电影的用户也可以对电影和电影院进行评价
    后台管理部分后台添加

    后台提供前台的各种数据支持,响应前台的各种操作请求,保证前台web端的正常健壮运行

    本文档只描述了Web部分的功能规范,其他部分可以参看另外两门课程(《SQL Server 2000 数据库程序设计》和《基于 C# 的 Windows 应用程序设计》或《基于 ASP. NET 的 Windows 应用程序设计 》)的功能规范。
    2.1.1 注册和登录登录界面如下图所示。登录时,需要输入用户名及密码,并单击“登录”按钮,完成登录过程,如果没有账户,可以直接在登录界面里创建账户并登录,点击重置按钮可以直接清除已经输入的信息。
    登录注册页面

    登录出错页面

    功能说明
    登录名/密码

    登录名由用户自己创建
    读取浏览器端的Cookie值,如果员工以前登录过并没有退出,且Cookie在有效期,则自动进入次用户的信息,如果没有登录过,则显示登录界面
    密码长度不得超过30个字符,对使用字符方面没有限制
    密码用掩码•显示,长度根据已设值进行限制(默认为8~20位),不能为空。若为空或是没有按照格式输入,则显示“密码错误,请重试!”

    登录

    如果登录者的输入是正确的,则直接进入“用户信息管理”模块的主界面
    若“登录名”不存在,则要求用户重新输入,并提示用户名不存在
    若“密码”输入有误,则在“登录”按钮下面显示错误提示信息:“密码错误,请重试!”
    点击重置重置所有信息

    注册

    如果登录者的所有输入是正确的,则直接进入“偏好管理页面”选择用户偏好
    若“登录邮箱”不符合格式,则要求用户重新输入,并提示错误
    若“密码”输入不符合格式,则要求重新输入,并提示错误
    两次密码输入不同则要求用户检查并重新输入
    点击点击重置重置所有信息


    控件说明


    控件
    控件类型
    控件的功能描述




    登录名
    文本框
    用户在这里输入登录名;如果是第一次登录则显示空白;默认显示最近一次的登录名


    密码
    文本框
    用户在这里输入登录密码


    登录
    按钮
    用户点击登录按钮,然后才能进入系统


    出错提示
    标签
    用户登录失败时出现此标签,显示失败原因;默认下不显示



    2.1.2 主界面用户在打开网站后会进入主界面,该主界面上面列出了所有功能模块的链接,单击链接即可进入相应模块的主界面。该导航栏方便了用户在不同模块之间的切换,如下图所示。

    功能说明点击导航栏中每个功能模块的链接,都会进入相应模块的主界面。这个主界面默认为该功能模块下属的几个子链接中的第一个链接页。但会根据用户是否登录,如果用户已经登录,会在用户信息直接显示用户昵称,点击后毋须输入帐号密码即可进入个人信息管理。
    控件说明


    控件
    控件类型
    控件的功能描述




    电影信息
    标签
    这是一个超链接;点击后显示电影详情


    影院
    标签
    这是一个超链接;点击后显示影院列表


    圆点
    按钮
    这是一个超链接;点击后显示下一页内容


    搜索
    按钮
    这是一个超链接;点击后根据前面的输入信息显示需要内容


    搜索框
    文本框
    用于输入内容供搜索按钮检索


    上映类型
    Selection
    用于选择内容供搜索按钮检索


    地区
    Selection
    用于选择内容供搜索按钮检索


    影院
    Selection
    用于选择内容供搜索按钮检索


    推荐
    标签
    这是一个超链接;点击后根据评价排名和显示电影;未登录用户不显示此项


    热度排行
    标签
    这是一个超链接;点击后根据评价排名和显示电影;默认根据热度排行


    评价排行
    标签
    这是一个超链接;点击后根据评价排名和显示电影



    2.1.3 各项列表电影院列表用户点击影院后进入此页,该页界面如下图所示。

    功能说明:

    查询的输入框查询时,可输入电影名和影院名,系统自动匹配文本框可以为空,,系统只根据前面三者的选项筛选搜索按钮以表格形式显示查询出的电影,如图 7所示单击电影名称跳转到影院详情单击正在上映的电影数则进入此影院正在上映的电影列表返回按钮点击返回上一页
    控件说明


    控件
    控件类型
    控件的功能描述




    返回图片
    按钮
    这是一个超链接;点击后返回上一页


    影院,位置,正在上映电影数
    标签
    这是一个标签;用来显示所列信息


    影院名
    标签
    这是一个超链接;点击后显示此影院详情


    区名
    标签
    用来显示此列中影院的位置


    正在上映*部电影
    标签
    这是一个超链接;点击后显示此影院上映的电影列表


    搜索
    按钮
    这是一个超链接;点击后根据前面的输入信息显示需要内容


    搜索框
    文本框
    用于输入内容供搜索按钮检索


    上映类型
    Selection
    用于选择内容供搜索按钮检索


    地区
    Selection
    用于选择内容供搜索按钮检索


    影院
    Selection
    用于选择内容供搜索按钮检索


    页数选择器
    标签
    这是一个超链接;点击后进入上一页或者下一页


    页数指示器
    标签
    用于指示当前所在页数



    单影院正在上映的电影列表默认界面如下图所示。

    功能说明
    查询的输入框

    查询时,可输入电影名和影院名,系统自动匹配文本框可以为空,,系统只根据前面三者的选项筛选
    搜索按钮

    以表格形式显示查询出的电影,如图 7所示单击电影名称跳转到电影详情单击点击购买则进入购票网站
    返回按钮

    点击返回上一页

    控件说明


    控件
    控件类型
    控件的功能描述




    返回图片
    按钮
    这是一个超链接;点击后返回上一页


    电影名,价格,点击购买
    标签
    这是一个标签;用来显示所列信息


    影院名
    标签
    这是一个超链接;点击后显示此电影详情


    价格
    标签
    用来显示此列中影院的位置


    点击购票
    标签
    这是一个超链接;点击后进入购票页


    搜索
    按钮
    这是一个超链接;点击后根据前面的输入信息显示需要内容


    搜索框
    文本框
    用于输入内容供搜索按钮检索


    上映类型
    Selection
    用于选择内容供搜索按钮检索


    地区
    Selection
    用于选择内容供搜索按钮检索


    影院
    Selection
    用于选择内容供搜索按钮检索


    页数选择器
    标签
    这是一个超链接;点击后进入上一页或者下一页


    页数指示器
    标签
    用于指示当前所在页数



    单电影上映的影院列表默认界面如下图所示。

    功能说明
    查询的输入框

    查询时,可输入电影名和影院名,系统自动匹配文本框可以为空,,系统只根据前面三者的选项筛选
    搜索按钮

    以表格形式显示查询出的电影,如图 7所示单击电影名称跳转到电影详情单击点击购买则进入购票网站
    返回按钮

    点击返回上一页

    控件说明


    控件
    控件类型
    控件的功能描述




    返回图片
    按钮
    这是一个超链接;点击后返回上一页


    电影名,价格,点击购买
    标签
    这是一个标签;用来显示所列信息


    影院名
    标签
    这是一个超链接;点击后显示此电影详情


    价格
    标签
    用来显示此列中影院的位置


    点击购票
    标签
    这是一个超链接;点击后进入购票页


    搜索
    按钮
    这是一个超链接;点击后根据前面的输入信息显示需要内容


    搜索框
    文本框
    用于输入内容供搜索按钮检索


    上映类型
    Selection
    用于选择内容供搜索按钮检索


    地区
    Selection
    用于选择内容供搜索按钮检索


    影院
    Selection
    用于选择内容供搜索按钮检索


    页数选择器
    标签
    这是一个超链接;点击后进入上一页或者下一页


    页数指示器
    标签
    指示当前所在页数



    2.1.3 详情页员工可通过单击电影名或者影院名进入此页面。
    电影详情该页由点击电影名进入,默认界面如图8所示。

    功能说明
    网页展示该电影的详情信息
    点击”点击购买可进入购票页面,显示该电影在各大影院的上映信息”
    点击我要评论显示个人评价:

    评价内容不能为空可选择影院的评星登录后自动获取用户昵称评价后返回评价列表
    点击返回图片返回上一页
    点击最新评论和最热评论可对评论排行显示
    点击分享按钮可对此信息进行分享

    控件说明


    控件
    控件类型
    控件的功能描述




    电影名
    标签
    显示该电影的名称


    评分
    标签
    显示该电影的评星


    电影详情
    标签
    显示该电影的简介


    电影海报
    图片
    显示该电影的海报


    最新评论,最热评论
    标签
    这是个超链接;默认为最新评论


    评论
    标签
    显示评论内容


    支持,反对
    表情
    用来展示其他人对评论的卡饭;点击后后面识字加1;每个人只能点一次,根据Cookie限制


    支持数,反对数
    标签
    展示支持数和反对数


    页数选择器
    标签
    这是一个超链接;点击后进入上一页或者下一页


    页数指示器
    标签
    指示当前所在页数


    返回图片
    按钮
    这是一个超链接;点击后返回上一页


    2 评论 47 下载 2018-11-05 11:13:06 下载需要13点积分
  • 基于JSP和SQL Server的个人健康数据采集与分析系统

    摘 要进入21世纪以来,人们开始更加关注个体的身体健康,加深了对健康的认识,健康的概念也从无病治疗转变为无病预防。为了更好的预防疾病、进行有效的健康管理,开展以个人和家庭为中心,以医疗服务为中心的个人健康数据收集和分析系统具有重要意义。
    本论文分析了国内外健康管理的现状,指出了当前健康管理发展中存在的问题,并阐述了建立健康个人管理体系的必要性,设计和实现了一个个人健康数据记载、查看和统计的管理信息系统,实现了对个人健康日常数据、体检数据和就医数据的分析管理,并以此为依据为个人提供健康生活的建议。
    本文着重讨论了面向对象的分析过程,研究了基于Web应用系统的开发过程和相关技术结合实际项目的功能需求,采用了B/S(Browser/Server,浏览器/服务器)架构在JAVAEE平台中使用JAVAEE和SQL Server技术相结合共同实现系统。
    关键词:健康管理;健康数据收集与分析;web应用系统;B/S
    ABSTRACTSince the beginning of the 21st century, people have begun to pay more attention to the health of individuals and have deepened their understanding of health. The concept of health has also changed from disease-free treatment to disease-free prevention. In order to better prevent diseases and perform effective health management, it is of great significance to develop personal health data collection and analysis systems centered on individuals and families and centered on medical services.
    This paper analyzes the current status of health management at home and abroad, points out the current problems in the development of health management, and elaborates the necessity of establishing a healthy personal management system. It designs and implements management information for personal health data records, reviews, and statistics. The system has realized the analysis and management of personal health daily data, physical examination data, and medical data, and based on this as a basis for individuals to provide healthy living advice.
    This article focuses on the object-oriented analysis process, researching the development process of Web-based application systems and related technologies combined with the functional requirements of the actual project, using the B / S (Browser / Server, browser / server) architecture used in the JAVAEE platform The JAVAEE and SQL Server technologies are combined to realize the system.
    Keywords: health management; health data collection and analysis; web application system; B/S
    第一章 前言1.1 课题背景身体健康是人们享受生活和提高生活质量的根本,拥有健康的身体才能更好的学习和工作,可是随着生活节奏的加快和生活压力的加大,越来越多的人处于亚健康的状态,人们在努力为自己创造美好生活的同时也对自己的身体健康越来越重视。
    健康管理的概念最早见于美国,早在1929年美国洛杉矶水利局就成立了最早的健康维护组织,健康管理既是一个概念,也是一种方法,更是一套完善、周密的服务程序,其目的在于使人们能更好地拥有健康、恢复健康和促进健康,并最终达到提高生活质量的目的,除此以外,良好的健康管理习惯也能减少疾病,有效降低个人和国家的医疗支出[1]。健康管理有如下几大作用:

    了解个人的身体和年龄变化,用历史数据来判断疾病指向
    根据日常健康数据判断发病概率,以此为依据提供给医生做出判断,并由医生提供降低慢性病发生危险性的行为干预方案
    长期(终生)跟踪高危人群的健康,最大限度减少重大疾病的发生
    节省维护健康的时间和金钱,提高保健效率

    在美国,医疗保险的发展和医疗服务模式的改变始于20世纪70年代,因此医生需要帮助预防疾病并节省医疗费用。卫生服务机构可以评估人群的健康状况和疾病的风险评估,科学地预测疾病的风险因素,并制定具体的目标预防性卫生措施。健康管理的实施取得了显着成效。通过管理美国医疗费用,与前一期间相比,我们节省了约10%。它还可以预防疾病的发生并提高生活质量。根据这些数据,美国的健康管理计划从1978年到1983年,美国的胆固醇水平下降了2%。高血压水平下降4%,冠心病发病率下降16%。密歇根大学健康管理研究中心主任W.Edington博士表示,美国20多年的研究时间已经达到9:90%的人通过健康管理,1法律结论,成本将下降到10%。 10%未管理的医疗保健费用增加了90%。通过经济分析,发现人民币1元的医疗保健费用相当于降低医疗费用3-6元。如果劳动生产率提高,实际收入将是投资的八倍。
    在日本,不到2亿人拥有60多万营养学家提供专业的保健服务。行政机构和非政府卫生管理机构为所有公民提供医疗服务,并提供注册的外国卫生管理服务。它拯救了成千上万的病人,并过着漫长而健康的生活。今天,日本人的平均预期寿命达到84岁,是世界上第一次。
    中国的健康管理刚刚起步,是一个朝阳产业。目前,中国大陆只有少数专业的健康管理机构,其中大部分是医院和体检中心的附属部门。目前没有关于健康管理从业人员的准确数据。据估计,全国有超过10万人,这意味着中国享受科学和专业健康管理服务的人数只有总人口的一半,十分之一。美国70%的人口。要从健康管理公司或公司获得完美服务还有很长的路要走。
    建立健康管理平台,利用健康数据和分析结果护送人们的健康,是健康管理与现代技术相结合的必然结果。这需要基本的医学知识,临床医学知识,流行病学知识,计算机技术和数理统计。具有如此综合素质的专业人员还必须得到大量健康医学,预防医学,临床医学和康复医学方面的资深专家的支持。
    个人健康数据是健康管理的重要基础。没有这些数据的支持,就不会有疾病控制和健康咨询的后续服务。但是,个人健康数据(包括日常体重指数,体检数据,医疗数据等)是分散的,众多的,独立的。如何收集属于不同系统的各种个人健康数据面临着很大的困难。建立个人健康数据收集和基本分析系统对健康管理尤为重要。
    1.2 课题的目的与意义传统的个人健康数据,特别是日常健康指标已被破坏和管理。人们生病或体检时只注意健康数据。此外,健康管理仍主要依靠单一的体格检查或医疗数据。医生还根据单一数据就一些生活习惯提供建议和意见。他们不会将个人历史记录和日常行为考虑在个体慢性病的影响之中。另外,所谓健康管理也主要针对已患病的患者,尚未实现“早期筛查,早期预防,早期发现,早期诊断”的健康管理模式。
    近年来,随着世界数字信息管理的进步,医院建立了自己的管理体系,系统地管理住院病人的病史和病历。许多医院也对人们的健康检查系统进行持续动态管理。 。利用计算机技术,健康信息管理系统以计算机为工具,对用户的体检数据进行信息管理,使管理人员免于繁琐的数据计算和处理,帮助用户更好地监督和监督身体健康。提高管理和效率。
    一些针对个人日常健康指数检测的产品也应运而生,例如风靡一时的各类健康手环,可以收集检测用户的日常健康指数,并建立健康数据变化曲线。
    虽然现在医院都建立了自己的体检和就医管理系统,运动手环等针对日常健康数据收集的产品也层出不穷,但是这些数据仍然处于割裂的状态,没有很好的平台将它们整合起来。
    一个能够解决大多数用户的个人健康数据收集和分析的系统应该具有几个优点:第一个用户可以随时随地通过计算机或手机的浏览器访问系统; 第二个可以在开启系统账户后随时随地跟踪您自己的健康数据; 第三是用健康数据可以建立历史变化曲线图。 此外,该平台还可以作为用户学习健康管理方法,基本健康知识和疾病预防控制知识的一种方式。
    1.3 本文研究的内容本课题将设计和实现一个Web系统能实时的让用户录入自己的各类健康数据,并根据数据做出简单分析建立个人健康曲线图,同时提供相关的信息资讯和知识,作为人们一个学习健康知识和更好管理自己健康的平台。
    1.4 论文结构简介本论文记录着对系统开发前期的调研、设计到系统的开发、测试和总结的全过程。

    前言:本章主要介绍系统当前社会背景及开发的目的与意义,同时对相应技术和开发工具进行说明
    面向对象的系统分析:本章主要好对开发系统进行可行性分析和用户需求调研,并对根据用户需求进行需求建模。根据需求,绘制用例图以及数据流图。为系统设计打下基础
    面向对象的系统设计:根据用户需求对系统进行概要设计,进行模块设计,绘制功能模块图,对数据库进行设计,绘制数据库物理模型图以及对表进行说明,为系统实现提供指导
    系统实现与测试:对系统中的功能实现进行介绍,介绍同时展现所实现的 UI 界面展示。另外是对系统测试进行说明
    结论:对系统进行总结和自我总结。另外,论文还包括结论、参考文献及致谢三部分,最后附录了全文表索引和全文图索引

    第二章 面向对象的系统分析2.1 可行性分析可行性分析是软件开发过程的一个关键阶段,也是项目规划阶段决策和启动的重要依据。可行性分析是利用系统化工程化的分析方法,为项目的启动和进行提供具有预见性、公正性、可靠性和科学性的依据,对整个系统的分析具有举足轻重的作用。
    本文将对系统进行经济可行性、技术可行性和操作可行性四个方面的论述,也是对课题研究必要性的一个更好的说明。
    2.1.1 经济可行性分析目前健康管理市场巨大,比如近几年兴起的健康手环类产品,由于系统的个人日常健康数据的录入需要用户自己采集。开发本系统之后可以联系制作健康手环的公司一起制作合作战略,比如本系统上可以给合作的公司打一些广告等。目前大数据是一个很火的话题,各个有能力的公司都在建立自己的大数据服务平台。由于本系统需要处理个人的各种数据用户的日常健康数据、体检数据、医疗数据这件为以后建立大数据平台提供了大数据支持。基于大数据之上的机器学习可以从目前的个人健康来预测以后的健康,这样就可以早预防,今后的这个功能也是个重要的卖点。
    本课题是在个人计算机上来实现软件的开发,在开发阶段不需要大量资金的投入,因此在经济上是可行的。在系统的运维阶段只需要一个系统管理员和几个医院的工作人员来管理数据,不需要大量的人员去运维成本低。系统的数据来自各个用户的日常录入和在医院体检和生病就医录入,只要有用户就会得到数据,因此数据成本底。这些数据可以为以后的系统升级做各种支持。
    2.1.2 技术可行性分析该系统采用的基本技术有JAVA技术,数据库技术,网络通信技术等,这些技术已经越来越成熟,能够充分满足应用需求。 硬件上的计算机计算速度快,存储容量大,可靠性高。 操作系统使用Windows 10,它具有强大的界面功能和稳定性。 因此,它在技术上是完整的。
    本系统在用到了MVC模式,前端用到了HIGHCHARTS图表工具。MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑,MVC独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中[2]。Highcharts是一个开源的也是一个用纯JavaScript编写的一个图表库,能够很简单便捷的在web网站或是web应用程序添加有交互性的图表,并且免费提供给个人学习、个人网站和非商业用途使用,HighCharts支持的图表类型有曲线图、区域图、柱状图、饼状图、散状点图和综合图表[3]。因此在开发系统中技术是成熟的。
    2.1.3 操作可行性分析从课题的选择到系统的设计和开发,在此期间收集了大量的健康管理和WEB系统开发等信息。通过对数据的阅读和系统的实际开发,对个人健康管理系统有了全面的了解。系统的详细设计采用模块化设计方法。通过系统需求分析,功能设计,数据库设计,详细设计和编写代码,实现数据库连接和系统操作。因此整个系统是可操作的。
    本系统的界面在WEB上,用户可以随时随地的通过电脑、智能手机、平板电脑等终端访问。因为系统的开发基于B/S,医院人员、运维人员多方都可以在上面操作。系统主要的网页界面最上面都有菜单这为用户提供了良好的用户体验。因此整个系统具有操作科学性。
    2.2 需求获取需求是用户一种期望,是用户期望改善现状,解决某些问题或达到某种目标的需要。需求实现的过程,就是通过软件产品的功能达成用户目标,使之与用户期望目标相符的过程。所以在系统设计之前,需要做好需求收集工作。
    个人健康信息的采集与分析系统的需求来自方方面面,这取决于医疗服务的特殊性质和环境,以及服务内容和环节的复杂性。根据现有的条件,针对需求分析目标,主要采取了以下方法收集需求:
    通过对部分潜在用户以及使用过网络医疗服务的用户采集相关需求,如期待的功能、服务过程中的用户体验,存在的问题和想法,以及用户心理等信息采集。
    为找出本课题软件产品的用户需求,采用的最直截了当的方法就是询问。通过直接与最终用户的访谈或调查,了解用户对于目前存在的个人健康系统使用过程中存在的问题和想法,对业务的未来发展趋势进行预测和展望,并将收集的信息经过整理分析形成软件的最原始需求。具体的调查方式和分析过程如图 2.1所示。

    2.3 业务流程分析经过对其他线上服务产品和传统医疗行业的医疗服务的业务流程调研,整理出医疗服务核心流程随着时代的变迁而变化的变化。
    传统行业医疗服务业务流程当患者生病之后,大概的分析自己病情,判断是否在哪家医院就诊,通过医院就诊得出生病就医记录情况,并且以纸质的形式打印出就医结果,得到生病信息报告单。传统行业服务业务流程图如图 2.2所示。

    互联网医疗服务业务流程,患者感觉自己的身体出现问题后在各个医院门户网站上向医生咨询,跟据咨询的信息选择是参加体检还是就医并且选择好医院,完成在医院的体检或者就医后得到身体出现问题的详细原因,得到体检或者医疗报告单。互联网医疗服务业务流程图如图 2.3所示。

    结合个人健康数据采集与分析系统的医疗服务业务流程用户首先查看自己的以前记录到系统的平时健康数据、体检数据、医疗数据根据系统反馈的健康情况在互联网上进行咨询,根据咨询的情况选择体检或者就医。在医院体检或者就医后等到的体检单和医疗单给医院的系统数据管理员录入系统。建立动态的医疗信息。个人健康数据管理医疗服务业务流程图如图 2.4所示。

    2.4 需求建模用例建模是用于描述一个系统的功能(即系统应该做什么)的建模技术[6]。根据调研系统需求,对个人健康信息采集与分析系统进行初步分析与设计,结合功能需求分析整理后,绘制个人健康信息采集与分析系统用例图如图,用例图如图 2.5所示。

    用例是描述了参与者为达到某个目的而与系统进行的一系列交互,执行结果将为参与者提供可度量的价值。这里使用用例描述对基本用例进行描述。
    2.4.1 添加日常健康数据用例添加健康数据用例是用户点击相应服务后,用户向系统中添加数据系统并保存数据。

    用例名称:添加健康数据
    用例编号:UC1
    用例描述:把个人健康数据信息登入到系统
    参与者:系统用户
    前置条件:用户登录系统成功
    后置条件:添加健康数据完成
    过程描述

    用户登录系统成功后,在主页面中找到健康数据管理信息专栏其中包括添加日常数据、添加体检数据、添加生病就医数据点开具体一项进行信息添加

    2.4.2 浏览健康数据曲线图用例用户通过添加健康数据之后,需要查看的各种健康数据的曲线或统计图,系统展示图表。

    用例名称:浏览身体健康信息图表
    用例编号:UC2
    用例描述:浏览身体健康数据信息图表
    参与者:系统用户
    前置条件:用户登录系统成功和添加健康数据完成
    后置条件:系统图表展示
    过程描述

    用户登录系统成功后,在主页面找到健康数据管理信息栏后在里面添加好日常数据、体检数据、生病就医数据后需要动态的有对比的分析身体健康信息用户点开身体健康数据图表,系统会向用户展示近段时间的身体数据信息状况

    2.4.3 查看身体健康状况用例图用户通过添加一段时间的健康数据和查看系统所展示的健康数据曲线和统计图表后,系统会根据几个重要参数来反馈出你的身体是否健康,体统把身体健康分为健康、亚健康、生病阶段并且系统对于你现在身体身处的阶段来给出一些简单的生活建议。用户可以点击查看身体健康状况从系统中得到身体健康状况信息。

    用例名称:查看身体健康状况
    用例编号:UC3
    用例描述:系统同过几个简单的健康值来反馈出你的身体状况
    参与者:系统用户
    前置条件:用户登录系统成功和添加健康数据完成
    后置条件:系统展示出身体基本状况
    过程描述

    用户登录系统成功后,在主页面中找到健康数据管理信息专栏其中包括添加日常数据、添加体检数据、添加生病就医数据后系统会从这些健康数据中选出几个中要的参数来得到用户的身体健康状况并且用户会给出一些合理的简单的建议

    2.4.4 用户管理用例图系统在运用之前系统里面已经默认了一个系统管理员,这个管理员拥有系统的最高权限能对系统中的数据增加、删除、修改、查看。系统管理员也可以对注册的用户账号的注册的医院数据管理员的账号进行添加和删除。

    用例名称:用户管理
    用例编号:UC4
    用例描述:管理系统中登入的健康数据和用户账号
    参与者:系统管理员
    前置条件:系统管理员登录系统成功
    后置条件:系统管理员对系统中的数据增、删、改、查成功
    过程描述

    系统管理员登录系统成功后,进入用户管理页面。系统管理点击查看所用户和医院数据管理员,删除用户或者医院数据管理员0 删除成功。更新用户表的中的数据

    2.5 系统数据需求分析数据流图简称 DFD,它从数据传递和加工角度,以图形方式来表达系统的逻辑功能、数据在系统内部的逻辑流向和逻辑变换过程,是结构化系统分析方法的主要表达工具及用于表示软件模型的一种图示方法,用于反映系统必须完成的逻辑功能[7]。其中矩形用于表示数据源和终点,圆型或圆角矩形用于表示数据加工处理,椭圆线用于表示数据存储。
    分析整个系统的数据需求得到以下的数据流图:
    顶层图,用户和系统管理员与系统的交互,其数据流图如图 2.6所示:

    0层图,系统内部的数据流向,其数据流图如图 2.7所示:

    2.6 本章小结本章主要是对系统开发前期的分析和调研进行说明。本章首先从技术,经济和社会多方面完成了对系统开发的可行性进行分析,判断系统是否具备开发价值,并对系统进行了各种方法的需求调研,整理出系统基本功能需求,并绘制用例图和数据流图,为后续的系统设计和开发提供了指导方向。
    第三章 面向对象的系统设计3.1 概要设计概要设计是在进行用户需求分析之后,对于需求分析阶段提出的实现问题进行概要的回答,确定系统的基本框架。
    3.1.1 功能模块图个人健康数据采集与分析系统功能总体如图 3.1所示:

    3.1.2 模块设计模块是数据说明、可执行语句等程序对象的集合,可以单独命名且可通过名字来访问。模块设计是概要设计的重要内容,主要是根据需求建模提炼系统的基本模块,以及这些模块的输入、输出和交互关系。在对个人健康数据采集与分析系统的需求进行全面和仔细的分析后,整理出系统的整体功能模块包括:健康数据管理模块,健康数据统计模块,健康分析管理模块,系统管理模块四大模块。

    健康数据管理:健康数据来源于个人平时的健康指数,如心跳、血压等,也包括体检记录和生病就医的医疗记录。本课题的系统中这些数据主要由用户录入,但在课题的延伸中,这些数据应该来自于各大医院的管理信息系统接口以及智能设备。该功能具体细分如下:

    日常健康数据:系统用户把每天的健康数据,如体温、血压等录入系统,并且用户可以查询当天的数据和历史记录体检数据:医院数据管理员或者后台工作人员根据用户的体检数据报告单把体检信息,比如血液、肝、肺等录入系统,并且提供用户查询生病就医数据:医院数据管理员或者后台工作人员根据用户的医疗信息,比如就诊科室、就诊医生、处方等录入系统,并且提供用户查询
    健康数据统计:通过收集的健康数据建立历史曲线图,做出历史统计,该功能具体细分如下:

    日常健康数据曲线图:经过系统采集的日常健康数据,并建立历史变化曲线,并以文字和表格界面的方式向用户展示体检数据分析柱状图:经过系统统计体检健康数据,并建立历史变化柱状图,并以在界面以柱状图的方式向用户展示生病就医统计:经过系统统计体检健康数据,建立饼状图统计
    健康分析管理:系统设置健康、亚健康、生病标记和简单的生活建议,通过健康数据曲线系统给出结果,该功能具体细分如下:

    日常健康分析:根据建立的历史变化曲线图,简单的判断身体健康状况和给出简单的生活建议并以文字的方式展示给用户体检和生病就医健康分析:跟据建立的体检历史变化柱状图和就医记录饼状图。简单的判断身体健康状况和给出简单的生活建议并以文字的方式展示给用户
    系统管理:主要提供网站维护和账号管理的基本功能,具体包括:

    账号管理:包括基本信息设置、手机号码绑定、邮箱账号绑定、退出登录、密码修改等内容

    3.2 数据库设计3.2.1 数据库物理模型图物理数据模型(Physical Data Model,PDM),提供了系统初始设计所需要的基础元素,以及相关元素之间的关系,即用于存储结构和访问机制的更高层描述,描述数据是如何在计算机中存储的,如何表达记录结构、记录顺序和访问路径等信息[4]。本系统的数据库物理模型图采用ProcessOn画图工具,ProcessOn是一个面向垂直专业领域的作图工具。个人健康数据采集与分析系统的设计与开发的数据库物理模型图如图 3.2所示。

    3.2.2 数据库表根据使用ProcessOn设计的数据库物理模型图,可以引申设计出系统的数据库表信息。此系统中主要包括的基本表包括:用户表、基本信息表、医疗记录表、健康信息表、日常健康表、体检信息表、健康信息表,具体的数据表结构设计如下说明。
    用户表:主要用于保存用户的账号密码和用户的权限信息。是系统中最基本的一张表。其表结构如表 3.1所示。



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




    身份证号
    Id_card
    VARCHAR
    20
    主键


    账号
    Account_number
    VARCHAR
    20



    密码
    Password
    VARCHAR
    20



    用户类别
    User_category
    VARCHAR
    1



    基本信息表:主要存放用户的基本信息,比如姓名、性别、职业等。其表结构如表 3.2所示。



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




    用户ID
    PersonID
    INT
    10
    自动增长


    身份证号
    Id_card
    VARCHAR
    20
    主键


    姓名
    Name
    CHAR
    20



    性别
    Sex
    CHAR
    2



    出生日期
    BirthDay
    DATETIME
    10



    职业
    Profession
    VARCHAR
    20



    医疗记录表:主要用于存放用户生病就医的数据,就诊的医院、医生、生病的原因等。其表结构如表 3.3所示。



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




    医疗ID
    Record_ID
    INT
    10
    主键


    身份证号
    Id_card
    VARCHAR
    20
    外键


    医院
    Hospital
    TEXT




    诊疗项目
    Treatmentltem
    TEXT




    诊疗原因
    TreatmentReason
    TEXT




    诊疗结果
    Result
    TEXT




    目前状况
    State
    TEXT




    备注
    Remarks
    TEXT




    诊疗日期
    Date
    DATETIME




    日常健康表:主要记录用户平时自己录入的健康数据,每天自己基本的生命特征。其表结构如表 3.4所示。



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




    生命体征ID
    Measure_ID
    INT
    10
    主键


    身份证号
    Id_card
    VARCHAR
    20
    外键


    体温
    Temprature
    DECIMAL
    20



    呼吸
    Brreathe
    INT
    50



    脉搏
    Pulse
    INT
    50



    心跳
    HeartRate
    INT
    50



    日期
    DateTime
    DATETIME




    体检信息表:主要记录在体检时人体各个功能的状况供其以后做分析。其表结构如表 3.5所示。



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




    体检单号ID
    Physicalexamination_ID
    INT
    10
    主键


    身份证号
    Id_card
    VARCHAR
    20
    外键


    红细胞
    RBC
    float
    10



    血红蛋白
    HGB
    float
    10



    白细胞
    WBC
    float
    10



    淋巴细胞
    LYM
    float
    10



    血小板
    PLT
    float
    10



    血糖
    Bloodsugar
    float
    10



    血脂
    Bloodfat
    float
    10



    日期
    DateTime
    DATETIME




    尿蛋白
    RBC
    float
    10



    尿葡萄糖
    HGB
    float
    10



    肝功能
    Liver_function
    bit
    2



    HbsAg抗原
    HbsAg
    bit
    2



    HbsAb抗体
    HbsAb
    bit
    2



    HbeAg抗原
    HbeAg
    bit
    2



    HbeAb抗体
    HbeAb
    bit
    2



    HbcAB抗体
    HbcAb
    bit
    2



    健康信息表:在经过医院的医护人员分析用户的各种健康数据之后需要填入的用户身体状况情况。其表结构如表 3.6所示。



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




    身份证号
    Id_card
    Nvarchar
    20
    主键


    日常健康等级
    DailySummary
    Nvarchar
    10



    日常健康分析
    DailyAdvise
    TEXT




    就医后等级
    MedicalSummary
    Nvarchar
    10



    就医后分析
    MedicalAdvise
    TEXT




    日期
    Date_time
    DATETIME




    3.3 类图类图(Class diagram)是显示了模型的静态结构,特别是模型中存在的类、类的内部结构以及它们与其他类的关系等,类图不显示暂时性的信息,类图是面向对象建模的主要组成部分[5]。它不仅用于应用系统分类的一般概念建模,而且用于详细建模和将模型转换成编程代码。类图也可用于数据建模。
    3.3.1 健康分析类图健康分析的过程是在用户把自己的日常健康数据和医生把用户的体检和就医数据录入系统之后。医生通过观察系统产生的数据统计后根据分析数据统计来为用户的身体健康做一个评估。由于用户的健康数据是经过用户本人和医生合起来录入的,所以健康的评估医生也要分为两种。一个是日常健康数据评估还有一个是体检和生病就医的总和评估。
    在系统中的过程是医院数据管理员通过点击按键,系统调用HealthAnalusisServlet的实例,MealthAnalusisServlet的实例再访问HealthAnalysisDao的实例。HealthAnalysisDao的实例通过调用Util包中的DbUtl来访问数据库。从而实现数据的录入。用户要看自己的健康分析结果在系统中的实例的调用也是基本差不多。系统中UerSerlet通过调用dao层的UserDao和HealthAnalysisDao的实例。Dao层的实例在来访问Util包中的DbUtil来访问数据库的健康分析数据。健康分析过程的类图如图 3.3所示。

    3.3.2 健康数据录入类图本系统研究的内容是个人健康数据采集与分析。健康数据的采集在系统中占很重要的一部分。用户有权限自己录入日常健康数据,医院的医生有权限录入。在系统运行过程中vitalSignServlet实例调用VitalSignDao来实现对日常的增、删、改、查alRecordServlet和PersonInformationServelet来调用MedicalRecordDao和PersonInformationDao一样来实现对体检和生病就医数据的增删改查。健康数据录入类图如图 3.4所示。

    3.3.3 用户管理类图个人健康数据采集与分析系统中的登录有三种权限。分为用户、医生或医院管理员、系统管理员。用户管理在本系统种十分重要。在系统的种UserServlet调用UserDao和HealthAnalysisDao。UserServlet也与HealthAnalysisServlet、PersonInfomationServlet间接有联系。系统管理员在删除一个用户的时候在系统种呈现如图关系。删除用户会连带着用户的所有数据都会一起删除。用户管理类图如图 3.5所示。

    3.4 本章小结面向对象的方法正受到全世界的强烈关注和高度重视,针对日趋复杂的软件需求,业界也越来越崇尚利用面向对象的方法和思想进行软件开发,面向对象技术也开始应用于软件的开发[8]。本章主要是通过面向对象思想对系统功能和业务逻辑设计进行说明,将系统需求进行细化,实现一个由粗到细的过程。根据本章可以明确的知道系统中各功能模块的设计、业务实现和对象的命名规范等相关信息,本章是系统实际开发过程中的一个指引说明。
    第四章 系统实现与测试4.1 系统实现的说明系统实现的目的,是以系统设计得到的系统物理模型为依据,通过某种程序设计语言及其编译平台,进行程序设计,实现每一个算法细节,并进行测试,最终获得一个能够实际运行的系统[7]。本系统的系统运行及测试环境如下说明:

    浏览器版本:google 66.0.3359.139
    处理器:Intel 酷睿i7 77700K
    运行内存:16GB
    机身存储:1TB
    屏幕分辨率:1920×1080

    4.2 项目程序结构4.2.1 项目总体程序结构图项目程序结构图体现的是一个项目的总体程序架构,在项目的结构中每个结构都有特定的功能,每种特定的功能都封装在一个包中。个人健康数据采集与分析系统的设计与开发项目总体结构图如图 4.1所示。

    4.2.2 数据访问层程序结构图项目总体程序结构图中的数据访问层程序结构是在用DButil工具类连接数据库后再对数据库里面的数据执行增、删、改、查。数据访问层程序结构图如图 4.2所示。

    4.2.3 JavaBean层程序结构图JavaBean是对象的标准,JavaBean满足了提供一个无参数的构造方法、私有化属性、提供公开的get和set方法,用于访问其属性。在个人健康数据采集与分析系统的设计与开发项目中JavaBean层的实例主要为正在处理的数据提供一个存放的容器。JavaBean层程序结构图如图 4.3所示。

    4.2.4 测试层程序结构图测试层主要为个人健康数据采集与分析系统的设计与开发项目放置各种对项目的测试程序。测试层程序结构图如图 4.4所示。

    4.2.5 工具层程序结构图主要放置个人健康数据采集与分析系统的设计与开发项目的工具类,工具层程序结构图如图 4.5所示。

    4.2.6 业务层程序结构图主要放置个人健康数据采集与分析系统的设计与开发项目中的业务逻辑处理类。业务层程序结构图如图 4.6所示。

    4.2.7 WebContent层程序结构图WebContent主要放置在Web界面上展示的文件。WebContent层程序结构图如图 4.7所示。

    4.3 系统界面实现4.3.1 系统登录界面实现打开google浏览器,输入localhost:8080/HMS/ ,进入登录界面。登录界面如图 4.8所示。

    4.3.2 系统注册界面实现点击注册账号,跳转到注册页面。登录注册界面如图 4.9所示。

    4.3.3 系统主界面个人健康管理系统进入后,进入个人健康服务主页,我以pengyongqian用户进入系统主界面。主界面会显示健康数据管理、健康数据统计展示、健康分析、系统管理这几个一级菜单。系统主界面如图 4.10所示。

    4.4 系统测试软件测试是对软件需求分析、设计规格说明和编码的最终复审,是软件质量保证的关键步骤[11]。本节将对系统开发完成后的测试进行说明,并从数据完整性、验证测试和业务逻辑功能测试三个方面进行说明。
    4.4.1 测试的目的与内容在系统开发过程中和开发完成后,为了保证系统运行的安全性、可行性、正确行和稳定性,我们需要对系统进行一系列的大量的数据测试,发现系统中存在错误和漏洞,进而修补漏洞,改正错误,完善系统。
    测试内容:

    功能测试:对各模块的具体功能进行测试,测试各模块是否能够完成需求报告文档中的功能
    性能测试:对系统能否快速准确无意外的完成功能进行测试
    安全性测试:主要对各用户权限操作进行测试。对数据的操作要严格按照用户权限进行。不能出现超越权限的数据操作行为
    用户界面测试:系统界面是否符合操作习惯和人们的审美程度

    4.4.2 具体测试说明测试方法可以分黑盒测试和白盒测试。黑盒测试主要是指在系统设计完成后,根据系统各个部分功能的不同,对各个具体的功能进行测试。白盒测试主要是根据规格说明书的要求和程序内部结构对程序进行测试。白盒测试的目的旨在于测试系统内部的设计思路是否清晰正确,系统逻辑结构是否正确。系统是否按照设计者所设计的思路进行正确运行。
    本系统的白盒测试贯穿了系统实现的整个过程,而在整体测试阶段则设计了一些测试用例,下面以登录和婚庆预约服务两个模块的测试进行具体的说明。
    登录模块测试
    测试流程:打开Web网页,进入登录页面,输入账号和密码看结果是否符合登录模块用例表。登录模块用例表如表 4.1所示:



    测试用例
    预期结果
    实际结果
    备注




    账号:pengyongqian
    弹出错误提示,密码为空
    登录失败,提示请重试
    通过


    密码:null





    账号:pengyongqian
    弹出错误提示,密码错误
    登录失败,提示请重试
    通过


    密码:123





    账号:pengyongqian
    登入系统,显示主界面
    登录成功,显示主界面
    通过


    密码:123456





    当用户登录输入错误信息时,系统会提示,然后页面会显示提示信息,如图 4.11所示:

    添加日常数据测试
    测试流程:成功登录Web主界面后,点击日常健康数据,点击添加。输入日常数据。添加日常数据测试用例表如表 4.2所示:



    测试用例
    预期结果
    实际结果
    备注




    身份证号:空
    添加失败
    添加失败
    通过


    体温:37





    呼吸:30





    心跳:70





    血压:60





    身份证号:15
    添加成功
    添加成功
    通过


    体温:37





    呼吸:30





    心跳:70





    血压:60





    当用户成功输入日常数据时并成功添加后,系统会提示添加成功。如图 4.12所示:

    4.4.3 测试结论经过多次的测试,本系统基本上已经达到需求定义阶段用户提出的要求;软件方面:软件功能较完整,用户界面良好,设计的比较人性化,处理错误正确,能正确提示错误种类,没有漏洞,用的体验度会比较好。由于时间因素以及其他自身因素,跟系统功能完整性而言,部分功能还未能实现,没有达到预期的效果。
    4.5 本章小结本章的主要是对系统中功能的实现和测试进行说明。系统功能实现对各个模块界面以及实现做了说明。系统测试主要通过使用常规的测试方法对主要模块进行数据的完整性、合法性、业务功能进行测试,最终达到使系统能正确运行的。
    结论对于目前完成的个人健康数据采集与分析系统,系统的优势主要体现在以下几个方面:在功能完整性方面,人体健康数据采集与分析系统可以实现业务需求的核心功能增加健康数据和系统显示。整个服务过程是闭环的。从用户体验的角度来看,交互设计相对简单,操作简单,系统运行平稳;界面设计布局清,界面的整体UI设计适合个人健康话题。从迭代开发的角度来看,在项目开发过程中使用了大量的注释文件,完整的数据建模和文档。因此,即使项目不涉及项目开发,项目的升级和维护也会变得相对简单。员工也可以扩展和修改他们的职能。项目开发的不足主要是由于早期设计中的一些设计不完善造成的。例如,个人健康数据分析不完整。
    另外,由于缺乏项目时间管理,部分功能无法实现,极大地影响了用户的实用性。
    在开发这个系统之后,我发现系统需求的设计和前一时期的设计在软件开发中更为重要。如果系统需求不清楚,系统的设计和开发可能会偏离系统需要实现的目标。这将导致客户不需要项目,最终导致项目不得不重新开发。因此,在项目开发过程中,需要明确研究需求,明确各个模块及各个模块的功能和功能,最大限度地满足客户的需求。如果条件得到满足,系统也可以应用于系统。要了解的环境。在需求得到改进之后,需要对每个功能模块进行更加详细和详细的设计,并根据要实现的功能设计一个数据库。其结果是由于数据库问题导致系统不完善或者项目不能继续发展。如果数据库设计中存在相对较大的问题,则可能导致“项目堕胎”。因此,项目开发过程中的前期设计比后期开发更重要。一个设计良好的系统在后来的开发过程中会非常有用,一个花费在不完善的预先设计的后期开发中的时间可能会超过以前的设计时间。
    因为这个项目是为自己独立开发的,所以没有感受到团队合作的感觉。在团队开发中每个人开发的功能模块的整合中,我们也希望遵循一些相关的约定,所以当开发项目时,每个功能都将是模块中类名和方法名称的同意。有利于项目的开发和后期维护。
    参考文献[1] 百度文库.国外健康发展状况 词条[OB/EL]. https://wenku.baidu.com/view/f4bd0516a66e58fafab069dc5022aaea998f411c.2018.05.
    [2] 百度百科.MVC 词条[OB/EL]. https://baike.baidu.com/item/MVC框架/9241230.2018.05.
    [3] 百度百科.highcharts 词条[OB/EL]. https://baike.baidu.com/item/highcharts/7645252.2018.05.
    [4] 百度百科.物理数据模型 词条[OB/EL]. https://baike.baidu.com/item/物理数据模型/4210416.2018.05.
    [5] 百度百科.类图 词条[OB/EL]. https://baike.baidu.com/item/类图/4670826.2018.05
    [6] 刁成嘉.UML 系统建模与分析设计[M].北京:机械工业出版社,2010.
    [7] 朴勇.软件工程实用教程[M].人民邮电出版社,2015.
    [8] 百度百科关于数据流图的词条[OB/EL].http://baike.baidu.com/view/228931.htm.2013.05.02.
    [9] Grady Booch 等.Object-Oriented Analysis and Design[M].ADDISON-WESLEY,2003
    [10] 王永贵,郭伟,冯永安,焦学理.Java 高级框架应用开发案例教——Struts2+Spring+Hibernate[M].北京:清华大学出版社,2012.
    [11] Bruce Eckel.Thinking in Java,Third Edition[M]. englewood cliff: Pearson Higher Isia Education,2003.
    [12] 张海藩.软件工程导论(第 5 版)[M].北京:清华大学出版社,2008.
    [13] 白尚旺,党伟超 等.软件分析建模与 PowerDesigner 实现[M].北京:清华大学出版社,2010.
    [14] 百度百科关于数据字典的词条[OB/EL].http://baike.baidu.com/view/70173.htm.2013-05-09.
    [15] 刘俊亮,王清华.JSP Web 开发学习实录[M].北京:清华大学出版,2011.
    [16] Julian Gold. Object-Oriented Game Development [M].Pearson Education Limited,2004.
    [17] 柳佩九,徐鸣,邹竞等.管理信息系统及其开发技术[M].长沙:国防科技大学出版社,2005.
    [18] 宫云战,赵瑞莲,张威等.软件测试教程[M].北就:机械工业出版社.2011.
    0 评论 2 下载 2020-08-27 10:16:42 下载需要13点积分
  • 基于JSP和MySql的资讯网站的设计与开发

    摘 要互联网时代是一个资讯爆发的时代,人们每天都能接收到各种平台推送的各式各样的资讯,这些资讯有可能是用户感兴趣的,也有可能是用户所厌恶的,如何在各种各样的资讯中最高效的获取自己需要的内容成为一个普遍的问题。本课题研究了技术发展所带来的信息爆炸情况,论证了有效筛选信息的必要性,本文主要内容是设计和实现一个资讯网站,为互联网时代的用户提供信息过滤的功能。
    本文对系统的可行性和用户需求进行了详细的描述,将设计的资讯网站定位为为用户收集和过滤资讯的一个资讯平台,利用协同算法针对用户偏好抓取最新的资讯,实现资讯展示、资讯推送、资讯搜索等功能。
    本文以软件工程的基本理念为指导思想,将课题的需求调研、分析与项目的设计工作进行了严格的阶段划分,同时用面向对象的分析设计思想对系统进行用例建模。系统的实现主要以Java作为开发语言,使用MySQL数据库对系统信息进行统一管理。
    关键词:信息爆炸;协同算法;用户偏好;信息筛选
    ABSTRACTThe Internet age is an era of information explosion. People can receive a wide range of information from various platforms every day. These information may be of interest to users, and may be disgusting to users. The most efficient way to get the content you need is the general problem. This topic studies the information explosion brought about by the development of technology and demonstrates the necessity of effectively screening information. The main content of this paper is to design and implement an information website to provide information filtering function for users in the Internet age.
    This article describes the feasibility of the system and user requirements in detail. The designed information website is positioned as an information platform for users to collect and filter information. It uses collaborative algorithms to capture the latest information based on user preferences, and realizes information display and information. Push, information search and other functions.
    This paper takes the basic idea of software engineering as the guiding ideology, divides the requirements research, analysis and project design work of the project into strict stages. At the same time, it uses the object-oriented analysis and design idea to model the use case of the system. The implementation of the system mainly uses Java as the development language, and uses the MySQL database to perform unified management of system information.
    Keywords: information explosion; collaborative algorithm; user preference; information screening
    第一章 前言1.1 课题背景随着科技的发展,互联网从1969年发展至今,从一开始的仅用于军事连接,到如今的家喻户晓,互联网承载着人们的信息需求、交易需求、交流需求、娱乐需求以及办公需求,而其中的信息需求占据着很大一部分。互联网的发展使得人们能够不受空间限制来进行信息交换,并且由于人们可以随时随地联入互联网,使得互联网的更新速度非常迅速,因为互联网的受众众多,加之使用成本低,整个互联网中的信息量是庞大的。现如今人们使用的智能设备每天都会收到众多的推送信息,如推送的聊天消息;推广活动;行业新闻;最新资讯等,蜂拥而来的信息给用户带来的将会是选择成本的影响,以及时间被碎片化。
    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,具有时效性和地域性。资讯不同于新闻,资讯和新闻的区别在于:资讯包括了新闻、供求、动态、技术、政策、评论、观点和学术的范畴,时效范围远宽于新闻,例如今天的新闻明天不再是新闻,但今天的资讯明天也可能作用依然。
    互联网时代的用户已经不仅仅只是关注于此时此刻或者过去发生了什么事情,他们可能为了更好的自我发展,会将关注点放在那些能够提高自我的资讯上面,比如领域类的最新技术、发展历史以及他人的经验分享。互联网时代同时也是一个资讯爆发的时代,各式各样的资讯如大潮般涌向用户,例如百度每天的搜索量达到60亿次,产生数据量达到几十PB,新浪微博高峰期每秒达到百万次访问。与海量资讯蜂拥而至相矛盾的是用户获取资讯的时间始终是有限的,怎么有效的筛选有意义的讯息变成了一个相当棘手的问题。
    本课题的核心内容就是利用协同算法为用户筛选出最合适的资讯,让用户在有限的时间里最大可能的接收到对自己最有价值的资讯。
    1.2 课题目的与意义互联网上有着许许多多的门户网站,如热点资讯、新浪新闻、搜狐新闻、腾讯新闻、网易新闻、央视新闻等,这些门户网站是现如今人们获取资讯的主要方式,但这些网站都有一个共同的特点,那就是页面元素过多,即使有相应的板块设置,但页面主体都是富含众多子栏目,这给用户的浏览带来极大的不便,眼花缭乱的页面元素使得用户不能专心于资讯的获取。并且页面中所包含的资讯可能是最新、最热或者是网站编辑所推送的,而不是用户可能感兴趣的资讯。
    基于这些原因,国内出现了类似于今日头条这样的基于数据挖掘的推荐引擎产品,这类产品能更好的将用户感兴趣的资讯呈现给用户。今日头条的资讯来自于其他的门户网站,主要通过爬虫进行抓取,它将抓取到的资讯呈现给用户,并对用户的过往浏览情况进行分析,得出用户可能感兴趣的内容,推送给用户。
    1.3 本文研究的内容用户体验决定了一个产品的存在周期。本文将重点研究如何实现为用户推送可能感兴趣的内容。在充分论证系统可行性和用户需求的基础上利用所学的面向对象设计方法对系统进行模块设计、界面设计和数据库设计。
    1.4 论文结构简介本论文记录着对系统开发的前期的调研、设计到系统的开发、测试和总结的全过程。

    前言:本章主要介绍系统当前社会背景及开发目的与意义,同时对当前社会中已存在的资讯网站进行分析与阐述
    算法介绍:本章主要对当前社会较流行的推荐算法——协同过滤算法进行说明,分析其类型、优缺点及当前社会的应用实例
    系统需求:本章主要对系统进行开发的可行性进行分析,并对用户需求进行说明,结合现如今类似资讯网站对用户界面需求进行阐述,绘制数据流图,为系统设计打下基础
    系统设计:根据用户需求对系统进行该要设计,模块设计,绘制功能模块图,并对数据库进行设计,绘制数据库社物理模型图以及对数据库表进行说明,为系统实现提供指导
    系统实现与测试:对系统中的功能实现进行介绍,介绍同时展现所实现的UI界面展示。另外是对系统测试进行说明
    结论:对系统进行总结和自我总结。另外,论文还包括结论、参考文献及致谢三部分,最后附录了全文表索引和全文图索引及部分核心代码

    第二章 算法介绍2.1 算法背景协同过滤算法是诞生最早,并且较为著名的推荐算法。主要功能是预测和推荐。协同过滤简单来说是利用某兴趣相投、拥有共同经验之群体的喜好来推荐用户感兴趣的信息,个人通过合作的机制给予信息相当程度的回应(如评分)并记录下来以达到过滤的目的进而帮助别人筛选信息,回应不一定局限于特别感兴趣的,特别不感兴趣信息的纪录也相当重要。
    1992年出现的Tapestry是最早应用协同过滤系统的设计,主要是解决Xerox公司在Palo Alto的研究中心资讯过载的问题。这个研究中心的员工每天会收到非常多的电子邮件却无从筛选分类,于是研究中心便发展这项实验性的邮件系统来帮助员工解决这项问题。
    然后是1994年的GroupLens,这个系统主要应用在新闻的筛选上,帮助新闻的阅听者过滤其感兴趣的新闻内容,阅听者看过内容后给一个评比的分数,系统会将分数记录起来以备未来参考之用,假设前提是阅听者以前感兴趣的东西在未来也会有兴趣阅听,若阅听者不愿揭露自己的身分也可以匿名进行评分。 和Tapestry不同之处有两点,首先,Tapestry专指一个点(如一个网站内、一个系统内)的过滤机制;GroupLens则是跨点跨系统的新闻过滤机制。再来,Tapestry不会将同一笔资料的评比总和起来;GroupLens会将同一笔资料从不同使用者得到的评比加总。
    随后出现的是电子商务的推荐系统,最著名的是亚马逊网络书店,顾客选择一本自己感兴趣的数据,马上会看到其他购买过该书的顾客买过的其他书籍。另外一个著名的例子是Facebook的广告,系统根据个人资料、周遭朋友感兴趣的广告等等对个人提供广告推销,也是一项协同过滤重要的里程碑,和前二者Tapestry、GroupLens不同的是在这里虽然商业气息浓厚同时还是带给使用者很大的方便。以上为三项协同过滤发展上重要的里程碑,从早期单一系统内的邮件、文件过滤,到跨系统的新闻、电影、音乐过滤,乃至于今日横行互联网的电子商务,虽然目的不太相同,但带给使用者的方便是大家都不能否定的。
    2.2 算法分类及原理协同过滤算法主要分为三类,分别是以用户为基础的协同过滤(User-based Collaborative Filtering,UBCF)、以物品为基础的协同过滤(Item-based Collaborative Filtering,IBCF)以及以模型为基础的协同过滤(Model-based Collaborative Filtering, MBCF),本节主要介绍以用户为基础的协同过滤以及以物品为基础的协同过滤。无论是UBCF还是以IBCF,其本质是通过对以往数据进行分析,找出其相似性,将相似度最大的结果推荐给用户。下面是对它们两者的详细介绍。
    2.2.1 以用户为基础的协同过滤以用户为基础的协同过滤主要是用相似统计的办法得到与用户兴趣或爱好具有相似度的其他用户。其主要步骤为:

    收集用户的特征数据。这种特征数据可以是网站主动提供给用户进行评定的“主动评分”,如评分功能;也可以是不需要经过用户操作,由用户的行为所产生的“被动评分”,如收藏、电子商务网站的购买等功能。无论是主动评分还是被动评分,都代表着用户对该物品的一个喜好情况及程度
    针对用户的最近邻搜索。以用户为基础的协同过滤是为目标用户A寻找出一组兴趣爱好相似的用户,将这些相似用户对其他物品X的评分作为目标用户对物品X的评分预测。在进行相似用户寻找时,一般根据所选取的数据选择相应的算法进行相似度计算,较常见的相似度推荐算法有皮尔森相关系数(Pearson Correlation Coefficient)、余弦相似性(Cosine-based Similarity)以及调整余弦相似性(Adjusted Cosine Similarity)
    产生推荐结果。通过第二部获取了最近邻集合以后,根据推荐目的的不同选择不同的推荐方式,常见的有Top-N推荐。Top-N推荐是针对单个用户进行推荐,不同的用户所产生的不同的结果,当然也有可能两个用户的相似度过高而产生相同结果。它的推荐方式是将在最近邻集合中出现频率高并且是要进行推荐的目标用户的评分项目中不存在的项,作为推荐结果

    2.2.2 以物品为基础的协同过滤以项目为基础的协同过滤是Sarwar于2001年提出的推荐算法,主要是为了解决基于用户的协同过滤算法随用户数量增长,而带来的计算时间变长的不足。其主要步骤为:

    收集用户的特征数据。这一步与基于用户的协同过滤算法相同
    针对物品的最近邻搜索。以物品为基础的协同过滤的目标为物品之间差异。通过计算用户已评分物品与未评分物品之间的差异,得出与用户已评分物品的相似性较高的物品集合,即最近邻集合。物品相似度的计算,根据不同的物品可以有不同的计算方式,简单的有电影的类别,如爱情片、惊悚片或恐怖片;音乐的风格,如流行乐、摇滚乐、古典乐等
    产生推荐结果。将与用户过往记录最相似并且用户未评分的物品推荐给用户

    2.3 算法优缺点以用户为基础的协同过滤及以物品为基础的协同过滤有着各自的优缺点,下面对他们进行分开讨论。
    2.3.1 以用户为基础的协同过滤的优缺点优点
    以用户为基础的协同过滤算法的优点主要体现在以下几方面:能够过滤一些机器难以判别分类的信息,如艺术品、音乐等;出发点为用户特征数据,避免了因内容分析问题而导致的推荐不准确;可以为用户推荐内容毫不相关的信息,用户可以发现潜在的但尚未发掘的兴趣爱好;个性化、自动化程度高,能有效利用相似用户的回馈信息、加快个性化学习的速度。
    缺点
    以用户为基础的协同过滤算法也有一些缺点,如如果用户很多,计算用户相似度矩阵代价很大;冷启动问题:新用户在系统开始时推荐质量较差;不同用户之间如果物品重叠性较低的情况下,导致算法无法找到相似用户的稀松性问题等。
    2.3.2 以物品为基础的协同过滤的优缺点优点
    以物品为基础的协调过滤的优点主要体现在以下几方面:用户有新行为产生时,一定会影响推荐结果的产生;利用用户的历史行为进行的推荐,用户对推荐结果比较信服;可以离线完成相似性计算,降低在线计算量,推荐效率提高。
    缺点
    以物品为基础的协调过滤也不可避免的有些缺点,例如如果物品过多,导致计算物品相似度矩阵复杂,计算代价很大;推荐精度较差等。
    2.4 算法适用场景在上述算法背景中,已经提到了几个应用了协同过滤算法的场景。现今用到协同推荐算法的有亚马逊和淘宝等购物网站的“猜你喜欢”、今日头条的新闻推荐等,这些网站的推荐算法中,有单独使用以用户为基础的协同过滤的,也有单独使用以物品为基础的协同过滤的,更主要的是两者结合起来共同进行推荐功能的。以物品为基础的协同过滤适用于网站用户数量大于物品数量,并且物品数量相对稳定;以用户为基础的协同过滤适用于新闻类、博客类网站。两类算法分别有着自己的优劣势,适应不同场景,结合两者或其他算法来进行推荐,用户得到的推荐结果更佳。
    2.5 本章小结本章主要是对协同过滤算法进行介绍。本章首先交代了协同过滤算法的历史背景,接着对算法的分类以及实现原理进行了阐述,然后对两类主要的协同过滤算法的优缺点进行了介绍,最后对协同过滤算法的适用场景进行了说明,为后续系统实现推荐功能提供技术指导。
    第三章 系统需求3.1 可行性分析可行性分析是整个软件生命周期中的第一个阶段,是软件开发过程中的一个关键阶段,是项目决策和启动的重要依据。如果问题不能得到解决,那么所花费的时间及精力都将会是无谓的浪费。
    基于协同算法的资讯网站的主体为Web网站,核心功能为基于协同算法而实现的资讯推送功能。本文将从经济可行性、技术可行性、社会可行性及操作可行性四个方面对本系统进行评估,对未来是否课题研究进行更好的论述。
    3.1.1 经济可行性分析门户网站经济客观。雅虎、今日头条、腾讯新闻等网站存在已有一定的年份,能够屹立不倒证明着有其经济价值,通过分析得出这些门户网站的主要盈利模式主要是通过广告推广来获得一定的利益。
    开发成本低,运营成本低。网站数据获取通过爬虫自动从网络中抓取,推荐算法实现以后将会不断发挥作用,网站开发完成以后,将能不断为用户提供服务。
    3.1.2 技术可行性分析该Web系统采用Java语言进行开发,使用tomcat作为Web服务器,利用MySQL数据库对系统数据进行存储与管理。整个项目搭建基于SSM架构,核心功能算法部分基于协同过滤算法。
    Java语言是有Sun公司开发的一门面向对象编程语言。它吸收了C++语言的各种优点,并且摒弃了C++里多继承、指针等复杂概念,具有功能强大和简单易用两个特性。并且由于Java具有平台独立及可移植性的特点,在开发使用方面非常便利。作为如今流行的开发语言之一,Java从1995年诞生以来,发展至今已有20多年的历史,在安全性及健壮性等方面也有非常好的优势。
    Tomcat是Apache软件基金会的Jakarta项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发所成。Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,适合中小型系统及并发访问量不是过多的场合,是开发和调试JSP程序的首要选择,而本网站从未来使用角度来分析,面临的高并发场景不多,因此使用Tomcat作为网站的服务器非常合适。
    MySQL是一个关系数据库管理系统,由MySQL AB公司开发,目前隶属于Oracle旗下。MySQL是最流行的关系型数据库管理系统之一,其体积小、速度快、总体拥有成本低,是一般中小型网站开发所钟爱的选择。
    SSM框架由Spring、Spring-MVC、MyBatis三个开源框架整合而成,是Web开发中常用的框架组合。
    Spring是一个轻量级的IoC和AOP容器框架,它是一个分层架构,由7个定义良好的模块组成,其核心容器定义了创建、配置和管理bean的方式,并且它的模块化设计对Spring-MVC及MyBatis的整合也非常方便。
    MVC全名为Model View Controller,是一种当前流行的软件设计典范,它的目的是将软件开发中的视图设计与业务逻辑编写分离开来,使得软件耦合性更低、可重用性更高,在软件维护性及成本方面也有了提升。而Spring-MVC作为常见的MVC框架之一,它基于MVC的设计理念,以及同为SpringFrame下的产品,使得网站开发在便利性方面得到了极大的提升。
    MyBatis前身为iBatis,为Apache的一个开源项目。MyBatis作为一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。
    协同过滤算法应用广泛,普遍存在与电子商务平台以及门户类网站中。在最近邻算法实现方面,Mahout提供了良好的库,可以对其库进行改进以实现实际需求。
    从上述技术的特点、成熟度及实用结果来看,实现本课题在技术上是完全可行的。
    3.1.3 社会可行性分析在这个信息爆炸的年代,人们面对的不再是资讯短缺,而是资讯过载。互联网时代的用户已经不仅仅只是关注于此时此刻或者过去发生了什么事情,他们可能为了更好的自我发展,会将关注点放在那些能够提高自我的资讯上面,比如领域类的最新技术、发展历史以及他人的经验分享。互联网时代也是一个资讯爆发的时代,各式各样的资讯如大潮般涌向用户,例如Google的每月查询量为1000亿次,百度每天的搜索量达到60亿次,产生数据量达到几十PB。与海量资讯蜂拥而至相矛盾的是用户获取资讯的时间始终是有限的,怎么有效的筛选有意义的讯息是当今社会面临的一个难题。
    3.1.4 操作可行性分析人类在科学探索路上不断追求进步,计算机技术发展至今,虽达不到百分百的普及,但网络已覆盖世界上绝大多数区域。智能手机、个人电脑的普及程度越来越好,有的人不仅仅只是拥有可以联网的设备,还可能拥有多台或配置更好的设备。网页操作对现如今的人们来说趋于成熟,用户的认知和接受程度应到了一个很高的水平,用户对于网站内容和形式以及对网站的操作不会人生地不熟。
    总结以上分析,本课题Web网站的开发在上述四个可行性方面都具有实施可能,因此该系统的设计与开发具有实现的意义。
    3.2 用户需求说明为了开发出真正满足用户需求的软件产品,首先必须知道用户的需求。对软件需求的深入理解是软件开发工作获得成功的前提条件,不论人们把设计和编码工作做得如何出色,不能真正满足用户需求的程序只会令用户失望,给开发者带来烦恼。[1]
    需求是用户为了解决现有问题,所提出的改善措施或改进建议,它是用户期望的一个准确描述。实现需求的过程中,就是通过实现软件功能,使其满足用户期望,达成用户目标。以下主要从三个方面对用户的需求进行说明:
    3.2.1 门户类网站访问量巨大在这个资讯爆发的年代,人们为了解决遇到的问题,或是为了获取新的信息来满足自我发展,需要经常在网络中搜索资讯或者浏览资讯。“有问题谷歌一下”或是“有问题百度一下”是IT技术以及中国民间所流行的两句俚语,百度甚至将其作为推广宣传的标语,这足以体现资讯搜索在现今社会中的重要性。搜索是用户以主动的方式从网络中获取想要的资讯,与其相对的被动获取则是各类资讯门户网站,这些网站通过人工的方式进行资讯的发布以及展示,是用户获取资讯的主要手段之一。有些门户网站因为它们的名称朗朗上口或是因为其优质的内容,已经成了人们生活中了解社会、行业或是为了自我提高而必不可少的一部分。
    据统计,搜索类网站中谷歌旗下的域名google.com独立访客(UV)月平均访问量达15亿,google.com(谷歌搜索,主要负责搜索)该域名占比67.85%,约10亿;百度旗下的baidu.com域名独立访客月平均访问量达3亿,baidu.com(百度搜索,同谷歌)该域名占比74.17%,约2亿,zhidao.baidu.com(百度知道,百度旗下的问答平台)占比31。04%,约9000万,baike.baidu.com(百度百科,百度旗下的网络百科全书平台)占比19.98%,约6000万。新闻类网站中新浪旗下的sina.com.cn域名独立访客月平均访问量达1.2亿,其新闻网站域名news.sina.com.cn占比34.02%,约4000万;腾讯旗下的qq.com域名月平均访问量达2亿,旗下新闻网站域名news.qq.com占比14.41%,约2800万。
    以上这些信息体现出,现今社会人们对于资讯的获取是极度渴望的。
    3.2.2 科技技术发展迅速随着人们在科学道路上的不断发展,科技技术水平不断提升,计算机已经从最开始的占地170平方米的庞然大物,缩小到了只有巴掌大小的智能手机,可以说是经历的巨大的改变。并且,随着网络技术的发展,及互联网概念的提出,人们获取资讯的方式极为便利,成本也得到了降低。人们回到家中,遇到了问题可以用PC打开如谷歌或者百度这样的搜索网站,键入自己遇到的问题或想要获取的资讯,随后将会得到“可能是自己想要的结果”,但由于这个互联网的发展,这个“可能的结果”通常都能解决用户的问题,或是用户想要的;而对于那些专注于一个领域,或是关注社会发展的用户,在网站持续运营的情况下,可以随时访问各类门户网站,获取社会最新动态、行业最新资讯或是领域内最新的研究成果;而出行在外,随着wifi的普及,人们可以使用笔记本电脑或是平板电脑查阅资讯,即使在不满足这些情况的条件下,人们的智能手机还能使用蜂窝网络连入互联网浏览资讯。
    以上信息体现出,人们获取资讯的方式多样,成本较低,不受时间地域限制。
    3.2.3 推荐功能的必要性无论是上面提到的搜索还是门户网站,都是需要用户主动去网络世界中获取,用户以该种形式获取资讯时,不能保证资讯的完整性,可能有些资讯是用户需要的关键点,但因为一些原因用户未能获取到的话,将有可能给用户带来极大的阻碍。这些原因可能是用户关键字的不准确表达造成的搜索结果不匹配;网页布局影响造成的用户没看到、时间影响造成资讯显示排序过于后面;人为对展示结果的影响等。为了解决这些潜在因素影响下,用户未能看到一些信息的问题,资讯推荐是一种有效且必要的措施,它能主动为用户推荐一些信息,消除用户主动获取时所隐含的部分劣势,弥补用户被动获取资讯的不足。
    3.3 用户界面需求3.3.1 界面设计风格现在市面上的新闻网站有很多,这些新闻网站的内容丰富全面,是用户获取讯息的重要途径。但是这些网站在用户体验上存在不足,包含的页面元素过多,容易给用户造成选择困难;另外页面布局排版及广告等对用户浏览造成视觉影响。本课题的网站的页面设计主要借鉴今日头条的页面样式来设计,以减少页面内容来突出显示用户感兴趣的资讯信息。
    3.3.2 交互设计根据《用户体验要素》、以及《DON’T THINK》提出的思想,让用户看得舒服,看得明白,用得舒服为原则,使用户在与网站进行交互操作时,感到舒适及舒心。

    看得明白:能看懂文字的意思,产品的组成和结构,产品运转方式
    看得舒服:能知道从何看起,找到想到的东西,能看懂布局,能分清视觉化差异的意思
    用得舒服:敲键盘,移动鼠标,鼠标单击、双击和拖动,切换输入方式,导航的点击次数

    3.3.3 界面要求考虑大龄用户、页面元素以及对计算机尚不熟悉的人群,网页操作的学习成本应该降低,网页的复杂度也不应太高。
    3.4 管理需求说明本课题系统基于协同算法的资讯网站,整个Web系统跟资讯息息相关,从资讯的获取、资讯的展示、资讯敏感词等各方面都有管理的需求。以下将对这三个方面进行说明。
    3.4.1 资讯管理资讯数据是个非常大数据集,其标题以及内容的数据量都是非常占用内存的,一两条可能看不出来,当数据量多起来的时候,那么存储量将会非常巨大,即使这样本Web系统还采用数据库的原因是这样能够方便对资讯的管理。本课题Web系统在资讯存储方面采用了数据库进行储存,那么后台管理模块中,需要能对数据库中的资讯进行管理。其中包括数据库中资讯信息的查看、资讯的删除。网站资讯数据来源于爬虫,所以资讯管理功能中将不包括资讯信息的添加以及资讯信息的修改。
    3.4.2 敏感词管理根据相关政策,或是为了网站健康良好的发展,需要对一些词汇进行设置,在网站显示或是其它功能中禁用这些词汇,这类词汇称作敏感词汇。敏感词汇可能是一些脏话、带有政治倾向、暴力倾向、不健康色彩的词语。本课题系统中用户可以自行查找资讯,在搜索时将会对搜索的关键词进行过滤,如果出现敏感词列表中的词汇,将会对用户进行提示“当前搜索中可能包含敏感词汇,请重新搜索!”。所以为了网站的持续发展,需要对敏感词进行管理,包括敏感词的添加、敏感词的查看以及敏感词的删除。遂网站后台模块需要有能对敏感词进行管理的模块。
    3.4.3 爬虫管理本课题Web系统中的资讯来源为爬虫获取,那么将会涉及到爬虫的一些相关操作,如:爬虫的启动、爬虫的停止、爬虫抓取链接的设置。那么爬虫管理功能对后台管理来说,也是必不可少的一部分。
    3.4.4 用户信息管理本课题Web系统涉及到用户的注册与登录,用户数据采用数据库存储,所以用户信息管理也将会是后台管理中的一部分。
    3.5 系统数据模型分析为了把用户的数据要求清楚、准确地描述出来,系统分析员通常建立一个概念性的数据模型。[1]通常使用ER图来建立数据模型。
    分析本课题系统得知,系统中存在的实体有用户、资讯、板块、用户喜好、用户评分、管理员以及敏感词,具体的ER图如图3.1所示:

    3.6 系统数据流图数据流图(DFD)是一种图形化技术,它描绘信息流和数据从输入移动到输出的过程中所经受的变换。它只是描绘数据在软件中流动和被处理的逻辑过程,是系统逻辑功能的图形表示。[1]其中矩形表示数据源和终点,圆角矩形或圆形表示对数据进行加工处理,双横线表示数据存储,箭头表示数据流。
    分析整个系统的数据需求得到一下的数据流图:
    登录模块:用户输入账号密码点击登录,网页将用户信息提交至后台,后台对用户信息进行验证,验证通过则跳转至主页并设置Session。其数据流图如图3.2所示:

    注册模块:用户点击注册,在弹出的注册界面中输入相应信息,符合注册条件则注册成功,信息存入用户表中。其数据流图如图3.3所示:

    后台模块:主要完成敏感词的设置以及板块的设置。管理员登录后台管理以后,对敏感词以及新闻版块进行相应的设置。其数据流图如图3.4所示:

    资讯模块:主要完成新资讯的获取,通过爬虫从门户网站抓取,并将新资讯的相信信息存入数据库中;用户浏览资讯时的板块选择功能,用户浏览网站时,点击想要浏览的板块,网页将板块信息提交至后台,后台从数据库中查询出相应板块的资讯返回网页;用户查看资讯,用户点击链接,网页将会把资讯的编号信息提交至后台,后台查询出资讯详情返回至网页;资讯搜索,用户在搜索框中输入关键字进行搜索,后台对用户提交的关键字进行过滤,如果属于敏感词,则返回空列表,网页进行相应的提示,如果不属于敏感词,则查询出标题和内容中包含关键字的资讯,返回给用户。其数据流图3.5如图所示:

    爬虫模块:主要负责资讯的抓取。爬虫从门户网站获取资讯数据,通过管道类存入数据库中。
    3.7 本章小结本章主要是对课题系统进行设计以前的调研及可行性分析。本章首先从经济、技术、社会和操作等方面对系统的可行性进行了评估,判断系统是否值得实现,是否有实现的可能,并对用户需求进行了说明,接着对系统的数据模块、功能模块、行为模块进行了分析与建模,绘制ER图、数据流图,作为后续系统设计与开发的指导方针。
    第四章 系统概要设计4.1 模块设计按照模块的定义,过程、函数、子程序和宏以及面向对象中的对象、对象的属性等,都可以作为模块。本节主要是对整个Web网站的功能模块进行分析与设计,为的是使软件结构更加清晰,提高软件的可靠性、可重用性、可维护性以及可修改性。
    4.1.1 模块划分在对本课题的需求进行分析以后,整个系统的功能模块主要包括:资讯模块、用户模块以及后台模块三个模块。

    资讯模块:该模块的主要实现资讯获取、资讯展示、资讯推送、资讯搜索以及资讯发布等功能。该模块是整个网站的核心模块,其中资讯推送为重中之重,为整个网站的灵魂所在。整个模块主要负责为用户推送可能感兴趣的资讯、显示资讯列表以及对资讯进行展示
    用户模块:该模块主要是负责与用户相关的一些功能,其中包括用户注册、用户登录、以及用户的个人信息管理。资讯模块中的推送功能需要对用户的历史行为进行一个统计与分析,所以该模块在整个系统中也是不可或缺的存在
    后台模块:该模块主要负责网站后台的一些管理功能,如与资讯获取有关的爬虫设置;管理与资讯搜索有关的敏感词设置。该模块是客户与网站进行交互的主要模块

    4.1.2 功能模块图系统的功能模块图如图4.1所示,核心模块为资讯获取和资讯推荐部分,其中资讯推荐为整个系统中的重中之重。其中资讯获取部分主要是使用WebMagic框架实现的网络爬虫,用以从门户网站中自动获取新的资讯;资讯推荐部分主要使用协同算法。

    4.2 数据库设计4.2.1 数据库物理模型图系统的数据库物理模型图如图4.2所示。它描述了数据库中系统所涉及到的各个表之间的关系。

    4.2.2 数据库存储结构本课题系统主要的数据库表包括:用户表、资讯表、板块表、用户喜好表、用户评分表、管理员表、敏感词表。具体的数据表结构设计如下。
    用户表:负责存储用户信息,主要包括主键、用户名及密码。其表结构如表4.1所示:



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




    编号
    id
    bigint
    20
    主键、自增


    用户名
    username
    text
    30



    密码
    password
    text
    16



    资讯表:负责存储资讯的详细信息,主要包括主键、标题、内容、发布时间、板块及点击数。其表结构如表4.2所示:



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




    编号
    bigint
    id
    20
    主键、自增


    标题
    text
    title
    65,535



    内容
    text
    content
    65,535



    板块编号
    int
    plateId
    11



    发布时间
    tinytext
    pub_time
    256



    点击数
    int
    clickNums
    11



    板块表:负责存储资讯的板块信息,主要包括主键、板块名。其表结构如表4.3所示:



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




    编号
    id
    int
    11
    主键、自增


    板块名
    name
    text
    15



    用户喜好表:负责存储用户所喜欢的板块信息。主要包括主键、外键用户ID、外键板块ID。其表结构如表4.4所示:



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




    编号
    id
    bigint
    20
    主键、自增


    用户编号
    userId
    bigint
    20



    评分
    val
    float
    10,2



    用户评分表:负责存储用户对新闻的喜好信息。主要包括主键、外键用户ID、外键板块ID、评分。其表结构如表4.5所示:



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




    编号
    id
    bigint
    20
    主键、自增


    用户编号
    userId
    bigint
    20



    资讯编号
    newsId
    bigint
    20



    评分
    val
    float
    10,2



    管理员表:负责存储管理信息,主要包括主键、管理员用户名及密码。其表结构如表4.6所示:



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




    编号
    id
    bigint
    20
    主键、自增


    用户名
    username
    text
    30



    密码
    password
    text
    16



    敏感词表:负责存储敏感词信息,主要包括主键、敏感词。其表结构如表4.7所示:



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




    编号
    id
    int
    11
    主键、自增


    敏感词
    word
    tinytext
    256



    4.3 本章小结本章主要是对用户需求进行详细划分,对系统的功能模块以及数据库表进行设计。通过本章可以大致了解系统的功能模块有哪些,以及所使用到的表及其结构。
    第五章 系统实现与测试5.1 系统实现说明系统实现就是对经过需求分析之后的设计结果进行编码与测试。本课题系统的运行及测试环境如下:

    操作系统:macOS Sierra 10.12.2
    处理器:1.6 GHz Intel Core i5
    运行内存:4GB
    机身存储:256GB
    编程语言:Java
    服务器:Tomcat 7.0
    浏览器:Google Chrome版本 66.0.3359.139(正式版本)(64 位)

    5.2 代码结构5.2.1 代码结构介绍整个系统的代码结构如下图所示,其中src/main/java目录下为系统的后台代码部分,总共包括六个子包,其中action包为系统的Controller,负责映射网页请求,并将请求转发至Service包下对应的Service,对用户请求进行处理。其中主要包括处理资讯相关请求的NewsAction类、与用户相关的UserAction类以及与爬虫相关的SpiderAction类。dao包下为程序的数据访问接口文件,主要负责系统数据的持久化工作,其中包括NewsDao、UserDao、PlateDao等接口文件。entity包下为整个系统中的实体类;mapper包下为MyBatis框架下各个dao的映射文件;service包下为系统的服务类;util包下为系统中包含的工具类,其中包括爬虫及推荐算法的实现。
    5.2.2 代码结构图
    5.3 系统实现5.3.1 推荐功能的实现核心推荐功能
    本系统中核心推荐功能主要是使用Mahout库中提供的方法,将数据库中记录的用户评分根据协同算法理念,通过使用皮尔森相关系数计算出与用户相关的其他用户,获取与用户关系最近的相邻用户,再通过Mahout提供的通用UBCF推荐器进行推荐。由于协同算法技术发展的成熟性,Mahout库中对协同算法中涉及到的一些计算方法都进行了封装,主要代码如下所示:
    // 核心算法功能public static List<RecommendedItem> recommend(User user,int neighborNum, int recommendedNum){ // 创建MySQL数据源 MysqlDataSource dataSource=new MysqlDataSource(); dataSource.setServerName("localhost"); dataSource.setUser("root"); dataSource.setPassword("mysqlVip847@"); dataSource.setDatabaseName("NEWS"); // 推荐结果集 List<RecommendedItem> recommendations = null; // 使用数据源读取数据库中的数据 JDBCDataModel dataModel=new MySQLJDBCDataModel(dataSource,"PREF","userid","newsid","val", "time"); // 对象赋值 DataModel model=dataModel; // 获取用户相似度,使用皮尔森相关系数算法 UserSimilarity similarity = new PearsonCorrelationSimilarity(model) // 根据neighborNum获取相邻用户 UserNeighborhood neighborhood = new NearestNUserNeighborhood(neighborNum,similarity,model); // 构建基于用户的推荐器 Recommender recommender=new GenericUserBasedRecommender(model,neighborhood,similarity); // 获取推荐结果集,recommendedNum为推荐结果的数量 recommendations = recommender.recommend(user.getUserId(), recommendedNum); // 返回推荐结果集 return recommendations;}
    推荐功能调用
    本系统中资讯列表的展示主要是通过下面的queryAllByPlateId()方法。其中plateId为板块编号,它来源于主页中侧边栏点击事件,当用户点击左边侧边栏对应板块时,index.js负责获取板块编号,通过jQuery中提供的ajax()方法,将板块编号通过post方式请求listNewsByPlateId.do发送至服务器后台,后台NewsAction中queryByPlateId()方法映射请求连接,并且通过判断plateId参数,获取相应板块的资讯信息,返回至网页浏览器。offset参数为页面控制参数,网页一次性显示30条资讯信息,下拉至底部时更新offset参数,获取下一页资讯。
    public List<News> queryAllByPlateId(long plateId,int offset, HttpSession httpSession) { List<News> list = null; if(plateId == -1){ User user = SessionUtils.getUser(httpSession); if(user != null){ list = new ArrayList(); List<RecommendedItem> items = UserBasedCollaborativeRecommender.recommend(user, 5, 50); for(RecommendedItem item : items){ long itemId = item.getItemID(); News news = newsDao.queryById(itemId); list.add(news); } }else{ list = newsDao.queryListByRand(); } }else if(plateId == 0){ list = newsDao.queryAll(offset, 30); }else{ list = newsDao.queryAllByPlateId(plateId, offset); } return list;}
    5.3.2 爬虫的实现资讯获取处理模块
    资讯的获取主要是通过实现WebMagic中PageProcessor接口下的process()方法,来对页面进行过滤和提取,主要是获取需要的资讯板块信息、资讯标题、资讯内容以及资讯的发布时间等。通过分析新浪滚动新闻发现,首次加载请求连接时,页面中只包含资讯的标题、内容和发布时间等信息,资讯的栏目信息是通过js请求异步加载的,所以处理板块请求是process方法中不可缺少的一部分。而通过分析新浪新闻资讯展示页得出了资讯展示页的布局规则,得到了爬虫中资讯信息提取相关的部分。 主要代码如下所示:
    // 页面处理方法public void process(Page page) { String title = ""; // 资讯标题 String contents = ""; // 资讯内容 String date = ""; // 资讯发布日期 // 判断是否属于资讯详情页 if (!page.getRequest().getUrl().startsWith("http://roll") && page.getHtml().css("div.article") != null) { // 获取资讯标题 title = page.getHtml().css("h1.main-title", "text").toString(); // 拼接资讯内容 for (String content : page.getHtml().css("div.article p").all()) { contents += content; } // 获取资讯发布日期 date = page.getHtml().css("span.date", "text").get(); // 从爬虫框架中获取栏目信息 Object channelText = page.getRequest().getExtra("栏目"); News news = new News(title, contents, date); // 将新闻信息和板块名添加 page.putField("news", news); page.putField("plateName", channelText.toString()); } // 获取滚动新闻列表中的资讯详情页链接以及对应的板块名 // js请求返回的数据为页面数据,将其转换成String类型进行处理 String text = page.getHtml().$("body", "text").toString(); if (text != null && !text.equals("") && text.startsWith("var")) { // 截取json对象字符串 text = text.substring(text.indexOf("{") - 1, text.length() - 1); // 将json字符串转换为json对象,获取资讯列表 JSONArray obj = JSON.parseObject(text).getJSONArray("list"); // 提取资讯列表中的板块及资讯详情链接 for (Object o : obj) { JSONObject o1 = JSON.parseObject(o.toString()); // 获取链接 String url = o1.getString("url"); // 获取板块信息 JSONObject channelObj = JSON.parseObject(o1.get("channel").toString()); String channel = ""; channel = channelObj.get("title").toString(); // 生成请求 Request r = new Request(url); site.setCharset("UTF-8"); r.putExtra("栏目", channel); // 加入抓取列表 page.addTargetRequest(r); } }}
    资讯存储模块
    WebMagic框架中,对于数据的存储提供了很多的实现方式,其中一种是通过实现Pipeline接口定制自己的数据存储管道。本课题系统通过爬虫获取的资讯信息通过定制的NewsDaoPipeline管道类,将资讯信息存储至数据库中。该管道类主要是调用了资讯以及板块的数据访问接口文件,将数据存入数据库。在存储之前,会对数据进行验证,如果数据已经存在,那么会对已有信息进行更新,当数据不存在于数据库中时,将直接把数据添加至数据库中。NewsDaoPipeline管道类中主要代码processe()方法如下所示:
    public void process(ResultItems resultItems, Task task) { // 获取域中的资讯对象 News newNews = (News)resultItems.get("news"); // 如果域中不存在资讯对象,返回 if(newNews == null) return; // 通过SpringTools工具类获取数据访问接口 newsDao = (NewsDao) SpringTools.getBean("newsDao"); plateDao = (PlateDao) SpringTools.getBean("plateDao"); // 查询数据库,检验资讯及板块信息是否已存在 News oldNews = newsDao.queryByTitle(newNews.getTitle()); String plateName = resultItems.get("plateName"); Plate plate = plateDao.queryByName(plateName); long plateId = -1; // 存储板块信息 if(plate == null){ plate = new Plate(); plate.setName(plateName); plateDao.add(plate); plate = plateDao.queryByName(plateName); } plateId = plate.getId(); newNews.setPlateId(plateId); // 存储资讯信息 if(oldNews != null){ oldNews.setContent(oldNews.getContent() + newNews.getContent()); oldNews.setDate(newNews.getDate()); oldNews.setPlateId(newNews.getPlateId()); newsDao.update(oldNews); }else{ if(!StringUtils.isEmpty(newNews.getTitle()) && !StringUtils.isEmpty(newNews.getContent())){ newsDao.add(newNews); } }}
    5.4 系统测试测试阶段的根本目标是尽可能多地发现并排除软件中潜藏的错误,最终把一个高质量的软件系统交给用户使用。[1]本节将从单元测试、集成测试对系统完成后的测试进行说明。
    5.4.1 测试的目的与内容系统测试是在系统开发时期与系统开发完成后,为保障系统运行的可行性、可靠性、稳定性和正确性,而进行的一些列测试,它旨在发现程序中潜藏的错误,并对错误进行及时的修改,完善系统。
    测试内容:

    单元测试:在各个模块实现完成以后进行测试,确认各模块是否能够完成其对应功能
    集成测试:将各个模块自底向上进行集成,并对各模块组成的集成结果进行测试,确认各个集成单元是否能够完成其对应功能
    用户界面测试:确认系统界面是否符合用户需求,页面元素对用户是否会造成影响,页面布局有无错误,页面有无乱码情况

    5.4.2 具体测试说明系统测试是软件开发周期中非常重要的一个时期,为了确保系统能够正常使用,并且能够满足需求分析中规划的各个功能,本系统将通过白盒测试以及UI测试来确认系统功能的实现。测试的内容主要包括确认爬虫能够抓取资讯;确认抓取数据的完整性以及正确性;确认获取的资讯能够按要求存入数据去;确认资讯展示的时候能够正确显示;确认资讯搜索时能正确过滤敏感词;确认资讯能够实现按用户不同得出不同的推荐结果;确认用户登录与注册功能的实现;确认用户能够发布自己的资讯。
    5.4.3 测试登录测试登录界面
    用户点击主页右侧的登录按钮,切换至登陆功能模块,结果如图5.2所示:

    测试登录成功
    用户于登录模块输入用户名及密码,点击登录进行身份验证,验证通过以后将会跳转至主页,并且右侧将会显示用户头像及用户名。测试结果如图5.3所示:

    测试登录失败
    用数据库中不存在的用户以及用户名或密码错误的账号进行测试,测试结果如图5.4所示:

    5.4.4 测试爬虫数据存储爬虫主要是在后台对新浪滚动新闻页面进行抓取,没有页面显示,下面主要是爬虫存储数据时,部分日志的截图。当抓取的资讯为数据库不存在的数据时,管道类将新数据插入数据库中,部分日志结果如图5.5插入新资讯日志所示:

    当新抓取的资讯已经存在于数据库中时,管道类将会对新旧数据进行判断是否重复,然后对数据库中的数据进行更新。部分日志结果如图5.6更新资讯日志所示:

    5.4.5 测试资讯相关功能测试资讯展示
    主要测试用户访问网站主页时,能否正确显示资讯列表,测试结果如图5.7所示:

    测试点击全部板块按钮
    测试选中主页左侧板块列表中的“全部”时,是否显示所有资讯数据。资讯显示按照发布时间降序排序,最新一条资讯应为最近一条抓取数据。测试结果如图5.8所示:

    测试点击体育按钮
    测试选择主页左侧板列表中的“体育”时,是否显示体育板块下的资讯数据。测试结果如图5.9所示:

    测试资讯详情展示
    测试用户浏览单条资讯详情,主要看资讯内容能否正确显示。测试结果如图5.10所示:

    测试搜索时包含敏感词汇
    测试搜索的关键字为敏感词时,能否正确过滤并对用户进行提示。测试结果如图5.11所示:

    测试搜索未包含敏感词汇
    测试搜索的关键字非敏感词时,能否正确显示搜索结果。测试结果如图5.12所示:

    测试未登录时发布资讯
    测试用户以游客身份发布资讯时,能否禁止其操作,并作出相应提示。测试结果如图5.13所示:

    测试已登录时发布资讯
    测试用户登录以后发布资讯时,能否进行发布。测试结果如图5.14所示:

    5.4.6 测试推荐功能测试推荐算法的实现
    测试推荐功能模块能否针对某个用户的浏览记录,推荐出资讯。测试结果如图5.15所示:

    游客身份推荐结果
    测试以游客身份浏览网站,推荐板块能否为其显示推荐结果。测试结果如图5.16所示:

    用户vip的推荐结果
    测试以用户vip的身份登入系统,推荐板块能否为其显示推荐结果。测试结果如图5.17所示:

    用户Wetoria的推荐结果
    测试以用户Wetoria的身份登入系统,推荐板块能否为其显示推荐结果。测试结果如图5.18所示:

    5.4.7 测试结论经过一系列测试,本系统基本已经实现需求分析阶段用户提出的需求;软件方面:软件功能较为完整,用户界面简洁大方,符合人性化设计,错误发生时,能正确提示,用户体验较好。由于时间原因以及其它自身因素,就系统功能完整性而言,部分功能还未实现,没有达到预期的效果,推荐结果的精准性以及效率还不够理想。
    5.5 本章小结本章主要说明了系统功能的实现以及测试。系统功能实现对各个模块功能实现及界面进行了说明。系统测试主要是通过白盒测试对系统进行了单元测试以及集成测试,以及通过黑盒测试对整个网站功能进行测试,确保了整个系统能够良好运行,以及符合用户实际需求。
    结 论针对目前实现的资讯网站,得出了以下结论:
    首先,从功能的完整性方面来说,整个Web网站能完成课题研究的核心基于协同过滤算法的推荐功能,能够根据用户的历史浏览记录及评分记录,为用户推荐资讯。但是由于个人的所学的不足,以及协同算法本身的限制,推荐结果在精确度方面还不够理想,不能保证推荐的资讯就是用户完全感兴趣的,在精确度方面,网站的建设还需要提升
    然后,从用户使用体验方面来说,整个网站需要用户进行的操作不多,足够简单。因为推荐功能需要对用户的浏览行为进行记录,所以注册登录功能是网站所必需的一部分,但用户在进行注册时只需要输入少量的用户信息即可完成注册,这对一些注重隐私保护的用户来说,是极大的便利条件。在整个网站的使用方面,用户所需要做的,仅仅只是选择板块进行咨询的浏览,没有其他多余的操作,及时是评分系统,也是为了对用户喜好做出的一个反馈系统,用户在进行浏览时,也可以不用进行相关操作,只是这样将对推荐结果的精度产生些微的影响。
    从网站样式方面来说,整个网站所包含的页面元素非常低,为了突出网站的核心,资讯列表占据整个页面中的绝大部份,将用户的关注点聚焦于资讯列表当中。页面两边的元素中则包括与资讯展示相关的板块列表,以及用户登录相关的操作区域,并且在用户信息展示部分下面,系统留有足够的空间对网站进行扩展,其中就已经完成了热点资讯的推荐,在今后的网站建设中还可以考虑增加多元的推荐结果展示,以及与网站发展相关的广告展示模块。
    最后,在网站运营方面,所需要付出的成本较低,仅仅只是服务器的搭建、爬虫的维护以及相关的资讯信息的管理等。
    本次课题的研究与开发对于我的技术来说也是有着极大的提升。此次课题研究期间不仅对过去的所学进行了巩固,并且还学到了许多新的技术。通过本次课题的研究首先我学会通过Maven进行搭建基于SSM框架的Web项目;然后在资讯获取功能的研究阶段,对Java语言环境下的WebMagic爬虫框架有了更好的认识;在系统结构方面加深了对MVC三层架构中各个层的作用的理解;学会了通过网络资源解决开发过程中不断遇到的大大小小的问题;开发过程中还实现了自己的Sublime下的日志高亮样式,来针对性的查看项目开发中所遇到的问题;此外还包括Bootstrap等开源框架的使用;以及开发过程中不断积累的单个技术点。此次课题研究过程,对我今后的学习方向提供了指导,该项目的开发让我明白了对于线程,我还只是会创建简单的线程并调用,对如何用线程实现想要的功能没有足够的头绪,这是我今后学习的方向之一。通过此次课题的研究,证明了我有独立完成项目的实力,虽然还有些欠缺,但是在今后不断成长中,我会逐一解决所遇到的问题,像是本课题系统中推荐算法的调用时机以及方式,是我需要考量的,所以今后的学习中,我会加大对代码效率的研究。
    参考文献[1] 张海藩,牟永敏.软件工程导论(第6版)[M].清华大学出版社,2013.
    [2] CAY S.HORSTMANN.JAVA核心技术(卷1)—基础知识(原书第9版)[M].机械工业出版社,2014.
    [3] CAY S.HORSTMANN.JAVA核心技术—高级特性(卷II)(原书第9版)[M].机械工业出版社,2014.
    [4] 孙卫琴.精通Struts:基于MVC的Java Web设计与开发[M].电子工业出版社,1900.
    [5] IanF.Darwin,达尔文,李新叶,等.Java经典实例[M].中国电力出版社,2016.
    [6] 王先国.UML基础与建模实践教程[M].机械工业出版社,2016.
    [7] 贾铁军.软件工程与实践[M].清华大学出版社,2016.
    [8] 史蒂芬森,宋丽华.数据库设计解决方案入门经典[M].清华大学出版社,2010.
    [9] 颜辉,王艳敏.数据库设计与应用.第3版[M].清华大学出版社,2016.
    [10] 张基温,曹渠江.信息系统开发案例[M].北京:清华大学出版社,2003.
    [11] Joshua Bloch. Effective Java中文版[M] .北京:机械工业出版社,2009.
    [12] 福勒.企业应用架构模式[M]北京:机械工业出版社,2010.
    [13] 杨云. SQL Server 2008数据库管理与开发[M]. 清华大学出版社, 2016.
    [14] 陈漫红. 数据库原理与应用技术:SQL Server 2008[M]. 北京理工大学出版社, 2016.
    [15] 陈锐忠,魏理豪,梁哲恒.基于UML建模的软件测试系统设计[J].电子设计工程,2016,24(21):57-59.
    [16] 王丹丹,陈康.软件工程技术现状与发展趋势[J].信息与电脑(理论版),2016(6):50-51.
    [17] 唐嘉,何彬彬,郝白东等.智能手环设计方案[J].电子技术与软件工程,2017(24):115-115.
    [18] 黄亚辉,叶璐,张旖旎等.一种可刷卡健康手环的设计[J].物联网技术,2015,5(10):53-55.
    [19] 肖辉,商建国,张帧等.以云盘为载体的个人健康档案私有云设计方法[J].中国数字医学,2016,11(12):81-83.
    [20] 梁秀林.医院信息化建设下健康体检管理系统的功能评价[J].信息系统工程, 2017(5):142-142.
    [21] 王彦平,张征宇,郭君.医院健康体检信息系统的应用效果[J].医药卫生:文摘版, 2016(8):00300-00300.
    0 评论 2 下载 2020-08-27 10:16:34 下载需要13点积分
  • 基于JAVA EE和豆瓣API实现的电影评论网站

    摘 要本网站通过对网上最新的热点影片的分门别类,采取简洁、直观的方式让观看者体验到前所未有的舒适感,通过对网站界面布局,信息采集,会员管理,观看者的互动等功能的规划来实现崭新的视听环境。
    本网站提供的电影资源和内容完全抓取自豆瓣,对来自豆瓣的数据进行处理,以更好的方式展示在用户面前,让用户尽快能找到自己需要的内容,并且对大多数电影提供下载地址。
    采用Java语言进行编写,使用Mysql数据库,SpringMVC + Hibernate进行后端开发。使用Jsp + Html + JavaScript + Bootstrap进行前端开发。
    关键字:电影, 影评, 豆瓣电影, 抓取、Java、Mysql
    AbstractThis website classification the latest online hot movies, usingsimple and intuitive way to provide unprecedented comfort experienceto the viewers. Through out the website interface layout, information collection, membership management,viewers interactive functions suchas planning to implement new audiovisual environment.
    The resources and content of the movies on the website aretaken from Douban Movie,deal with the data and display them in a better way infront for the users,so that the users can find the content they want as soon aspossible,and download links are provided for most of the movies.
    Using Java language and Mysql Database, SpringMVC + Hibernate for the back-end development, and Jsp + Html + JavaScript + BootStrap for the front-end development.
    Keywords:movie, movie review,Douban movie, Spiders crawling, Java,Mysql
    1 绪 论1.1 研究目的电影是一种表演艺术、视觉艺术及听觉艺术,利用胶卷、录像带或数字媒体将影像和声音捕捉起来,再加上后期的编辑工作而成。电影的奥秘它能够借由其影像表现出现实世界之丰富,而其本身任然停留在影像。电影是现在人们休闲的重要方式之一。电影里面往往都是:爱情、友情、生活、生命、现在、未来,不管是真实的、还是虚幻的,几乎每一部电影都能把一些种子植入你的大脑中,指不定哪天就发芽了。真的把一部部电影看进去了,它解决的绝对不是你的孤独、无聊。它会让你对生活有了新的看法,甚至会改变你人生的轨迹。
    在科技高速发展的今天,人们的日常生活、工作、学习等活动,越来越依赖于网络。在物质生活过剩的今天,追求精神生活,就是很大一部分人对生活的定义。而从最早的黑白无声电影开始,通过一代又一代的影视大师的演绎,电影也成为了人们生活中必不可少的精神食粮。喜欢看电影的人很依赖电影网站,电影网站能提供热映电影、历史电影、电影分类、电影推荐、电影评论等内容。
    1.2 发展概况随着时代的发展,如雨后春笋般的出现了很多的电影网站,可是质量却是参差不齐。很多的电影类型的网站,在商业环境的影响下,通过在各大门户网站挂外链,采取非常规手段刷关键字等各种各样的方式,在网站推出的短时间内达到一个惊人的“浏览量”,而很多并不知情的网友们,恰恰就是通过判断这种“浏览量”来决定自己平时观看电影的时候所使用的网站。这就使得现如今能够适应国内平民家庭的电影评论网站或多或少都存在这样那样的安全问题,所以一个拥有简洁的界面,并且初期投入不多,拥有井井有条的内容,以及新鲜网站主题的电影类网站的出现就会大大的抓取广大电影爱好者的眼球。
    1.3 开发工具的选择1.3.1 IDE选择IntelliJ IDEA是一种商业化销售的Java(Integrated Development Environment,IDE)工具软件,由捷克软件公司JetBrains在2001年1月时推出最初版。IntelliJ IDEA被认为是当前Java开发效率最快的IDE工具。它整合了开发过程中实用的众多功能,几乎可以不用鼠标可以方便的完成你要做的任何事情,最大程度的加快开发的速度。简单而又功能强大。与其他的一些繁冗而复杂的IDE工具有鲜明的对比。本网站开发IDE选择IDEA。
    1.3.2 操作系统选择代码部署在Linux机器上。
    1.3.2.1 免费的操作系统Linux是开源免费的操作系统,任何机构和个人都能自由的查看Linux的底层源码,并自由的修改和再发布。免费意味着零成本,无需购买任何licence,开发和部署都不需要花一分钱。
    1.3.2.2 软件优势Linux内置GCC、VI、Mysql等强大的编程软件和工具以及强大的命令行支持,你仅需几行命令就能完成一系列的工作。同时市面上的编程软件和工具几乎都对Linux支持最好,而在其它平台如windows可能支持不太好,甚至完全没法使用。
    1.3.2.3社区支持开源的解决方案几乎都是最先基于Linux的,Linux有最强大的社区支持,几乎你遇到的任何问题都能在社区上找到答案,你所需要做的事情就是放心折腾,出现麻烦Google一下,或者去社区发帖求助,问题就能迎刃而解。
    虽然Java是跨平台的语言,但Linux对Java提供了最好的支持。以最少的资源消耗,最方便的操作,优雅的完成你所需要的做事情。
    1.3.3 Web容器选择Web容器采用Nginx和Tomcat
    1.3.3.1 Jsp容器采用TomcatApache Tomcat是Apache基金会来发和维护的椅子Servlet容器,支持Servlet和Jsp,是世界上使用最广泛的Web容器。Tomcat的主要目的是实现JavaServlet API和执行Java Servlet构建动态网站。还可以使用Tomcat作为一个常规的HTTP服务器,静态页面,但这不是它的主要目的。Tomcat的Servlet引擎通常与Apache或者其他Web服务器一起工作。除了用于开发过程中的调试以及那些对速度和事务处理只有很小要求的用户,很少会将Tomcat单独作为Web服务器。但随着版本的更新,正有越来越多的用户将其单独作为Web服务器用以那些对速度和可靠性有较高要求的环境中。
    1.3.3.2 静态资源、反向代理服务器采用NignxNginx是HTTP反向代理服务器,邮件代理服务器,和通用的TCP代理服务器,相较于Apache、lighttpd等传统的HTTP Server具有占有内存少,稳定性高等优势。很多繁忙的网站都运行在Nginx上。与传统的服务器相比,Nginx并不依赖线程来处理请求。相反,它使用一个更加可伸缩的事件驱动架构(异步)。此体系结构占用的资源少但是负载巨大。即 使你不希望处理成千上万的同步请求,你仍然可以受益于Nginx的高性能和小内存占用。
    自2004年发布以来,Nginx一直专注于高性能、高并发性和低内存的使用。拥有大量的Web服务器功能,如负载平衡、缓存、访问和带宽控制等,并且能够有效地集成各种应用程序。目前Nginx是互联网上第二流行的开源Web服务器。
    1.3.4 数据库本论文网站数据库采用Mysql 。MySql是世界上最流行的开源数据库,Mysql完美支持高性能和可伸缩的网络和嵌入式数据库应用程序。由于Mysql可靠性好、性能高、成本低,吸引了很多开发者。大部分网站都使用Mysql,比如Google、Facebook等世界顶级的网站。
    1.3.5 编程语言编程语言采用Java Java是一种计算机编程语言,拥有跨平台、面向对象、泛型编程的特性,广泛应用于企业级Web应用开发和移动应用开发。Java是最流行的语言之一,国内外大型互联网公司大多使用Java。
    1.3.6 编程框架1.3.6.1 Bean管理使用Spring FrameworkSpring Framework是一个开源的Java开发框架,它提供了一个全面的现代Java企业应用程序编程和配置模型——在任何类型的部署平台。使用SpringFramework,你可以专注于应用程序的业务逻辑,没必要关心特定的部署环境,也省去了大量复杂的帮助类和配置文件。基于控制反转(IOC)的配置管理让应用程序的组建开发变得更为简洁方便。Spring核心支持依赖注入、事务管理、Web应用程序、数据访问、消息传递等。Spring Framework能与市面上绝大部分的主流Java框架进行无缝集成和兼容。
    1.3.6.2 MVC框架使用SpringMVCSpring框架是一个流行的开源应用程序框架,它可以使Java EE开发变得更容易。它由一个容器,一个框架来管理组件,包含一组Web用户界面管理,事务和持久性。Spring Web MVC是Spring框架是的一部分,是一个用来创建Web应用程序的可扩展的MVC框架。
    Spring Web MVC框架提供了模型-视图-控制器体系结构和组件,可以用来开发灵活、松散耦合的Web应用程序。MVC模式可以分离应用程序的不同方面(输入逻辑、业务逻辑和UI逻辑),同时提供这些元素之间的松散耦合。
    1.3.6.3 Dao层使用HibernateHibernate是一个开源的Java持久性框架项目。执行强大的对象关系映射,使用HQL和SQL进行数据库查询。Hibernate是一个伟大的Java ORM映射工具。它可以减少大量的SQL操作带来的复杂性,并且对于SQL知识有限的开发者来说,带来了巨大的方便。
    Hibernate是一个纯Java对象关系映射和持久性框架,允许你使用XML配置文件或者注解将普通旧式Java对象映射到关系数据库表。使用Hibernate项目可以节省大量的开发时间,因为整个JDBC层都是由框架在管理。这意味着您的应用程序的数据访问层将依赖于Hibernate,完全是从底层数据模型中抽象出来。
    Hibernate有许多超过其他类似的对象-关系映射方法优点,Hibernate开放源码,免费使用,正在很多成熟的商业项目中广泛使用,并且有一个非常活跃的社区论坛。
    2 系统分析2.1 主要功能
    一共有两个角色:评论人和管理员
    评论人可以在网站中进行账号注册
    评论人可以对电影进行简短评论、打分
    管理员上传电影的画报、各类简介信息
    网站根据某种规则自动统计、计算每部电影的分数情况
    网站自动生成电影的排行榜
    网站可以根据电影的年份或分数情况对电影进行自动排序

    2.2 方案论证2.2.1 设计原理
    网站界面:在界面上不追求奢华或者繁杂的功能,只追求两个字:“简洁”,通过干净的首页、功能、观看页面,让观看者体会到舒适的观看环境。
    功能实现:通过判断登陆权限,以不同的身份登陆到网站,分为网站管理员以及会员。管理员拥有对节目单表的增删改查等操作,并且对网站内电影有简单的处理功能,意在对网站进行管理与维护;会员则区别于游客,登陆会员之后,可以对电影进行影评或与管理员交流等操作。
    内容多样:通过管理员对信息的掌握程度以及采集速度的保证,每天进行更新内容的操作,并且通过挑选分类,精心的编排到各个模块。最好是用爬虫自动采集信息。

    2.2.2 方案选择
    资源来源:电影的信息一定要有稳定的来源,需要考察豆瓣电影API。
    爬取策略:由于电影资源需要定期更新,需要设定爬虫的爬取策略。
    自动化处理:对爬虫爬来的数据要进行自动化分类、处理,方便展示在页面上。
    评分规则制定:因为电影需要根据评分排序,需要制定一个评分规则。
    角色界定:系统需要根据用户不同的角色(访客、普通用户、管理员)来展示不同的界面。
    电影分类:需要根据电影年份、类别等分类。

    2.3 基本思路2.3.1 网站UI的思路UI,对于设计者来说,可以算是最简单的地方;但对于用户一个良好的用户界面非常重要,普通用户根本不会关心你的界面时怎么实现的,他所关心的是UI是否美丽、大方、好看。如果一个网站的UI不好看,可能用户根本没有用下去的心思了。本网站使用Bootstrap作为UI框架,简单优美。
    2.3.2 获取资源的思路通过豆瓣电影API https://developers.douban.com/wiki/?title=movie/_v2 ,制定合适的抓取策略,获得所需要的资源。
    2.3.3 权限控制思路网站分为管理员和前台用户,必须得根据权限来展示不同的界面和功能。可以利用Java注解来实现。注解可以看成是一个接口,注解实例就是一个实现了该接口的动态代理类。注解大多是用做对某个类、方法、字段进行说明,标识的。以便在程序运行期间我们通过反射获得该字段或方法的注解的实例,来决定该做些什么处理或不该进行什么处理。
    2.4 主要问题设计网站时,主要有以下几个方面的问题要解决:如何设计网站的界面;如何提高丰富的内容;如果较为方便的筛选内容;如何提供下载地址。
    2.5 网站要求本网站要求能适配绝大部分浏览器,并且有较快的响应速度。
    3 系统设计3.1 概要设计3.1.1 系统结构图针对上面的需求分析,我们把整个系统分成三个模块:

    Model:实现数据抓取,数据处理等功能。View:实现网站的界面布局和接收用户响应。Controller用来接收view层的响应,转发给model层。
    以下就是系统结构图如图3-1-1所示:

    3.1.2 系统组件图构件是系统中遵从一组接口且提供其实现的物理的、可替换的部分。构建图显示构建与构建之间的相互关系。构件图是对系统物理方面建模的两个图之一。如图3-1-2 所示是系统的构件图:

    3.1.3 系统界面设计系统界面主要有正在热映、分类、注册、登陆。
    3.2 详细设计3.2.1 版面设计系统的界面是由由html+css来完成的,一个软件的成功与否,不仅在于软件本身的效率、稳定性、用户界面(UI)也是一项非常重要的因素。
    HMTL是用来表述网页的一种语言。HTML文档=网页
    HTML 标记标签通常被称为 HTML 标签 (HTML tag)。Web 浏览器的作用是读取 HTML 文档,并以网页的形式显示出它们。浏览器不会显示 HTML 标签,而是使用标签来解释页面的内容。
    <html> 与 </html> 之间的文本描述网页 <body> 与 </body> 之间的文本是可见的页面内容 <h1> 与 </h1> 之间的文本被显示为标题 <p> 与 </p> 之间的文本被显示为段落
    3.2.2 功能设计主要有正在热映、分类、排行、注册、登陆。

    首页:首先进入的是首页,首页展示正在热映的电影的海报和概要信息,点击可以进入具体电影的详情页。
    注册、登录:网站发布评论需要先注册和登录,注册时候需要限制用户用户名格式。
    分类:需要根据条件去筛选电影和排序,并根据关键字搜索。

    4 系统实现4.1 创建系统外观界面根据网站的需要设计网页,主要分为首页、注册、登陆、分类等界面,有公共的头部和尾部。用Html+Css+Bootstrap实现。
    4.2 获取图片功能的实现为了增加响应速度,图片从豆瓣上抓取下来,上传到七牛云。
    public static void uploadToQiniu(String from, String subjectId) { String to = BUCKET_NAME.concat(":").concat(subjectId); String encodeFrom = EncodeUtils.urlsafeEncode(from); String encodeTo = EncodeUtils.urlsafeEncode(to); String url = "http://iovip.qbox.me/fetch/" + encodeFrom + "/to/" + encodeTo; Mac mac = new com.qiniu.api.auth.digest.Mac(QiniuUtils.ACCESS_KEY, QiniuUtils.SECRET_KEY); Client client = new DigestAuthClient(mac); CallRet ret = client.call(url);}
    4.3 根据条件排序和筛选功能的实现可以根据电影年份、地区、类型、关键字进行筛选,按照热门、评分、上映日期进行排序:
    public List<Subject> listBySearch(int start, int end, String year, String place, String type, String sort, String key) { Criteria criteria = getCurrentSession().createCriteria(Subject.class); if (!year.contains("不限")) { criteria.add(Restrictions.eq("year", new Short(year))); } if (!place.contains("不限")) { criteria.add(Restrictions.like("countries", "%".concat(place).concat("%"))); } if (!type.contains("不限")) { criteria.add(Restrictions.like("genres", "%".concat(type).concat("%"))); } if (sort.equals("rating")) { criteria.addOrder(OrderBySqlFormulaUtils.sqlFormula("totalRating / ratingCount desc")); } else if (sort.equals("date")) { criteria.addOrder(Order.desc("pubDate")); } else if (sort.equals("hot")) { criteria.addOrder(Order.desc("commentCount")); } if (StringUtils.isNotEmpty(key)) { criteria.add(Restrictions.disjunction() .add(Restrictions.like("title", "%".concat(key).concat("%"))) .add(Restrictions.like("originalTitle", "%".concat(key).concat("%"))) .add(Restrictions.like("casts", "%".concat(key).concat("%"))) .add(Restrictions.like("directors", "%".concat(key).concat("%"))) .add(Restrictions.like("writers", "%".concat(key).concat("%"))) ); } criteria.setFirstResult(start); criteria.setMaxResults(end); return criteria.list();}
    4.4 基于注解的权限认证网站需要区分管理员和普通用户,判断是否登陆等,来展示不同界面和功能:

    可以继承springmvc的HandlerInterceptorAdapter,然后拦截每个请求,判断是否有@LoginRequired或者@AdminRequired的注解,如果有,记录下当前uri(base64 URLEncoder之后),然后401到登陆界面,登陆成功后再跳回来。可以在一个需要验证的Controller class上写上@LoginRequired,然后整个Controller的所有method都会去做权限验证。可以用@FreeAccess 去排除不需要的的method。
    代码如下:
    public class AuthenticationFilter extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HandlerMethod method = (HandlerMethod) handler; FreeAccess freeAccess = method.getMethodAnnotation(FreeAccess.class); if (freeAccess != null) { return true; } boolean adminRequired = AnnotationUtils.findAnnotation(method.getBean().getClass(), AdminRequired.class) != null || method.getMethodAnnotation(AdminRequired.class) != null; boolean loginRequired = AnnotationUtils.findAnnotation(method.getBean().getClass(), LoginRequired.class) != null || method.getMethodAnnotation(LoginRequired.class) != null || adminRequired; if (loginRequired && !checkLogin(request)) { String url = request.getRequestURI(); String queryString = request.getQueryString(); if (StringUtils.isNotEmpty(queryString)) { url = url + "?" + queryString; } url = new String(Base64.encodeBase64(url.getBytes())); url = URLEncoder.encode(url); //如果是ajax请求响应头会有,x-requested-with if (request.getHeader("x-requested-with") != null && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) { response.setHeader("sessionStatus", "timeout");//在响应头设置session状态 return false; } response.setStatus(401); String redirectUrl = "/login?redirect=" + url; response.sendRedirect(redirectUrl); return false; } if (adminRequired && !checkAdmin(request)) { response.setStatus(403); response.sendRedirect("/403"); return false; } return true; } public boolean checkLogin(HttpServletRequest request) { return ContextUtils.getSessionUtils(request).getUser() != null; } public boolean checkAdmin(HttpServletRequest request) { User user = ContextUtils.getSessionUtils(request).getUser(); if (user == null) { return false; } else { return user.isAdmin(); } }}
    4.5 根据权限来展示界面用户的评论有删除功能,只有用户本人和管理员才能删除评论。扩展Jsp的tag来实现这个功能。
    public class SecurityTagHandler extends SimpleTagSupport { @Setter private String userId; @Override public void doTag() throws JspException, IOException { SessionUtils sessionUtils = getSessionUtils(); if (null == sessionUtils) { return; } User currentUser = sessionUtils.getUser(); if (null == currentUser) { return; } if (currentUser.isAdmin() || currentUser.getId().equals(userId)) { getJspBody().invoke(null); } return; } /** * 获取当前的SessionUtils * * @return */ private SessionUtils getSessionUtils() { JspContext jc = getJspContext(); Object sessionUtils = jc.getAttribute(ContextUtils.SESSIONUTILS, PageContext.SESSION_SCOPE); if (sessionUtils != null && sessionUtils instanceof SessionUtils) { return (SessionUtils) sessionUtils; } return null; }}
    在页面下添加删除按钮:
    <mv:securityTag userId="${comment.userId}"> <button type="button" class="close btn-danger delete_comment" data-dismiss="alert" value="${comment.id}"> </button></mv:securityTag>
    只要满足对应权限的用户才能删除评论。
    4.6 定时更新正在热映电影每天零点定时更新正在热映电影列表,用Spring注解来实现定时任务。
    @Scheduled(cron = "0 0 0 * * ?") //每天零点执行一次public void renewPlaying() { String id; List<Playing> playingList; String responseBody = HttpClientUtils.get(DoubanServiceImpl.DOUBAN_PLAYING_URL); JSONObject jsonObject = new JSONObject(responseBody); JSONArray jsonArray = jsonObject.getJSONArray("entries"); int length = jsonArray.length(); logger.debug("{} movies are playing", length); playingList = new ArrayList<>(length); for (int i = 0; i < length; i++) { id = jsonArray.getJSONObject(i).getString("id"); doubanService.find(id); playingList.add(new Playing(id)); } playingDao.renew(playingList);}
    4.7 前后端认证对用户输入的数据要进行前后端验证,防止用户在数据库中插入非法数据。

    前端用Js + 正则表达式来验证。
    function checkLoginName() { var jqCtrl = $("#txt_loginname"); var loginName = $.trim(jqCtrl.val()); if (!loginName) { jqCtrl.focus(); return false; } var ret = clientValid.validate("LoginName", jqCtrl.val()); if (!ret.success) { jqCtrl.focus(); tool.tooltip(jqCtrl, ret.comment, null, true); return false; } //server validation $.getJSON("checkUserName", {userName: loginName}, function (data) { if (!data.success) { jqCtrl.focus(); tool.tooltip(jqCtrl, data.comment, null, true); return; } }); return true;}

    后端用hibernate-validator来实现。
    /** * Validation constraints for loginName * 限制登录名不能为手机号或者邮箱地址 * * @author veryyoung */@Pattern(regexp = "^(?!(([1][3|5|8][0-9]{9})|([\\\\w-]+(\\\\.[\\\\w-]+)*@[\\\\w-]+(\\\\.[\\\\w-]+)+)))([0-9a-zA-Z_\u4E00-\u9FBF]+)", message = "用户名为数字字母或汉字,不能为手机号或邮箱")@NotNull(message = "用户名不能为空")@Size(min = 2, max = 30, message = "用户名长度需为2-30位")@Constraint(validatedBy = {})@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface UserName { String message() default "{common.loginName}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {};}用这个注解来修饰UserName,然后验证的时候只需要try { getValidatorWrapper().tryValidate(user); userService.create(user);} catch (InvalidException ex) { logger.error("Invalid User Object: {}", user.toString(), ex); modelAndView.addObject("error", ex.getMessage()); return modelAndView;}
    5 系统运行5.1 首页进入首页显示的是正在热映的电影的海报和简要信息,点击能进入对应电影的详情页。

    5.2 详情页详情页能看到该电影的详细信息,并且提供了豆瓣链接和下载链接,同时下面有五条短评,可以在该节目发布评论,也可以点击链接查看所有评论。如果是管理员或评论作者,可以删除该评论。

    5.3 评论页评论页提供了所有评论(翻页实现)。

    5.4 发布评论在电影详情页和评论页都可以对电影进行评论。

    5.5 分类页分类页可对电影进行搜索、分类、排序,方便更快的找到需要的信息。

    5.6 注册&登录页发布评论需要注册&登录。

    5.7 个人中心页个人中心页可以查看用户发布的所有评论,如若有权限可以删除评论

    结束语从最开始确定要写个电影网站,到这个网站的整体完成。我从中学到了不少知识与编程技巧。这为我将来的工作积累了一笔财富。毕业设计是我们对知识运用能力的一次全面的考核,也是踏上社会前最后一个专业项目。从接受课题到系统的完成,到论文的编写,每个过程都有很多的收获。
    虽然这个系统还不是很成熟,还比较简陋,但我可以很自豪的说,我是很认真的在写每一行代码,这个系统里的每一个细节我都了如指掌,收获很多,感触很多。
    系统不足:现在网站资源还很少,大部分电影都没有,很多资源都要实时从豆瓣获取,这无疑会拖慢网站的速度,可以制定抓取策略把豆瓣大部分电影都抓取过来,然后做更优雅的展示。
    致 谢四年的大学生活就快走入尾声,伴随着这篇毕业论文的落笔,我四年的本科大学生活也即将画上了句号。回忆这大学四年生活的滴滴点点,美好的大学生活的过往,一切都是历历在目,让人非常留恋,思绪万千。
    非常感谢我的同学们。当我在毕业设计过程中遇到困难和问题时,他们给我提出非常多的建议和意见,使我对整个系统有了总体的思路,并耐心的帮我解决了很多技术上的难题,让我毕设的过程轻松了不少。
    最后,我要特别感谢指导老师。老师在我们毕业的最后关头给了我重要的鼓励和帮助,从课题的选定到开题报告,任务书,整个系统的完成,论文的编写,格式以及内容的检测,老师全程参与进来,并提出了重要的意见和建议,老师严谨的科研精神和认真负责的工作态度都给我树立了正确的榜样,在此表示衷心的感谢。
    这是第一次写真正意义上的论文,马上要踏入企业工作了,希望这篇论文不会是学术思考的终点。
    参考文献[1] 【法】克里斯蒂安▪梅茨编著,《电影的意义》[M], 江苏:江苏教育出版社, 2005
    [2] 【德】齐格弗里德•克拉考尔编著 ,《电影的本性》[M], 江苏:江苏教育出版社, 2006
    [3] 罗刚/王振东编著,《自动动手写网络爬虫》[M], 北京:清华大学出版社, 2010
    [4] 【美】Bruce Eckel编著,《Java编程思想》[M], 机械工业出版社, 2005
    [5] 【美】Baron Schwartz 编著,《高性能Mysql》[M], 电子工业出版社, 2010
    [6] 【美】皮克编著,《Hibernate Quickly》[M], 人民邮电出版社, 2005
    [7] 【美】艾里特编著,《精通Hibernate》[M], 机械工业出版社, 2009
    [8] 周志明编著,《深入理解Java虚拟机》[M], 机械工业出版社, 2011
    [9] 【美】Jon Bentley编著,《编程珠玑》[M], 人民邮电出版社, 2008
    [10] 《编程之美》小组编著,《编程之美》[M], 电子工业出版社, 2008
    [11] 【美】鲍斯维尔编著,《编写可读代码的艺术》[M], 机械工业出版社, 2012
    [12] 子柳编著,《淘宝技术这十年》[M], 电子工业出版社, 2013
    [13] 郭欣编著,《构建高性能Web站点》[M], 电子工业出版社, 2009
    [14] 【美】Cal Henderson 编著,《构建可扩展的Web站点》[M], 电子工业出版社, 2008
    [15] 【美】Eric S. Raymond 编著,《UNIX编程艺术》[M], 电子工业出版社, 2006
    [16] 【美】Martin Fowler 编著,《重构》[M], 中国电力出版社, 2003
    4 评论 80 下载 2018-10-01 22:25:53 下载需要16点积分
  • C语言实现huffman编解码与压缩文本

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

    摘 要对于小区物业管理来说,其工作流程的繁杂性、多样化、管理复杂、收缴费用与设备维护繁琐。计算机已完全能够胜任物业管理工作,而且更加准确、方便、快捷、高效、清晰、透明,它完全可以克服以上所述的不足之处。这将给项目查询和管理带来很大的方便,从而给物业管理工作带来更高的效率,这也是物业管理正规化、现代化的重要标志。
    因此,开发一套高效率、无差错的小区物业管理系统软件十分必要。本系统的主要目的是告别帐本,安全、快捷的保存数据信息。由于小区物业管理涉及到费用问题,为了增强系统的保密性,使业主利益不受损害,使业主能够对自家的物业费用和投诉等情况提供透明化、直观的了解。
    本毕业设计的内容是设计并且实现一个基于web技术的小区物业管理系统,故而系统主要以J2EE作为开发基础,主要使用了Struts2+Spring+Hibernate等多种框架的结合使用,用Myeclipse作为开发工具,以SQL Server作为数据库,以Macromedia公司的Dreamweaver作为界面美化工具,使用JAVA语言开发,页面采取JSP动态页面开发技术。该系统界面简单、操作方便,容易维护。
    关键词:小区物业管理系统;SSH;JSP动态页面开发
    AbstractFor residential property management, the complexity of the work flow, diversification, management of complex, tedious collection costs and equipment maintenance. The computer is fully qualified to work in property management, and more accurate, convenient, fast, efficient, clear, transparent, it can overcome the shortcomings mentioned above. This will give the project inquiry and management bring great convenience, to the property management work more efficient, this is also the regularization of property management, an important symbol of modernization.
    Therefore, the development of an efficient, error-free residential property management system software is very necessary. The main purpose of this system is to bid farewell to the books, safe, fast and the preservation of data. Because the plot estate management costs involved, in order to enhance the system security, so that the interests of owners from damage, to the property owner can own property costs and complaints, provide transparent, intuitive understanding of.
    The content of graduation design is to design and implement a web based residential property management system, so the system is mainly to j2EE as a development base, the main use of struts2+spring+hibernate and other frame used in combination, using MyEclipse as a development tool, using SQL Server as the database, with Macromedia’s Dreamweaver as the interface landscaping tools, the use of JAVA language development, page take JSP dynamic page technology. This system interface is simple, convenient operation, easy maintenance.
    Keywords: District property management system SSH JSP dynamic page
    第1章 绪论1.1 课题背景科学技术日新月异,信息化时代的来临,以计算机为基础的信息科学在经济和社会生活各个领域得到了极为广泛的应用,尤其在信息管理方面,计算机已是必不可少的管理工具。
    目前,信息已成为继劳动力、土地、资本之后的又一大资源。谁控制的信息越多,谁利用信息资源的效率越高,谁就会在各方面的竞争中占有一席之地,谁就会有更多的优势。从微观上讲,建立一套管理信息系统能够加快信息的周转速度,提高生产效率,从而加强了管理的信息化手段,提高了本单位的经济效益。从宏观上讲,顺应了社会的信息化、社会化潮流,加快了社会的发展速度。据统计,美国在信息管理管理方面80-100%的信息处理由计算机完成;计划管理是80—90%;在计算机应用发展较快的国家中,计算机应用于经济管理的占80%;用于科技计算的占8%,用于生产过程控制的占12%;由此可以看出,信息管理是计算机应用的主要领域。
    1.2 课题目的和意义由于种种原因,我国的信息资源建设水平远远落后于信息基础设施的建设的水平。长期以来,我国信息资源的开发管理未能与信息资源的增长同步进行。我国的计算机应用要比西方国家落后十几年。因此,现在信息资源的开发和利用已被确立为国民经济信息的核心内容,利用现有的信息基础设施,重点开发和推广应用于各类科技、经济等数据库和网络资源服务系统,已经取得巨大的社会效益和经济效益。
    对于小区物业管理来说,其工作流程的繁杂性、多样化、管理复杂、收缴费用与设备维护繁琐。计算机已完全能够胜任物业管理工作,而且更加准确、方便、快捷、高效、清晰、透明,它完全可以克服以上所述的不足之处。这将给项目查询和管理带来很大的方便,从而给物业管理工作带来更高的效率,这也是物业管理正规化、现代化的重要标志。
    因此,开发一套高效率、无差错的小区物业管理系统软件十分必要。本系统的主要目的是告别帐本,安全、快捷的保存数据信息。由于小区物业管理涉及到费用问题,为了增强系统的保密性,使业主利益不受损害,本系统具有仅管理员式的保密功能,还有查询、录入、修改、删除、以及对物业设备统计等功能,使业主能够对自家的物业费用和投诉等情况提供透明化、直观的了解。
    1.3 系统设计思想本系统采用Jsp技术,基于MVC模式开发,使用SSH框架(Struts2、Spring、Hibernate)来增加系统的开发速度。所谓的MVC模式是”Model-View-Controller”的缩写,中文翻译为”模式-视图-控制器”。程序就是用Struts2和Hibernate这两个框架来实现模型层和控制器这两层,Jsp实现视图这一层。一般来说程序就是在数据库和页面之间起桥梁作用的,Jsp页面请求先到action,再到dao,再回到action,回到Jsp页面,action主要处理来自页面的请求,dao主要是和数据库的交互,Struts2主要用在action,处理来自页面的请求,处理完请求后跳转回页面。Hibernate主要用在dao,包括对数据库的增、删、改、查的操作,Spring控制程序的流程。
    SSH框架是J2EE应用中Struts2+Spring+Hibernate三大免费开源框架的结合使用, 它可以看成工具,也是中间件。他是用来提高我们的开发效率,提高我们软件产品的可维护性、可扩展性乃至敏捷性的。他们里面有很多优秀的设计理念及模式应用。比如,Struts属于MVC框架,关键是要了解MVC的概念及大致原理;而Hibernate属于ORM系统,属于持久层的解决方案,同样需要对ORM的概念及原理有一个总体的了解。而Spring属于应用程序框架,其核心是IOC容器以及AOP,Spring中还集成了很多适用东西,比如对JDBC的封装、自己的MVC、对动态语言的简洁访问等,它由以下3个框架构成:
    1.3.1 Struts2框架Struts2是Apache组织的一个开放源码项目。Struts2是一个比较好的MVC框架,提供了对开发MVC系统的底层支持,它采用的主要技术是Servlet,JSP和Custom tag library。
    1.3.2 Spring框架Spring 的核心是个轻量级(Lightweight)的容器(Container),它是实现IoC(Inversion of Control)容器、非侵入性(No intrusive)的框架,并提供AOP(Aspect-oriented programming)概念的实现方式,提供对持久层(Persistence)、事务(Transaction)的支持,提供MVC Web 框架的实现,并对一些常用的企业服务API(Application Interface)提供一致的模型封装,是一个全方位的应用程序框架(Application framework),除此之外,对于现存的各种框架(Struts、JSF、Hibernate 等),Spring 也提供了与它们相整合的方案。
    1.3.3 Hibernate框架Hibernate 是一个开放源码的 ORM 持久层框架。作为优秀的持久层框架实现,Hibernate 框架提供了强大、高性能的对象到关系型数据库的持久化服务,开发人员可以使用面向对象的设计进行持久层开发。简单的说,Hibernate 只是一个将持久化类与数据库表相映射的工具,每个持久化类实例均对应于数据库表中的一个数据行而已。用户只需直接使用面向对象的方法操作此持久化类实例,即可完成对数据库表数据的插入、删除、修改、读取等操作。
    第2章 可行性分析管理信息系统的强大功能越来越被物流行业内的相关人士所重视,通过系统企业能够更直接、清晰的看到数据。管理系统全面的、周到的信息服务使之逐渐成为物流行业发展前进的风向标。信息管理系统,主要用于对公司的信息进行存储,有高效、快速、不易丢失的好处,也帮助公司解决了大数据量的存储。
    2.1 经济可行性经济可行性包括两个方面的内容:一是某一备选方案占有和使用经济资源的可能性,进而实现政策目标的可能性;二是实施某一政策方案所需花费的成本和取得的收益。政府的财政资源是有限的,任何政策方案占有和使用的经济资源也是有限的。因此,任何一项公共政策都存在一个争取公共经济资源的问题。一般说来,“公共政策的经济资源的占有量与其政策目标的期望值成正比例关系。”当然,这还涉及到一个成本效益问题。如果某一方案的成本大于收益,显然这项政策是不可行的。
    在开发小区物业管理系统之前实地考查开发所需条件以及使用中所需要的耗费维护资金,在系统投入使用后带来的受益是否值得花费所需要花费的资金以及资源去进行开发。
    在我的小区物业管理系统中,开发阶段只需要一台带XP系统的电脑以及My eclipse、SQL Server 2008数据库,系统开发周期为五至八周,个人独立完成。
    在投入使用后需要物业管理人员对其进行操作、维护等日常管理,只需这些投入便可以使小区物业管理实现初步的信息化,
    2.2 技术可行性该系统由管理员和业主两种不同的功能并在两者之间进行交互操作,所以系统采用B/S模式来实现。JSP在服务器端执行,通常返回给客户端的就是一个HTML文本,因此客户端只要有浏览器就能浏览,很适合做B/S模式的WEB系统,JSP具备了Java技术的简单易用,完全的面向对象,具有平台无关性且安全可靠,主要面向因特网的所有特点。所以JSP技术对于该系统完全可行。
    2.3 系统流程图在数据库设计过后,接着就应该考虑功能实现,通过功能描述的分析,构思出系统整体结构,采用业务流程图的方式具体介绍系统大概的处理方式,以下为系统的业务流程。
    投诉信息管理系统流程图
    投诉流程由业主发起投诉信息,管理员收到信息后处理反馈,用户再对反馈信息进行察看核实,如图2-1所示。

    登陆系统流程图
    系统分为管理员与业主类型登陆,登陆后根据功能略有不同,具体的操作流程图如2-2图所示:

    缴费信息管理系统流程图
    系统缴费流程由管理员添加缴费信息后,用户查看到自己有未缴费信息进行缴费后管理员确认缴费,具体操作如图2-3所示:

    2.4 本章小结可行性分析是在系统调查的基础上,针对新系统的开发是否具备必要性和可能性,对新系统的开发分别从经济可行性、技术可行性和社会因素可行性,对本系统进行多方面的分析。根据经济、技术和需求等方面的可行性分析,可以确定本系统的开发是完全有必要的,而且是可行的,可以立项开发。
    第3章 需求分析软件需求分析工作是软件生存周期中重要的一步。只有通过需求分析才能把软件功能和性能的总体概念描述为具体上的软件需求规格说明,从而奠定软件开发的基础。软件需求分析工作也是一个不断认识和逐步细化的过程。该过程将软件调研阶段的需求资料进行分析和设计,使软件范围逐步细化到详细定义的程度,并分析出各种不同的软件元素,然后为这些元素找到可行的解决办法。本章将从不同角度的需求分析问题,讲述软件需求类型,分析过程,并部分给出了数据字典和数据流图。
    3.1 物业管理的发展成因改革开放以来,住宅建设飞速发展。我国城镇现有住宅已近80亿平方米。仅79年至99年城镇新建住宅52.5亿平方米。大量住宅小区投入使用,带来了管理工作的变化。除了对房屋进行维修外,还必须对附属物、设备、场地、环卫绿化、道路、治安进行专业化管理,以保持新建住区的完好,发挥其整体功能和综合效益。国外和香港对住宅区和其它物业实施专业化管理的经验被引入,取得了较好的效果,带动了全国物业管理工作的起步和发展。
    住房制度改革的逐步深化。随着房改的步步深化,城镇居民住房自有率已经超过75%,形成一个住区内,一幢房子里的产权多元化格局。房管所及单位房管处(科)的管房体制已经完全不能适应。对管理的社会化形成了客观的要求。物业管理从体制上克服了房改后形成的多个产权单位多头、多家管理,各自为政、扯皮推诿等旧管理体制的弊端。
    体制改革的推动。随着计划经济体制加快向社会主义市场经济体制的转轨,政府职能的转变,以前那种由政府行政福利型直接管理房屋,政府对住区环境、社区服务直接负责的办法,已经不能适应形势的变化。一个由业主自治与物业公司专业化管理结合,由物业管理企业实施经营型管理和有偿服务,使管理得以以业养业、自我发展、良性循环,既减轻了政府的压力和负担,又使得管理经费有了稳定来源的机制,日益显示其新体制的优越性。
    人民群众生活水平的不断提高。居民对住房问题的关切从有无转为大小,继而更加关注环境和社区服务。同时,广大住户拥有了自己的产业,对保持房产和附属设施的完好,以达到保值、增值的观念也逐步树立,使得物业管理的好坏已经成为居民选购住房考虑的重要因素,物业管理为越来越多的人接受,其行业地位不断攀升,外部环境逐步改善。
    3.2 小区物业管理系统需求分析信息管理系统(Information management system)是为了满足客户的需求,对公司货物的信息进行一个统计,高效、快速、方便的存储在数据库当中,不仅节省了人力,还节省了时间,对公司未来发展有着不可估量的好处。
    随着时代的发展、生活节奏的加快、买卖之间的数据量越来越大,现有的靠人工管理的模式已经越来越跟不上当今商务飞速发展的脚步。计算机辅助管理势在必行。
    3.2.1 数据流图数据流图(Data Flow Diagram):简称DFD,它从数据传递和加工角度,以图形方式来表达系统的逻辑功能、数据在系统内部的逻辑流向和逻辑变换过程,是结构化系统分析方法的主要表达工具及用于表示软件模型的一种图示方法。数据流是指处理功能输入或输出,用一个水平箭头或垂直箭头表示。数据存储是数据保存的地方。数据源去向表示数据的来源或数据的流向。

    管理员处理用户提交的投诉、维修信息
    管理员添加缴费信息用户查看缴费后进行处理

    小区物业管理系统由管理员添加以及处理缴费信息,业主对其进行查看确认是否缴费,另外业主进行投诉与维修等上报,管理员获取信息后进行处理反馈结果,用户获取反馈结果,该系统的顶层数据流图如图3-1所示。

    小区物业管理系统一共包括六个表:用户信息表、缴费信息表、投诉信息表、维修信息表、用户信息表、房产信息表。分别有六个数据流,具体如图3-2所示。

    3.2.2 数据字典数据字典(Data dictionary)是一种用户可以访问的记录数据库和应用程序源数据的目录。主动数据字典是指在对数据库或应用程序结构进行修改时,其内容可以由DBMS自动更新的数据字典。被动数据字典是指修改时必须手工更新其内容的数据字典。
    它是关于数据的信息的集合,也就是对数据流图中包含的所有元素的定义的集合。数据字典的作用是在软件的分析和设计过程中提供关于数据的描述信息。一般说来,数据字典应该由下列四类元素构成:数据元素,数据流,数据存储和数据处理数据字典的作用是在软件分析和设计的过程中给人提供关于数据的描述信息。它主要是对数据流图中的数据流、处理逻辑、外部实体、数据存储和数据项等方面进行具体的定义。数据流程图配以数据字典,就可以从图形和文字两个方面对系统的逻辑模型进行完整的描述。
    数据项定义
    数据元素也称为数据项,是不可再分的数据单位,是数据的最小组成单位,具体内容如表3-1所示。



    编号
    数据项名称
    名称
    NULL
    备注




    I01-1
    房产编号
    id
    no
    主键


    I01-2
    备注信息
    beizhu
    yes
    备注


    I01-3
    时间
    createtime
    yes
    添加时间


    I01-4
    是否删除
    fangshanlock
    no
    是否删除标志


    I01-5
    结构
    fangwujiegou
    yes
    房屋结构


    I01-6
    门牌号
    menpaihao
    yes
    门牌号


    I01-7
    面积
    mianji
    yes
    房屋面积


    I01-8
    设备
    shebei
    yes
    设备


    I01-9
    住址
    zhuzhi
    yes
    住址


    I01-10
    房产关联业主
    zhuhuid
    yes
    关联的业主ID


    I01-11
    投诉编号
    id
    no
    主键


    I01-12
    投诉反馈
    chulifankui
    yes
    处理反馈


    I01-13
    投诉结果
    chulijieguo
    yes
    处理结果


    I01-14
    投诉内容
    content
    yes
    投诉内容


    I01-15
    投诉时间
    createtime
    yes
    添加时间


    I01-16
    投诉标题
    title
    yes
    投诉标题


    I01-17
    删除标志
    tousulock
    no
    是否删除标志


    I01-18
    投诉关联业主
    zhuhuid
    yes
    关联的业主


    I01-19
    维修编号
    id
    no
    主键


    I01-20
    维修信息
    chulifankui
    yes
    处理反馈


    I01-21
    维修结果
    chulijieguo
    yes
    处理结果


    I01-22
    维修内容
    content
    yes
    维修内容


    I01-23
    维修时间
    createtime
    yes
    添加时间


    I01-24
    维修标题
    title
    yes
    维修标题


    I01-25
    删除标志
    weixiulock
    no
    是否删除标志


    I01-26
    维修关联业主
    zhuhuid
    yes
    关联的业主ID


    I01-27
    业主编号
    Id
    no
    主键


    I01-28
    业主电话
    dianhuahaoma
    yes
    电话号码


    I01-29
    业主身份证
    huzhufz
    yes
    业主身份证


    I01-30
    业主姓名
    huzhuxingming
    yes
    姓名


    I01-31
    业主入住时间
    ruzhushijian
    yes
    入住时间


    I01-32
    是否删除标志
    zhuhulock
    no
    是否删除标志


    I01-33
    业主住址
    zhuzhi
    yes
    住址


    I01-34
    用户编号
    id
    no
    主键


    I01-35
    用户添加时间
    createtime
    yes
    添加时间


    I01-36
    用户密码
    password
    yes
    密码


    I01-37
    用户权限设定
    role
    no
    用户权限


    I01-38
    用户姓名
    truename
    yes
    真实姓名


    I01-39
    是否停用
    userlock
    no
    是否停用标志


    I01-40
    用户姓名
    username
    yes
    用户名


    I01-41
    用户关联业主
    zhuzhiid
    yes
    关联的业主ID


    I01-42
    缴费编号
    id
    yes
    主键


    I01-43
    备注
    beizhu
    yes
    备注


    I01-44
    费用
    feiyong
    no
    费用


    I01-45
    费用周期
    feiyongzhouqi
    yes
    周期


    I01-46
    是否删除标志
    jiaofeilock
    no
    是否删除


    I01-47
    缴费类型
    leixing
    yes
    类型


    I01-48
    缴费时间
    shoufeishijian
    yes
    时间


    I01-49
    缴费状态
    shoufeizhuangtai
    no
    是否已交费


    I01-50
    房产id
    fangchanid
    yes
    关联房产


    I01-51
    用户id
    zhuhuid
    no
    关联用户




    数据流编号:D1—01

    数据流名称:房产信息数据流来源:管理员数据流去向:F6数据流组成:I01-01+I01-02+I01-03+I01-04+I01-05
    数据流编号:D1—02

    数据流名称:用户信息数据流来源:F1数据流去向:F5数据流组成:I01-34+I01-36+I01-38+I01-40
    数据流编号:D1—03

    数据流名称:缴费信息数据流来源:管理员数据流去向:F2数据流组成:I01-42+I01-43+I01-44+I01-45+I01-46+I01-47
    数据流编号:D1—04

    数据流名称:业主信息数据流来源:管理员数据流去向:F1数据流组成:I01-1+I01-2+I01-3+I01-4+I01-5
    数据流编号:D1—05

    数据流名称:投诉信息数据流来源:F1数据流去向:F3数据流组成:I01-11+I01-12+I01-13+I01-14+I01-15+I01-16+I01-17+I01-18
    数据流编号:D1—06

    数据流名称:维修信息数据流来源:F1数据流去向:F4数据流组成:I01-19+I01-20+I01-21+I01-22+I01-23+ I01-24+I01-25

    需求分析是一项重要的工作,也是最困难的工作。该阶段工作有以下特点:

    供需交流困难:在软件生存周期中,其它四个阶段都是面向软件技术问题,只有本阶段是面向用户的。需求分析是对用户的业务活动进行分析,明确在用户的业务环境中软件系统。但是在开始时,开发人员和用户双方都不能准确地提出系统。因为软件开发人员不是用户问题领域的专家,不熟悉用户的业务活动和业务环境,又不可能在短期内搞清楚;而用户不熟悉计算机应用的有关问题。由于双方互相不了解对方的工作,又缺乏共同语言,所以在交流时存在着隔阂。
    需求动态化:对于一个大型而复杂的软件系统,用户很难精确完整地提出它的功能和性能要求。一开始只能提出一个大概,模糊的功能,只有经过长时间的反复认识才逐步明确。有时进入到设计,编程阶段才能明确,更有甚者,到开发后期还在提新的要求。这无疑给软件开发带来困难。
    后续影响复杂:需求分析是软件开发的基础。假定在该阶段发现一个错误,解决它需要用一小时的时间,到设计,编程,测试和维护阶段解决,则要花2.5,5,25,100倍的时间。

    因此,对于大型复杂系统而言,首先要进行可行性研究。开发人员对用户的要求及现实环境进行调查,了解,从技术,经济和社会因素三个方面进行研究并论证该软件项目的可行性,根据可行性研究的结果,决定项目的取舍。
    3.3 本章小结本章对物流管理系统的需求进行分析,通过本章的论述对整个系统的设计有更加详细的了解。熟悉所依据的系统流程,根据系统流程图画出系统的数据流程,根据系统的数据流程写出所用到的数据字典,本章为整个系统的需求分析部分需求分析阶段结束之后进入总体设计阶段。
    第4章 系统设计4.1 系统功能设计需求分析说明小区物业管理系统主要为了物业管理员与业主设计的,架构在web的内部服务器上面。管理员对业主以及缴费信息进行管理,业主可以查看或者提交投诉维修等信息。整个系统就是这样的一个组织结构模式。
    依据上述功能的分析,系统中模块分别为:业主管理、用户管理、缴费管理、投诉管理、维修管理、房产管理。
    各功能模块的具体功能如下:

    业主管理:管理员对业主信息进行添加修改等功能
    用户管理:管理员对业主的用户信息是否停用进行控制,业主可以自己对自己所有用户进行密码修改等业务
    缴费管理:管理员添加以及处理缴费信息,业主查看自己所有已缴费和未缴费的信息详情
    投诉、维修管理:用户提交投诉、维修信息后,管理员查看到及时进行处理反馈结果,用户可以通过查看投诉、维修信息得知结果。具体如图4-1所示


    该系统主要包括系统管理员与业主俩个界面,系统管理员与业主分别具有不同的功能,分为两个不同的界面,之间存在信息交互等操作。
    4.2 数据库设计直到现在,我们可以设计的数据库必然是有结构的数据, 譬如说,我们已经确定了许多张表。但为什么会得到引起结构呢? 答案很简单,在数据库设计时数据库的结构是确定的,然而,进行数据库的设计,可能非常复杂。为了开发一个系统满足该组织的信息需求,要求采取不同办法在文件系统中,那里的工作为个别部门推动了应用的需要。在方法中的这种改变被子称为模式转变。为了使系统可以被用户最终接受,数据库的设计活动是至关重要的。一个没设计好的数据库中会产生错误, 这可能造成严重后果的组织。另一方面,以有效的方式精心设计制作的数据库,可以提供正确的资料。
    总之,在数据库开发中,设计的好坏是决定后续工作顺得与否的关键。
    我们小区物业管理系统使用SQL Server数据库,在数据库中考虑到几大功能模块所需数据创建了房产、维修、投诉、缴费、业主、用户这六个表。
    4.2.1 数据分析根据数据库中表的设计,数据应该是清晰的、具体的、并且要是一个合理的数据。在我们使用数据时,需要考虑到数据是否符合我们的需求,对于数据的使用我们也要遵循一定的规则。
    在我们系统中每一个表的数据类型、主键、NULL以及是否唯一等都按照系统所需分别设置,充分考虑到我们对于该系统的需求以及实现功能,为我们系统的数据正确性提供保证。
    4.3 数据库的详细设计数据库中重点为表的设计与表间的关联,在一个项目的实施过程中前期的数据库设计没有设计好就是大副度的减化系统开发的进度。分析表与表间的关系也可以帮助我们在开发项目时建立良好的流程,具体的功能和业务实现。
    数据库存在表与表间的关系,有三种形式:一对一关联,一对多关联,多对多关联,他们是对自然联接等方式来对表进行关联。表自身间的关系也是一种关联,在数据库设计中,我们不仅要对数据库中的数据类型进行了合理定义,还要对应的建好表与表间的关系才能作好数据库的设计。
    在设计数据库前应对现有类似系统的数据库进行仔细研究,找出它的不足以完善自己所设计的数据库。
    在设计前,应考虑以下事项:

    定义标准的对象命名规范
    工欲善其事,必先利其器。选择理想的数据库设计工具
    了解你的业务。根据业务需要创建数据表
    创建数据字典和E-R图表
    数据库维护

    4.3.1 数据表的设计对于小区物业管理系统,数据基本上都是使用数据库进行管理。数据库设计是对保存管理系统数据的数据库结构进行设计,对整个系统的开发具有非常重要的作用,我们一共包括以下这些表。
    房产表
    数据项包括:房产编号、备注、添加时间、是否删除标志、房屋结构、门牌号、房屋面积、设备、住址、关联业主ID,如表4-1所示。



    名称
    类型

    备注




    id
    bigint(20)
    no
    主键


    beizhu
    varchar(255)
    yes
    备注


    createtime
    datetime
    yes
    添加时间


    fangshanlock
    int(11)
    no
    是否删除标志


    fangwujiegou
    varchar(255)
    yes
    房屋结构


    menpaihao
    varchar(255)
    yes
    门牌号


    mianji
    varchar(255)
    yes
    房屋面积


    shebei
    varchar(255)
    yes
    设备


    zhuzhi
    varchar(255)
    yes
    住址


    zhuhuid
    bigint(20)
    yes
    关联的业主ID



    缴费表
    数据项包括:缴费编号、备注、添加时间、费用、费用标题、是否删除标志、缴费类型、收费时间、缴费状态,如表4-2所示。



    名称
    类型

    备注




    id
    bigint(20)
    no
    主键


    beizhu
    varchar(255)
    yes
    备注


    createtime
    datetime
    yes
    添加时间


    feiyong
    varchar(255)
    yes
    费用


    feiyongzhouqi
    varchar(255)
    yes
    费用标题


    jiaofeilock
    int(11)
    no
    是否删除标志


    leixing
    varchar(255)
    yes
    缴费类型


    shoufeishijian
    datetime
    yes
    收费时间


    shoufeizhuangtai
    varchar(255)
    yes
    缴费状态


    fangchanid
    bigint(20)
    yes
    关联的房产ID


    zhuhuid
    bigint(20)
    yes
    关联的业主ID



    投诉表
    数据项包括:投诉编号、处理反馈、处理结果、投诉内容、添加时间、投诉标题、是否删除标志、关联业主信息,具体如表4-3所示。



    名称
    类型

    备注




    id
    bigint(20)
    no
    主键


    chulifankui
    varchar(255)
    yes
    处理反馈


    chulijieguo
    varchar(255)
    yes
    处理结果


    content
    varchar(255)
    yes
    投诉内容


    createtime
    datetime
    yes
    添加时间


    title
    varchar(255)
    yes
    投诉标题


    tousulock
    int(11)
    no
    是否删除标志


    zhuhuid
    bigint(20)
    yes
    关联的业主信息



    维修表
    数据项包括:维修编号、处理反馈、处理结果、维修内容、添加时间、维修标题、是否删除标志、关联业主ID,具体如表4-4所示。



    名称
    类型

    备注




    id
    bigint(20)
    no
    主键


    chulifankui
    varchar(255)
    yes
    处理反馈


    chulijieguo
    varchar(255)
    yes
    处理结果


    content
    varchar(255)
    yes
    维修内容


    createtime
    datetime
    yes
    添加时间


    title
    varchar(255)
    yes
    维修标题


    weixiulock
    int(11)
    no
    是否删除标志


    zhuhuid
    bigint(20)
    yes
    关联的业主ID



    业主表
    数据项包括:业主编号、电话号码、业主身份证、姓名、入住时间、是否删除标志、住址,具体如表4-5所示。



    名称
    类型

    备注




    id
    bigint(20)
    no
    主键


    dianhuahaoma
    varchar(255)
    yes
    电话号码


    huzhufz
    varchar(255)
    yes
    业主身份证


    huzhuxingming
    varchar(255)
    yes
    姓名


    ruzhushijian
    varchar(255)
    yes
    入住时间


    zhuhulock
    int(11)
    no
    是否删除标志


    zhuzhi
    varchar(255)
    yes
    住址



    用户表
    数据项包括:用户编号、添加时间、密码、用户权限、真实姓名、用户名、关联业主ID,具体如表4-6所示。



    名称
    类型

    备注




    id
    bigint(20)
    no
    主键


    createtime
    datetime
    yes
    添加时间


    password
    varchar(255)
    yes
    密码


    role
    int(11)
    no
    用户权限


    truename
    varchar(255)
    yes
    真实姓名


    userlock
    int(11)
    no
    是否停用标志


    username
    varchar(255)
    yes
    用户名


    zhuzhiid
    bigint(20)
    yes
    关联的业主ID



    4.3.2 数据库的E-R图设计E-R图为实体-联系图,提供了表示实体型、属性和联系的方法,用来描述现实世界的概念模型。构造E-R图的基本要素是实体型、属性和联系的方法。由属性构成实体型,标明实体型的PK,用菱形来表示联系通过连线写明互相之间的对应关系。实体型是具有相同属性的实体具有相同的性质和特征,用实体名及其属性名集合来抽象和刻画同类实体;属性是实体所具有的某一特征,一个实体有若干个属性来刻画;联系也称为关系,信息世界中反映实体内部或实体之间的联系。
    在E-R图中联系可分为三种类型:

    一对一联系(1:1)
    一对多联系(1:N)
    多对多联系(M:N)

    一个较好的系统在设计时要做好分析工作,并且要按照一定的次序将其完成,首先做好数据的分析,设计好数据库。在分析数据库的建设问题时,首先就要从需求分析中获取系统中要用的数据,将其规化好,抽取实体及其属性,建立模型。以下为系统所有要使用的数据,以E-R图的形式表示如图4-7所示。

    系统E-R类图包括本系统六个表:业主表、用户表、房产表、投诉表、缴费表与维修表。
    在小区里,每个业主能够拥有多套房产,所以业主表与房产表属于一对多的包含关系;每个业主拥有一个用于用户端登录的用户账户密码,所以用户表与业主表是一对一的包含关系;在投诉与维修上报上是一样的,每个业主能够发起多个投诉与维修信息,所以投诉表跟维修表与业主表的关系都是一对多的生成关系;最后还有一个缴费表,每个业主每个月都会有多项缴费信息,每个业主应该对应多项缴费信息并且业主对缴费信息只允许进行查看不允许修改,所以业主表与缴费表是一对多的查看关系
    4.4 本章小结根据本章系统设计的分析,我们可以清楚知道我们的系统通过需求分析后做出了业主与管理端两个不同的界面,其中管理员有八个功能模块,而用户有七个功能模块。我们对系统所需做出了对应的数据库设计,用六个表来存储我们系统的数据。
    第5章 系统实现JavaBeans是用java语言编写的可重用的软件组件。使用javaBeans组件,以使用可视的应用程序开发工具将它们编写到java程序中。javaBeans规范为java开发人员提供了一种“组件化”其java类的方法,是实现代码重用的一个很好的机制。同时它也被广泛地应用到jsp技术中实现代码的重用,还可以实现显示和逻辑的一定程度上的分离,在实际应用中得到广泛的应用。
    5.1 系统和数据库的配置系统按通用的B/S(浏览器、服务器)模式进行设计(如图4-1)

    数据库在一个信息管理系统中占有非常重要的地位,数据库结构设计的好坏将直接对应用系统的效率,以及实现的效果产生影响。合理的数据库结构设计可以提高数据存储的效率,保证数据的完整和一致。
    5.2 数据库逻辑模型
    房产表(主键、备注、添加时间、是否删除标志、房屋结构、门牌号、房屋面积、设备、住址、关联的业主ID)
    缴费表(主键、备注、添加时间、费用、费用标题、是否删除标志、缴费类型、收费时间、缴费状态、关联的房产ID、关联的业主ID)
    投诉表(主键、处理反馈、处理结果、投诉内容、添加时间、投诉标题、是否删除标志、关联的业主信息)
    维修表(主键、处理反馈、处理结果、维修内容、添加时间、维修标题、是否删除标志、关联的业主ID)
    业主表(主键、电话号码、业主身份证、姓名、入住时间、是否删除标志、住址)
    用户表(主键、添加时间、密码、用户权限、真实姓名、是否停用标志、用户名、关联的业主ID)

    5.3 系统设计5.3.1 用户登录的设计与实现对于用户登录的设计需要用户输入正确的登录用户名、密码后台利用Ajax自动判断用户的权限,并进入相应的页面。
    用户登录程序流程描述
    在进入登录界面时,需要用户输入正确的用户名和密码,选择权限,如果用户名或密码为空时,会返回到登录界面重新输入,错误时也是,当输入正确时就会进入管理系统的主界面中。
    实现过程
    index.jsp页面合法用户的核查页面,即起到Login.jsp页面与数据库之间的一个桥梁作用,将index.jsp页面中输入的用户名、密码送入到StudentServlet中通过SQL语句与数据库中的用户名、密码进行对比,找到后即为合法用户,说明可以进入系统,在此页面中需要引入一个BaseDbOper.java文件,它起到连接数据库和对数据库的访问。
    5.3.2 系统功能的设计与实现**业主信息管理设计
    管理员应能够添加新主以及对原有业主进行查看、修改或者删除等功能,所以界面设计如图5-2所示。

    同时,在用户端应可以查询到自己的业主信息但不能查询到他人信息并且不允许进行修改,所以界面设计如图5-3所示。

    房产信息管理设计
    在房产信息管理上,管理员应该可以对业主添加、修改、删除以及查看,所以房产信息管理界面应图5-4所示。

    业主可以查看到自己的房产信息而不能查看其他人的信息,并且不允许进行修改操作,所以房产信息管理在业主节目应如图5-5所示。

    缴费信息管理设计
    缴费信息管理在管理员界面中有两次处理,一次是添加、修改等操作添加新的缴费信息,然后再运营中的收费管理进行查看以及确认缴费,在用户界面中能够查看到缴费信息但无法进行修改等操作。所有已缴费和未缴费信息是显示在一起,管理员界面中显示所有的缴费信息,用户界面中只显示自己的缴费信息,这样的方式可以给用户隐私带来保障,不允许他人查看到自己的信息。
    在添加缴费信息时先进行格式判定,缴费信息为空时不符合格式要求添加失败需要重新输入,判定成功后添加到缴费信息表中。在确认缴费信息时候如果不确认则保持未缴费状态,确认缴费后该缴费数据项的缴费状态更改为已缴费。具体如图5-6所示。

    管理员统一添加每月缴费信息后,查看确定是否有误,需要修改删除等操作,所以缴费信息管理页面如图5-7所示。

    在添加缴费信息后业主可以查看到缴费信息,业主缴费信息界面如图5-8所示。

    在业主查看到自己未缴费的信息后进行缴费,管理员应该对其进行确认缴费,如图5-9所示。

    投诉信息管理的设计
    投诉信息由业主发起投诉信息,所以业主投诉界面应该设计如图5-10所示。

    在业主发起投诉后由管理员对投诉信息进行查看处理以及反馈结果,所以投诉信息管理界面应该设计如图5-11。

    5.4 本章小结到现在为止,我们的系统功能模块基本实现完成。在数据库方面,我们有业主、用户、房产、缴费、维修以及投诉六张表,我们做出了这六张表的实体对应关系,可以让我们很清楚的知道表与表之间联系。其后我们按照需求设计了合理的系统界面,让我们的系统功能更加合理、完善。
    第6章 系统测试信息技术的飞速发展,使软件产品应用到社会的各个领域,软件产品的质量自然成为人们共同关注的焦点。不论软件的生产者还是软件的使用者,生存在竞争的环境中,软件开发商为了占有市场,必须把产品质量作为企业的重要目标之一,以免在激烈的竞争中被淘汰出局。用户为了保证自己业务的顺利完成,当然希望选用优质的软件。质量不佳的软件产品不仅会使开发商的维护费用和用户的使用成本大幅增加,还可能产生其他的责任风险,造成公司信誉下降,继而冲击股票市场。在一些关键应用 (如民航订票系统、银行结算系统、证券交易系统、自动飞行控制软件、军事防御和核电站安全控制系统等) 中使用质量有问题的软件,还可能造成灾难性的后果。
    6.1 软件测试的目的软件测试的目的,第一是确认软件的质量,其一方面是确认软件做了你所期望的事情,另一方面是确认软件以正确的方式来做了这个事件。
    第二是提供信息,比如提供给开发人员或程序经理的反馈信息,为风险评估所准备的信息。
    第三软件测试不仅是在测试软件产品的本身,而且还包括软件开发的过程。如果一个软件产品开发完成之后发现了很多问题,这说明此软件开发过程很可能是有缺陷的。因此软件测试的第三个目的是保证整个软件开发过程是高质量的。
    软件质量是由几个方面来衡量的:一、在正确的时间用正确的的方法把一个工作做正确。二、符合一些应用标准的要求,比如不同国家的用户不同的操作习惯和要求,项目工程中的可维护性、可测试性等要求。三、质量本身就是软件达到了最开始所设定的要求,而代码的优美或精巧的技巧并不代表软件的高质量。四、质量也代表着它符合客户的需要。作为软件测试这个行业,最重要的一件事就是从客户的需求出发,从客户的角度去看产品,客户会怎么去使用这个产品,使用过程中会遇到什么样的问题。
    6.2 软件测试的任务在软件投入生产性运行之前,尽可能多地发现并排除软件中潜藏的错误,最终把一个高质量的软件系统交给用户使用。软件测试是保证软件软件质量的关键步骤,它是对软件规格说明、设计和编码的最后复审。软件测试的结果也是分析软件可靠性的重要依据。具体包括登录是否成功、缴费添加是否合理、缴费处理是否有反馈、投诉维修等信息添加后是否能够回馈回去信息等操作。
    6.3 测试环境Apache提供的Web服务器Tomcat 6.0使得用户可以在Windows 2000以上操作系统下发布自己设计的动态网页。因此对论坛的调试工作主要是利用Tomcat 6.0的强大功能在本机下完成的。为了在本机下浏览Web页面,首先在创建该系统的站点上(该系统使用的是Web的默认站点)将IP地址设定为127.0.0.1,它的缺省域名值为localhost。然后向IE浏览器输入本地动态网页的URL,Web服务器在收到浏览器传送的URL之后找到网页文件,并在服务器端执行该文件后将此文件以HTML文件的形式返回该浏览器。
    6.4 本系统测试设计测试方案是测试阶段的关键技术问题。所谓测试方案包括预定要测试的功能。应该输入的测试数据和预期的结果,目标是设计一组可能发现错误的数据。本系统中,我应用了如下测试方案:白盒测试、黑盒测试。
    对于测试过程我只列出缴费与投诉两个部分,给出了单元测试部分的实例。
    6.5 测试用例在系统测试中有很多种测试方法,现在我们针对系统部分功能进行一次测试记录下来。
    首先,进入缴费信息管理添加新的缴费信息。添加后自动返回缴费信息管理界面,这时候到运营的收费管理中确认下是否已经添加进入,并确认收费。
    现在我们对缴费信息进行添加,添加时候对缴费名称、费用以及备注进行测试是否能够为空、特殊字符以及测试是否有字符数的限制,测试添加功能是否符合我们的需求,如果有限制时候是否对限制有警告处理信息。
    添加缴费信息测试时发现缴费名称不允许为空,所有项可以未任何字符。能够符合当前对该系统的需求。添加缴费信息测试通过,没有存在任何问题。下面添加完成,查看缴费信息管理页面的其他功能以及添加后的现实情况。具体软件缴费实例如表6-1所示。



    动作
    期望结果
    实际情况




    添加缴费信息
    缴费信息界面添加上新的缴费信息
    与期望相吻合


    查看缴费信息
    打开所查看的缴费项的信息,表示出它的所有信息
    与期望相吻合


    确认缴费
    缴费信息状态更改为已缴费
    与期望相吻合


    删除缴费信息
    所要删除项的缴费信息全部被删除
    与期望相吻合



    结论:经测试,小区物业管理系统缴费功能不存在BUG,功能已全部实现。
    6.6 本章小结软件测试是软件开发中的重中之重,没有一点可以马虎的,在项目管理过程中,强调的是每个过程的每一个环节都要进行测试,保证系统在每个阶段可以控制。因为软件测试中考虑的问题基本上是项目管理中需要考虑的问题。具体说,软件测试是事务性的,而项目管理是策略性,一些策略性的东西必须在一些事务性的事务上来实现。
    结论至此,小区物业管理系统设计与实现顺利完成。在几天的试运行的过程中,在连接数据库时一度出现过错误,经过调试改正后错误点全部清楚,此系统可以按着设计思想和需求功能正常运行。
    由于当今的物业管理部门还不能有一个很统一的模式化,所以本系统仅考虑到一般小区所需要的物业管理的基本和主要的几项功能,一个完好的小区物业管理系统还需要更多更复杂的功能要求。由于开发周期短和开发人员等局限性,不能将本套系统尽善尽美。希望在以后能够对小区的物业做更深一步的调研,在原由系统的基础上不断添加新功能。最终能够开发出一套完善的小区物业管理系统。
    本系统在开发过程中,在固定的物业管理要求的模式下还添加了一些人性化的,个人的构思和创意。
    本套小区物业管理系统符合基本需求功能,易于操作,应该可以在简单化模式下的小区内应用,存在要改进的地方再以后会进一步完善。希望本系统能够给用户带来方便。
    在这次毕业设计论文撰写过程中,时间很紧迫。由于已经参加实习工作,很多计划使得没有充分的时间去实习,去准备。希望在以后能够进行二次开发,继续完善它,使投入使用后更变得有实用价值。
    参考文献
    李春葆.数据库原理与应用.北京:清华大学出版社,2012
    普西金.深入体验JSP项目开发.北京:机械工业出版社,2011
    邹劲松.物业管理信息系统. 北京:清华大学出版社,2010
    季如进.物业管理(修订第二版). 北京:机械工业出版社,2010
    陈朗钦.图书管理信息系统设计. 北京:人民邮电出版社,2011
    萨师煊.数据库系统概论. 北京:清华大学出版社,2010
    张建.基于WEB的人力资源管理系统的设计与实现.大连:吉林大学出版社,2013
    王国辉.JSP项目开发全程实录(第2版).北京:清华大学出版社,2013
    韩万江.软件项目管理案例教程(第二版).机械工业出版社.2011
    Paul Nielson .Microsoft SQL Server 2008 Bible.[M]. Neurology,2011
    Jan L.Hamington.SQL Clearly Explained.[M].JRD,2011
    Thomas Kyte.Programming Techniques and Solutions[M].BeiJin:Posts& Telecom Press,2013
    Ted Neward.Server-based Java Programming.[M].JIDD,2012
    Bryan Basham.Head First Servlets and JSP .中国电力出版社,2010
    Jeremy Keith.JAVAScript DOM.人民邮电出版社,2011
    2 评论 86 下载 2019-05-16 11:50:38 下载需要15点积分
显示 75 到 90 ,共 15 条
eject