分类

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

资源列表

  • 基于java和Sql Server数据库的停车场管理系统

    一、实验内容:实现停车场管理系统,应用于车辆的出、入管理。
    二、功能要求:包括车辆进出管理与系统管理等功能模块,可根据车辆停放时间及收费标准自动收费。用户需要事先办理停车卡并充值,停车卡分优惠卡和普通卡两类。

    车场管理:车辆入场、车辆出场
    信息查询:某时间段的出入场信息,当前在场信息,车辆历史停车记录及收费信息
    信息维护:用户及停车卡信息维护、充值等
    系统管理:车位信息,计费标准等

    系统包含两类用户:管理员用户和普通用户。
    管理员可以使用系统所有功能,普通用户只能查询车辆历史记录、用户信息、停车卡充值,查询计费标准。
    三、实验环境:
    Windows XP
    JDK 1.6
    Eclipse
    SQL Server
    备注:

    在XP平台开发DK(JavaDevelopment Kit)是Sun Microsystems针对Java开发员的产品Eclipse进行前台和程序设计,开发图形用户界面和停车收费功能实施
    SQL建立数据库

    四、需求分析与设计:4.1 需求分析:本软件具有如下主要功能:

    本系统包括两类用户:管理员用户和普通用户。管理员可以使用系统所有功能,普通用户只能查询车辆历史记录、用户信息(只限于个人信息)、查询计费标准、查询当前在场信息、查询出入场信息、当前可用车位信息、口令修改。具体模块划分为如下模块:车场管理模块、信息查询模块、信息维护模块、系统管理模块。
    车场管理模块:(应该分为车辆入场和车辆出场两部分)

    车辆入场功能描述:车辆进入停车场时进行登记,记录入场时间并指定车位。只有具有停车卡的车辆才可进场,没有办理停车卡的车辆,应先办理车卡。如果没有相应车位,不能入场;如果卡中余额低于100元,应先充值后再入场。满足条件的车辆,为其指定车位并记录入场时间。车卡分两种类型普通型和优惠型。车辆出场功能描述:车辆开出停车场时进行登记,记录出场的时间并进行自动收费(从卡上扣除)。根据车辆进场时间,出场时间及收费标准自动计算车主应该缴纳的费用。如果停车时间包含不足一小时的时间,超过30分钟按一小时计算,不足三十分钟不计算。如果卡上余额足够则直接扣除;如果卡上余额不足,则应先充值后再扣除相应费用。
    信息查询模块功能描述:在这个模块里用户可以查询出入场信息、当前在场信息、用户个人信息、用户历史记录、收费标准以及当前可用车位信息
    查询出入场信息功能描述: 查询当前在场信息户可以在这里查询到两种车位的总量及当前可有的车位数量。
    查询用户个人信息功能描述:登录的管理员可以根据卡号和名字查询用户信息。登陆的普通用户只可以查到自己的信息。
    查询用户历史记录功能描述:用户可以输入卡号查询相应卡号的历史记录,包括车位号、开始停车时间、结束停车时间、停车总时间、相应收取的费用。
    收费标准功能描述:用户可以在这里查询不同种类的车位和不同卡的计费标准。
    当前在场信息功能描述:用户可以在这里查询到当前在场的车辆信息,包括卡号,车位号,开始停车时间。
    当前可用车位信息功能描述:在这里用户可以查询当前可用的车位的信息,包括车位号、车位类型。
    信息维护模块在这个模块里用户可以实现用户注册、用户修改及用户充值
    用户注册功能描述:在这里管理员可添加新的用户(普通用户)。
    用户修改管理员在这里可以修改用户。这里会以表的形式显示所有的用户信息,包括用户的停车卡信息维护,充值信息等。管理员点击相应的一行用户信息,这行信息会自动填充到表下的面板里,用户可以在面板里修改用户信息,面板下面有两个按钮,修改、删除,点击相应的按钮可以实现相应的功能。
    用户充值功能描述:用户可以再这里查到自己的余额,并且可以在这里完成充值。
    系统管理模块功能描述:在这个模块里可以修改相应的车位信息计费标准、注册管理员、更改用户口令以及查看系统声明信息。
    管理员注册功能描述:管理员可以在这里添加新的管理员。
    更改口令功能描述:用户可以在这里更该自己的密码。注:操作员只可以修改自己的密码。
    计费标准管理功能描述:管理员可以在这里不同车位类型、不同车卡类型的收费标准。
    关于功能描述:用户可以在这里看到系统声明。

    4.2 界面设计登陆界面

    管理员主界面

    普通用户主界面

    车辆入场界面

    车辆出场界面

    计费标准界面

    当场在场信息界面

    用户历史信息界面

    用户个人信息界面

    普通用户个人信息界面

    出入场信息界面

    当前可用车位信息界面

    用户注册界面

    用户修改界面

    用户充值界面

    管理员注册界面

    更改口令界面

    计费标准管理界面

    关于界面

    五、数据库设计5.1 数据库关系图
    5.2 数据表的结构设计


    用户表:users








    字段名称
    数据类型
    可空
    默认值
    说明


    cardid
    int
    不可

    主键,用户的停车卡号


    name
    Nvarchar(20)
    不可

    用户姓名


    password
    Nvarchar(20)


    用户密码


    cardtype
    Nvarchar(20)


    停车卡类型


    userstype
    Nvarchar(20)


    用户类型


    carid
    int


    用户车牌号


    tel
    int


    用户电话号码


    overage
    int


    用户余额






    车位信息表:sit_infor








    字段名称
    数据类型
    可空
    默认值
    说明


    stationid
    int
    不可

    主键,车位号


    stationtype
    Nvarchar(20)
    不可

    车位类型






    停车收费卡收费表:charger








    字段名称
    数据类型
    可空
    默认值
    说明


    cardtype
    Nvarchar(6)


    车卡类型


    stationtype
    Nvarchar(20)


    车位类型(车卡类型与车位类型一起作为主键)


    charge
    int


    价格






    停车表:park








    字段名称
    数据类型
    可空
    默认值
    说明


    cardid
    int


    车卡号(外键)


    stationid
    int


    车位号(外键)


    parkid
    int

    1,每次增加一
    停车号,主键


    startpark
    datetime


    停车开始时间


    endpark
    datetime


    停车结束时间


    fee
    int


    停车的收费


    sumpark
    int


    停车总时间



    六、关键技术介绍6.1 在其他类中得到当前登录用户对象 实现方法:在LoginFrame类中设置两个静态方法,在其他类中只需要引入LoginFrame类,然后调用他的静态方法即可。方法体如下:
    public static users getUser() { return user; } public static void setUser(users user) { LoginFrame.user = user; }
    6.2 实现用户类型不同,主界面不同的功能 可以定义静态方法disMenu().当用户是普通用户时,调用disMenu()方法即可。具体实现如下
    public void disMenu() { mnuPark.setEnabled(false); mnuSever.setEnabled(false); mnuManZhuCe.setEnabled(false); mnuManCharge.setEnabled(false); } if(user.getUserstype().equals("管理员")) { MdiFrame frame1 = new MdiFrame();//创建一个主窗体 frame1.setVisible(true);//设置其可见 LoginFrame.this.setVisible(false);//设置登录窗体为不显示 } else {//判断用户名是否为null MdiFrame frame = new MdiFrame();//创建一个主窗体 frame.disMenu(); frame.setVisible(true);//设置其可见 LoginFrame.this.setVisible(false);//设置登录窗体为不显示 }
    6.3 怎么得到系统时间 SimpleDateFormat myfmt=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String a4 = myfmt.format(new java.util.Date()).toString();
    6.4 怎么计算时间差值 try { java.util.Date now = myfmt.parse(a3);//a3是系统当前时间(即出场时间) java.util.Date date=myfmt.parse(a7);//a7是入场时间 int l=(int) (now.getTime()-date.getTime());//计算毫秒差值 day=l/(24*60*60*1000);//获取天数 hour=(l/(60*60*1000)-day*24);//获得小时 min=((l/(60*1000))-day*24*60-hour*60);//获得分钟 } catch (Exception e1) { JOptionPane.showMessageDialog(null,"消费计算错误"); } if(min < 30)//如果分钟小于30分钟 a8 = day*24+hour; else //如果分钟大于30分钟 a8 = day*24+hour+1;
    6.5 怎么让布局更优美 使用布局管理器; GridBagLayout,以更改密码界面为例:
    getContentPane().setLayout(new GridBagLayout()); setBounds(234, 129, 285, 223); final JLabel label_5 = new JLabel(); label_5.setText("登 录 名:"); final GridBagConstraints gridBagConstraints_11 = new GridBagConstraints(); gridBagConstraints_11.gridy = 2; gridBagConstraints_11.gridx = 0; getContentPane().add(label_5, gridBagConstraints_11);
    七、系统实现功能结构图
    14 评论 419 下载 2018-11-19 09:31:15 下载需要10点积分
  • 仿天猫电子商务(含前端后台数据库)

    一、基础1.1 项目简介1.1.1 基于J2EE整套技术本项目没有使用SSH,SSM框架,而是使用J2EE整套技术来作为解决方案,实现各种业务场景。在项目中借助反射等技术,采用了精妙的设计模式,开发效率并不低于使用框架。
    1.1.2 典型场景一个完整的J2EE应用包含的各种典型商务应用场景的需求,展示相应的解决思路与办法
    1.2 开发流程1.2.1 技术准备
    Java:java基础和java中级的内容
    前端:html,css,js,jquery
    J2EE:tomcat,servlet,jsp,filter
    数据库:mysql

    1.2.2 开发流程模仿天猫整站是一个比较大的项目,将按照商业项目的开发流程有条不紊的一一展开:
    1.2.2.1 需求分析首先确定要做哪些功能,需求分析包括前台和后台。前台又分为单纯要展示的那些功能-需求分析-展示,以及会提交数据到服务端的哪些功能-需求分析-交互。
    1.2.2.2 表结构设计接着是表结构设计,表结构设计是围绕功能需求进行,如果表结构设计有问题,那么将会影响功能的实现。除了表与表关系,建表SQL语句之外,为了更好的帮助大家理解表结构以及关系,还特意把表与页面功能一一对应起来
    1.2.2.3 原型接着是界面原型,与客户沟通顺畅的项目设计流程里一定会有原型这个环节。 借助界面原型,可以低成本,高效率的与客户达成需求的一致性。 同样的,原型分为了前台原型和后台原型。
    1.2.2.4 实体类设计接着开始实体类的设计与开发,实体类不仅仅是对数据库中的表的一一映射,同时还需要兼顾对业务功能的支持。
    1.2.2.5 DAO类设计然后是DAO类的设计,除了进行典型的ORM支持功能之外,也需要提供各种业务方法。
    1.2.2.6 业务类介绍讲解的业务类的概念,以及为什么在本项目中没有包含这一层
    1.2.2.7 后台-分类管理接下来开始进行功能开发,按照模块之间的依赖关系,首先进行后台-分类管理功能开发。严格来说,这是开发的第一个功能,所以讲解的十分详细,不仅提供了可运行的项目,还详细解释了其中用到的设计模式,JSP包含关系,以及每个具体的功能: 查询,分页,增加,删除,编辑,修改。 把每个细节都掰的很细,可以更好的理解,消化和吸收。 在把后台-分类管理 吃透之后,后续的其他后台管理功能,做起来就会更加顺畅。
    1.2.2.8 后台-其他管理在把后台-分类管理 消化吸收之后,就可以加速进行 后台其他页面的学习。
    1.2.2.9 前台-首页前台也包括许多功能, 与后台-分类管理类似的,首先把前台-首页这个功能单独拿出来,进行精讲。前台-首页 消化吸收好之后,再进行其他前台功能的开发。
    1.2.2.10 前台无需登录从前台模块之间的依赖性,以及开发顺序的合理性来考虑,把前台功能分为了 无需登录 即可使用的功能,和需要登录 才能访问的功能。 建立在前一步前台-首页的基础之上,开始进行一系列的无需登录功能开发。
    1.2.2.11 前台需要登录最后是需要登录的前台功能。 这部分功能基本上都是和购物相关的。 因此,一开始先把购物流程 单独拿出来捋清楚,其中还特别注明了购物流程环节与表关系,这样能够更好的建立对前端购物功能的理解。随着这部分功能的开发,就会进入订单生成部分,在此之前,先准备了一个 订单状态图,在理解了这个图之后,可以更好的进行订单相关功能的开发。
    1.2.2.12 总结最后总结整个项目的项目结构,都实现了哪些典型场景,运用了哪些设计模式,把学习到的知识都沉淀下来,转换,消化,吸收为自己的技能。
    二、需求分析2.1 概述以下需求都是基于模仿天猫整站整理出来的,主要分为3类:
    2.1.1 前端展示在前端页面上显示数据库中的数据,如首页,产品页,购物车,分类页面等等。
    2.1.2 前端交互这里的交互指的是通过POST,GET等http协议,与服务端进行同步或者异步数据交互。 比如购买,购物车,生成订单,登录等等功能。
    2.1.3 后台功能比如分类管理,分类属性管理,产品管理,产品图片管理,用户管理,订单管理等等。
    2.2 前台展示2.2.1 首页
    步骤 1 : 先看完整页面效果
    步骤 2 : 在横向导航栏上提供4个分类连接
    步骤 3 : 在纵向导航栏上提供全部17个分类连接
    步骤 4 : 当鼠标移动到某一个纵向分类连接的时候,显示这个分类下的推荐商品
    步骤 5 : 按照每种分类显示5个商品的方式,显示所有17种分类

    2.2.2 产品页
    步骤 1 : 显示分辨率为950x100的当前商品对应的分类图片
    步骤 2 : 显示本商品的5个单独图片
    步骤 3 : 商品的基本信息,如标题,小标题,价格,销量,评价数量,库存等
    步骤 4 : 商品详情
    步骤 5 : 评价信息
    步骤 6 : 5张商品详细图片

    2.2.3 分类页
    步骤 1 : 显示分辨率为950x100的当前分类图片
    步骤 2 : 显示本分类下的所有产品

    2.2.4 搜索结果页
    步骤 1 :显示满足查询条件的商品
    2.2.5 购物车查看页
    步骤 1 :在购物车中显示订单项
    2.2.6 结算页
    步骤 1 :在结算页面显示被选中的订单项
    2.2.7 确认支付页
    步骤 1 :确认支付页面显示本次订单的金额总数
    2.2.8 支付成功页
    步骤 1 :付款成功时,显示本次付款金额
    2.2.9 我的订单页
    步骤 1 :显示所有订单,以及对应的订单项
    2.2.10 确认收货页
    步骤 1 : 显示订单项内容
    步骤 2 : 显示订单信息,收货人地址等

    2.2.11 评价页
    步骤 1 : 显示要评价的商品信息,商品当前的总评价数
    步骤 2 : 评价成功后,显示当前商品所有的评价信息

    2.2.12 页头信息展示
    步骤 1 : 未登录状态
    步骤 2 : 已登录状态

    2.3 前台交互2.3.1 分类页排序
    步骤 1 : 按照综合,人气,新品,销量,价格排序
    步骤 2 : 进行价格筛选,这个不算,这个是做在浏览器端的,并不是和服务器端的交互

    2.3.2 立即购买
    步骤 1 : 在产品页,未登录状态时候,点击立即购买
    步骤 2 : 在产品页,如果已经登录,点击购买

    2.3.3 加入购物车
    步骤 1 : 在未登录状态,点击加入购物车
    步骤 2 : 在已登录状态,点击加入购物车

    2.3.4 调整订单项数量
    步骤 1 :在购物车页面,调整订单项数量
    2.3.5 删除订单项
    步骤 1 :在购物车页面,删除订单项
    2.3.6 生成订单
    步骤 1 :在结算页面,提交订单
    2.3.7 订单页功能
    步骤 1 :我的订单页面:订单页面上有3个按钮,付款,确认收货和评价,这些按钮都没有提交数据到服务端,而是提交到下一个页面的二次操作,才提交数据到服务端的。
    2.3.8 确认付款点击确认支付,提交本信息到服务端,服务端修改订单中的支付日期
    2.3.9 确认收货确认收货页面,点击确认支付,提交数据到服务端,并且修改订单中的确认收货日期
    2.3.10 提交评价信息提交评价信息到服务端
    2.3.11 登录输入正确账号密码,登录成功后跳转到首页,失败提示错误信息
    2.3.12 注册
    步骤 1 : 注册页面
    2.3.13 退出退出登录
    2.3.14 搜索提交关键字到服务端,服务端查询数据库,并返回匹配的产品
    2.3.15 前台需求列表2.4 后台管理2.4.1 分类管理
    步骤 1 : 分页查询
    步骤 2 : 新增分类
    步骤 3 : 编辑修改
    步骤 4 : 删除

    2.4.2 属性管理
    步骤 1 : 属性概念这里的属性,指的是产品属性。假定同一类产品,都有相同的属性
    步骤 2 : 分页查询
    步骤 3 : 新增属性
    步骤 4 : 编辑修改
    步骤 5 : 删除

    2.4.3 产品管理
    步骤 1 : 分页查询
    步骤 2 : 新增产品
    步骤 3 : 编辑修改
    步骤 4 : 删除

    2.4.4 产品图片管理
    步骤 1 : 产品图片概念一件产品,对应多条 单个图片一件产品,对应多条 详情图片
    步骤 2 : 产品图片管理

    2.4.5 产品属性管理
    步骤 1 : 产品属性值设置根据属性管理中的讲解,一种产品所具备的属性,在其对应的分类中进行了维护。那么,要修改产品的这些属性值,就在本页面进行。这里采用异步提交方式,编辑即修改,修改成功用绿色边框表示
    2.4.6 用户管理用户管理就提供了一个分页查询,做的比较简约,几个原因:

    用户是不能删除的
    用户信息的修改,应该交由前端由客户自己修改,比如密码,基本信息等
    用户的增加,是前端注册导致的,后台不负责用户的增加

    2.4.7 订单管理
    步骤 1 : 订单分页查询
    步骤 2 : 查看详情
    步骤 3 : 发货

    2.4.8 后台需求列表三、表结构设计3.1 概述在需求分析结束之后,接下来要做的不是马上开发功能,而是进行表结构的设计。
    3.2 数据库创建数据库:tmall。并且将数据库的编码设置为utf8,便于存放中文
    3.3 表与表关系3.3.1 表关系图
    3.3.2 表


    表名
    中文含义
    介绍




    Category
    分类表
    存放分类信息,如女装,平板电视,沙发等


    Property
    属性表
    存放属性信息,如颜色,重量,品牌,厂商,型号等


    Product
    产品表
    存放产品信息,如LED40EC平板电视机,海尔EC6005热水器


    PropertyValue
    属性值表
    存放属性值信息,如重量是900g,颜色是粉红色


    ProductImage
    产品图片表
    存放产品图片信息,如产品页显示的5个图片


    Review
    评论表
    存放评论信息,如买回来的蜡烛很好用,么么哒


    User
    用户表
    存放用户信息,如斩手狗,千手小粉红


    Order
    订单表
    存放订单信息,包括邮寄地址,电话号码等信息


    OrderItem
    订单项表
    存放订单项信息,包括购买产品种类,数量等



    3.3.3 表关系从最上面的表关系图中可以看到,有关系的表之间,都是一对多关系(反过来就是多对一关系),并没有一对一关系,和多对多关系。
    3.4 建表sql语句3.4.1 建表顺序在建表过程中,会设置外键约束,所以表和表之间有依赖关系。 因此会先建立被外键指向的表,比如User,Category,然后再是其他表
    3.4.2 表的字段
    用户表user主键Id,name用户名,password登陆密码
    分类表category主键id,name分类名
    属性表property主键id,名称name,外键cid指向category的id
    产品表主键id, name产品名称,subTitle小标题,orignalPrice原始价格,promotePrice优惠价格,stock库存,createDate创建日期,外键cid指向category的id
    属性值表propertyvalue主键id,属性值value,外键ptid指向property的id,外键pid指向product的id
    产品图片表主键id,type图片文件,外键pid指向product的id
    评价表主键id,content评价内容,createDate创建日期,外键pid指向product的id,外键uid指向用户表的id
    订单表

    orderCode:订单号address:收货地址post: 邮编receiver: 收货人信息mobile: 手机号码userMessage: 用户备注信息createDate: 订单创建日期payDate: 支付日期deliveryDate: 发货日期confirmDate:确认收货日期status: 订单状态外键uid,指向用户表id字段
    订单项表

    外键pid,指向产品表id字段外键oid,指向订单表id字段外键uid,指向用户表id字段number字段表示购买数量

    四、实体类4.1 概述所谓的实体类,就是对于数据库中的表的互相映射的类。 这是一种ORM的设计思想,即一个对象,对应数据库里的一条记录
    4.2 所有实体类对于一对多的表,在“一”的类中添加“多”的类集合,在“多”的类中添加“一”的类。
    五.DAO类设计5.1 概述DAO是Data Access Object的缩写,这些类专门用于进行数据库访问的操作。

    首先讲解两个工具类,DBUtil和DateUtil,因为在DAO类中会用到这两个工具类
    接着按照依赖顺序,逐个讲解不同的DAO类以及其中的方法

    5.2 工具类
    DBUtil类初始化驱动,并返回数据库连接
    DateUtil用于实体类和数据库中日期格式的转换

    5.3 DAO类六.Service6.1 通常的设计流程作为J2EE web 应用,一般会按照如图所示的设计流程进行Servlet -> Service(业务类) -> DAO -> database当浏览器提交请求到tomcat web 服务器的时候,对应的servlet的doGet/doPost方法会被调用,接着在servlet中调用Service类,然后在Service类中调用DAO类,最后在DAO中访问数据库获取相应的数据。

    6.2 不使用Service的原因在本模仿天猫整站-J2ee 版本中,不使用Service这一层。 原因是在DAO进行了比较详细的设计,已经提供了很好的支持业务的方法。
    七.后台7.1 原型-后端7.1.1 概述本项目里的后端又不仅仅是CRUD维护管理页面,还有一些其他略复杂的功能,所以还是把这些原型界面都做出来。 后续开发功能的时候,就可以基于这些原型界面进行。
    7.1.2 分类管理
    7.1.3 属性管理
    7.1.4 产品管理
    7.1.5 产品图片管理
    7.1.6 产品属性管理
    7.1.7 用户管理
    7.1.8 订单管理
    7.2 后台-分类管理7.2.1 概述开发整站的顺序,通常来说还是按照依赖性来进行,前端需要的数据,都要先通过后台的功能维护在数据库中,才可以拿到。 所以,先进行后台功能的开发,然后再是前台功能的开发。
    后台在系统设计的时候,并不是简单的每个功能对应一个Servlet,而是使用了反射的技术,结合过滤器Filter进行了封装,使得开发配置以及维护成本降低了很多。
    7.2.2 静态资源接下来,解析这个可运行项目。 首先从最简单的静态资源开始。
    7.2.3 Filter配合Servlet步骤一:每种实体类,对应了一个Servlet,而不是对应了5个,这样首先从Servlet数量上来讲,就大大的减少了。原理流程图:

    假设访问路径是 http://127.0.0.1:8080/tmall/admin_category_list
    过滤器BackServletFilter进行拦截,判断访问的地址是否以/admin_开头
    如果是,那么做如下操作

    取出两个下划线之间的值 category取出最后一个下划线之后的值 list然后根据这个值,服务端跳转到categoryServlet,并且把list这个值传递过去
    categoryServlet 继承了BaseBackServlet,其service方法会被调用。 在service中,借助反射技术,根据传递过来的值 list,调用对应categoryServlet 中的方法list()
    这样就实现了当访问的路径是 admin_category_list的时候,就会调用categoryServlet.list()方法这样一个效果

    步骤二:代码讲解-BackServletFilter:

    首先在web.xml配置文件中,让所有的请求都会经过BackServletFilter<url-pattern>/*</url-pattern>
    还是假设访问的路径是:http://127.0.0.1:8080/tmall/admin_category_list
    在BackServletFilter 中通过request.getRequestURI()取出访问的uri: /tmall/admin_category_list
    然后截掉/tmall,得到路径/admin_category_list
    判断其是否以/admin开头
    如果是,那么就取出两个_之间的字符串,category,并且拼接成/categoryServlet,通过服务端跳转到/categoryServlet
    在跳转之前,还取出了list字符串,然后通过request.setAttribute的方式,借助服务端跳转,传递到categoryServlet里去

    步骤3:代码讲解-CategoryServlet和BaseBackServlet服务端跳转/categoryServlet就到了CategoryServlet这个类里

    首先CategoryServlet继承了BaseBackServlet,而BaseBackServlet又继承了HttpServlet
    服务端跳转过来之后,会访问CategoryServlet的doGet()或者doPost()方法
    在访问doGet()或者doPost()之前,会访问service()方法
    BaseBackServlet中重写了service() 方法,所以流程就进入到了service()中
    在service()方法中有三块内容

    第一块是获取分页信息第二块是根据反射访问对应的方法第三块是根据对应方法的返回值,进行服务端跳转、客户端跳转、或者直接输出字符串。
    第一块和第三块放在后面讲解,这里着重讲解第二块是根据反射访问对应的方法

    取到从BackServletFilter中request.setAttribute()传递过来的值 list根据这个值list,借助反射机制调用CategoryServlet类中的list()方法,这样就达到了CategoryServlet.list()方法被调用的效果

    7.2.4 JSP包含关系步骤一:分类查询对应的JSP文件分类查询对应的JSP文件是listCategory.jsp,用到了4个公共包含文件:

    <%@include file=”../include/admin/adminHeader.jsp”%>
    <%@include file=”../include/admin/adminNavigator.jsp”%>
    <%@include file=”../include/admin/adminPage.jsp”%>
    <%@include file=”../include/admin/adminFooter.jsp”%>

    步骤二:每个后台页面都在开始使用了adminHeader.jsp

    html5
    jsp指令
    引入JSTL
    引入js和css
    预先定义一些判断输入框的js函数
    对于删除链接,需要进行确认操作

    步骤三:adminNavigator.jsp导航部分,包括一张图片和4个链接
    7.2.5 查询步骤1:MVC设计思想根据 MVC设计模式的思想,做J2EE web应用,从MVC的角度来看,就是把不同的数据显示在不同的页面上。数据就是 模型 ( bean, dao )、页面就是 视图 ( jsp )、控制不同的模型显示在不同的视图上,这件事,就是由控制器来完成 ( servlet )。所以分类管理,从MVC的角度来看,就是把多条分类Category数据放在一个集合里, 让listCategory.jsp 这个视图去显示出来。
    步骤2:list()方法在list()方法里做的事情是,取出数据,并且交由jsp显示。

    通过categoryDAO取得数据集合 cs
    通过request.setAttribute 放在 “thecs” 这个key中,为后续服务端跳转到jsp之后使用
    return “admin/listCategory.jsp”;

    步骤3:服务端跳转list()方法跳转到jsp页面
    步骤4:listCategory.jsp作为视图,担当的角色是显示数据。所以关键就是从第44行开始,借助JSTL的c:forEach标签遍历从CategoryServlet的list() 的request.setAttribute(“thecs”, cs); 传递过来的分类集合。
    7.2.6 分页步骤1:page.javaPage这个类专门为分页提供必要信息。
    步骤2:获取分页参数Service方法获取网页上传递来的开始位置,以及每页需要显示的数量。如果传递数据过来,开始位置取0,每页显示的数量取默认值:5.
    步骤3:基于分页参数,获取数据通过反射调用list()方法,list调用DAO获取分页数据。
    步骤4: 为page对象设置总数在分页显示的时候,依据这个总数来判断一共有多少页面,最后一页是多少。
    7.2.7 增加步骤1:增加的部分是坐在查询结果页面的。步骤2:提交数据会导致add()方法被调用。步骤3:接收数据并处理:parseUpload方法获取文件流步骤4:ImageUtil工具类:转换文件格式为jpg,改变文件大小步骤5:中文问题,在过滤器中对提交的数据进行统一编码步骤6:客户端跳转,add()方法返回@admin_category_list
    7.2.8 删除步骤1:用于删除的超链,指向地址admin_category_delete,并且会传递当前分类对象的id过去。步骤2:在adminHeader.jsp中对所有的删除连接都进行了监听。步骤 3 : 删除调用CategoryServlet.delete()方法。
    7.2.9 编辑步骤1 : 编辑超链,用于编辑的超链,指向地址admin_category_edit,并且会传递当前分类对象的id过去。步骤2 : 调用CategoryServlet.edit()方法。步骤3:服务端跳转到editCategory.jsp,在editCategory.jsp页面里,获取由CategoryServlet.edit() 通过request传递过来的Category对象,获取name和id。
    7.2.10 修改步骤1:编辑页面提交数据。步骤2:CategoryServlet.update() 方法和CategoryServlet.add()方法的处理很类似,有所不同之处在于增加操作一定会提交图片,而修改不一定提交图片。
    7.3 后台-其他管理7.3.1概述后台的其他管理页面与分类管理用到的设计思路类似。
    7.3.2 属性管理7.3.3 产品管理7.3.4 产品图片管理7.3.5 产品属性管理7.3.6 用户管理7.3.7 订单管理八. 前台8.1 原型-前端8.1.1 概述在开发功能之前,都会先有原型界面。 通常原型界面的数据不是真实的,是临时写在页面上,为用户提供一个直观的界面感受的。
    关于前端的关注点,着重落在如何获取服务端的数据,显示在页面上,以及前端页面与服务端的同步/异步数据交互上。
    8.1.2 首页
    8.1.3 分类页
    8.1.4 产品页面
    8.1.5购物车页面
    8.1.6 我的订单页面
    8.1.7 结算页面
    8.1.8 查询结果页面
    8.1.9 支付页面
    8.1.10 支付成功页面
    8.1.11 确认收货页面
    8.1.12 收货成功页面
    8.1.13 评价页面
    8.1.14 登录页面
    8.2 前台-首页8.2.1 概述8.2.1.1 前台无需登录从前台模块之间的依赖性,以及开发顺序的合理性来考虑,把前台功能分为了 无需登录 即可使用的功能,和需要登录 才能访问的功能。 建立在前一步前台-首页的基础之上,开始进行一系列的无需登录功能开发。
    8.2.1.2 前台需要登录接着是需要登录的前台功能。 这部分功能基本上都是和购物相关的。 因此,一开始先把购物流程 单独拿出来捋清楚,其中还特别注明了购物流程环节与表关系,这样能够更好的建立对前端购物功能的理解。随着这部分功能的开发,就会进入订单生成部分,在此之前,先准备了一个 订单状态图,在理解了这个图之后,可以更好的进行订单相关功能的开发
    8.2.2 静态资源步骤1:图片资源Site目录,轮播图片,分类图片,产品图片
    步骤2:css,js
    8.2.3 Filter配合Servlet步骤1:ForeServletFilter与BackServletFilter相似,如果访问路径以/fore而不是以/foreServlet开头,就跳转到foreServlet。
    步骤2:ForeServlet和BaseForeServlet在ForeServlet类里,就提供了所有前端需要用到的业务方法。BaseForeServlet与BaseBackServlet相似,不过前台没有用到分页,所以service主要是根据反射调用ForeServlet的home()方法以及根据home()的返回值进行跳转。
    8.2.4 home方法步骤1:首页展示的数据

    在横向导航栏上提供4个分类连接
    在纵向导航栏上提供全部17个分类连接
    当鼠标移动到某一个纵向分类连接的时候,显示这个分类下的推荐商品
    按照每种分类显示5个商品的方式,显示所有17种分类

    步骤2:home方法获取所有分类,为分类填充产品,推荐产品。
    8.2.5 home.jsp步骤1:包含页面根据前台页面的特点,我们把home.jsp设计成如代码所示。

    header.jsp引入标准标签库,js,css,自定义javascript函数等
    top.jsp置顶导航
    search.jsp搜索栏
    homePage.jsp首页业务页面
    footer.jsp页脚

    8.2.6 homePage.jsp步骤1:homepage.jsp所包含的页面关系

    categoryAndCarousel.jsp,分类和轮播
    categoryMenu.jsp,竖状分类菜单productsAsideCategorys.jsp,竖状分类菜单右侧的推荐产品carousel.jsp,轮播。
    homepageCategoryProducts.jsp主题的17种分类以及每种分类对应的5个产品
    步骤2:categoryAndCarousel.jspcategoryAndcarousel.jsp 页面利用ForeServlet传递过来的数据,天猫国际几个字旁边显示4个分类超链,另外包含了其他3个页面:categoryMenu.jsp、productsAsideCategorys.jsp、carousel.jsp

    8.3 前台-无需登录8.3.1 概述我们把前台功能分为两部分:

    无需登录有一些功能,无需登录也可以使用的,比如登录,注册本身,分类页面,查询,产品页面等
    需要登录有一些功能,必须建立在已经登录的基础之上,比如购买,加入购物车,查看购物车,结算页面,订单页面等等。

    8.3.2 注册与首页的home.jsp相仿,register.jsp也包含了header.jsp,top.jsp,footer.jsp等公共页面。不同的是,没有使用首页的search.jsp,而是用的简单一点的 simpleSearch.jsp。
    8.3.3 登录与register.jsp相仿,login.jsp也包含了header.jsp,footer.jsp等公共页面。中间是登录业务页面loginPage.jsp
    8.3.4 退出清除session中的user
    8.3.5 产品页product()方法用来展示产品。productPage.jsp 又由3个页面组成

    imgAndInfo.jsp:单个图片和基本信息
    productReview.jsp:评价信息
    productDetail.jsp:详情图片

    8.3.6 模态登录在未登录状态,点击购买或者加入购物车就会弹出这个模态对话框,在这个模态对话框上可以进行登录操作.
    立即购买和加入购物车这两个按钮的监听是放在imgAndInfo.jsp页面中这两个按钮都会通过JQuery的.get方法,用异步ajax的方式访问forecheckLogin,获取当前是否登录状态。如果返回的不是”success” 即表明是未登录状态,那么就会打开登录的模态窗口。
    模态窗口modal.jsp被footer.jsp所包含。
    8.3.7 分类页步骤1:5个Comparator比较器分类这个页面有排序功能,所以ForeServlet之前,先准备5个Comparator比较器:

    ProductAllComparator 综合比较器,把 销量*评价 高的放前面
    ProductReviewComparator 人气比较器,把 评价数量多的放前面
    ProductDateComparator 新品比较器,把 创建日期晚的放前面
    ProductSaleCountComparator 销量比较器,把 销量高的放前面
    ProductPriceComparator 价格比较器,把 价格低的放前面

    步骤2:ForeServlet.category()根据cid获取分类c,为c填充产品,为产品填充销量和评价。获取参数sort,进行排序。
    步骤3:categoryPage.jspcategoryPage.jsp 里有3个内容:

    显示当前分类图片
    <img src="img/category/${c.id}.jpg">排序条 sortBar.jsp
    产品列表 productsByCategory.jsp

    步骤4:sortBar.jspsortBar.jsp即排序条,作用如下:

    根据sort参数判断那个排序按钮高亮
    每个排序按钮提交到本页面,即/forecategory,并带上参数sort

    步骤5:productsByCategory.jspproductsByCategory.jsp显示当前分类下的所有产品,通过forEach遍历c.products集合里的每个产品,并把产品标题,价格,图片,评价数,成交数打印出来。categorycount是用于测试的,在访问地址的时候加这个参数可以控制显示的产品数量。
    8.3.8 搜索Search()方法进行模糊查询,将结果返回给jsp,最终在productBySearch.jsp页面中显示出来。
    8.4 前台-需要登录8.4.1 购物流程步骤1:购买的业务流程

    登录

    访问产品页
    立即购买

    进入结算页面

    加入购物车

    查看购物车

    选中购物车中的商品

    又到了第4步的结算页面
    在结算页面生成订单
    付款

    确认收货
    评价

    步骤2:购物流程环节与表观系围绕购物流程最重要的两个表是OrderItem 和 Order表,关于OrderItem的业务行为:

    立即购买 —— 新增 OrderItem
    加入购物车 —— 新增 OrderItem
    查看购物车 —— 显示未和Order关联的OrderItem
    选中购物车中的商品 —— 选中OrderItem
    结算页面 —— 显示选中的OrderItem


    生成订单 —— 新增Order
    付款 —— 修改Order状态
    我的订单 —— 显示Order
    确认收货 —— 修改Order状态

    8.4.2 立即购买步骤1:buyone()

    获取p和user
    增加订单项OrderItem或调整数量
    跳转到结算页面/forebuy

    8.4.3 结算页面步骤1:buy()

    getParamValues获取多个oiid
    根据oiid将订单项放入集合ois中
    计算ois的价格总数total
    ois放入session,total放入request
    服务端跳转到buy.jsp

    步骤2:buyPage.jsp

    遍历出订单项集合ois中的订单数据,从立即购买跳转到结算页面只会有一件产品。
    显示总金额
    提交订单项到订单

    8.4.4 加入购物车步骤1:登录之后,点击加入购物车,会使用Ajax提交数据到addCart()
    步骤2:addCart()和buyone()一样:

    获取pid,num
    从session中获取user
    新增订单项或只增加数量

    8.4.5 查看购物车页面步骤1:cart()

    获取当前用户
    获取用户的ois
    跳转到cart.jsp

    8.4.6 登录状态Filter准备一个过滤器,当访问那些需要登录才能做的页面的时候,进行是否登录的判断,如果不通过,那么就跳转到login.jsp页面去,提示用户登录。新建过滤器ForeAuthFilter,

    不需要登陆的页面注册,登录,产品,首页,分类,查询
    需要登陆的页面购买行为,加入购物车,查看购物车,查看订单

    8.4.7 购物车页面操作步骤1.调整订单数量,通过ajax访问/forechangOrderItem

    判断用户是否登录
    获取pid和number
    遍历OrderItem
    根据pid找到OrderItem,更新OrderItem
    返回success

    步骤2.删除订单项,通过ajax访问/foredeleteOrderItem

    判断用户是否登录
    获取oiid
    删除oiid对应的OrderItem数据
    返回字符串”success”

    8.4.8 订单状态图

    首先是创建订单,刚创建好之后,订单处于waitPay 待付款状态
    接着是付款,付款后,订单处于waitDelivery 待发货状态
    前两部都是前台用户操作导致的,接下来需要到后台做发货操作,发货后,订单处于waitConfirm 待确认收货状态
    接着又是前台用户进行确认收货操作,操作之后,订单处于waitReview 待评价状态
    最后进行评价,评价之后,订单处于finish 完成状态

    比较特殊的是,无论当前订单处于哪个状态,都可以进行删除操作。 像订单这样极其重要的业务数据,实际上是不运行真正从数据库中删除掉的,而是把状态标记为删除,以表示其被删掉了,所以在删除之后,订单处于 delete 已删除状态
    8.4.9 生成订单步骤1.提交订单调用createOrder()方法

    获取参数创建订单对象
    更新订单项
    跳转到确认支付页forealipay,并带上id和总金额

    步骤2:确认支付页显示总金额,支付后跳转到forepayed页面,带上id和总金额
    步骤3:支付成功页显示订单的基本信息
    8.4.10 我的订单页bought方法获取user中不是delete状态的订单集合osbought.jsp显示订单的日期、金额等信息,显示每个订单项对应的产品
    8.4.11 我的订单操作步骤1:在我的订单页面,根据订单的不同状态,可以做出如下不同的操作:

    付款 —— 已经生成,但是未付款
    确认收货 —— 通过后台发货后
    评价 —— 确认收货后, 进行评价
    删除 —— 任意状态下

    步骤2:确认收货/foreconfirmPay

    为订单对象o填充订单项,
    confirmPay.jsp显示订单的创建的时间等信息

    步骤3:确认收货成功/foreorderConfirmed

    修改订单o的状态为等待评价,修改其确认支付时间
    更新到数据库
    orderConfirmPage.jsp显示成功信息

    步骤4:评价
    步骤5:删除/foredeleteOrder

    修改状态,更新
    返回字符串success
    boughtPage.jsp的js代码隐藏当前订单

    8.4.12 评价产品步骤1:评价产品页面/foreview

    为订单o填充订单项
    获取第一个订单项的产品,显示其图片
    获取这个产品的评价集合
    为产品设置数量和销量
    把产品,订单和评价放在request上
    在reviewPage.jsp中显示产品图片,产品标题,价格,产品销量,产品评价数量,以及订单信息等。 同时还显示出了该产品所有的评价,但是默认是隐藏的

    步骤2:提交评价/foredoreview

    获取订单o,修改状态,更新到数据库
    获取产品对象p,获取参数content(评价信息),对评价信息进行转义
    获取当前用户,获取评价对象review
    为review设置评价信息等,提交到数据库
    跳转到/foreview:参数showonly=true,显示评价信息

    九.总结9.1 项目总结9.1.1 项目结构
    项目名称 tmall
    ava源代码包结构

    tmall.bean 实体类tmall.comparator 比较器tmall.dao DAO类tmall.filter 过滤器tmall.servlet servlettmall.test 测试类tmall.util 工具类
    web目录

    css css文件img 图片资源js文件admin 后台管理用到的jsp文件include 被包含的jsp文件

    9.1.2 典型场景
    购物车
    订单状态流转
    CRUD
    分页
    一类产品多属性配置
    一款产品多图片维护
    产品展示
    搜索查询
    登录、注册
    登录验证

    9.1.3 设计模式
    MVCMVC设计模式贯穿于整个后台与前台功能开发始末
    Filter+Servlet+反射采用Filter+Servlet+反射的设计模式,把原本后台需要20多个Servlet的经典Servlet设计方式,精简到了7个。把原本前台需要20多个Servlet的经典Servlet设计方式,精简到了2个。web.xml的配置文件也大大减少,降低了开发和维护的工作量,减少了出错的几率。
    统一的分页查询简化开发所有的后台都使用同一个分页机制,仅仅需要一份简化的adminPage.jsp即满足了各种分页功能的需求,简化了开发,提升了开发速度。
    模块化JSP设计从大的JSP文件中,通过JSP包含关系抽象出多个公共文件,并把业务JSP按照功能,设计为多个小的JSP文件,便于维护和理解

    9.2 改进练习还有些功能可以继续完善。

    后台管理员登陆模块
    产品图片排序
    前台分类下显示产品,提供分页功能

    等等
    0 评论 1 下载 2019-07-16 18:06:17 下载需要20点积分
  • 基于C++实现的LZW压缩算法

    1 特点基于C++实现的LZW压缩算法,特点如下所示:

    使用stl::map键值对作为字典存储
    感觉算是简单的文件操作
    字典无限长,字典自生长。但是字典只能解析存储ascii编码之类存在,中文符号之类的碰到就挂

    2 逻辑设计2.1 总体思路
    2.2 模块划分

    3 总结LZW算法的核心时字典的生成,因为字典是不保存的,是动态生成的,不管是在压缩还是解压缩的情况下都是如此。既然字典是自生成的,就需要解决解压或者压缩第一个输入字符的问题。在这里我使用的是ASCII码,在字典中声明256个空间,在读入第一个字符便可以对应之。关于编码存储,可以使用16进制来存储。
    同时,既然是一种压缩算法,压缩率和压缩速度便是其两大评价标准。关于压缩率,限于算法性能,在压缩小型且重复率低文件时甚至会有副作用,这是无可避免的,只能在这种前提下避免使用这种算法。至于压缩速度,在我第一次编写程序时,因为使用的是Map来做字典,而且为了解压缩的方便,两种方法使用同一种字典,即<编码值, 关键字>存储,这样造成的问题是,在压缩时,要经常且循环检查关键字是否在字典中存在,而又因为map是形如红黑树的构造,在查找键的环境下时间效率是对数n,但是查找关键字就需要借助自行编写的迭代器,就造成了很大时间性能限制。所以,在第二次改进时,压缩变成了<关键字, 编码值>,解压缩则还是<编码值, 关键字>。这样虽然在同时进行压缩和解压缩的情况下会加大内存开销,但是在提升4-5倍速度的情况下我认为还是值得付出的代价。
    4 程序主界面
    1 评论 27 下载 2018-11-02 15:56:05 下载需要4点积分
  • 基于PHP和MYSQL数据库实现的公共考试报名管理系统网站

    前 言随着社会的快速发展,体力不再是我们唯一的生存方式了,人们也越来越注重自身的文化素养,随之而来的也有许多成人考试,为已经步入社会的人提供一个再学习的机会。
    众所周知,作为学生,考试是我们必经的过程,选考也会非常容易。甚至在初高中时我们不需要选择考试,而是在学校的安排下直接参加考试。而对于已经步入社会的成人来说,他们选考就会比较的麻烦。一方面他们面临着工作的压力,另一方面工作之余还会有许多别的社会活动。为了不让选考成为广大人群的负担,我们小组一起设计编写了公共考试报名管理系统,目的就在于让所有人都有一个方便、公平的选考平台。不管是学生还是成人,都可以通过注册自己的信息,登录公共考试管理系统选择考试。
    而一个考试报名管理系统,它所要面对的对象不仅仅是广大考生群体,还需要管理员来进行管理整个考试报名系统的运作。而考生和管理员作为不同的人员类型,当然具有不同的权限,并且具有不同的页面。考生的权限包括用户账号注册,修改自身注册信息,查询考试列表以及报名需要的考试,同时可以查看自己已报名的考试以及退选。管理员分为两种,第一种是超级管理员,它拥有此系统的最高权限,包括考生管理(添加考生,以及对已注册的考生进行管理包括编辑信息,和删除考生),考试管理(添加考试即发布考试,以及删除考试),管理员管理(添加、编辑管理员信息以及删除管理员)和系统设置(注册界面,考生登录界面的公告栏的编辑);另一种是招生人员,它和超级管理员之间的差别就在于缺少对管理员的管理。
    为使网页模块紧凑,功能完善,需对每一个模块都要进行检测,如在输入错误数据后,会给出相应错误提示;而在进行正确操作后,则进入相应的界面。
    在本次设计中,通过“发现问题,分析问题,最终解决问题”三步。对系统作了认真的分析和测试,用实际操作实现了知识的积累和运用。并在开发过程中初步掌握PHP技术,MySQL数据库技术,git的使用方法以及协同编程的过程。通过设计,使我们对基础知识有了更深入的了解,并培养了团队的合作精神。
    第一章 系统分析1.1 需求分析
    实现公告栏的告示(包括注册公告栏和考生登录公告栏)
    实现用户的注册和登录
    实现用户对注册信息进行修改
    实现用户查看系统中已发布考试
    实现用户报名考试
    实现用户查看自己已报名的考试
    实现用户对自身已报名的考试进行退选
    实现管理员对考生进行添加
    实现管理员对考生进行管理(编辑,删除)
    实现管理员对考试进行添加即发布考试
    实现管理员查看已发布的考试并可以对相应考试进行删除
    实现管理员查看某门考试的已报名该考试的考生列表
    实现超级管理员对管理员进行添加,以及编辑管理员信息,删除管理员
    实现管理员进行公告栏的修改及发布
    系统运行稳定,具有强大的数据处理功能

    1.2 可行性分析
    操作方便

    考生界面设计简洁,功能操作较为方便
    在界面切换的过渡时均有提示,使用户的操作更为明了
    当用户输入错误信息时,有提示弹窗对用户进行提示
    系统的各种设置较为简单

    适用性广

    本系统并不是专为学校里的学生报名而做的,它是一个公共考试报名系统,意味着它还面向社会大众
    而本系统中的报名方式简单而不随便,适用于各种考试的报名

    统一管理

    管理员可以对考生及考试进行统一管理
    统一管理使得管理员的工作变得更为方便,管理工作更为简单


    第二章 总体设计2.1 项目规划公共考试报名管理系统是一个典型的数据库开发应用程序,由前台考生报名管理区和后台管理员管理区组成,规划系统功能模块如下:
    前台考生报名管理区主要功能

    修改考生自身注册信息
    查看可报名的考试
    对目的考试进行报名
    查看已报名的考试
    退选已报名的考试

    后台管理员管理区主要功能

    超级管理员

    考生管理(添加,编辑,删除,查看列表)考试管理(添加,删除,查看某种考试的已报名学生,查看所有已发布考试)管理员管理(添加,编辑,删除),系统设置(编辑状态栏信息)
    招生人员

    考生管理(添加,编辑,删除,查看列表)考试管理(添加,删除,查看某种考试的已报名学生,查看所有已发布考试)系统设置(编辑状态栏信息)。

    注:招生人员与超级管理员是两类管理员。超级管理员拥有最高权限,而它与招生人员的主要区别就是它可以进行管理员管理,而招生人员是不具备这种功能的。
    2.2 系统功能结构图网上报名系统功能结构图,前台报名管理模块如图1所示。
    考生报名流程

    后台功能模块如图2所示:
    管理员流程图

    第三章 系统设计3.1 使用语言在本次课程设计对公共考试报名管理系统的设计中,我们采用PHP脚本语言并嵌入HTML脚本来进行网站的设计。
    PHP是一种开源的通用计算机脚本语言,尤其适用于网络开发并可嵌入HTML中使用。PHP的语法借鉴吸收C语言、Java和Perl等流行计算机语言的特点,易于学习。PHP的主要目标是允许网络开发人员快速编写动态页面。
    PHP的应用范围相当广泛,尤其是在网页程序的开发上。一般来说PHP大多运行在网页服务器上,通过运行PHP代码来产生用户浏览的网页。
    使用PHP进行WEB应用程序开发,具备如下的优点:

    解释与编译PHP是性能优越的编译程序,又具备解释过程的优点
    开发效率高,函数语言简洁明了
    输出控制灵活,可在HTML中内嵌PHP代码,也可以由PHP输出HTML运行,也可以在命令行下执行,将结果输出到其他设备
    可实现模板化,实现程序逻辑与用户界面分离
    跨平台可运行在Win32或UNIX/Linux/Macintosh/FreeBSD/OS2等平台上
    与多个WEB服务器兼容,如Apache、MS IIS、Netscape Server等
    完全支持面向对象开发,并向下兼容,支持过程与面向对象两种风格的开发
    内嵌Zend加速引擎,性能稳定快速
    PHP编写容易,内置函数丰富,几乎涵盖了WEB开发的所有方面
    组件化开啊,提供MySQL、Oracle、MS SQL等多种数据库的访问接口,支持ODBC
    扩展性好,支持访问Win32系统的COM对象
    支持正则表达式,内置POSIX与Perl兼容两类的正则表达式支持
    开发成本低,开发工具多,且有众多使用PHP开发的开放源代码项目供我们参考和二次开发
    完全支持企业级开发,PHP并非只能做网站,在国内外有金融行业、能源行业、打得政府型采购系统采用PHP开发系统平台,并且近年来IBM、Adobe、Intel等行业巨头在为PHP以及其商业公司Zend提供了巨大的资本投入,并得到Oracle、Adobe、微软等公司的支持,另外以PHP软件开发商如NuSphere、Borland等公司均在为PHP的企业化助力驰援
    PHP5的下一版本6.0将全面支持多线程以及Unicode-16、il8n、字符集整理(Collation)、亚洲语言翻译(str_transliterate)等国际化及其他新技术
    支持桌面级系统开发,PHP不仅能够开发动态网站系统,还能够开发Win32/X-window桌面级(PHP GTK、Winbinder)应用程序,以及Shell或命令行下运行的deamon守护脚本以及服务器端管理程序
    支持加密分发代码,在使用Java、.net这些虚拟机字节码的语言,在某些时候非常容易被反编译,导致一些安全问题,使用Zend Optimizer不仅可以使PHP实现“编译”运行,不仅实现速度的飞跃,而且可以实现PHP源代码的完全加密,从而保护作者的利益以及软件版权。这是PHP的最大特点之一

    3.2 使用框架在本次程序设计中,为了方便进行web开发,我们使用了CI框架来进行网站开发。
    CodeIgniter是一套给PHP网站开发者使用的应用程序开发框架和工具包。它提供一套丰富的标准库以及简单的接口和逻辑结构,它可以为开发者们建立功能完善的 Web 应用程序,其目的是使开发人员更快速地进行项目开发。
    CodeIgniter 的开发基于 MVC(模型-视图-控制器)设计模式。MVC 是一种用于将应用程序的逻辑层和表现层分离出来的软件方法。

    模型(Model) 用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。“ Model ”有对数据直接访问的权力,例如对数据库的访问。“Model”不依赖“View”和“Controller”,也就是说, Model 不关心它会被如何显示或是如何被操作。但是 Model 中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此 Model 的 View 必须事先在此 Model 上注册,从而,View 可以了解在数据 Model 上发生的改变。(比较:观察者模式(软件设计模式))
    视图(View)能够实现数据有目的的显示(理论上,这不是必需的)。在 View 中一般没有程序上的逻辑。为了实现 View 上的刷新功能,View 需要访问它监视的数据模型(Model),因此应该事先在被它监视的数据那里注册。
    控制器(Controller)起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据 Model 上的改变。

    以下是CI框架定义的应用程序流程:


    index.php 文件作为前端控制器,初始化运行 CodeIgniter 所需的基本资源
    Router 检查 HTTP 请求,以确定如何处理该请求
    如果存在缓存文件,将直接输出到浏览器,不用走下面正常的系统流程
    在加载应用程序控制器之前,对 HTTP 请求以及任何用户提交的数据进行安全检查
    控制器加载模型、核心类库、辅助函数以及其他所有处理请求所需的资源
    最后一步,渲染视图并发送至浏览器,如果开启了缓存,视图被会先缓存起来用于 后续的请求

    3.3 服务器在本次程序设计中我们选用的服务器为Apache,当然我们使用的是xampp,一个Apache,MySQL等的集成软件。
    将Apache的配置文件中的路径DocumentRoot改为我们的项目所在的路径,即搭好了我们的服务器。
    3.4 MYSQL数据库由于我们采用的是xampp,一个Apache、MySQL等的集成软件。它里面存在一个对MYSQL的管理工具PHPMyAdmin。因此我们首先写好一个创建数据库,数据表的SQL语句的.sql文件,然后将其导入该管理工具。
    本系统创建的数据库名称为management。数据库中共包含五张表,分别为student、exam、admin_core、student_exam和info。

    Student表:用于存储学生信息。主键为考生号,即id,并定义考生号必须为11位。

    注:此处插入的数据使用的密码均为123456。而插入数据时使用了两次md5加密,所以上面显示的一样。
    Exam表:用于存储考试信息。主键为考试编号,即id。

    Admin_core表:用于存储管理员信息。主键为管理员编号,即id。在这里将管理员编号定义为四位,若不是四位则提示错误。

    Student_exam表:用于存储考生的报名信息,每当考生报名某门考试,则将考生的id和考试的id一并存入作为一条数据。

    Info表:用于存储公告栏的信息。主键为id,0表示注册界面的公告栏,1表示考生登录界面的公告栏。

    3.5 源代码管理使用国内源代码托管服务coding来进行源代码及版本的管理通过增加SSH公钥的方式来给予组内成员推送的权限。
    第四章 视图(view)主要模块详细设计4.1 视图文件总体架构
    4.2 视图主要模块详细设计4.2.1 登录界面在登录界面创建了三个文本框,分别是用来进行输入用户名,密码,以及验证码。而输入验证码的文本框右侧有一张显示验证码的图片,它的来源是index控制器的random函数。
    在此界面还包括两个按钮——注册和登录。注册按钮是一个超链接,连接到index控制器的register函数。登录按钮是提交按钮,当按下这个按钮,form表单中的数据则将传送到由action定义的index控制器的login函数中。
    在这个文件中使用JavaScript定义了一个函数,当用户在文本框中填入的数据为空的时候直接进行弹框显示。
    以下是登录界面的截图:

    4.2.2 注册界面注册界面由考生须知和添加考生组成。考生须知是注册界面的首页,这里主要是一个公告栏显示对注册考生的提示信息,而公告栏中的数据是由控制器index中的register函数通过查询数据库传入本视图的。添加考生视图在下一节进行解释。

    4.2.3 添加考生界面添加考生界面是一个被多角色多任务复用的视图。多角色说的是它同时被考生和管理员使用,多任务是说它进行多种页面显示。
    添加考生界面同时也是编辑考生界面,它在控制器传进来不同的参数时显示不同的标题。控制器传给此视图一个list数组,当这个数组中的action键中存储的值是‘add’时,显示的标题为“添加考生”,而当list数组中的action键中存储的值是‘edit’时,显示的标题是编辑考生。这也就是进行页面的复用。
    而在添加考生和编辑考生的情况中,表单提交的目的地是不一样的。因此在form表单的action定义时,也需要进行对list数组中action键的值的判断,然后将action定义为不同的值。
    接下来说一下这个页面的主要组成部分,这个页面包括六个文本框和一个选择框,文本框用于对考生基本信息的输入,选择框用于选择性别。提交按钮则是用来提交表单中的数据。
    在这里,由于添加和编辑考生任务的不同,需要对页面进行一些必要的处理。例如在编辑考生的时候,我希望它是可以将原来考生的信息输出到文本框中的,这有利于我对它进行编辑。而出于安全考虑,在编辑考生时我们没有将它的密码显示出来,当考生在密码的文本框中填入了新密码时,我们将它一并提交,并进行数据库的更新,而当考生不需要改密码,则可以不进行填写,这里就提交一个空的密码到控制器。而控制器判断到密码为空时,则进行数据库的查询,将该考生原来的密码再重新更新至数据库。
    注:考生号是不允许编辑的,因为在控制器端更新数据库时,是以它来作为查询的关键码。
    以下是添加考生界面截图:

    4.2.4 考生界面当考生进行登录后,进入到考生界面。考生界面由考生管理和考试管理组成。考生管理包括考生须知,考生信息,以及修改信息。考生须知是考生界面的主页,和前面注册界面的考生须知一样,只不过这两个界面的公告栏是不同的,管理员可以对这两个公告栏里的信息进行编辑显示。考生信息界面则是显示考生基本信息的页面,在控制器中使用该考生的考生号查询数据库,将得到的数据分别给list数组中的不同键,然后将list数组传进本页面,通过不同的键值进行输出即可。修改信息界面也就是编辑考生界面,在上一节中已经介绍过。
    考试管理包括报名考试和考试列表两个界面。
    报名考试界面显示所有已发布考试的具体信息,以及可以进行考试的报名操作。控制器中查询考试表得到考试表中所有的信息,将它存在一个list数组中的list键中,并将list数组传入此页面,然后经过for循环将list数组送list键中的数据进行一行一行的输出。
    而在输出每一行考试信息的末端,有一个报名的超链接,当按下这个超链接则将连接到exam控制器的exam_signdo的函数中,并将考试的考试编号一并传过去。在控制器端通过Session得到考生的考生号然后再讲考生号和考试编号一并插入student_exam表中。
    在这个页面中,当考生报名了某门考试时,我们想要的是之前报名的超链接被“已报名”取代。实现这个的方法是在这个视图中通过session得到考生id然后与考试id一起作为条件来进行查询student_exam表,当查询到表中存在某行数据包括这两个ID,则表示考生已报名该门考试,则输出“已报名”三个字。若是不存在该数据,则输出“报名”的超链接。
    该段代码如下:
    <td><!-- 如果发现已经报名。则显示已报名 --><?php $this->load->model ( 'Data_model' );$data ['query'] = $this->Data_model->get_exists_data ( array ( 'id' => $this->session->userdata('id'), 'exam_id' => $item['id'],), 'student_exam' );if($data['query']>0){ echo 已报名;}else{?><!-- 未报名则可以报名 --><a href="<?php echo site_url("exam/exam_signdo/".$item['id']);?>" title="报名">报名</a>  <?php }?></td>
    考试列表界面由下一节来进行阐述。
    考生主界面:

    报名考试界面:

    4.2.5 考试列表界面考试列表界面是一个复用的界面,也就是考生和管理员复用的界面。考生端要显示的是自已选的考试列表,而管理员界面显示的考试列表要显示的是考试表里所有的考试。
    因此这个界面在不同角色登录时所要展示的页面使不同的,而这些不同信息的展示则是通过控制器加载此页面时所传过来的list数组来实现的。例如考生界面中考试列表的界面的标题是已选考试列表,管理员界面中显示的标题是考试列表,这个标题便是存在list数组的info键中。在这里只要将这个键中的值输出即可。
    而在这个视图中,有些内容是在管理员中显示而在考生界面是不显示的,有些界面则是只显示在考生界面中。要实现这些则是通过session来实现,提取session中所存储的相应信息,得到这个用户的身份(这是因为在用户登录中,将这个用户的角色身份存进了session),然后经过判断其身份的不同来使得界面显示的不同。
    考生界面的考试列表:

    管理员界面的考试列表:

    4.2.6 管理员界面当管理员进行登录后,则进入管理员界面。管理员界面包括考生管理,考试管理,管理员管理和系统设置,其中管理员管理是超级管理员才有的权限,一般的管理员(招生人员)不具有该权限。
    考生管理包括添加考生和考生列表,其中添加考生在4.2.3节中讲过,考生列表的基本原理和考试列表差不多,而考生列表界面也是一个复用界面,它在这里是显示所有考生的信息,并且可以进行删除和编辑考生。而在考试列表中点击某门考试的已选人数时,也会调用考生列表界面,在这个界面中显示的是该门考试所对应的所有考生的信息(也就是考生报名了该考试科目)。这两个界面和之前讲的考试列表的复用类似,就不再赘述。
    考试管理包括添加考试和考试列表。添加考试和之前讲的添加考生界面类似,考试列表在4.2.5节中讲过。
    管理员管理包括添加管理员和管理员管理。添加管理员和之前的添加考生界面类似,管理员管理则是显示管理员表中的所有管理员信息,并可以进行编辑和删除,这和之前的列表界面类似。
    系统设置包括的就是公告栏的编辑界面,其中包括两个公告栏的编辑。每次按下提交按钮的时候,则将文本域中的内容提交至相应控制器,在控制器端更新相应数据库。
    管理员主界面:

    考生管理界面:

    添加管理员界面:

    管理员管理界面:

    系统设置-修改公告栏界面:

    第五章 模型(Models)主要模块详细设计5.1 数据库配置通常来说,模型类将包含帮助我们对数据库进行增删改查的方法。在本节我就先讲讲数据库的配置。CodeIgniter 有一个配置文件用来保存数据库配置(用户名、密码、数据库名等等),这个配置文件位于 application/config/database.php。
    配置文件中的语句如下:

    5.2 自定义模型类在模型类中已经包含对数据库进行增删改查的方法,而在这里我们将自定义一个类,让它继承模型类,并在这个类中自定义一些函数来方便我们的控制器的调用。
    自定义的函数通常是通过传入不同的参数,然后调用模型类中已经有的对数据库进行增删改查的方法,来进行对数据库的操作,通常该函数都会将一个以对象形式返回的结果集返回。下面这个是自定义的一个函数,它的作用是获取某个学生已报名的考试,代码如下:
    function get_alldata($id,$table1,$table2){ //获取某个学生已报名的考试 $query2 = $this->db->get_where($table1, array('id'=>$id)); //$some 类似数组 array('city_name' => $city_name) $num=$query2->num_rows(); //返回条数, if($num>0){ $query1=$this->db->where('id',$id)->select('exam_id')->get($table1)->result_array(); $re=array(); foreach($query1 as $resp){ $re[]=$resp['exam_id']; } $query=$this->db->where_in('id',$re)->get($table2)->result_array(); return $query; }else return ' ';}
    第六章 控制器(controllers)主要模块设计6.1 控制器文件总体架构
    6.2 控制器主要模块详细设计控制器中的函数众多,因此我就挑几个主要的模块来进行讲述。这几个主要的模块分别是登录模块(讲述考生和管理员的不同身份登录),添加和编辑信息模块(以添加考生和编辑考生为例进行讲述),列表显示模块(以考生界面的“已选考试列表”和管理员界面的“考试列表”为例进行讲述),删除模块(以删除考生作为重点讲述对象)。
    6.2.1 登录模块index.php 文件作为前端控制器,初始化运行 CodeIgniter 所需的基本资源。登录视图是由index.php所定义的运行程序时首次加载的页面。而登录视图中定义了将表单数据提交至index控制器的login函数中,因此在这个函数中我们将对表单中传入的数据进行处理。
    首先用以下语句得到表单提交的数据,并赋给相应变量。
    $manage_name = trim(htmlspecialchars($this->input->post('username')));$manage_password = trim(htmlspecialchars($this->input->post('password')));$yzm = trim(htmlspecialchars($this->input->post('yzm')));
    由于在视图中form表单中定义的method为“post”,所以在这里使用post方法来得到表单提交的数据。Trim则是起到忽略原字符串中的空格的作用。
    这样便得到了用户在文本框中填写的登录信息,我们首先就要判断其验证码填写是否正确,然后再判断用户名、密码填写是否为空,若是,则进行相应的弹窗显示。同时退出本函数。接下来才是进行查询数据库来判断该用户能否登录。
    由于考生和管理员是在同一个登录界面进行登录的,但是我们不能将考生和管理员归为一类来进行查询,因为他们在不同的表中。因此必须用一个判定条件来将管理员和考生区分开,然后进行不同表的查询。在本程序中我们定义的规矩是管理员的管理员编号(id)必须为四位,而考生号(id)则必须为11位。所以在这里,我们已经得到了用户登录时输入的用户名也就是id,因此首先判断它为多少位,若是4位,则说明他是管理员,若是11位则说明是考生,若二者都不是,则弹窗显示用户名输入错误。
    在控制器中需要查询数据库时,首先加载相应的自定义的函数所在的模型,然后再调用这个模型中的函数。
    当输入的为管理员账号,则现在需要判断的是他是否为管理员,能否进行登录,首先通过自定义函数通过输入的用户名和密码来进行查询管理员表,若是存在则首先得到该管理员的一部分信息,然后存进session。接下来进行页面跳转至管理员界面。
    当输入的为考生账号,则进行查询考生表,若是考生表中存在该用户,则得到该考生的一部分信息,然后存进session。然后跳转考生界面。
    在存入session的信息中包含有一个是确定用户的身份信息的,它的关键码是‘statement’,若是它的值为0,则表示超级管理员,若是它的值为1,则表示招生人员,若是它的值为2,则表示考生。这个在之前的视图模块中用到了。
    6.2.2 添加和编辑信息模块添加和编辑信息模块包括添加考生,添加考试,添加管理员,编辑考生信息,编辑管理员信息。这里就以添加考生和编辑考生为例进行讲述。
    添加考生:在控制器端得到视图页面中所提交的表单数据,然后要做的当然是将这些信息插入考生表。但是在插入之前要做一些判断,首先需要确定填入的所有信息都不为空,然后需要判断其考生号填写的是否为11位,接下来则需要判断的是这个考生是否已经存在于数据库中,所以需要调用模型中的函数来进行操作。以上条件只要不符合条件就进行弹窗显示错误。若都符合条件,则进行插入操作。
    编辑考生:在控制器端得到视图页面中所提交的表单数据,编辑考生的时候,若是用户没有对考生的密码进行修改,则控制器端得到的密码为空,这时候就需要在这里根据传过来的考生ID来进行查询该考生密码,得到之后再进行考生所有信息的更新(考生号(id)不允许编辑)。
    注:插入密码时将密码经过两次md5加密后再进行插入。
    6.2.3 列表显示模块列表显示包括考生界面的考试列表和已选考试列表,管理员界面的考试列表,考生列表,管理员列表等等,在这里就以考生界面的“已选考试列表”和管理员界面的“考试列表”为例进行讲述。
    因为这两个视图都是提交给同一个控制器端的函数进行处理,所以在这个函数中需要判断登录用户的身份,通过其登录时存在session中的一个statement的值来判断。若判断后,该用户为考生的话,则在这个函数中我要得到的是该考生已报名的考试。这时候调用模型中一个专为这个功能封装的函数,即可得到这个考生所选的考试的所有信息。而模型中的这个函数的实现的过程如下:首先判断该考生是否有报名的考试,即用这个考生的id去查询‘student_exam’表,若是查询到的结果不为空则进行接下来的操作。接下来再通过考生的id去查询同一个表,选择‘exam_id’属性,也就得到了该考生所有已报名的考试。但这只是得到了考试的id,接下来则用考试id去查询‘exam’表,再将得到的结果返回。控制器将返回的结果集赋给list数组的一个键,最后在加载相应页面时将list数组传进去即可。
    而管理员界面的考试列表则是直接显示‘exam’表中的所有考试的所有信息。也就是直接将‘exam’表中数据全部返回即可。控制器将返回的结果集赋给list数组的一个键,最后在加载相应页面时将list数组传进去即可。
    6.2.4 删除模块删除模块包括考生删除,考试删除,管理员删除,某一条报名信息的删除。这里以考生删除作为例子来讲述删除的步骤。
    当用户在视图端摁下删除考生时,会传入一个考生的id进入控制器kaosheng的kaosheng_del函数中,函数接收到参数之后则要进行删除工作。
    而当一个考生被删除,也就意味着它的报名考试的记录也应该被删除,而它所报名的考试的报名人数也应该减1。这就是这个函数的工作。
    首先得到该考生所选的所有考试的具体信息选择其中的‘id’,‘number’属性,之后将得到的数据进行减1,然后在for循环中通过id将‘exam’表中的‘number’进行更新。然后在‘student_exam’表中通过考生的id将与其相关的所有信息删除。最后将‘student’表中的该考生删除。然后弹窗显示“删除成功”。
    关键代码如下:
    $this->load->model ( 'Data_model' );$que=$this->Data_model->get_alldata ( $id, 'student_exam','exam' );foreach($que as $resp){ $rea=$resp['id']; $re=$resp['number']-1; //更新考试的已选人数 $this->Data_model->update_data( $rea,array('number'=>$re), 'exam' );}//删除学生_考试表中的该考生所选的所有考试$data ['query2'] = $this->Data_model->delete_data( $id, 'student_exam' );//删除学生表中的信息$data ['query'] = $this->Data_model->delete_data ( $id, 'student' );
    第七章 总结后端的流程处理和前端的显示安排
    总结:在这次网络数据库的课程中,让我第一次如此接近地了解到了一个网站开发,初步了解了php的运行方式,在协同工作中能更好地调配自己与其他同伴之间的工作安排。我在项目中主要负责的是后端的流程处理和前端的显示安排。
    第一部分:首先说说学了什么,大概从上个学期开始就开始接触git这样的源代码管理工具,从基本不会使用到了解了各种分支以及合并冲突的操作,了解了密码的认证方式,也就是ssh-keygen(ssh)的使用并且记录到了博客。在原本稍微了解了一点HTML的内容之后开始了进行php的学习。使用php来进行后端的流程控制,使用框架来满足mvc模式的需要。在JavaScript学会了简单的使用判断。
    第二部分:确定了下一步的目标,JavaScript这个门非常火的语言现在很多地方都已经用到了前端到后端的使用,而且github上面近70%的项目都是JavaScript的项目,非常的强大。如果在接下来的学习时间里面还有空闲的时间将会把JavaScript放在第一位的学习方向。
    第三部分:感想和体会,php在调侃中总被提到是“世界上最好的语言”,说明了它的学习成本比较低,在之前看完了php的基本教程之后就直接上手开始通过HTML写好的模板开始进行网站的开发,因为之前java的课设比较熟悉http协议的方式,过程中并没有什么阻碍的感觉,这门语言在网站的开发方面确实比较方便,不过这样的一个报名系统也并没有涉及太复杂的操作。在学习的过程中的一个非常深刻的体会是如果有了C/C++的基础再去学习一门语言简单的使用确实比较快(深入使用可能还是需要比较长的时间)。在这次的项目完成之后了解了原本看似神秘的网站大概的开发方式,对自己在的贡献和成果还是比较满意的,同时也认识到了一个大型项目的开发和小型自己的程序之间差异性,合作很重要。
    所有有关数据库的操作
    总结:这一次网络数据库的课程设计做一个网站,而写网页在本学期的Java课程中也进行学习过。当时在做Java的课程设计时,我也曾利用Java连接数据库来进行一些操作。当时使用的数据库是微软的Access,而在Java中的加载驱动,连接数据库也还算简单,所以对数据库这方面我还算是有一定的了解。因此本次课程设计,我选择负责有关数据库的一些操作。
    这次课程设计,我们使用的语言是PHP,其实刚开始组长决定使用PHP的时候,我是有一些异议的,因为这门语言我几乎都没接触过,更何况来用它进行网页开发。但经过了解,我决定先学习学习,当我大概的了解这门语言,又了解到CI框架,我才发现开发一个大型网站原来如此简单。所以说,我们大学生确实不能够只满足于课堂上所教授的一些知识,更应该去探索更多课堂外有用的东西。
    而本次课程设计进行的还算顺利,小组成员间的合作显得很默契。有一些bug,我们前前后后改了十几遍,提交了好几个版本,但最终呈现出来的结果让人满意。相信如果只有我一个人的话,那是做不出这个东西的,因此团队合作显得尤为重要。
    材料模板的收集、细节规划的建议、后期测试审核
    总结:网络数据库结束了,我们组做了公共考试管理系统,虽然做的比较简陋,但是这让我感觉到我们也是可以做出产品出来的。我感觉对以后的学习充满了信心,从对PHP的一无所知,到去学习、使用并最终做出成品出来,这是一个充满挑战的过程。我们也遇到过许多困难,这时我们就需要不断的查找资料,不断的尝试,直到把它解决。在这个过程中,我们学到了很多东西,首先是面对难题的勇气,其次就是团队合作的必要。有时一个小小的问题可能卡住我们一个下午,甚至是晚上加班,但是我们没有放弃,坚持把这个东西给做出来了。
    不管是在查找资料还是写代码方面,我们小组都非常团结,但是由于我个人能力的问题,可能给团队的帮助不是很大,但是团队给我的帮助是巨大的,它让我明白了很多道理。每当我想要放弃的时候,队员都会拉我一把,他们会告诉我,不要放弃,还有他们,所以感谢我的队友。然后还要感谢老师,教授了我们网络数据库的知识,让我们在做自己的项目的时候不会茫然。
    总之,做出自己的东西是一个艰辛的过程,特别是从我们一无所知开始,但是幸好我有队友,让我在遇到困难的时候不会绝望。
    3 评论 55 下载 2018-11-05 23:11:20 下载需要7点积分
  • 基于Laravel-PHP框架的网上订餐管理系统

    摘 要随着电子商务的发展,O2O电子商务模式越来越兴起。网上订餐系统就是这种商务模式的一种体现。目前在校园周边有许多提供外卖服务的餐厅,但是大部分餐厅还是采取电话订餐、人工手写记录等较为原始的方式。这些方式不仅麻烦费时,而且,由于外卖通常具有集中性,在午餐和晚餐这两个时段,会有很多人同时打来电话。面对这种情况,餐厅要么增加同时接线的数量,这样会增加成本;要么什么都不做,这样会失去原本能够赚取的利润。网上订餐系统可以很好的解决这个问题。本毕业设计网站使用国际上非常流行的Laravel框架进行开发,大大优化路由设置,同时,简便的登录验证系统,和完善的数据库迁移功能组合在一起,使得本系统能够得到更加快速和便捷的开发与完善。利用网上订餐系统,可以同时进行并发业务处理,从而避免了因为在同一时刻有多人打入电话无法接通而导致流失顾客的情况,而且,本毕业设计还具有短信通知功能,可以在用户下单订餐、餐厅送餐时自动发送短信提醒用户,具有十分现实的意义。
    关键词:O2O;网上订餐;PHP;Laravel框架
    AbstractWith the development of e-commerce, O2O growing rise of e-commerce model. Online reservation system is a manifestation of this business model. Now we have a lot of takeout around the campus, but most still take phone ordering, handwritten notes and other artificial methods. Online reservation system can solve this problem, the network can handle concurrent operations simultaneously, thus avoiding the situation because there are many people at the same time to enter the phone unable to connect and lead to the loss of customers. Website using very popular PHP framework — Laravel , can greatly optimize the routing settings, simple login authentication system, database migration evening, these powerful features are combined to develop faster and more convenient and improve the system.
    Key words:O2O; online meal ordering; PHP; Laravel framework
    1 绪论1.1 课题的背景和意义随着电子商务的发展,O2O电子商务模式逐渐兴起。网上订餐系统就是这种商务模式的一种体现。现在我们校园周边有好多外卖,但是大部分还是采取电话订餐、人工手写记录等方式。这种方式不仅麻烦费时,而且,由于外卖通常具有集中性,在午餐和晚餐这两个时段,会有很多人同时打来电话。面对这种情况,餐厅要么增加同时接线的数量,但是这样会增加成本;要么什么都不做,这样会失去原本能够赚取的利润。
    网上订餐系统可以很好的解决这个问题,网络可以同时进行并发业务处理,从而避免了因为在同一时刻有多人打入电话无法接通而导致流失顾客的情况。同时,电子化的订餐方式也便于进行数据收集和分析。因此,本毕业设计可以实现网络同步订餐,用户只要在网上订餐,便与通过电话订餐方式一样可以获得送餐服务,而且更加方便快捷。
    1.2 网站设计任务一个网站的前端是非常重要的,它是用户直接面对的。一个优秀的前端设计,可以让用户体验提升不少。所以,在此次毕业设计里面,前端的设计占了很大部分,涉及到了很多方面的技术。
    页面前端使用 HTML配合JavaScrip等技术来支持前端的运作,并使用Ajax技术向服务器Post数据,使得页面可以在不刷新的情况下,与服务器进行数据交互。网站结构被设计成顾客可以在网站上注册后,直接在网页上订餐。餐厅可以在网站上注册后,可以在后台管理的自己餐厅的各项设置,包括餐厅名字、营业时间、餐厅的介绍、餐厅电话(手机号、座机)等信息,还可以定制自己的起送要求等。在定制过这些信息之后,餐厅用户就可以上传自己的食品信息了,上传食品信息之后,再上传食品图片,最后,在后台里再点击餐厅上线按钮,这样,餐厅里面的食品就可以正常发布了。对不同角色的用户权限进行了控制,使得所有商品信息可以及时的更新,所有的订单可以及时进行处理,真正实现了网上办公,减少工作成本、提高工作效率。
    1.3 主要架构以及采用的技术介绍此次毕业设计的开发环境是,Window 8.1 ,开发语言是 PHP ,数据库采用开源的 MySql,服务器使用的是著名的开源服务器 Apache。采用 Wamp 开发环境包安装的,这样在安装之后不需要单独配置PHP、Apache以及MySql的环境变量。Wamp集成PHP、Apache、MySql配置在一起,开发过程中可以非常方便的修改各个配置信息,并且,Wamp还附带phpMyAdmin工具,可以通过网页非常方便的对数据库进行各项操作。
    在此次毕业设计的开发中并没有采用任何IDE(集成开发环境,Integrated Development Environment)来帮助开发,仅使用文本编辑器 Sublime Text 2 来写PHP、Mysql、HTML、Javascript代码,调试使用Chrome 34.0.1847.131 m 版本。因此开发也可以在Linux下进行,并且网站的服务器也是可以架设在Linux系统下的。
    本次毕业设计使用了一个名为 Laravel 的PHP框架,这个框架是在PHP 版本5.3以后发布的,这说明它具有非常多的优势相对于别的PHP框架。
    之所以采用PHP语言进行开发,是因为根据Alexa统计,在2013年,大约有40%的网站是采用PHP配合MySql数据库进行开发的,作为即将毕业的我很好奇,使用这么广泛的技术到底是什么样子的,希望能从本次毕业设计的开发中学习到很多知识。
    1.3.1 基于 B/S 的体系结构在 B/S 体系结构系统中,用户通过浏览器向分布在网络上的服务器发出请求,服务器对浏览器的请求进行处理,然后将用户所需信息返回到浏览器。B/S 结构简化了客户机的工作。服务器将担负更多的工作,对数据库的访问和应用程序的执行将在服务器上完成。浏览器发出请求,而其余如数据请求、加工、结果的返回以及动态网页生成等工作全部由Web Server完成。实际上 B/S 体系结构是把两层 C/S 结构的事务处理逻辑模块从客户机的任务中分离出来,由 Web 服务器单独组成一层来负担其任务,这样客户机的压力减轻了,把负荷分配给了Web 服务器。
    这种三层体系结构如图1-1所示。

    1.3.2 PHPPHP(全称:PHP:Hypertext Preprocessor,即“PHP:超文本预处理器”)是一种开源的通用计算机脚本语言,尤其适用于网络开发并可嵌入HTML中使用。PHP的语法借鉴吸收了C语言、Java和Perl等流行计算机语言的特点,易于一般程序员学习。PHP的主要目标是允许网络开发人员快速编写动态页面,但PHP也被用于其他很多领域。PHP最初是由勒多夫在1995年开始开发的。而现在PHP的标准由PHP Group和开放源代码社区维护。PHP以PHP License作为许可协议,不过因为这个协议限制了PHP名称的使用,所以和开放源代码许可协议GPL不兼容。PHP的应用范围相当广泛,尤其是在网页程序的开发上。一般来说PHP大多运行在网页服务器上,通过运行PHP代码来产生用户浏览的网页。PHP可以在多数的服务器和操作系统上运行,而且使用PHP完全是免费的。根据2007年4月的统计数据,PHP已经被安装在超过2000万个网站和100万台服务器上。如图1-2所示。

    1.3.3 Bootstrap 前端开发框架页面使用最的 Bootstrap V3版本,它是Twitter推出的一个开源的用于前端开发的工具包。它由Twitter的设计师Mark Otto和Jacob Thornton合作开发,是一个CSS/HTML框架。Bootstrap提供了优雅的HTML和CSS规范,它即是由动态CSS语言Less写成。Bootstrap一经推出后颇受欢迎,一直是GitHub上的热门开源项目,包括NASA的MSNBC(微软全国广播公司)的Breaking News都使用了该项目。
    国内外有很多优秀的企业都是用了 Bootstrap 来作为网站的前端开发框架,Twitter自己的页面就是采用Bootstrap开发,国内的豆瓣的开发者后台也是采用Bootstrap写的。使用动态CSS语言Less开发的好处在于,可以像编程一下来书写CSS代码,使得开发效率大大提高。
    1.3.4 JavaScriptJavaScript,一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML网页上使用,用来给HTML网页增加动态功能。然而现在JavaScript也可被用于网络服务器,如Node.js。
    在本次毕业设计中,使用了非常流行的jQuery库。jQuery是一套跨浏览器的JavaScript库,简化HTML与JavaScript之间的操作。由John Resig在2006年1月的BarCamp NYC上发布第一个版本。目前是由 Dave Methvin 领导的开发团队进行开发。全球前10000个访问最高的网站中,有65%使用了jQuery,是目前最受欢迎的JavaScript库。
    jQuery 是开源软件,使用MIT许可证授权。jQuery的语法设计使得许多操作变得容易,如操作文档对象(document)、选择DOM元素、创建动画效果、处理事件、以及开发Ajax程序。jQuery 也提供了给开发人员在其上创建插件的能力。这使开发人员可以对底层交互与动画、高级效果和高级主题化的组件进行抽象化。模块化的方式使 jQuery 函数库能够创建功能强大的动态网页以及网络应用程序。
    本系统使用了两个版本的jQuery,前台用的是最新的2.1.0版本,后台用的是2.0.3版本,使用jQuery最大的好处在于,用考虑浏览器的兼容性问题,这样就不必在各种浏览器下面进行调试。
    1.3.5 Ajax介绍AJAX即“Asynchronous JavaScript and XML”(异步的JavaScript与XML技术),指的是一套综合了多项技术的浏览器端网页开发技术。Ajax的概念由Jesse James Garrett所提出。
    传统的Web应用允许用户端填写表单(form),当提交表单时就向Web服务器发送一个请求。服务器接收并处理传来的表单,然后送回一个新的网页,但这个做法浪费了许多带宽,因为在前后两个页面中的大部分HTML码往往是相同的。由于每次应用的沟通都需要向服务器发送请求,应用的回应时间依赖于服务器的回应时间。这导致了用户界面的回应比本机应用慢得多。
    与此不同,AJAX应用可以仅向服务器发送并取回必须的数据,并在客户端采用JavaScript处理来自服务器的回应。因为在服务器和浏览器之间交换的数据大量减少(大约只有原来的5%),服务器回应更快了。同时,很多的处理工作可以在发出请求的客户端机器上完成,因此Web服务器的负荷也减少了。
    此次毕业设计中,Ajax库使用的是jQuery中的库,所有与服务器进行交互的数据一律都采用了json格式,避免出现格式不统一的情况发生。
    1.3.6 Laravel——PHP框架Laravel是一套web应用开发框架,它具有富于表达性且简洁的语法。Laravel的开发者们相信,开发过程应该是愉悦、创造性的体验。Laravel努力剔除开发过程中的痛苦,因此提供了验证(authentication)、路由(routing)、session和缓存(caching)等开发过程中经常用到的工具或功能。
    在本次毕业设计的开发中,Laravel的学习成本最大,因为Laravel出现的比较晚,是在PHP5.3以后出现的。这是它的优势,也是它的劣势。
    优势是Laravel没有其他PHP框架的那些包袱,很多框架因为出现的早,还必须支持PHP4.0,这使得框架本身变得非常臃肿。
    劣势在于它太年轻了,而且,国内使用Laravel开发的并不多,以至于在开发过程中遇到问题的时候,只能去英文的stackflow.com上去寻找答案,Stack Overflow 是一个程序设计领域的问答网站。
    Sitepoint网站做了一个小的调查,看看PHP开发者们最喜欢使用哪个PHP框架。调查结果显示,最流行的PHP框架前三甲为:Laravel、Phalcon、Symfony2。

    1.3.7 PHP依赖管理包Composer是PHP中的一个依赖管理工具. 它可以让你声明自己项目所依赖的库,然后它将会在项目中为你安装这些库。
    2 需求分析2.1 可行性分析2.1.1 技术可行性分析可行性分析是在系统开始实施之前,进行系统可行性的提前设想、估算以及研究的一种方法。在项目开始实施之前,进行可行性分析是非常有必要的。通过可行性分析可以提前了解整个项目成功实施的可能性,以及在项目实施期间可能遇到的阻力。当然,系统项目实施中,特别是作为第一次独立来完成这个订餐系统的我来说,可能会遇到各种各样的问题,更加需要一个长远的计划和在系统实施之前的可行性分析。
    系统的实施架构是Wamp,即:Windows系统,Apache服务器,Mysql数据库,PHP语言。这是一套在Windows平台非常成熟的架构,对于硬件和网络的要求不是非常高,作为学生或者一般的网站创建者来说足够应付了。
    2.1.2 经济可行性分析从硬件角度上来分析,实际上此次毕业设计的实施,只需要一台服务器即可,也就是本人的电脑。
    从版权保护角度上来分析,服务器使用的框架是开源的PHP框架——Laravel,它使用MIT许可协议。MIT是开源许可协议中非常宽松的一种。服务器使用Apache,Apache使用Apache 2.0许可协议。PHP使用PHP license许可证。Bootstrap前端开发框架是开源的,jQuery是使用的是MIT许可协议。所以,无需进行任何支付,即可使用上面的框架和库。
    2.2 业务流程分析未注册登录用户,可以在不注册、不登录的情况下,浏览主页和所有处于销售状态的食品。用户注册之后就可以进行更进一步的操作,比如在个人信息页面查看网站活动,修改个人信息等。餐厅用户在注册之后,可以进入属于自己的餐厅后台进行相应的操作,比如设置餐厅的名字、开始营业时间、结束营业时间、餐厅的描述等一系列的设置,并且可以上传食品信息,并上传食品对应的照片文件。
    2.2.1 用户注册在主页或者其他页面进行浏览不需要注册,但是一旦用户有更进步的操作时,就必须注册才可以进行。
    每个页面的右上角都有注册和登录按钮,用户点击注册按钮之后,就会被引导至注册页面。
    在注册页面,需要用户填写用户名、密码、电子邮箱、选择所在地区、生日、手机号、以及验证码等信息。
    填写完毕,用户点击提交信息按钮后,页面会用Ajax向后台post数据,在后台Laravel会先验证用户提交的信息是否规范,比如:被要求输入的内容用户是否已经输入了,用户名在用户表中是否是唯一的,邮箱在用户表中是否是唯一的,用户名不能小于六位不可以大于十二位,密码以及确认密码的内容是否一致,密码是否大于六位小于十二位等各项验证。
    Laravel已经封装好了各种正则表达式验证条件,所以本系统不用自己再重复去写相对应的正则表达式了,引用写好的验证规则后,直接提交给Laravel中的validator类去验证即可,如果验证失败,会自动返回错误信息。
    当验证失败的时候,系统会返回用户注册的页面,附带着用户之前输入过的内容,以及错误信息。由于Laravel默认的语言包是英文的,所以,Laravel的错误信息默认也是英文的,本系统已经准备好了中文的语言包(app/lang下),并且在 app/config/app.php 中设置好了对应的语言包,这样,返回的错误信息就会是之前设定好的内容了。
    当本系统设定的验证全部通过之后,才会进入到真正的注册步骤——写入数据库。
    最后提示用户成功注册,并跳转到主页。如图2-1所示。

    2.2.2 用户登录用户可以在主页直接输入账号、密码、以及验证码,来实现登录。验证码的作用是为了避免用户信息被暴力破解。当用户访问别的需要登录验证的页面时,会被跳转到一个登录页面。当用户成功登录之后,主页以及食品页中本来显示用户登录的地方就会变成“欢迎回来,(用户名)”等字样。如图2-2所示。

    2.2.3 用户邮箱验证以及用户请求再次发送邮箱验证信在用户注册信息提交给服务器,服务器判断注册信息无误之后,用户成功注册,并且,系统会在数据库 confirmemail表里生成一个用户名对应验证码的一条数据,之后自动向用户注册时所填写的邮箱,发送一封带有唯一验证码的验证邮件,用户只有在点击这个验证之后,才完成邮箱的验证。
    当用户因为某种原因没有成功接收到服务器发送的验证邮件,用户可以在后台再次请求发送验证邮件,这时候服务器会再次生成一个唯一验证码并且在confrimemail表中重写上一次生成的验证码,最后把验证邮件发送到用户的邮箱中,整个过程都是使用Ajax方式,用户不需要等待,只需要向服务器发送请求即可。

    2.2.4 用户订餐流程未登录的用户可以浏览主页的所有内容和食品页面的所有内容。当用户想要有更进一步操作的时候,就必须登录了。
    在用户订餐的时候,如果用户未登录,订餐按钮会提示用户登录,并跳转到登录页面。未登录的用户可以选择登录或者注册一个账号。
    当用户登录之后,可以选择先将想要购买的食品放在购物车中。用户放入购物车的食品会以Ajax方式提交给服务器,这样可以不必刷新页面。当用户已经选中足够的食品后,可以选择结算。
    用户会被引导至结算页面,在这个页面如果用户之前有输入过订餐地址的话,会有订餐地址显示出来,如果没有的,则需要用户输入送餐地址,最后生成订单。

    2.2.5 餐厅管理员登陆流程未注册的餐厅管理员无法登录后台,想要加入的餐厅可以在后台登录页面直接进行初步注册,在注册信息都验证通过之后,就可以登录后台了。或者也可以在前台进行餐厅注册。
    餐厅管理员在注册之后,就可以登录后台进行餐厅信息的设置和上传食品了。
    2.2.6 用户评价流程用户在一份订餐订单完成之后,就可以对该订单进行评价,未完成的订单无法进行评价。
    2.2.7 订单管理流程订餐的顾客可以在后台查看自己所有的订单,可以对订单进行评价或者在订餐未完成之前取消订单。
    2.2.8 食品信息上传只有登录的餐厅管理员可以对食品信息进行上传,修改和删除,同时,可以在图片上传页面上传食品对应的图片。所有的图片都会被无损处理成600PX*600PX样式,以此来使得图片在任何地方显示正常。
    2.3 系统流程图分析系统流程图的重要性在于,它是描述系统逻辑模型的主要手段。通过对整个订餐系统的了解,把系统分为几个重要的功能模块,明确各个模块之间相互协调,制作出数据的流程图。在绘制数据流程图的过程中,各个符号对应关系如下:

    2.3.1 顶层数据流程图顶层数据流程图包含网站服务的范围、页面信息的输入以及输出,充分阐释了网站所应该设定的边界,可以抽象出整个网站。网站的顶层数据流程图如下图所示。它包含的实体有,顾客,餐厅、网站管理员。主要的数据流有会员信息、餐厅信息、餐厅上传的食品信息,最后完成订餐,网站管理员进行全局的控制。

    2.3.2 第 1 层数据流程图在顶层数据流程图的下面是中层数据流程图,它是由若干个数据流程图组成的。它不但细化了顶层数据流程图的内容,同时又是使得下一层可以继续分解。此次毕业设计订餐网站在将顶层数据流程图分解之后,得到了三个一层数据流程图。分别是顾客信息、菜品信息、网站管理员。
    第1层客户信息数据流程图

    第1层菜品信息数据流程图

    第1层管理员数据流程图

    2.3.3 第 2 层数据流程图将第 1 层顾客信息流程图分解得到了顾客的第2 层流程图,如图 2-10 所示。

    将第 1层的菜品管理数据流程图分解得到了餐厅管理菜品的第2 层数据流程图,如图 2-11 所示。

    将第 1 层网站管理员的数据流程图分解得到了管理员的第2层数据流程图,如图 2-12所示。

    2.4 软硬件需求分析因为开发没有使用任何IDE进行,所以仅仅使用文本编辑器就可以完成开发,不过为了提高效率,本系统使用的是Sublime Text 2,如果在Linux平台下可以是用Vim。
    服务器使用的Apache for windows的版本,windows版本在XP以上都可以运行。
    开发环境是直接使用网上非常有名的Wamp,W指windows环境,a指Apache服务器,m指Mysql,p指PHP,这个环境安装包会自动配置好Mysql和PHP的环境变量,以及Apache的服务器配置信息,而且,非常方便在开发中进行各项管理。
    另外,为了在开发过程中便于调试,数据库与服务器在同一台电脑上。

    数据库及应用服务器
    CPU:P4 以上 2M L2cache 硬盘空间:>=10G 内存:>=512M 操作系统:windows2003 及以上版本或 Linux、Unix 数据库:Mysql

    3 系统设计3.1系统功能图
    网站的系统功能一共分为三个部分,第一部分是订餐顾客,第二部分是餐厅用户,第三部分是网站管理员。
    具体功能描述如下:

    订餐顾客

    订餐顾客可以注册和登录网站,来进行订餐订餐顾客可以浏览的食品,同时也可以把希望要订餐的食品放入到购物车中订餐顾客可以登录自己的个人信息页面,查看和修改自己登录是填写的注册信息,并且可以查看自己所有的订单状况
    餐厅用户

    餐厅用户可以在网站上进行注册和登录,以此来在网站上发布食品餐厅用户可以在网站后台餐厅管理页面进行一系列的操作。查看以及修改餐厅的各项信息,餐厅的上线以及下线餐厅用户可以在后台上传食品信息以及食品的图片餐厅用户可以在后台查看所有的评论,并且可以对评论进行回复
    网站管理员

    网站管理员在登录之后,可以在后台进行会员信息的查看以及管理网站管理员在登录之后,可以在后台进行餐厅信息的查看以及管理网站管理员在登录之后,对主页的广告进行管理可以对餐厅或者用户发送站内信对于所有的菜品进行管理

    3.2 系统结构设计3.2.1 订餐顾客登录模块订餐顾客在注册之后可以,进行登录。登录模块的作用是用户登录,用户在页面上填写个人账户与密码信息后,提交给服务器,服务器判断用户提交的信息,如果用户提交的信息正确,那么就成功登录系统,并被引导至主页。否则回到登陆页面,然后显示相应的错误信息。

    3.2.2 菜品管理模块餐厅用户和网站管理员登录成功后,即可进入属于各自的后台管理页面。在各自的后台管理页面,可以对菜品进行管理,增加、修改或者删除菜品,如下图所示:

    3.2.3 会员管理网站管理员进入后台后,可以对所有的会员信息进行浏览和管理。对于长期不上线或者不正常行为的会员进行禁止登录,使得该会员不能登录,只有管理员才可以解除登录限制。
    如图所示:

    3.2.4 网站后台管理模块网站管理员在登录网站后台系统之后,可以对会员信息、餐厅信息、所有的订单信息、菜品信息、评论信息等进行查看、修改或者删除等操作。还可以对指定类型的用户(餐厅或者是订餐的顾客)发送站内信、发布网站活动信息等事项操作。还可以对网站主页的广告内容进行定制。
    3.2.5 订单管理当餐厅用户登录之后,可以查看订单信息,并且对已经进行配送完成的订单修改相应的订单状态。
    对于因为意外而无法完成的订餐,取消掉订单。
    如果所示:

    3.2.6 评论管理餐厅用户在登录餐厅后台之后,可以查看所有该餐厅食品的评论,并且对评论进行回复网站管理员在登录网站后台之后,查看到所有的评论,并且可以对评论进行删除操作。
    如图所示:

    3.2.7 网站活动模块网站管理员在登录网站后台操作页面之后,可以发布、修改或者删除网站的活动。所有的用户在登录之后,进入个人信息页面都可以看到网站当前的活动信息。如图所示:

    3.2.8 广告管理模块网站管理员在登录网站后台管理页面之后,可以对网站主页显示的广告进行管理,修改网站主页广告的图片、或者链接。
    4 数据库设计4.1 数据流需求分析根据之前设计的网站模块以及功能要求,在网站整体设计上建立数据库的逻辑结构,以及相互之间的关系。在实体数据库中就可以相应的实现了。
    综上所述,网站所需要的基本表有:用户表,网站活动表,站内信表,确认邮箱表,餐厅表,顾客表,密码重置表,食品评论表,餐厅评论表,食品表,订单表,地址表,购物车表。共计13张表。
    各模块需求数据库表的逻辑如下所示:

    会员模块:该模块涉及到用户表、顾客表、食品表、地址表、购物车表、订单表、食品评论表、餐厅评论表,等这八张表
    餐厅模块:该模块涉及到用户表、餐厅表、食品表、地址表、食品评论表、餐厅评论表等六张表
    网站管理员模块:该模块涉及到用户表、网站活动表、站内信表、餐厅表、顾客表、食品评论表、餐厅评论表、食品表、订单表、地址表等9张表

    4.2 数据库E-R图ER 图是用来描述某一组织的概念模型,提供了表示实体、属性和联系的方法。构成ER 图的基本要素是实体、属性和关系。实体是指客观存在并可相互区分的事物;属性是指实体所具有的每一个特性。本网站使用的E-R图如下所示:
    站内信的E-R图,如图所示,包含了站内信自身的ID,站内信的发送者,站内信的接受者,站内信的标题,站内信的内容,站内信是否是可回复的。
    如图所示。

    会员个人信息的E-R图,如图所示,包含了会员的ID,用户名,性别,手机号,手机号验证状态,邮箱,邮箱验证状态,所在地区,生日,以及地址ID。

    餐厅的E-R图,如下图所示,包含了餐厅ID,地址ID,名字,用户名,手机号,手机号验证状态,座机号码,送餐需求(起送数量或者起送金额的下限),邮箱,邮箱验证状态,开始营业时间,关门时间,所在地区,以及餐厅描述。
    如图所示。

    菜品的E-R图,如图所示,它包含了菜品的ID,属于的餐厅的用户名,菜品的名字,价格,库存数量,描述,图片名称,菜品的状态,菜品属于的类型,以及菜品图片保存的名字。
    如图所示。

    网站活动的E-R图,如上图所示,它包含了活动的ID,活动的标题,活动的内容,以及活动的图片所在的地址。
    如图所示。

    给餐厅的评论的E-R图,如下图所示,它包含了评论的ID,被评论的餐厅名,评论的内容,以及提交这份评论的用户名。
    如图所示。

    给菜品的评论的E-R图,如图所示,它包含了评论的ID,被评论的菜品名,评论的内容,以及提交这份评论的用户名。

    订单的E-R图,如下图所示,它包含了订单的ID,购买菜品的ID,菜品名,购买数量,订单状态以及送餐地址。
    如图所示。

    4.3 数据库文件设计根据之前的数据库需求分析,得出网站各个数据库表的设计,如下面的表所示:
    表 4.1地址表 addresss



    字段
    类型

    主键
    注释




    Id
    int(10)


    自增,地址ID


    username
    varchar(255)


    属于的用户的用户名


    address
    varchar(255)


    地址信息


    created_at
    timestamp

    0000-00-00 00:00:00
    创建时间


    updated_at
    timestamp

    0000-00-00 00:00:00
    更新时间



    表4.2 餐厅评论表cffs



    字段
    类型

    主键
    注释




    id
    int(10)


    自增,菜品评论ID


    foodname
    varchar(255)


    评论的菜品名


    comment
    text


    评论的内容


    username
    varchar(255)


    评论的用户ID


    created_at
    timestamp

    0000-00-00 00:00:00
    评论的创建时间


    updated_at
    timestamp

    0000-00-00 00:00:00
    评论的更新时间



    表4.3 菜品评论表cfrs



    字段
    类型

    主键
    注释




    id
    int(10)


    自增,餐厅评论ID


    restaurantname
    varchar(255)


    餐厅名称


    comment
    text


    评论内容


    username
    varchar(255)


    评论的用户名


    created_at
    timestamp

    0000-00-00 00:00:00
    评论的创建时间


    updated_at
    timestamp

    0000-00-00 00:00:00
    评论的更新时间



    表4.4 邮箱验证表confirm_emails



    字段
    类型

    主键
    注释




    id
    int(10)


    邮箱验证码的ID,自增


    username
    varchar(255)


    属于的用户名


    confirm_code
    varchar(255)


    验证码


    created_at
    timestamp

    0000-00-00 00:00:00
    验证码的创建时间


    updated_at
    timestamp

    0000-00-00 00:00:00
    验证码的更新时间



    表4.5 手机验证表confirm_mobiles



    字段
    类型

    主键
    注释




    id
    int(10)


    手机验证码的ID,自增


    username
    varchar(255)


    验证码属于的用户名


    confrim_code
    varchar(255)


    生成的6位验证码


    created_at
    timestamp

    0000-00-00 00:00:00
    验证码的创建时间


    updated_at
    timestamp

    0000-00-00 00:00:00
    验证码的更新时间



    表4.6 顾客信息表customers



    字段
    类型

    主键
    注释




    id
    int(10)


    顾客的ID


    username
    varchar(255)


    顾客使用的用户名


    sex
    varchar(2)


    性别


    mobile
    varchar(255)


    手机号


    mobile_status
    varchar(255)


    手机号验证状态


    birthday
    date


    生日


    email
    varchar(255)


    邮箱地址


    email_status
    varchar(255)


    邮箱的验证状态


    status
    varchar(255)


    账户的状态


    district
    varchar(255)


    所在地区


    addressid
    varchar(255)


    地址ID


    created_at
    timestamp

    0000-00-00 00:00:00
    创建时间


    updated_at
    timestamp

    0000-00-00 00:00:00
    更新时间



    表4.7 网站活动表events



    字段
    类型

    主键
    注释




    id
    int(10)


    活动的ID,自增


    title
    varchar(255)


    活动的标题


    content
    text


    活动的内容


    imgaddress
    varchar(255)


    活动图片的地址


    created_at
    timestamp

    0000-00-00 00:00:00
    活动创建时间


    updated_at
    timestamp

    0000-00-00 00:00:00
    活动更新时间



    表4.8菜品销量表foodcount



    字段
    类型

    主键
    注释




    foodid
    varchar(255)


    菜品的ID


    foodname
    varchar(255)


    彩屏的名字


    sum(count)
    double

    NULL
    菜品的销量



    表4.9 菜品信息表foodinfos



    字段
    类型

    主键
    注释




    id
    int(10)


    菜品详细信息ID


    belongto
    varchar(255)


    菜品属于的餐厅用户名


    name
    varchar(255)


    菜品的名字


    price
    varchar(255)


    菜品的价格


    stock
    varchar(255)


    菜品的库存数量


    note
    varchar(255)


    菜品的描述


    savename
    varchar(255)


    菜品图片的存储名称


    status
    varchar(255)


    菜品的状态


    restaurantname
    varchar(255)


    菜品属于餐厅的名字


    moring
    varchar(255)


    餐厅开始营业时间


    night
    varchar(255)


    餐厅结束营业时间


    demand
    varchar(255)


    餐厅是是否有起送要求


    typeofdemand
    varchar(255)


    起送要求类型


    demandfornum
    varchar(255)


    起送要求数量


    demandformoney
    varchar(255)


    起送要求金额


    addressid
    varchar(255)


    餐厅地址


    mobile
    varchar(255)


    手机号


    phone
    varchar(255)


    座机号



    表4.10菜品表foods



    字段
    类型

    主键
    注释




    id
    int(10)


    菜品的ID


    belongto
    varchar(255)


    菜品属于的餐厅用户名


    name
    varchar(255)


    菜品名


    price
    varchar(255)


    菜品价格


    stock
    varchar(255)


    菜品库存


    note
    varchar(255)


    菜品描述


    foodimg
    varchar(255)


    菜品图片名


    status
    varchar(255)


    菜品状态


    savename
    varchar(255)


    菜品图片保存名


    type
    varchar(255)


    菜品类型


    created_at
    timestamp

    0000-00-00 00:00:00
    菜品创建日期


    updated_at
    timestamp

    0000-00-00 00:00:00
    菜品更新日期



    表4.11站内信表messages



    字段
    类型

    主键
    注释




    id
    int(10)


    站内信ID


    sent
    varchar(255)


    站内信发送者


    receive
    varchar(255)


    站内信接受者


    title
    varchar(255)


    站内信标题


    content
    text


    站内信内容


    status
    varchar(255)


    是否可以回复


    created_at
    timestamp

    0000-00-00 00:00:00
    站内信创建日期


    updated_at
    timestamp

    0000-00-00 00:00:00
    站内信修改日期



    表4.12 数据迁移表migrations——Laravel数据迁移



    字段
    类型

    主键
    注释




    migration
    varchar(255)


    数据库表迁移的名字


    batch
    int(11)


    迁移的分支



    表4.13 订单表orders



    字段
    类型

    主键
    注释




    id
    int(10)


    订单的ID


    foodid
    varchar(255)


    订单菜品的ID


    foodname
    varchar(255)


    菜品名字


    count
    varchar(255)


    购买的数量


    addressid
    varchar(255)


    送餐地址ID


    status
    varchar(255)


    订单状态


    restaurantname
    varchar(255)


    被订餐的餐厅名


    created_at
    timestamp

    0000-00-00 00:00:00
    订单的创建日期


    updated_at
    timestamp

    0000-00-00 00:00:00
    订单的修改日期



    表4.14重置密码表resets



    字段
    类型

    默认
    注释




    id
    int(10)


    密码重置ID


    username
    varchar(255)


    用户名


    email
    varchar(255)


    邮箱


    reset_code
    varchar(255)


    重置码


    created_at
    timestamp

    0000-00-00 00:00:00
    重置密码申请日期


    updated_at
    timestamp

    0000-00-00 00:00:00
    重置密码更新日期



    表4.15 餐厅详细信息表restaurantprofiles



    字段
    类型

    主键
    注释




    username
    varchar(255)


    餐厅用户名


    email
    varchar(255)


    邮箱


    email_status
    varchar(255)


    邮箱验证状态


    restaurantname
    varchar(255)


    餐厅名字


    describe
    text


    餐厅自我描述


    moring
    varchar(255)


    餐厅开始营业时间


    night
    varchar(255)


    餐厅结束营业时间


    typeofdemand
    varchar(255)


    起送要求类型


    demandfornum
    varchar(255)


    起送数量要求


    demandformoney
    varchar(255)


    起送金额要求


    mobile
    varchar(255)


    餐厅手机号


    mobile_status
    varchar(255)


    手机号状态


    phone
    varchar(255)


    座机号码


    status
    varchar(255)


    餐厅状态


    address
    varchar(255)


    餐厅地址



    表4.16 用户表users



    字段
    类型

    主键
    注释




    id
    int(10)


    用户的ID


    username
    varchar(32)


    用户名


    password
    varchar(64)


    密码


    role
    varchar(255)


    身份


    remember_token
    varchar(255)


    Laravel本次密码对应的token


    created_at
    timestamp

    0000-00-00 00:00:00
    用户创建日期


    updated_at
    timestamp

    0000-00-00 00:00:00
    用户修改日期



    5 网站的功能实现5.1 首页功能的实现网上订餐系统的主页主要包括主打菜品的推荐、今日销量榜、月销量榜、季度销量榜、购物车和用户登录注册板块。主打菜品模块主要是销量最高的三个菜品显示成幻灯片形式在主页展示;然后在幻灯片的右边显示按照分类推荐的菜品;今日销量榜主要显示当日销量最好的菜品;月销量榜按照销量排布显示上个月菜品的销量;季度销量榜按照季度销量来显示菜品;用户可以将食品存入购物车内,统一结算,同样的,购物车内的菜品可以被修改和删掉;登录注册板块分别向已注册和未注册用户提供系统登录和会员注册功能, 如图所示:

    5.2 会员注册模块未注册的用户可以在会员注册页面进行注册。会员注册页面交互友好,可以向用户提供用户名、密码等信息的输入建议,并可提供相应的纠错功能,保证注册信息正确、合法。
    如图所示。

    5.3 会员模块会员在成功注册完成之后,可以从主页或者其他页面进行登录,如图所示:

    会员在成功登录之后,可以进入自己的个人信息页面查看自己的站内信,网站活动,订单,个人信息以及登出。
    如图所示。

    5.4 餐厅后台模块想要加入到网站的餐厅可以去餐厅注册页面注册,注册页面如图所示,依旧是非常友好的tip提示方式。
    在餐厅注册过之后,就可以登录后台了,餐厅后台登录页面如图所示:

    在餐厅后台登录页面,为了用户体验的友好,同时还提供餐厅的注册和忘记密码的功能页面,它们都是在同一个页面上实现的。如图所示,是一个简单的餐厅注册页面,餐厅在这个页面注册之后,还需要在后台完善相应的信息,在此之后餐厅就可以正式上线了。
    下图所示是餐厅后台登录页面的忘记密码功能,只需要提供注册时候使用的邮箱,就可以进行密码的重置了。服务器会向该邮箱发送一份密码重置信,在进入到邮箱查看到密码重置新之后,点击密码重置信上面的地址,就可以跳转到密码重置页面了。
    如图所示。

    当餐厅用户完成登录之后,就会被引导至餐厅后台主页界面。如下图所示:

    因为本系统使用的电脑屏幕分辨率是1600*900,所以显示会比较松散一些,该页面采用了Bootstrap响应式布局,在IPAD等移动设备上也可以正常显示。
    餐厅信息设置页面,如下图所示:

    5.5 菜品管理模块餐厅在登录后台之后,可以对菜品进行管理,首先是菜品总览,总揽页面如图所示:

    在菜品管理模块之中的第二个是菜品的管理,包含了菜品信息的上传、修改、和删除。如下图所示:

    该模块最后一个功能是上传菜品的图片,页面采用JavaScript控件完成,传输方式采用Ajax,该控件支持直接拖放式的图片上传,避免繁琐的文件查找操作。页面如图所示:

    5.6 购物车模块顾客可以在页面中选中菜品后,可以先把菜品放进购物车里面,继续浏览,最后再去购物车页面进行下单操作,也可以直接去下单。
    在购物车页面还可以对选中的菜品数量进行修改,菜品数量的改变会自动修改单项菜品的总价以及订单的总价。同样的,删除操作也会有同样的效果。
    购物车的设计是数据全部放进数据库中,所以需要用户必须登录之后才可以使用购物车。当用户退出之后,购物车里面的内容还会保留下来,直到用户下一次登录时查看。
    如图所示:

    5.7 订单模块用户在选中菜品之后,可以从购物车里进行下单,也可以从页面中进行下单。但用户下单成功之后,会有短信通知到用户和对应的餐厅。餐厅就开始准备菜品。
    当餐厅菜品准备完成,开始配送的时候,餐厅只需要在后台修改订单状态为配送状态,服务器会自动发送短信到该订单顾客的手机上,通知改顾客菜品已经开始配送,请准备好相应的零钱等信息。
    一旦送餐完成,餐厅修改订单状态为送餐完成,这样订单就完成了。
    在下单之前,顾客必须验证手机号才可以进行下单,验证手机号页面如图所示:

    5.8 评价模块在完成一项订单之后,顾客可以对此次的菜品以及菜品进行评价。
    同时,当顾客评论完成之后,顾客的评论就会显示在菜品页面中。同时,餐厅也可以在后台查看到顾客给菜品的评价。
    如图所示:

    5.9 短信通知模块当顾客注册、订餐下单、餐厅配送、订单完成等情况发生时,会自动有短信通知顾客。
    当有餐厅用户注册、顾客订餐时,也会自动有短信通知到餐厅。
    短信模块专门为了与顾客和餐厅进行短信通知使用。它包含以下功能:验证手机号,会发送6位验证码到注册的手机上,只有正确在网页上输入验证码才可以通过验证。通知顾客下单成功功能,当顾客成功下单之后,不仅在网页上会有提示,短息模块还可以发送下达订单成功短息,通知顾客下单成功,短信中还包含部分订单关键信息。通知餐厅有顾客下单功能,与通知顾客下单成功功能类似,用来通知餐厅的。开始配送通知功能,当餐厅准备好菜品开始配送的时候,会激发此功能,此功能会向顾客发送餐厅已经开始配送的短信,其中包含部分订单信息以便顾客了解。
    如图5-20所示:

    5.10 管理员模块管理员可以对网站进行各项管理,查看所有的顾客和餐厅信息,并进行相应的操作。控制网站活动。
    在管理员模块中,查看以及修改顾客信息,查看和修改餐厅信息。给某个用户发送站内信。增加、修改或者删除网站的活动。查看所有的评论。以及进行广告的控制。

    6 总结与展望Laravel作为2014年使用率最高的PHP框架,能够学习并使用Laravel开发此次系统,恐怕是本毕业设计最大的收获了。
    其实,从一开始选择使用何种PHP框架来进行开发,我一直也犹豫过,像国内势头正旺的ThinkPHP或者Yii。ThinkPHP中文PHP框架,易学易用,完善的中文开发文档,遇到问题或者bug可以非常容易的在中文社区得到解答。但是我最后选择了外国人开发Laravel,不仅仅因为它广泛,而是我希望能够挑战自己。
    6.1网站结构设计回顾一开始,本人对于网站的结构是什么太多想法的,按照之前的设计做就好了。但是,实际上对于网站我还是有一个最初的想法,就是顾客——餐厅,这样的设计方式,一开始整体都是对于顾客来设计的,从注册、登录,当然,自始至终我都是非常关注显示效果的,不过后来因为时间有限,我必须加快进度,所以有些东西就必须有舍有得了。
    网站结构第一保证顾客可以很容易的注册,和验证。每个注册的页面我都用JavaScript制作tooltip来弹出小提示用户。之后,顾客还可以非常方便的订餐,不需要考虑太多东西,就可以订餐,这是我希望做的。
    第二个需要保证的就是餐厅的部分了,订餐网站没有了餐厅就不是订餐网站了。对于餐厅我找一个后台管理模板,对于这个模板修改了好几天,再加上后来信息的打入,jqGrid的配置使用、信息的传输、操作的响应,还有dropzone的使用,确实让我花费了一些时间。
    这样做都是为了让餐厅的后台尽可能的好看,以及对于餐厅的管理员来说友好的使用,所有的功能更加的清晰和完善。
    在对顾客友好的方面,本系统有一个设计,那个用户注册不光会有一封邮件确认信,还有一封站内信,让用户觉得你不是注册就完了,“欢迎来到这个大家庭中!”,希望顾客能够在这里有一个归属感,这里不仅仅只是一个订餐的地方。
    参考文献[1]王衍,姚建荣,管理信息系统教程,浙江科学技术出版社
    [2]王珊,数据库系统概论,北京教育出版社
    [3]孟宪虎、马雪英、邓绪斌,大型数据库系统管理、设计与实例分析,电子工业出版社
    [4]卞文志,网上订餐将成为餐饮业利润第二落点[J].烹调知识.2007,(4):26~27
    [5]田杰,乔东亮,秦必瑜,电子商务:模式系统及其运营,中国传媒大学出版社,2009-10-01
    [6]李建忠,电子商务网站建设与管理,清华大学出版社,2012-01-01
    [7]赵祖荫 主编,张瑜,张玮颖 等编著,电子商务网站建设实验指导(第二版),清华大学出版社,2008-3-1
    [8]张波, O2O:移动互联网时代的商业革命, 机械工业出版社
    [9]列旭松,陈文 著,PHP核心技术与最佳实践,机械工业出版社,2012-11-1
    [10] Shawn McCool 著 ,Laravel Starter , Packt PublishingLimited
    [11] (美)弗兰纳根 著,淘宝前端团队 译 ,avaScript权威指南(第6版) , 机械工业出版社,2012-4-1
    [12] (美)凯西恩 著,陈升想 等译,ML 5应用开发实践指南,机械工业出版社,2013-4-1
    [13] 高洛峰 编著,细说PHP(第2版),电子工业出版社,2012-10-1
    [14] 单东林 张晓菲 魏然 编著,锋利的jQuery(第2版),人民邮电出版社,2012-7-1
    [15] (澳)威利,(澳)汤姆森 著,武欣 等译, php和mysql web开发,机械工业出版社,2009-4-1
    2 评论 11 下载 2019-04-12 09:36:10 下载需要16点积分
  • 基于Java的仿QQ即时聊天系统

    一、项目需求分析1.1 项目介绍这是一个模仿QQ的即时聊天软件,可以通过运行在本地的服务端,实现两个客服端之间的通信,即聊天。采用的是javafx架构作为GUI设计架构,个人认为优点是可以自己设计css,使界面达到美观的目的。本项目共有登录、注册、重置密码、主界面发消息、添加好友、好友列表项、查看聊天记录、删除聊天记录、未读消息提醒、好友主页、我的主页等模块,还实现了聊天气泡以及皮肤,消息提示音。该项目还调用了短信验证码的api和图灵机器人的api。在进行注册和重置密码时,都会有发送验证码的按钮,通过输入的手机号接收验证码。每个人的账号都会有个聊天助手,聊天助手就是接入的图灵机器人,可实现自动智能回复。
    二、系统分析与设计2.1 本程序需解决的关键技术问题
    短信验证码和图灵机器人的api调用
    多个客户端通过多线程的方式与服务端实现通信
    好友列表项通过listView来实现,将每个好友作为一个pane,将信息放在pane上,把新加的好友直接添加到好友列表
    聊天记录的实现,两方发的消息一左一右的显示,好友的消息作为一个pane添加在listview的左边,我的消息作为一个人pane添加好listview的右边
    两个好友之间发消息的气泡的大小自动调整,根据传入的消息的类型和长度来设置气泡的高度和宽度
    记住密码和自动登录的复选框的DIY设计,通过三个方框来作为按钮的背景来实现三种状态的不同显示
    实现编辑我的资料时不跳转页面,即在我的主页直接进行编辑,点击编辑会显示完成按钮,点击完成后隐藏
    实现我的信息数据在多个页面之间的调用。通过写了一个userdata类来管理我的信息,登录时将我的信息从数据库中读取出来,然后通userdata调用
    聊天气泡皮肤的实现,将一个气泡皮肤分成七个部分来实现,将七个部分完美拼接
    消息提示音的设置,通过导入jar包来实现java播放MP3文件

    2.2 功能模块
    三、项目设计与实现3.1 工程文件组织结构


    3.2 程序设计Controller是个全局操作类,所有的登录、注册、运行、不同界面之间的连接等主要功能都在这里实现。Model里面都是一些数据库操作、气泡调整助手、验证码api、图灵api等,还有一些数据的操作类,View里面主要就是界面的设计及功能的实现。Main就是个主函数,运行controller以运行整个程序。
    Companion表:我的好友,里面将每个账号都匹配自己的好友和好友的备注。

    Dialog表:将已经登录的账号临时存储在这个表中,当账号注销后,自动清除。

    Offlinemsg表:将发给不在线好友的离线消息存储起来,当对应好友读取完信息后就删除信息。

    Save_pass表:把勾选了记住密码的账号和密码存储在这个表中,打开程序时自动显示到对应的文本框。

    user表:存储用户所有信息的表。

    登录界面
    进行了账号和密码的验证,同时还有记住密码的选项,当你登录账号时勾选了该选项,下次将在登录界面展示前显示在输入框中。还会检查该账号是否已经登录,如果已经登录则不能再进行登录。如果该账号登录成功后会将该账号数据暂时存储在一个表dialog中。界面是仿QQ登录界面设计的,背景用的是类QQ登录界面的gif动画实现的。另外当鼠标焦距输入款时,对应的图标会发生变化,其实是背景图的变化。自定义了界面的最小化和关闭按钮以及记住密码复选框,使得界面更加的美观。

    注册界面
    该界面有一些注册信息的验证,采用的是java的正则匹配。首先会对输入框进行验证,如果为空则显示提示信息。如果不符合正则匹配也会提示相应的错误信息。当你输入了手机号后,还要点击获取验证码的按钮,获取到一个六位数的随机验证码,当你正确输入验证码后才可以进行注册。另外这里还有一个选择头像的设置,点击选择头像,会展示系统自带的一些头像,你可以进行选择自己喜欢的。


    忘记密码
    其实该界面跟注册界面类似,就是少了年龄和性别的输入。其他验证与验证码的获取都差不多,就不过多介绍了。

    主界面
    首先左边是好友列表,列出了所有好友的头像和备注,以及在线状态。好友列表解释个listview,然后每个好友是个pane,在pane里面添加信息,再将pane添加到listview里就实现了添加到好友列表。在这里有个右键菜单,可以实现消息标为未读已读,查看好友资料,清除聊天记录,删除好友等功能。
    中间是个发消息的模块,主要也是由listview和一些pane组成。和好友列表类似。一共定义了两种pane,好友消息是左,我的消息是右。这样就实现了一左一右的“添加”消息。在这里“我”发送的消息都会被传到服务端,然后服务端再传给对应的好友。如果好友不在线,就进行离线处理:将“我”发的所有消息以“我的账号+好友账号+消息”存在数据库的一张表offlinemsg中。当该好友上线时,就会出现消息提示,也就是我离线发的消息,好友读取消息后,这些数据就会在数据库中被删除,避免出现重复提醒相同消息。当好友在线时,也会实时提示好友未读的消息。

    实现效果大概是这样。当然这里还有好玩的聊天助手哦,那就是图灵机器人,可以实现无限陪聊的功能。
    在右边就是我的主页信息了,上面展示我的一些基本信息:我的头像、姓名等,还有一些按钮,可以实现添加好友,查看我的更多资料,最小化、关闭等功能。

    好友主页
    该页面显示的好友的全部资料信息,这里有个修改备注的按钮,当你点击后,就可以对备注文本框进行编辑,当编辑完成,点击完成按钮,信息就会在数据库中更新,并在好友列表上更新。

    我的个人主页
    跟好友主页类似,就是增加了一点权限,可以更改所有信息。

    添加好友
    当你输入账号,然后按回车键时,就会在下面显示对应的好友账号,并可以进行添加。如果账号不存在,或者是已经添加的好友则会报错。

    气泡皮肤的实现
    把气泡一共分为七个部分来实现(本来是分为九个部分来实现的,但是能力有限,九个部分的难以实现):左上,左中,左下,右上,右中,右下,中间。由于技术有限,把一个完整的气泡皮肤分成了六个部分,分别作为除中间以外的气泡背景,中间的颜色用气泡颜色填充,颜色获取可以用ps的吸管工具。主要是七个部分的完美衔接花了很多时间。
    消息提示音的实现
    导入了jl1.0.1.jar,实现了java的简单播放mp3文件,在将服务器发来的给好友的消息的同时加上该消息提示音,并在播放完提示音再展示消息,以达到“网络延迟”的效果。
    四、个人小结该项目一共花了我两周多的时间完成的,可以说是比较久了,个人对于最终的结果还是比较满意,期间也遇到了很多问题,出现了很多bug,最终都一个一个的解决了。但是现在的程序还是存在很多待进一步改善的地方,我将会在之后的时间里对它进行进一步完善。
    1 评论 1 下载 2019-07-14 10:22:09 下载需要17点积分
  • 基于Winpcap的网络数据包嗅探抓包和发包工具的设计与实现

    摘 要本文课题设计为基于WinPcap的开源网络数据处理工具程序包的设计与实现,使用MFC库和C++来实现。
    本文首先说明了课题研究的目的、意义和网络监听的背景,讨论了在网络数据处理领域领先的工具以及当前网络学习的困难,以此引出了本课题研究的需求和可行性分析。然后分析了网络结构,重要网络协议和网络数据传输的基本原理,介绍基于WinPcap、MFC实现网络监听。接着罗列了本程序设计思路和架构,功能流程及其实现逻辑,自顶向下,结合源码逐一展开描述。最后将程序的功能测试及其结果进行展示。
    关键词:网络协议,数据包,TCP/UDP,socket,ARP,WinPcap
    ABSTRACTThis article is designed to subject the design and realization of WinPcap open source tool for network data processing package based on the use of MFC and C++ libraries to achieve.
    This paper describes the purpose, significance and network monitoring research background ,discusses network data processing field-leading tools and the difficulty of the current network learning , this leads to the need for and feasibility of this research . Then it analyzes the basic principles of network architecture,network protocols, and important network data transmission introduced on WinPcap, MFC for network monitoring. Then a list of design ideas and architecture, functional flow of the program and its implementation logic ,top-down , one by one to start binding source description . Finally, the functions of the program and the test results show.
    KEYWORDS:network protocol, datagram, TCP/UDP, socket, ARP, WinPcap
    1 绪论1.1 网络与监听互联网时代与大数据时代的到来,愈发体现出了信息的快速增长与知识膨胀的力量。信息的不平等造就了当前这个时代的不平等,只有掌握了最新、最全的数据,才能在这个时代立足脚跟,快速前进。而网络,则是承载信息的天桥,伸手在信息的洪流中抓一把,逝去的会多于获得的,因此我们更加需要了解网络的结构和数据传输的协议、方式,以提供更高效的信息获取手段。
    然而,随着计算机的普及,网络已成为人们生活中不可或缺的工具,随之而来的非法入侵也不断加剧着计算机网络系统的安全问题。正是由于以太网中采用广播方式,因此,在某个广播域中可以监听到该域所有的信息包,利用一定是技术手段,还能向外拓展,侵入其他网络。
    网络监听是一种监视当前网络状态以及网络上数据传输的管理工具,它可以将计算机网卡设定成监听模式,从而获取该域网络上所传输的信息。对于网络管理员来说,网络监听技术可以用来查看、分析该域网络的性能和实时状态;对于入侵者来说,网络监听技术可以用来获得网络中传输的各种数据。为了保护网络信息的安全,必须采用网络监听技术进行反跟踪,时刻探明网络的安全现状,掌握先机,才能保证网络的信息安全。
    目前,市场上针对不同版本的操作系统,有不同版本的网络数据监听软件,如 Window9x 平台的NetXray、Win2000/xp平台下的Sniffer Pro以及UNIX 平台Netman和SunSniff 等等。
    其中要数翘楚的,有NAI公司推出的一款一流的网络管理和应用故障诊断分析软件Sniffer。不论是在有线网络还是在无线网络中,它都能够帮助网络管理人员进行实时的网络监视、数据包捕获以及故障诊断分析。对于在实时快速的网络问题故障诊断中,基于该便携式软件的解决方案具备很高的性价比,它能够让用户获得强大的网络管理和应用故障诊断能力。
    说到Sniffer就不得不提Wireshark了,我校网络工程专业在本科三年级的网络协议学习中,就使用WireShark来帮助获取本机网络中的实时数据,以此学习分析TCP/IP等协议。WireShark(前称Ethereal)是一个免费开源的网络数据包分析软件。网络数据包分析软件的功能是截取网络数据包,并尽可能显示出最为详细的网络数据包数据。
    以上介绍的均是由单纯软件实现的网络嗅探器,其功能相对硬件嗅探器来说还是较为简单。下面将罗列几款由硬件实现的网络嗅探器。硬件的网络嗅探器又称为网络分析仪(协议分析仪)。目前,网络分析仪的技术已经非常的成熟,产品种类繁多。但各种产品的功能略有差异,有的专精于某种协议,有的“包罗万象”。一般的情况下,大型的企业网络都会使用软硬件想结合的网络分析仪。如:1)安捷伦网络分析仪系统,2)Fluke Optiview 综合网络协议分析仪等。
    1.2 研究意义网络数据的传输、网络协议和网络结构对于计算机的使用者来说是透明的,它们非常重要但又十分复杂,需要初学者去好好了解和学习。然而,由于无法直观地获取到网络实时传输的数据,在课堂上学习到的都是相关的理论知识,对于学习者来说是无法具象化的,难以理解的。使用网络数据处理工具能解决这一问题,但是目前该领域的优秀工具使用起来步骤繁琐,在学习协议之前需要学习如何使用该工具,有着“先有鸡还是先有蛋”的矛盾,不适合网络协议的初学者使用。
    因此,本着开源的精神来做一款工具,帮助了解、学习网络数据的传输、网络协议和网络结构。本毕业设计软件是基于OSI(Open System Interconnection)参考模型以及一些常用的网络协议,采用C++语言,使用MFC库、WinPcap库和Visualstudio 2012作为开发工具编写本软件。本系统操作界面简单大方,功能较为齐备。是一个简单实用的网络数据处理软件,本系统具有以下基本功能:
    本机网卡扫描/选择,混杂模式抓包,协议过滤,数据包分析,数据包导入导出,自制ARP包。
    本软件的目的重在抓取经过本机网卡的数据包,对其进行加工处理、分析展示,供初学者学习、参考。
    2 网络数据处理工具需求分析2.1 网络数据处理工具的需求分析对于网络数据的处理,大部分软件或系统是不会直接读写该数据包的每一位的,因为有了各大协议的存在,它们只需要建立在OSI七层模型中的应用层就足够了。通过协议的转换,软件或系统可以从整个数据包中只读取需要的相应字段,之后再进行相应的数据处理。因此,在这里要说的是很重要的一部分功能,即捕获数据包。
    业务需求:

    满足网络管理员对网络内流量的实时观察。满足学生对网络协议的学习和练习使用。扫描本机网卡和本网段内活跃主机信息。满足对网卡内流过的数据读写操作 。
    性能需求:

    网卡混杂式捕获不造成2G内存计算机宕机。文件磁盘IO操作不造成软件奔溃。任何操作不造成GUI交互无响应。并发不造成内存泄露等问题。程序流程合理,不会造成逻辑上的死循环。
    可靠、可用性需求:

    在规定的条件下,在规定的时间内,软件不引起系统失效的概率。在规定的时间周期内,在所述条件下程序执行所要求的功能的能力。
    2.2 网络数据处理工具的可行性分析在大部分传输介质上,网络信息的传输是有被截获、监听的可能性的。在网络上,实施监听最好的地方是在网关、路由器和防火墙一类的位置,因为这些位置是网络数据的汇聚节点,经常有大量的数据经过它们,但它们的防御措施也相应得做地更好。大多数黑客用来监听网络传输的地方是以太网中任何一台连网的主机上,因为这是监听最方便的地方,数量多、防御能力低。因此,本工具也打算从个人计算机入手,进行网络数据处理的第一步:网络监听。下面,将主要从经济可行性、技术可行性、运行可行性和操作可行性等方面进行分析本毕业设计。
    2.2.1 经济可行性开发该软件所需的相关资料可以通过文献资料和网络进行调查采集,所需的软件系统、硬件平台等都易于获得,无需特殊工具,开发成本低,简单易实现,从经济角度来看,开发该软件经济可行。
    2.2.2 技术可行性因为以太网是一种广播型的网络,且目前人们使用的因特网多是使用以太网技术来实现的,所以大多数网络数据的截获是可以在以太网上实现的,其中可以分为共享式以太网监听和交换式以太网监听。因此,从技术角度来说,以某一网络域中的计算机为节点,监听该域网络,这种方式是可行的。
    2.2.3 运行可行性运行性是对组织结构的影响。该软件界面简洁,操作十分简单,只需要相应的windows系统和动态库(都是可以下载获得的)就可以运行起来,所以从运行角度上看,该软件是可行的。
    综上所述,该系统的开发从经济、技术、运行等方面完全可行。
    2.2.4 操作可行性分析开发所采用的工具是VisualStudio 2012,开发出的应用程序在windows系统的计算机上,以窗口的方式展现,接收鼠标和键盘的输入,以显示器为输出,符合当代计算机使用者的使用习惯,方便人们对网络数据的监视和处理,简单易上手。所以此软件在操作上是可行的。
    3 网络数据处理工具开发相关知识3.1 MFC框架的介绍MFC(Microsoft Foundation Classes)是微软基础类库的简称,MFC提供了面向对象的框架,采用面向对象技术,将大部分的WindowsAPI 封装到C++类中,以类成员函数的形式提供给程序开发人员调用。

    参见微软定义:https://msdn.microsoft.com/en-us/library/d06h2x6e.aspx
    3.2 OSI模型简介OSI(Open System Interconnection,开放系统互连)七层网络模型被称为开放式系统互联参考模型 ,是一个人为抽象的定义,它把网络概念从逻辑上分为了七层。 OSI 七层模型是一种框架性的设计,建立七层模型的主要目的,是为解决异种网络互连时所遇到的兼容性问题,分层的左右就是起到了“低耦合,高聚合”的效果。其最主要的功能就是帮助数据在不同类型的主机间实现传输。它的最大优点是将服务、接口和协议这三个抽象概念清晰地区分开来,通过七个层次化的结构模型使不同的系统不同的网络之间进行可靠的设备通讯。


    物理层:提供为建立、维护和拆除物理链路所需要的机械的、电气的、功能的和规程的特性 。数据链路层:负责网络寻址、错误侦测和修正等;提供数据链路的流控。网络层:决定数据的传输目的和寄转,添加网络表头(NH),如IP协议首部。传输层:添加传输表头(TH)形成数据包,如TCP协议首部。会话层:提供两进程之间建立、维护和结束会话连接的功能。表示层:转换数据格式使其与接收者系统兼容;完成数据转换、格式化和文本压缩。应用层:为应用软件而设定的层,不同软件有不同的通讯方式,如HTTP,FTP等。
    3.3 网络协议简介网络协议是为在计算机网络中进行数据交换而建立的规则、标准或约定的集合,由三个要素组成:

    语义:说明控制信息每个部分的意义。它规定了计算机需要发出何种控制信息,实现的的过程,以及做出何种响应。语法:用户数据与控制信息的相关结构、格式,以及各种意义数据出现的顺序。时序:对事件、协议发生顺序的详细说明。
    人们形象地把这三个要素描述为:语义表示要做什么,语法表示要怎么做,时序表示什么时候做。
    结合OSI模型,可以更好地理解抽象的“网络协议”这个概念,在硬件和软件的双重人为规定下,形成了各大网络协议。
    3.3.1 数据包嵌套形式
    数据通过OSI模型,被分片、包装、嵌套处理之后,最后形成了一个完整、符合以太网协议的数据包。
    3.3.2 以太网协议首部说明
    对应程序中的数据结构
    struct eth_hdr{ u_char eth_tar[6]; u_char eth_src[6]; u_short eth_op;};
    3.3.3 IP协议首部说明
    字节和数字的存储顺序是从右到左,依次是从低位到高位(Big Endian),而 网络存储顺序是从左到右,依次从低位到高位(Little Endian)。

    版本:占第一个字节的高四位。头长度:占第一个字节的低四位。
    服务类型:前三位为优先字段权,现已忽略。接下来四位用来表示最小延迟、 最大吞吐量、最高可靠性和最小费用。
    封包总长度:整个 IP 报长度,单位为字节。
    存活时间:就是封包的生存时间。
    协议:定义了数据的协议,分别为:TCP、UDP、ICMP 和 IGMP。定义为:
    #define PROTOCOL_TCP 0x06#define PROTOCOL_UDP 0x11#define PROTOCOL_ICMP 0x06#define PROTOCOL_IGMP 0x06
    检验和:首先将该字段设置为0,然后将IP头的每16位进行二进制取反求和,将结果保存在校验和字段。
    来源IP地址:将来源IP地址看作是32位数值则需要将网络字节顺序转化位主机字节顺序。
    目的IP地址:将目的IP地址看作是32位数值则需要将网络字节顺序转化位主机字节顺序。

    在网络协议中,IP协议是面向非连接的,所谓的面向非连接就是传递数据时,不检测网络是否连通,所以IP协议是不可靠的数据报协议。它主要负责在主机之间寻址和选择数据包路由。
    对应程序中的数据结构
    typedef struct ip_header{ u_char ver_ihl; // 版本 (4 bits) + 首部长度 (4 bits) u_char tos; // 服务类型(Type of service) u_short tlen; // 总长(Total length) u_short identification; // 标识(Identification) u_short flags_fo; // 标志位(Flags) (3 bits) + 段偏移量(Fragment offset) (13 bits) u_char ttl; // 存活时间(Time to live) u_char proto; // 协议(Protocol) u_short crc; // 首部校验和(Header checksum) ip_address saddr; // 源地址(Source address) ip_address daddr; // 目的地址(Destination address) u_int op_pad; // 选项与填充(Option + Padding)}ip_header;
    3.3.4 ICMP协议首部说明

    类型:一个8位类型字段,表示ICMP数据包类型(类型繁多,不一一列举)。代码:一个8位代码域,与类型组合,表示指定类型中的一个功能。如果一个类型中只有一种功能,代码域置为0。检验和:数据包中ICMP部分上的一个16位检验和。
    对应程序中的数据结构
    typedef struct _ICMPHeader{ UCHAR icmp_type; //消息类型 UCHAR icmp_code; //代码 USHORT icmp_checksum; //校验和 //下面是回显头 USHORT icmp_id; //用来惟一标识此请求的ID号,通常设置为进程ID USHORT icmp_sequence; //序列号 ULONG icmp_timestamp; //时间戳}ICMPHeader,*PICMPHeader;
    3.3.5 TCP协议首部说明

    TCP源端口(Source Port):源端口和IP地址的是用来标识报文的发送地址。TCP目的端口(Destination Port):16位的目的端口域指明报文接收计算机上的应用程序端口地址。序列号(Sequence Number):TCP连接发送方向接收方发送的封包顺序号,用于重组分片。确认序号(Acknowledge Number):接收方应答顺序号。头长度(HeaderLength):表示TCP头的双四字节数,转化为字节个数需乘以四。URG:紧急指针标志位,0为不使用,1为使用。ACK:请求/应答状态标志位。0为请求,1为应答。PSH:以最快的速度传输数据标志位。RST:连线复位标志位,先断开,再重建。SYN:同步连线序号标志位,用来建立连线。FIN:结束连线标志位。0是结束连线请求,1表示结束连线。窗口大小(Window):目的机使用十六位的域告诉源主机,它想收到的每个TCP数据段大小。校验和(CheckSum):这个校验和和IP的校验和不同,对首部数据和封包内容都进行校验。紧急指针(Urgent Pointer):当URG为1时才有效。
    对应程序中的数据结构
    typedef struct _tcp_hdr { unsigned short src_port; //源端口号 unsigned short dst_port; //目的端口号 unsigned int seq_no; //序列号 unsigned int ack_no; //确认号 #if LITTLE_ENDIAN unsigned char reserved_1:4; //保留6位中的4位首部长度 unsigned char thl:4; //tcp头部长度 unsigned char flag:6; //6位标志 unsigned char reseverd_2:2; //保留6位中的2位 #else unsigned char thl:4; //tcp头部长度 unsigned char reserved_1:4; //保留6位中的4位首部长度 unsigned char reseverd_2:2; //保留6位中的2位 unsigned char flag:6; //6位标志 #endif unsigned short wnd_size; //16位窗口大小 unsigned short chk_sum; //16位TCP检验和 unsigned short urgt_p; //16为紧急指针 }tcp_hdr;
    3.3.6 UDP协议首部说明

    源端口(SourcePort):十六位的源端口域包含初发送方端口号。源端口和IP地址表示了报文的返回地址。目的端口(DestinationPort):六位的目的端口域定义传输的目的地。这个端口指明报文接收计算机上的应用程序端口地址。封包长度(Length):UDP首部和封包数据的总长度。校验和(CheckSum):和TCP校验和一样,不仅对首部数据进行校验,还对封包的内容进行校验。
    对应程序中的数据结构
    typedef struct udp_header{ u_short sport; // 源端口(Source port) u_short dport; // 目的端口(Destination port) u_short len; // UDP数据包长度(Datagram length) u_short crc; // 校验和(Checksum)}udp_header;
    3.3.7 ARP协议首部说明

    硬件类型:指明了硬件接口类型,以太网的值为1;协议类型:指明了高层协议类型,IP为0x0800;硬件地址长度,协议长度:硬件地址和高层协议地址的长度,这样ARP报文就可以在任意硬件和任意协议的网络中使用;操作字段:报文的类型,ARP请求为1,ARP响应为2,RARP请求为3,RARP响应为4……;发送方硬件地址(0-3字节):源主机硬件地址的前3个字节;发送方硬件地址(4-5字节):源主机硬件地址的后3个字节;发送方IP地址(0-1字节):源主机硬件地址的前2个字节;发送方IP地址(2-3字节):源主机硬件地址的后2个字节;目的硬件地址(0-1字节):目的主机硬件地址的前2个字节;目的硬件地址(2-5字节):目的主机硬件地址的后4个字节;目的IP地址(0-3字节):目的主机的IP地址。
    对应程序中的数据结构
    //28字节的ARP头typedef struct _ARPHeader { USHORT hrd; //硬件地址空间,以太网中为ARPHRD_EHER USHORT eth_type; //以太网类型,ETHERTYPE_IP UCHAR maclen; //MAC地址的长度,为6 UCHAR iplen; //IP地址的长度,为4 USHORT opcode; //操作代码,ARPOP_REWUEST为请求,ARPOP_REPLY为响应 UCHAR smac[6]; //源MAC地址 UCHAR saddr[4]; //源IP地址 UCHAR dmac[6]; //目的MAC地址 UCHAR daddr[4]; //目的IP地址}ARPHeader,*PARPHeader;
    3.4 WinPcap简介本工具所使用的WinPcap大大降低了本软件的开发难度。由于Window操作系统没有提供可以直接捕获网络传输数据包的API,尽管提供了一些内核模块接口,但存在着严重的局限性。例如:IP Filter Driver只运行在 Windows 2000 下,且仅支持IP协议;对内核的操作和对文件I/O的操作都带来了设计上和使用上的复杂度飙升;Windows内核的不透明等。由于这些局限,使得Windows平台下的网络安全管理和分析工具无论在数量上,还是质量上都与Unix下有很大的差距。为此,微软研究院赞助了意大利一家开发机构,为Win32平台底层网络分析开发了一套有力且易扩展的体系结构——WinPcap,它将Unix支持的数据包捕获功能移植到Win32系统中,从而弥补了Windows操作系统在网络分析方面的欠缺。而且WinPcap完全开放,提供源代码,同时它提供了与Libpcap相兼容的函数接口,是的程序代码在不同操作系统平台间的可读性大大提升。
    WinPcap是一个基于Win32平台的,用于捕获数据包并进行网络分析的体系结构。它包括了一个内核级的数据包过滤器,一个低层的动态链接库(packet.dll),一个高层的,依赖于系统的动态链接库(wpcap.dll)。其结构图如下所示:

    4 网络数据处理工具的设计4.1 模块结构本网络数据处理工具是一般的PC桌面软件,由于都是二进制的数据分包,不适合使用数据库来存储数据,因此没有使用数据库,而是直接转储为.CAP后缀文件。开发之初,在构思软件时设计了一套软件架构,从底层网卡获取数据开始,由WinPcap混杂式获取数据包,交由Filter层过滤数据,经过过滤层之后的数据由提供给用户界面的各个功能模块进行相应的数据处理:导出、展示、包装等。抛开该网络数据监听功能,还提供一个手动创建数据包并发送的功能接口,并将这些功能都统一交付给捕获器处理。

    4.2 流程关系本程序流程其实不复杂,只是有一些流程需要有上下级关系,有一些流程需要并行,有一些流程需要串行互斥。正如下图所示,和捕获网络数据包有关的流程都必须先设置需要捕获的本机网卡,因为,就算一台PC,也可能会有多张网卡的情况(目前而言,这种情况是多数)。接着,开始捕获的数据包会经过过滤层,也就是自定义的过滤条件。然后被程序中的分派器分配到不同的协议分析模型下,不同的协议分析模型会对相应的协议进行相同格式地解析,并将解析后的数据交由下一级处理:展示和转储。
    上述所涉及到的流程是数据包捕获的主流程,下面说下其他功能流程:

    发包流程:在发包时,也必须选择用来发包的本机网卡(基本上都是以太网卡),然后手动填写相应协议的数据包格式,点击发包即可。这里需要对该协议每一个字段有一定的了解;导入导出流程:在导入导出流程中,不需要选择网卡(当然选择也是可以的),之后就是对文件的I/O操作和MFC的展示了,就不再多说;扫描本网段主机流程:同样需要选择网卡,然后在菜单中选择“scanhost”功能。由于本功能需要花费一定时间,同时不能与本工具的任意一个功能同步进行,所以需要等扫描结束,或者退出本次扫描,才能进行其他操作。

    4.3 功能设计及分析4.3.1 网卡扫描/选择
    在软件打开的界面,选择WinPcap扫描出来的本机网卡。只有在选择了网卡之后,才能进行相应的数据操作。下拉条中列出了本机的所有网卡,选中一块网卡,下方的静态文本框会显示相应的描述信息。关键代码如下所示:
    /***********************adapterDlg.cpp***********************//** * 单击combo box中条目时的回调函数 */void CAdapterDlg::OnCbnSelchangeAdapterCombo(){ //一些变量的声明和条件判断 … // 利用WinPcap遍历本机所有网卡,将用户选择的网卡存入adp_info对象中 for (adp_info.usedDevs = adp_info.allDevs; adp_info.usedDevs; adp_info.usedDevs = adp_info.usedDevs->next){ if (name == adp_info.usedDevs->name) { CString content = "Name: " + name + "\r\nDescription: " + adp_info.usedDevs->description; GetDlgItem(IDC_ADAPTER_EDIT)->SetWindowText(content); /** * 将具体信息存入适配器对象中 */ if ((adp_info.ahandler = pcap_open(adp_info.usedDevs->name, 65535, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, adp_info.errBuf)) == NULL) { MessageBox("Open the adapter failed."); } break; } }}
    4.3.2 抓包
    在选中网卡后,即可开始抓包。每捕捉到一条不满足过滤条件(不会被过滤)的数据包,就会在List Ctronller中显示,并根据实际封包数据,显示相应信息。如果单机选中某一条目,还会在下方的两个静态文本框内显示更详细的十六进制内容。如果双击条目,还能弹出详细信息框。
    本功能在实现的时候,在多个层有不同功能代码。关键代码如下所示:
    /***********************captureDlg.cpp***********************//** * 开始、停止抓包 */void CcaptureDlg::OnBnClickedBegStp(){ //一些变量的声明和条件判断 … //清空列表 m_listctl.DeleteAllItems(); //锁定“扫描主机”菜单 GetMenu()->GetSubMenu(2)->EnableMenuItem(0, MF_BYPOSITION | MF_DISABLED | MF_GRAYED); //dump出去一个缓存包,这样内存就不用一直添加数据包内容了 hThreadCapture = (HANDLE)_beginthreadex(NULL, 0, (THREAD_PROC)captureDataInfo, (LPVOID)this, 0, NULL); // 设置界面、功能锁定 …}
    正如代码中判断的一样,根据adp_info对象中的isCapturing标志来表示是否进行多线程数据包捕获工作和转储、展示数据包工作。在开始捕获时,利用新的工作线程进行数据捕获处理,GUI线程依旧对用户提供快速响应。
    /***********************captureServiceImpl.cpp***********************//** * 显示捕获的数据包内容 * * @param lParam * @return */unsigned WINAPI captureDataInfo(LPVOID lParam){ … //打开导出文件 dumpfile = pcap_dump_open(adp_info.ahandler, lp->CapFilePath); … while ((res = pcap_next_ex(adp_info.ahandler, &(adp_info.header), &(adp_info.pkt_data))) >= 0 && adp_info.isCapturing){ // 读取并展示 readAndDisplay(res, lp, dumpfile, nIndex); } pcap_dump_close(dumpfile); return 1;}
    /** * 展示数据 * * @param res * @param lp * @param dumpFile * @param nIndex */void readAndDisplay(int res, CcaptureDlg *lp, pcap_dumper_t *dumpfile, long &nIndex){ // 一些变量声明和条件判断 … switch (ntohs(eth->ehr_ftp)) { case ETHERTYPE_ARP: // ARP协议处理 … break; case ETHERTYPE_REVARP: //RARP协议处理 … break; case ETHERTYPE_IP: //IP协议簇处理 … switch (ip_hdr->proto) { case IPTYPE_ICMP: // ICMP协议处理 … break; case IPTYPE_TCP: // TCP协议处理 … break; case IPTYPE_UPD: // UDP协议处理 … break; default: // 未知协议处理(未添加的协议) … break; } break; default: // 未知协议处理(未添加的协议) … break; } … //记录在缓存文件中 if(dumpfile != NULL){ pcap_dump((u_char *)dumpfile, adp_info.header, adp_info.pkt_data); } // 发送自定义消息WM_UPDATE_LIST给captureDlg SendMessageTimeout(lp->m_hWnd, WM_UPDATE_LIST, (WPARAM)&Data, 0, SMTO_BLOCK, 1000, NULL);}
    4.3.3 过滤
    过滤格式目前只支持当前这几种协议(分析功能也是如此)。可以多选需要查看的协议和根据接收包的IP地址来进行过滤。
    协议的过滤采用标志位设定的方式,相应的单选框对应相应的协议类型。
    4.3.4 分析
    双击软件主界面的任意一条捕捉的信息条目,将会弹出此“细节分析”对话框。正如其命名,其中包含了许多细节信息,例如:被捕捉的时间、数据包长度、源MAC地址、目标MAC地址、具体协议类型、协议数据内容(十六进制形式显示)等,帮助了解各种协议的数据格式和当前记录的详细数据内容。
    协议的分析其实是对主界面的List组件的单击和双击消息进行了重写,并分派给对应的协议分析器来分析对应的协议为相同的格式,不同的协议展示方式继承自同一个“分析父类”,以便程序扩展:
    /***********************AnalyseDispatcher.cpp***********************//** * 分析数据入口,分发数据处理器 * * @param res * @param data * @param header * @return */bool AnalyseDsipatcher::analyseData(CString &res, const u_char* data, pcap_pkthdr *header = NULL){ // 一些变量的声明 … // 协议头格式化,增加可读性 if (header != NULL) { … } // 以太网头首部数据获取 … // 协议分派,使用组合的设计模式 switch (ptype) { case ETHERTYPE_ARP: analyseService = new AnalyseARPService(); break; case ETHERTYPE_REVARP: res += "RARP datagram\r\n"; break; case ETHERTYPE_IP: analyseService = new AnalyseIPService(); break; default: res += "unknow\r\n"; break; } // 具体分析交由相应协议的分析派生类完成 analyseService->analyse(res, data); delete analyseService; analyseService = NULL; return true;}
    4.3.5 导入导出
    导入导出功能是对此次捕捉的数据转存。其实在本次捕捉时,已经实时dump为一个默认的,名为:capture_data.cap的,WinPcap格式数据包。
    导入导出数据包只是对系统文件的I/O操作,源码如下所示:
    /***********************captureDlg.cpp***********************//** * 导入抓取的数据包文件 */void CcaptureDlg::importData(){ // 一些变量的声明和条件条件判断 … CString extFileCategory = CString("capture data file|*") + dumpFileSuffix + CString("||"); CFileDialog fileDlg(TRUE/*打开文件*/, extFileCategory, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, extFileCategory); fileDlg.m_ofn.lpstrInitialDir = currentDir; if(fileDlg.DoModal()==IDOK){ CString openFilePath = fileDlg.GetPathName(); CapFilePath = openFilePath; DataIOService dataIOServiceInstance(openFilePath.GetBuffer(openFilePath.GetLength()), this); //清空列表 m_listctl.DeleteAllItems(); dataIOServiceInstance.display(); }}
    void CcaptureDlg::exportData(){ //一些变量的声明和条件判断 … CString extFileCategory = CString("capture data file|*") + dumpFileSuffix + CString("||"); CFileDialog fileDlg(FALSE/*写入文件*/, extFileCategory, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, extFileCategory); fileDlg.m_ofn.lpstrInitialDir = currentDir; if(fileDlg.DoModal()==IDOK){ CString outputFile = fileDlg.GetPathName(); DataIOService dataIOServiceInstance; if(false == dataIOServiceInstance.exportData(CapFilePath, outputFile, false)){ MessageBox("Cannot export file!"); } }}
    4.3.6 扫描本网段主机
    如图所示,本软件利用ARP协议,自动遍历本网段内的所有活跃主机,并把它们的MAC值和IP地址列出来。
    对于本网段内主机的扫描,采用了发送UDP报文给本网段内所有主机,在规定时间内查看是否有响应的方式来判断,源码如下所示:
    /***********************scanHostDlg.cpp***********************//** * 将CScanHostService类的构造放在另一个线程中,主线程用来绘窗口,提高用户体验 * * @Param lParam*/unsigned int WINAPI scanThread(LPVOID *lParam){ CScanHostDlg *pScanHostDlgPtr = (CScanHostDlg *)lParam; CScanHostService *hostScan = new CScanHostService(pScanHostDlgPtr); pScanHostDlgPtr->setHostScan(hostScan); … return 0;}
    /***********************scanHostServiceImpl.cpp***********************//** * 利用winsock取得本机MAC和网关MAC,也为后来取得网关IP打下坚实的基础!*/void CScanHostService::getMAC(){ //一些变量的声明和条件判断 … //接收线程开始 _beginthread(recvThread, 0, (void*)this); WSAStartup(MAKEWORD(2, 2, ), &wsadata); SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); int err = GetLastError(); SOCKADDR_IN addr; addr.sin_family = AF_INET; addr.sin_port = htons(8888); addr.sin_addr.S_un.S_addr = destIP; sendto(sock, buff, strlen(buff), 0, (SOCKADDR*)&addr, sizeof(SOCKADDR_IN)); // 等待两秒 Sleep(2000); terminate = true; Sleep(1000); WSACleanup(); …}/** * 念念不忘,必有回响 * 接收发送出去的UDP报文,该报文有MAC地址*/void recvThread(void *lp){ //一些变量的声明和条件判断 … while (!np->getTerminate()){ //分析接收到的ARP回应 res = pcap_next_ex(adp_info.ahandler, &header, &pkt_data); if (res == 0) //超时时间到 continue; if (res >0){ mhdr = (EHR*)pkt_data; if (mhdr->ehr_ftp != 0x0008) continue; iphdr = (IP_HDR*)(pkt_data + 14); // 分析本机MAC地址 if (iphdr->daddr[0] == 9 && iphdr->daddr[1] == 2 && iphdr->daddr[2] == 0 && iphdr->daddr[3] == 5){ np->setMac(mhdr->ehr_sha); np->setGatewayMac(mhdr->ehr_tha); np->setGwayFlag(true); break; } } } _endthreadex(0);}
    /***********************scanHostServiceImpl.cpp***********************//** * 扫描主机 */bool CScanHostService::scanHost(){ // 一些变量声明和条件判断 … //打开接收线程 this->scanRevThreadHandle = (HANDLE)_beginthreadex(NULL, 0, (THREAD_PROC)scanRev, (LPVOID *)this, NULL, 0); Sleep(500); //扫描本网段活动主机,逐一遍历 u_int ip = (g_netmask & g_localip) + 1, tmp; u_char tp[4]; do{ tmp = ntohl(ip); memcpy(tp, &tmp, 4); fillARP(tp); pcap_sendpacket(adp_info.ahandler, (const u_char*)&arp, 42); ++ip; Sleep(50); } while ((ip&g_netmask) == (g_netmask&g_localip) && !terminate); …}/** * 主机扫描接收ARP包线程 * * @param lParam */unsigned int scanRev(LPVOID *lParam){ // 一些变量声明和条件判断 … if (pcap_next_ex(adp_info.ahandler, &header, &data) <= 0) continue; … if (htons(eth_hdr->ehr_ftp) == 0x0806) //只接收ARP包 { arp = (ARP*)data; if (ntohs(arp->arp_hdr.arp_op) == 0x0001) //只接收reply ARP包 continue; // 将接收到的特定回响存入“存活主机”队列 CListCtrl *m_list = np->getList(); int nCount = m_list->GetItemCount(); m_list->InsertItem(nCount, ""); m_list->SetItemText(nCount, 0, hostMac); m_list->SetItemText(nCount, 1, hostIp); }…}
    4.3.7 自制ARP包
    根据ARP的格式,填写正确的ARP信息,点击start发送。
    /***********************manualDlg.cpp***********************//** * 发送数据包线程 * @param lParam*/unsigned int WINAPI sendPackThread(LPVOID lParam){ CManualDlg *lp = (CManualDlg*)lParam; switch (lp->choice) { case ARP_TYPE: if (lp->fillARP() == false) break; lp->sendPacket(); break; // 其他协议 … } lp->isSending = false; lp->m_bn_beg_stp.SetWindowText("Start"); return 1;}/** * 启动按钮*/void CManualDlg::OnBnClickedStart(){ … //锁定“扫描主机”菜单 lp_Main->GetMenu()->GetSubMenu(2)->EnableMenuItem(0, MF_BYPOSITION | MF_DISABLED | MF_GRAYED); m_bn_beg_stp.SetWindowText("Stop"); //打开发送packet线程 _beginthreadex(NULL, 0, (THREAD_PROC)sendPackThread, (LPVOID)this, NULL, 0);…}
    4.4 网络数据处理工具开发方法软件工程中经常可以遇见的系统开发方法有:结构化开发方法、面向对象的开发方法、可视化开发技术。
    结构化开发方法依照功能分解的原则,自顶向下、逐步求精,最终实现软件功能。它以功能划分为基础,简单、实用。结构化开发方法将系统开发总共分为五个阶段:划定系统开发范围、系统分析、系统设计、系统实现和系统支持。
    面向对象的方法是将现实世界问题向抽象对象空间直接映射,以此实现对现实世界的直接模拟,它以数据为中心,而不是基于对功能的分解,所以软件结构相对来说稳定,软件的重用性、可靠性、可维护等特性都不错。
    可视化开发技术是由图形用户界面的兴起而发展起来的,是通过事件驱动实现应用软件的。良好的图形库简化了图形用户界面的设计和编码工作,将开发人员的注意力主要集中在程序的执行逻辑和工作流程上。
    对于本软件的可扩展性而言,继承和组合在各个协议的数据处理上有了单独的派生类,便于新增和减少对其他协议的支持。
    4.5 定义规范虽然这是单独完成的一个项目,但是作为一名程序员,是需要有行业规范来约束自己,帮助自己融入团队的。代码规范就是很重要的一点。
    4.5.1 代码注释规范1.头文件注释
    所有头文件开头都要加注释,写明文件创建时间、作者、用途、概述等。格式如下所示:
    /* * 属于:个人 * 创建日期:2016.5.12 * 作者:XXX * 功能说明:XXXXXXXXXXXXXXXXX */
    2.函数注释
    所有函数一定要注明函数的作用、参数的作用、返回值的作用等。格式如下所示:
    /**<summary> * </summary> * @param * @param * @return */
    3.常量变量注释
    所有的常量和变量,无论全局或者局部只要在代码中起关键作用的必须都加上注释。格式如下所示:
    // 变量或常量作用
    4.测试用例文件存放位置
    在项目的test目录下,新建与功能逻辑相同的目录结构树,在对应的目录下存放对应的测试用例;
    5.测试用例命名
    文件名:[被测试类名]Test.cpp格式,对应的类名为[被测试类名]Test,具体实现按照CppUnitTestFramework框架规定。
    4.5.2 代码命名规范采用驼峰命名法。

    类命名:英文,单词首字母大写,剩余字母小写。在意义上表达该类的作用,如:CaptureDlg,是捕获对话框类。函数命名:英文,首字母小写,剩余单词首字母大写,剩余字母小写。在意义上表达该函数的作用,如:analyseData,是分析数据的函数。
    5 网络数据处理工具测试与调试5.1 程序调试在开发软件的过程中无法避免会产生一些问题,除开最常见的环境错误,语法错误之外,还在实际的开发过程中遇到了许多其它的问题。首先,在构建整个软件主体的过程中,主要采用模块化的构建方式。从磁盘文件组织上来看,每一个独立的功能都是一个独立的文件,单独编写,单独测试,从物理上就已经把每一个单独的功能分开,减少因文件互相耦合度过高而出错的概率。
    在测试与调试过程中主要的调试工具是Visual Studio的错误语法提示和Debug断点单步调试,用来快速定位错误代码,和显示错误内存信息。
    5.2 工具的测试5.2.1 测试的意义及目的软件测试的目的,是在真实的软件运行环境下通过与软件起初的需求定义作比较,发现软件与软件/子软件设计文档和软件开发合同约定不符或与之矛盾的地方。
    5.2.2 测试框架由于开发集成工具是VisualStudio 2012,并采用MFC框架,所以打算使用Microsoft的原生测试框架:Microsoft::VisualStudio::CppUnitTestFramework。
    5.2.3 测试步骤测试是一门学问,有多重分类方式和多重测试技巧。由于本软件目前的功能几乎不涉及与其他主机的交互,同时也不需要对其他用户开放,只是对个人电脑的网卡数据包抓取和处理,因此,本工程只打算通过手工测试、单元测试、集成测试和系统测试来对系统的功能和稳定来做保证。
    开始是单元测试,集中对用源代码实现的每一个功能单元进行测试,尽量争取覆盖每一个函数,最终组合,检查各个程序模块是否正确地实现了所描述的功能。
    集成测试是把已测试过的模块拼凑、组装起来,主要是针对软件体系结构的构造进行测试。
    系统测试把已经经过确认的软件纳入实际运行环境中(分别在Windows XP、Windows 7、Windows 8中运行),与其它系统成份组合在一起进行环境相关的测试。
    5.3 测试用例设计本项目的测试用例根据功能模块进行划分,在业务逻辑代码同等级的目录结构下新建对应[ClassName]Test.cpp用例文件。

    这里列举两个例子:
    5.3.1 适配器选择测试用例#ifdef _TEST… TEST_CLASS(AdpInfoImplTest){ // 预备和清理工作,宏定义 TEST_CLASS_INITIALIZE(AdpInfoImplTestInit){ … } TEST_CLASS_CLEANUP(AdpInfoImplTestEnd){ … } TEST_METHOD(showAllDevs){ … // 断言 Assert::IsNotNull(dlg);… }#endif
    该测试用例对应于sourcecode->biz->analyse->AdpInfoImpl.cpp,被存放于test->biz->analyse->AdpInfoImplTest.cpp。需要注意TEST_CLASS_INITIALIZE、TEST_CLASS_CLEANUP、TEST_CLASS等宏的使用,具体参阅MSDN文档,此处统一使用了预编译字段_TEST,用来区分Debug模式、Release模式和自定义的unit test编译模式。
    5.3.2 分析功能测试用例… TEST_CLASS(AnalyseDsipatcherTest){ /** * header数据生成器 */ struct pcap_pkthdr *ARPHeaderGenerator(){ … } /** * 期望结果 */ CString ARPResGenerator(){ … } /** * 数据分派测试,ARP协议测试具体期望结果 */ TEST_METHOD(analyseARPDataTest){ // 数据准备 … analyser.analyseData(res, data, headerPtr); CString expectRes(this->ARPResGenerator()); // 结果断言 Assert::AreEqual(expectRes, res); } …#endif
    该测试用例对应于source code->biz->analyse-> AnalyseDsipatcher.cpp,被存放于test->biz->analyse-> AnalyseDsipatcherTest.cpp。这里展示了测试过程中的几个阶段:数据准备阶段,功能执行阶段和结果验证阶段,是比较典型、常规的测试步骤。
    由于目前代码中较为繁重的是图形处理过程,所以单纯的业务逻辑代码被覆盖后,显示的测试用例覆盖率不高,目前为34%,还有待提升。
    5.4 测试数据在每一个功能完成之后都会进行分模块的功能测试,以确保这个功能模块的正常运行,同时也是为了方便之后功能的整合。通过选择某些具有代表性的数据和某些边界数据来测试可以很好的测试程序的健壮性,以保证程序的良好运行。下表是本软件中选择某些主要功能所做的测试以及出现的问题和解决方案,以及应用此解决方案后产生的效果。



    功能模块
    测试方法
    测试数据
    测试出现过的问题
    解决方法
    结果




    网卡扫描
    在不同网卡数量机器上运行本软件
    各种网卡


    正常


    扫描本网段主机
    压力测试

    并发执行时,会出现重复机器条目或者程序崩溃
    设置本功能和其他功能以及自身为串行
    正常


    自制ARP包
    填写ARP欺骗包内容并发送
    ARP欺骗包


    正常


    导入导出
    手动测试
    随机几次实时抓包结果


    正常


    过滤
    设置过滤条件
    随机几次实时抓包


    正常


    抓包
    正常上网抓包
    随机几次上网过程


    正常



    结 论开源网络数据处理工具程序包采用了C++技术开发,利用MFC库、WinPcap库使程序界面和Windows系统接口对接,加入多线程并发技术以及多种设计模式,并以企业级规范开发。本程序代码已推送到github、gitlab以及coding.net上开源,并在CSDN上写明详细开发过程和程序代码介绍。如有意向者,可以阅读后提交请求共同开发。
    对于网络协议以及计算机对网络数据的处理,我一直以来都抱有强烈的好奇和热烈的兴趣,很想对计算机网络和操作系统一探究竟。于是,我就动手收集相关资料,从最基础的概念看起。在不断地积累中,我对计算机的认识和网络的认识越来越清晰,就好像自身如同一串二进制比特流,经过物理层,被网卡读取,被上层系统一层层剥去外壳,展示出自己的数据。我将本程序中的资料罗列在了纸上,大概都有10多张A2的白纸那么多,沉甸甸的,特别有成就感。“纸上得来终觉浅”,在明白了这些协议的关系和一些网络的概念后,我动手写了这个程序,来帮我更加直观和清晰地认识我从书上的知识。一边写,一边温习和学习新知识的过程是非常愉悦的,在完成这个工程后,趁着知识记忆深刻和项目脉络清晰,又高高兴兴地在网络上描述了自己的代码,将这些天来的成果展示给大家。
    参考文献[1] Stanley B. Lippman , Josée Lajoie , Barbara E. Moo. C++ Primer 第5版[M].
    北京:电子工业出版社, 2013.9
    [2] [美]ames F.Kurose / [美] Keith W. Ross.计算机网络(第4版):自顶向下方法. 机械工业出版社. 2009.11
    [3] Programming Applications for Microsoft Windows [M], Microsoft Press (October23, 1999)
    [4] msdn.microsoft.com .Microsoft API and reference catalog [OL]. 微软开发手册
    [5] www.winpcap.org/docs/docs_412/html/main.html. WinPcapDocumentation [OL]
    [6] https://www.wireshark.org [OL].WireShark官网
    [7] http://www.http-sniffer.com [OL].Sniffer官网
    [8] Beard, Jonathan C., Peng Li, and Roger D. Chamberlain. “RaftLib: a C++template library for high performance stream parallel processing.”InProceedings of the Sixth International Workshop on Programming Models andApplications for Multicores and Manycores, pp. 96-105. ACM, 2015.
    [9] 龙昱程. “基于 TCP 协议 的应用层协议设计” [M]. 信息通信 5 (2015): 69-70.
    [10] 李玉石. “基于 C++ Builder 的网络调试助手设计与实现” [M]. 品牌与标准化 5 (2015): 85-87.
    [11] 刘志蕾, 陈艳花, 冯志亮, 乔森, 张芳.”基于 TCP/IP 协议的测控系统的开发” [M]. 计算机测量与控制 23, no. 10 (2015): 3418-3420.
    [12] https://git-scm.com/documentation [OL].Github官方手册
    [13] 侯俊杰 . 深入浅出MFC[M] . 华中科技大学出版社 .2001.1
    [14] Kevin R. Fall. TCP/IP Illustrated, Vol. 1: The Protocols[M] 2nd Edition. Addison-WesleyProfessional. November 25, 2011
    [15] W. Richard Stevens. TCP/IP Illustrated, Vol. 2: The Implementation[M] 1stEdition. Addison-Wesley Professional. February 10, 1995
    [16] W. Richard Stevens. TCP/IP Illustrated, Vol. 3: TCP for Transactions, HTTP,NNTP, and the UNIX Domain Protocols[M] 1st Edition. Addison-Wesley Professional.Addison-Wesley Professional. January 29, 1996
    [17] 董越. 未雨绸缪:理解软件配置管理[M].电子工业出版社.2008-5
    [18] Ron Patton. 软件测试(第二版)[M].机械工业出版社.2006-4
    2 评论 41 下载 2018-11-25 09:14:47 下载需要20点积分
  • 基于JSP和MYSQL的学生会事务活动管理的设计与实现

    摘 要随着数据时代的来临,高等学校的信息化建设也越来越深入,学生会管理的信息化建设也呈现出大好的局面。学生会信息管理系统的设计与开发是必然存在的一种趋势。目前,学生会管理日常的工作量是非常庞大的、复杂的。尤其是对一些数据的收集和整理,采用传统的手工方式已经远远不能满足当前的趋势了。因此,急需开发一套完整的系统,用来管理学生会信息。
    本篇文章运用JSP技术开发,Java语言,MySQL数据库,基于MyEclipse平台进行开发了一套关于学生会信息管理系统的软件。开发的模块包括财务报销模块、学生评优模块、请假管理模块、活动发布模块、缺勤查询模块、早操出勤情况查询模块、论坛发布模块。系统分为前台和后台两部分,系统角色分成学生、学生会成员、团委老师三种角色,希望通过信息化建设更好更快的与学生联系,提高对学生的管理,实现学生信息数据化管理,方便管理者对学生信息的管理和收集,减轻了工作量,提高了便利性。
    关键词:学生会管理系统;Java;MySQL
    AbstractWith the advent of the data age, the informatization construction of higher education institutions has become more and more in-depth, and the informatization construction managed by the Student Union has also shown a good situation. Therefore, the design and development of the student union information management system is an inevitable trend. At present, the daily workload of student union management is very large and complex. Especially for the collection and sorting of some data, the traditional manual method is far from meeting the current trend. Therefore, there is an urgent need to develop a complete system for managing student union information.
    This article uses JSP technology, Java language and MySQL database to develop a set of software about student union information management system based on MyEclipse platform. The developed modules include financial reimbursement module, student evaluation module, leave management module, activity release module, absence inquiry module, morning exercise attendance inquiry module and forum release module. The system is divided into foreground and background parts. The system roles are divided into students, members of the student union and teachers of the Communist Youth League. It is hoped that through information construction, students can be contacted better and faster, the management of students can be improved, the data management of student information can be realized, the management and collection of student information can be facilitated, and the work can be reduced.
    Key words: Student Management System; Java; MYSQL
    一、绪论(一)选题背景随着国家对教育事业的越来越重视,各大高等大学的招生领域也跟着扩大。而采取传统的信息管理办法解决学生的日常事务活动不仅花费巨大的财力、物力和人力,更为重要的是效率较为低下。早已不能满足现下的高等学校学生会对日常事务的管理现状了。众所周知,高校的学生会管理在学校的日常管理事务中扮演着非常重要的角色,学生会的管理水平高低很有可能影响着当前学校的发展和对外建树的口碑。学生会在各大高等学校是一种必不可少的存在。学生会管理水平的高低决定了高等学校对人才的培养质量的影响。由于现在高等学校的规模在不断的扩大,对于学生会的管理也亟需制定一个高效、合理的平台,这样才能更快的解决学生的各种信息问题,方便学校对学生进行管理。
    学生会是学校的组织结构之一,学生会也是学校对外的一张小名片。学生会主要是由团委老师和学生组成的用这个沟通学校师生的纽带和桥梁。学生通过申请加入学生会,并接受学生会组织的监督和领导,积极参与学生会举办的各项活动,为非学生会的学生创造良好的课余生活环境和活动。因此,学生会在高校中扮演着非常重要的角色。由于学生会是给予学校而存在的,所以学校的规模越大,学生会的信息也就越大,需要管理的空间也就越多。由于现在处于大数据的时代,所以学校的管理基本都已经步入了数据化的时代。但是笔者通过调查发现,我小的学生会管理仍然处于传统的手工时代,学生会的成员每天需要对信息进行手工整理,检查,没有一个信息化的平台,日常的工作量大,而且效率较低。因此,笔者认为很有必要为学校的学生会管理搭建一个信息化的平台,方便学校的师生对学生会进行管理,以便提高办事的效率,解放多余的劳动力,使得学生会的工作更加轻松快捷。
    关于学生会信息管理的工作包含了很多方面,比如说对新申请加入学生会的成员进行筛选和管理,对学生会成员的职务管理和任务分派,对学生会成员的绩效考核,还有对日常学生会举办活动所产生的费用进行报销审核管理等等工作,在这么多的复杂工作中,如果纯粹依靠手工来解决的化,不仅仅对工作人员来说是一种痛苦的折磨,对于学生会日常活动的开展也是由推迟的影响。而且这种的管理方式很容易出错,进行更改也耗费了大量的人力和时间。在当今时代的要求学,学校的管理都已经步入了信息化的时代,因此为了提高学生会的管理效率,更好更方便的联系全校的师生,特地开发了此系统。
    (二)研究状况目前,虽然各大开源网站上有售卖这一些简单的学生会信息管理系统,但是由于各大高校的组织机构大不相同,关于学生会的组织机构也是存在着很大的差异。因此,要找到一个符合本校的学生会管理的系统仍然是不可能的。而且目前关于学生会信息管理系统的研究基本上是一些开发程度不够,设计不完整的系统。大部分网站上售卖的学生会信息管理系统是基于C/S结构的,不仅增加了客户对系统维护的工作量,而且缺乏系统性,不利于办公。学生会信息管理系统是基于学校管理所研究开发出来的一个系统,要想提高学生会信息管理系统的利用率,就必须按照学校的真实情况进行设计开发,是学生会信息管理系统符合当下学校的管理,为学校的管理提供便利。所以关于学生会信息管理系统的设计要符合学校的管理要求,网络化,数据化。总的来说当今关于学生会信息管理系统的研究与开发还是处于初级阶段,依旧存在着许多还未解决的问题。
    云南大学的硕士研究生周正仁[1]基于中职学校学生会的现状以及市场上系统发展的一些基本状况,使用MyEclipse开发平台、MySQL数据库开发了一套基于中职学校学生会自身特点的学生会管理系统。研究的主要目的是为了方便学生会的管理,是学生会管理更加信息化、智能化。其研究的主要功能包括了财务报销信息、器材租借信息、活动管理信息等。与之相类似的研究还有三明学院的硕士研究生叶超[2]的基于三明学院学生会现状而开发的学生会管理系统。采用UML建模,关于研究学生会的活动费用管理、组织机构管理、活动宣传管理和后台数据管理,也是一套关于学生会信息化管理的系统。厦门大学研究生林菡、陈书林等基于B/S架构研发了一套关于学生会内部成员与团委老师之间的关联系统[3]。厦门大学硕士研究生张红基于MyEclipse平台、Oracle Database 数据库研发了一套关于中职学生会的信息管理系统。该系统包含的功能较多也比较齐全,对学生会的信息进行数据化编制,满足了当今的时代要求,提高了学生会的办事效率[4-10]。
    虽然当前关于学生会信息管理系统的研发程度已经达到较高的水平,但是目前市面上的学生会管理系统主要是基于教师和团委内部成员这两方面的模块。系统的设计并不完善,而且只有部分的学校在使用这类的系统,大多数的学校还是处于人工数据处理学生会信息管理的时代。在当前大数据的时代,软件系统与日常的管理工作是息息相关、密不可分的,尤其是教育组织机构的管理,软件为教育机构的管理带来了极大的方便。当今现存的软件系统并不是针对特定的学校开发的,所以很多的功能方面存在着不足,各大高等学校或教育组织由自己员工设计出的软件或购买软件公司的软件,是没有标准的,很多设计存在兼容性问题[10-15]。
    (三)论文结构
    第一章绪论部分:本章主要分析了研究开发学生会信息管理系统的背景和具体意义
    第二章相关技术:本章主要是讲述了学生会信息管理系统所采用的开发工具,包括前台开发工具和后台数据库的开发工具
    第三需求分析:本章是针对学生会信息管理系统的坑性行进行分析,并且规划需要开发的功能和相关的组织结构,主要是为系统的开发搭建大框架
    第四章系统设计:本章主要讲述的是系统的设计部分,包括系统的总体功能,系统的流程,功能业务流程、后台的数据库等方面的设计,主要是为了方便系统功能的实现
    第五章系统的实现:本章主要是展示了学生会信息管理系统的一些重要模块,如系统相关页面展示和系统相关业务展示
    第六章系统的测试:本章是利用一些常用的测试方法对系统进行测试,并且得出结论
    第七章结论:本章主要是讲述了通过系统的开发和测试的过程中所收获的总结

    二、相关技术(一)JAVA语言Java是在1995年5月被Sun Microsystems公司正式推出的一种关于面向对象程序设计的语言。Java语言的推出吸引力全球与计算机先关的公司的目光。而且,Java语言的出世对整个计算机行业的发展有着重大的影响。和C++语言相通的是Java语言也是关于面向对象程序设计的一门语言。而且,Java语言继承了C语言的一些优点。对于计算机人员来说,这很方面他们的学习和使用。在C语言和C++语言中,他们的语言设计主要是采用指针,但是因为指针容易出现错误,所以在Java语言的开发过程中,开发者就采用了引用来代替指针。与C++的多程序继承不同的是Java语言采用的是接口方式进行的。和其他的语言不通的是java语言是作为一种开源的编程语言。世界各地的诸多java开发公司开发的Java语言都要求具有兼容性,所以Java是靠群体的方式汇编的一种语言。这种方式得到了许多公司和开发商的认同。而且Java编程语言是一门分布式的、健壮的、可移植的、多线程的、面向对象的、高性能语言。因此java语言是一门较为健全的语言[16]。
    (二)JavaEE概述JavaEE也是由Sun Microsystems公司开发的基于企业版的一种体系结构。JavaEE在以前的版本中也叫J2EE,主要是为了帮助企业开发Java服务器端的一种体系结构。Java语言的核心技术平台就是JavaEE技术。JavaEE技术主要是为了满足广大用户的需求开发,其使用成本较低,可靠性强,具有可拓展性,利于广大用户的使用。而且JavaEE海棠果了支持的技术平台,这不仅降低了成本费用,还给程序的统一化运行提供了有利的环境条件。JavaEE技术是目前成长最快的一门技术应用框架,全球有很多公司的研发工具就是基于JavaEE技术开发的,例如国外的SAP系统。因此采用JavaEE体系结构很有利于本系统的研发工作[17]。
    (三)MySQL数据库MySQL数据库是一个开源的数据库,目前市场上的中小型网站都是运用MySQL数据库的。MySQL数据库不仅成本低、便于操作、速度快,而且还是一中开源的数据库。许多的网站开发为了节约经济成本都是使用MySQL数据库的。MySQL数据库有其主要的特性。使用C语言和C++语言进行编译测试时,MySQL数据库的源代码具有可移植性。而且MySQL数据库为多种语言提供了相应的API,比如说Java语言、PHP语言等。除此之外,MySQL数据库还可以存储大量的数据库,记录了成千上万条数据的存储。因此MySQL数据库是目前研发人员最为喜欢的开源数据库[18-22]。
    三、需求分析(一)可行性分析1.技术可行性基于JSP技术开发的系统较为稳定,而且具有良好的升级性、容易开发、方便管理。提高较好的开发环境和全新的语言,不仅方便开发者的使用,更方便系统使用者的操作。JSP技术不需要重复不重要的操作,属于较为简便的语言技术,而且关于和方面的信息资料也比较丰富。数据库服务器采用My SQL数据库,这是当前使用人数较多的数据库服务器,比其他的数据库较为便捷。而且基于B/S没事的WEB数据库技术现在已经是越来越成熟。因为JAVA语言是新型的关于面向对象的开发语言。无论是用哪个平台进行系统的开发,都很便于系统的调试。也不容易出现错误。现在的开发人员也更加愿意使用JAVA语言来进行网络系统的开发与设计。所以本系统的开发技术具有可行性,而且开发的技术人员掌握了一定的开发技术,对于本系统的开发是可以实现的[23]。
    2.操作可行性本系统采用基于B/S的模式下开发完成的,主要是针对Chrome浏览器开发的系统平台。客户可以登录到WEB服务器和数据库服务系,对数据进行访问和操作,而且系统的界面较为简单,操作方便,用户平常只需要通过浏览器登录到系统中就可以进行访问和其他操作。而且本系统具有操作简便、容易管理、交互性好等特点,系统在操作上是非常简单的。因此可以对本系统进行设计开发[24]。
    3.经济可行性本系统的设计是WEB网站设计,采用JSP技术,基于MyEclipse平台和MySQL数据库开发的系统,系统的开发设计较为边间,而且MyEclipse平台和MySQL数据库的使用较为方便。所以系统的开发在人力、物力、财力等方面的要求不高,不仅节省了时间成本,财力方面的需求也不高,具有经济可行性[25]。
    (二)系统功能分析学生会信息管理系统的设计模块主要分为前台登录模块和后台管理模块。

    前台登录模块:用户登录、用户注册、部门介绍、活动信息、加入学生会、论坛信息
    后台管理模块:论坛信息、论坛管理、部门编辑、活动发布、请假管理、报销管理、加入学生会、文件管理、部门成员管理、晚归管理、评优管理等模块
    论坛信息管理:包括添加论坛信息和管理用户发布的信息
    部门编辑管理:添加部门信息和查询部门信息
    活动发布管理:添加活动信息和查询活动信息
    请假管理:添加请假信息和查询请假的详细内容
    报销管理:添加报销信息和审核报销信息
    加入学生会管理:管理员可以查看申请加入学生会的名单
    文件管理:上传文件信息和审核文件信息
    部门成员管理:添加部门成员和查询部门成员
    晚归管理:管理员查晚归人员,还可以对晚归人员的记录名单进行查询
    评优管理:添加评优申请信息、查询评优申请信息、审核评优申请信息

    (三)系统用例分析系统的用例图主要是为了方便外部用户了解系统功能信息的模型图,是关于绘制系统用户和系统功能之间的管理的图例,主要是对系统的相关功能进行建模。下面是本系统管理员用例分析,如图3-1所示:

    四、系统概要设计(一)系统设计系统设计主要是根据用户的需求说明书进行设计分析出相关的逻辑关系和功能需求的一个步骤。这个步骤主要是设计出满足客户相关需求的反感,即在系统中创建物理模型。这个过程的主要任务是设计系统的模块层次结构、模块的流程结构和数据库的表结构,即明确该系统如何去做。这个阶段分为两个大步骤,一是总体设计,即概要设计,其主要任务是解决系统的模块层次结构、模块的划分和数据库表结构设计。二是详细设计,主要任务是解决每个具体模块的详细算法、控制流程和数据库结构设计。本章将从两个部分本系统进行介绍[26]。
    系统架构设计,即总体设计,也就是对系统的全局设计,是设计处理系统的总方案,又称为概要设计。其主要任务是设计系统模块结构及软件功能分解。在一般的总体设计是按照计划任务书来进行大致计算,画出功能结构图并附上必要的文字说明,又称为初步设计,系统架构设计是软件工程中的一个重要阶段。
    (二)系统功能结构图系统设计中的功能实现是衡量一个系统功能强弱的最根本的标准。通过对系统的可行性分析、需求分析、数据分析等调研,结合现实情况的需求,确定了本系统的基本功能模块,如图4-1所示。

    (三)系统处理流程设计1.系统登录流程系统的登录操作主要包括系统的注册、登录、密码修改等基本操作。用户首先要在系统中填写相关的注册信息才可以进行登录。登录到系统后可以修改注册的密码或者个人信息等操作。具体的操作如图4-2所示。

    2.数据增加流程数据信息在添加时,后台会自动生成相关的编号,而且自动生成的编号是不能修改的。用户输入其他的相关信息,数据信息先进行合法判断,如果是合法的数据,就西融入到数据库中保存,否则就需要重新输入数据。数据增加流程图如图4-3所示。

    3.数据修改流程信息修改操作是先选中一条需要修改的信息,进入到页面中对信息进行修改编辑。数据修改流程图如图4-4所示。

    4.数据删除流程信息删除是用户选择需要删除的数据,进入到相关的页面中点击删除按钮,系统会同事用户是否删除该条数据,然后删除数据库中的相关数据,更新页面显示。数据删除流程图如图4-5所示。

    5.数据库查询流程当用户选定一条数据进行查询的时候,在输入框中输入查询信息,点击查询按钮,然后进行查询数据库中的相关内容。数据库查询流程图如图4-6所示。

    (四)系统业务流程设计1.申请加入学生会流程当非学生会的学生创建账户后登陆到学生会信息管理系统是,页面会出现“申请加入学生会”的按钮,点击加入学生会可以触发申请的流程。首先学生要填写申请加入的部门、申请说明和申请日期,接着该流程就会走到学生会成员和团委老师这边,学生会成员主要是负责审核非学生会成员加入到各大部门,团委老师负责审批是否申请加入主席团。如图4-7是非学生会成员进行申请加入学生会。

    2.学生会成员请假申请流程由于学生会的成员是有学生组成的,所以有时候学生会遇到学生会活动与课程起冲突的情况,或者其他特殊情况,这个时候,学生会的内部成员就需要使用到请假申请流程。学生会成员登录到学生会信息管理系统,进入到请假申请页面,填写相关的请假信息。如申请人、请假说明,请假原因等。接着流程会走到团委老师处,团委老师通过审批是否通过该学生的请假申请。如图4-8的流程所示。

    3.财务报销流程学生会举办日常的活动难免会产生相关的费用,这个时候就需要进行活动费用的报销。该财务报销的流程也是针对于学生会内部的成员使用的,学生会内部成员通过财务报销页面,进行填写相关信息,上传报销的发票,提交财务申请,等待审核。财务报销的流程是先到团委老师处进行审核修改申请是否是可以报销的,接着由专门的人员(本系统设定的专门人员为团委学生会办公室的人员)进行整理资料,进行付款。如图4-9所示。

    4.活动流程学生会的活动申请比价复杂,需要先制定活动计划,审核通过后才可以举办活动。具体的活动流程如图4-10所示。

    5.查勤流程学生成员专门负责学校的查勤率,学校会不定期的对上课的班级进行查勤,这个时候有团委老师安排任务,学生会成员完成任务。成员需要到各个班级去查看缺勤的人员,将数据录入到学生会信息管理系统,方便老师进行查看。具体流程如图4-11所示。

    6.学生会成员评优流程学生会的全员都有权利进行评优申请,基本上是每一学期进行一次评优申请,评优申请是按照学生会成员本学期在学生会所做出的贡献大小和学生的绩点为参考依据进行评优评选的。学生需要填写先关的材料,如申请理由、申请时间、申请人绩点等重要信息。学生提交完申请后团委老师会查看各位学生的申请,进行判定。判定结果又专门人员进行收集,并且举办表彰大会。表彰大会由团委老师对优秀的学生会成员进行颁奖。具体的操作流程如图4-12所示。

    7.数据库表结构数据库的数据设计划分为两个部分,一部分是关于数据的插入、更新、删除的存储操作,另一部分是关于数据的查询和数据统计,本系统设计的数据库均是采用SQL标准语句。数据库表结构如下:
    表4-1为论坛信息模块的相关数据库字段信息。
    表4-1:论坛信息模块



    序号
    列名
    数据类型
    长度
    小数位
    标识
    主键
    允许空
    默认值
    说明




    1
    id
    int
    11





    auto_increment


    2
    t_title
    varchar
    20








    3
    t_content
    longtext









    4
    t_date
    varchar
    20








    5
    t_level
    varchar
    20








    6
    t_sync
    varchar
    20








    表4-2为部门信息编辑的相关数据库字段信息。
    表4-2:部门编辑模块



    序号
    列名
    数据类型
    长度
    小数位
    标识
    主键
    允许空
    默认值
    说明




    1
    id
    int
    11





    auto_increment


    2
    t_subject
    varchar
    20








    3
    t_datefrom
    varchar
    20








    4
    t_address
    varchar
    20








    5
    t_zuzhiren
    varchar
    20








    6
    t_content
    longtext
    500








    7
    t_remark
    longtext









    8
    t_bumen
    varchar
    100








    表4-3为活动发布模块的相关数据库字段信息。
    表4-3:活动发布模块



    序号
    列名
    数据类型
    长度
    小数位
    标识
    主键
    允许空
    默认值
    说明




    1
    id
    int
    11





    auto_increment


    2
    t_subject
    varchar
    10








    3
    t_datefrom
    varchar
    20








    4
    t_address
    varchar
    20








    5
    t_zuzhiren
    varchar
    200








    6
    t_content
    longtext









    7
    t_remark
    longtext









    表4-4为请假申请的相关数据库字段信息。
    表4-4:请假申请模块



    序号
    列名
    数据类型
    长度
    小数位
    标识
    主键
    允许空
    默认值
    说明




    1
    id
    int
    11





    auto_increment


    2
    t_title
    varchar
    20








    3
    t_content
    longtext









    4
    t_userid
    varchar
    20








    5
    t_username
    varchar
    200








    6
    t_datetime
    datetime









    表4-5为报销申请的相关数据库字段信息。
    表4-5:报销申请模块



    序号
    列名
    数据类型
    长度
    小数位
    标识
    主键
    允许空
    默认值
    说明




    1
    id
    int
    11





    auto_increment


    2
    t_subject
    varchar
    20








    3
    t_qingjialeibie
    varchar
    200








    4
    t_datefrom
    varchar
    20








    5
    t_dateto
    varchar
    20








    6
    t_totaldays
    varchar
    100








    7
    t_status
    varchar
    100








    8
    t_sendid
    varchar
    20








    9
    t_sendname
    varchar
    10








    10
    t_remark
    longtext









    表4-6为加入学生会申请模块的相关数据库字段信息。
    表4-6:加入学生会申请模块



    序号
    列名
    数据类型
    长度
    小数位
    标识
    主键
    允许空
    默认值
    说明




    1
    id
    int
    11





    auto_increment


    2
    t_sendid
    varchar
    20








    3
    t_sendname
    varchar
    20








    4
    t_datefrom
    varchar
    100








    5
    t_department
    varchar
    100








    6
    t_content
    longtext









    7
    t_status
    varchar
    100








    8
    t_remark
    longtext









    表4-7为文件管理模块对应的相关数据库字段信息。
    表4-7:文件管理模块



    序号
    列名
    数据类型
    长度
    小数位
    标识
    主键
    允许空
    默认值
    说明




    1
    id
    int
    11





    auto_increment


    2
    t_name
    varchar
    200








    3
    t_gender
    varchar
    200








    4
    t_age
    varchar
    200








    5
    t_college
    varchar
    200








    6
    t_bumen
    varchar
    200








    7
    t_telephone
    varchar
    200








    8
    t_email
    varchar
    200








    9
    t_qq
    varchar
    200








    10
    t_address
    varchar
    200








    11
    t_xingquaihao
    varchar
    200








    12
    t_remark
    longtext









    表4-8为部门成员信息管理模块对应的相关数据库字段信息。
    表4-8:部门成员信息模块



    序号
    列名
    数据类型
    长度
    小数位
    标识
    主键
    允许空
    默认值
    说明




    1
    username
    varchar
    25








    2
    password
    varchar
    25








    3
    isLocked
    varchar
    25








    4
    isLogon
    varchar
    25








    5
    lastLoginTime
    datetime









    6
    usertype
    varchar
    20








    7
    accountCreateTime
    datetime









    8
    passErrorTimes
    int
    11








    9
    name
    varchar
    20








    10
    gender
    varchar
    10








    11
    telephone
    varchar
    11








    12
    address
    varchar
    20








    13
    email
    varchar
    20








    14
    qq
    varchar
    11








    15
    age
    int
    11








    16
    flag
    varchar
    20








    17
    college
    varchar
    20








    18
    remark
    varchar
    200








    19
    xingquaihao
    varchar
    20








    20
    file
    varchar
    255








    21
    bumen
    varchar
    25








    表4-9为查勤模块相关数据库字段信息。
    表4-9:查勤模块



    序号
    列名
    数据类型
    长度
    小数位
    标识
    主键
    允许空
    默认值
    说明




    1
    id
    int
    11





    auto_increment


    2
    t_subject
    varchar
    20








    3
    t_datefrom
    varchar
    20








    4
    t_address
    varchar
    20








    5
    t_quexiren
    varchar
    20








    6
    t_qingjiaren
    varchar
    200








    7
    t_userid
    varchar
    10








    8
    t_username
    varchar
    200








    9
    t_remark
    longtext









    表4-10为评优模块先关数据库字段信息。
    表4-10:评优模块



    序号
    列名
    数据类型
    长度
    小数位
    标识
    主键
    允许空
    默认值
    说明




    1
    id
    int
    11





    auto_increment


    2
    t_subject
    varchar
    20








    3
    t_datefrom
    varchar
    20








    4
    t_address
    varchar
    20








    5
    t_quexiren
    varchar
    20








    6
    t_qingjiaren
    varchar
    200








    7
    t_userid
    varchar
    20








    8
    t_username
    varchar
    10








    9
    t_remark
    longtext









    五、系统详细设计前面几章对网站系统整体架构具体的分析,并且对其中的部分功能模块做了概要的设计并对其做了解释。系统采用模块化设计,将系统中实现各种不同功能的代码分离出来,独立为一个模块,在需要时进行调用,使系统的结构更加清晰明了,一目了然。
    (一)页面设计1.首页登录用户可以通过网站首页进行登录。如图5-1所示。

    2.前台注册用户可以通过网站进行注册之后进行登录,然后使用网站功能。如图5-2所示。

    3.申请加入用户可以填写详细的资料选择加入学生会部门。如图5-3所示。

    4.查看学生会部门用户可以查看学生会部门信息、成员信息等基本信息。如图5-4所示。

    (二)系统管理1.系统管理用户打开软件的初始页面,用户输入用户密码后判断用户密码是否正确;如果正确登陆成功跳转到主画面,如果不正确重新输入,并在输入了错误的或者是不存在的账户和密码时,系统会给出出错信息提示,指明登录过程中的错误输入或者错误操作,以便用户进行正确的登录。如图5-5所示。

    2.用户管理用户管理:可以进行新用户的添加、修改以及删除等功能以及用户信息的查看。如图5-6所示。

    3.会议信息管理管理员可以对会议信息进行添加、修改和删除,以及会议信息的查询。如图5-7所示。

    4.部门成员管理管理员可以对部门成员信息进行添加、修改和删除,以及部门成员的查询。如图5-8所示。

    5.学生会成员评优管理学生会成员可以进入到后台系统中,进行评优申请,管理员可以对评优申请进行审核、查询。前台页面如图5-9所示,相关代码如图5-10所示。


    6.报销申请管理学生会成员对举办活动产生的相关费用进行报销,上传报销发票、等待审核。前台页面如图5-11所示,后台相关代码如图5-12所示。


    六、软件测试(一)软件的测试我们知道在完成了一个系统的开发之后,有一个必不可少的步骤就是对已经开发好的系统进行测试。因为未经过测试的系统存在着不稳定性和不确定性,不能够直接就投放到市场中进行使用。所以一个已经设计完成的系统需要经过多次的测试调试才可能顺利的运行。进行软件测试的主要目的是为了保证系统的稳定性,在系统正式使用前尽可能多的发现系统存在的问题,并且提早解决该类问题,在系统正式使用的时候不会因为正式运行的错误,造成客户对系统的不满意。在目前的开发过程中,测试是一个非常重要的环节,它保证了系统的质量,这个是软件规范、设计和编码的最后一个重要的环节。这个环节对系统进行评审,只有评审通过的系统才可以正式上线。也是在大型软件的开发过程中,必须面对的一道程序。软件开发的每一个生命周期都应该确保其准确性,我们需要在每一个阶段结束之前对软件进行测试,要通过严格的技术审核,及时的发现测试过程中遇到的错误并纠正错误。在一般的情况下,系统在测试的时候可以从整体到局部,由此进行划分,将其划分为模块调试和整体调试。在进行模块调试之前要进行全面的调试,就是说必须经过模块调试,才可以进行全面的调试。要根据这种步骤进行具体的系统调试。在相关的系统开发过程中,软件的测试阶段也是必不可少的一个过程,测试的每一步骤都是按照一定的逻辑进行测试的。一般来说,软件的测试步骤分为模块测试、子系统测试、系统测试、验收测试和调试。本论文设计的系统也是严格的按照以上的测试步骤进行测试的。
    (二)设计测试用例基于测试的基本原则,本系统在进行设计测试的时候是采用黑盒技术进行测试的,测试主要是采用划分等价类方案。划分等价类测试又分为合理等价类测试和不合理类等价测试,具体的测试数据如表6-1所示
    表6-1:划分等价类



    输入条件
    合理等价类
    不全理等价类




    用户名
    1、存在的用户名
    2、未被使用的用户名


    查询关键字
    3、匹配的关键字
    4、不匹配的关键字


    登录信息
    5、合法的输入
    6、不合法的输入



    合理类测试的相关用例,如表6-2所示
    表6-2:合理类测试用例



    测试数据
    期望结果
    覆盖范围




    zheng(用户名)
    输入有效
    1


    请假申请信息
    输入有效
    3


    考勤管理
    输入有效
    5


    密码修改
    输入有效
    7



    不合理类测试的相关用例,如表6-3所示
    表6-3:不合理类测试用例



    测试数据
    期望结果
    覆盖范围




    zhang(用户名)
    输入无效
    2


    申请信息为空
    输入无效
    6


    空值
    输入无效
    8



    七、总结在当下的大数据环境中,本片文章所提到的学生会信息管理系统的设计也存在着一些局限性,系统的设计较为简单,但是使用便捷、效率高。通过大学四年所学的知识的整合运用和对系统进行的设计与分析,考量在当下社会环境中设计系统的可行性与需求性,搭建基本的框架结构,设计出符合学校要求的学生会信息管理系统。实现了学生会信息管理的要求。通过设计学生会信息管理系统,增创建学生会管理系统的管理平台和后台的模块数据管理,从而实现了学生会的信息管理,实现了系统的四大基础功能,即增、删、改、查功能,也实现了信息最基础化的录入和收集。在提交论文之前,由于时间的限制以及自已的学习的程度的限制,笔者设计的学生会管理平台还存在着很多功能没能被开发出来。比如说关于提醒学生进行查看学生会发布的活动信息、提醒学生参加学生会的日常会议,团委老师更换管理等模块的设计这些功能。笔者希望在以后的开发设计过程中能够有全面的设计框架,尽可能多的满足到大部分用户的基本需求,收集关于开发此套系统的数据调查,便利此系统进行二次开发,为系统能够更加完善创造有利的条件。
    通过此篇论文,笔者深深的意识到在进行学生会信息系统的规划前,应该先深入了解关于学生会内部的基本信息,要结合实际情况,这样才能设计出更加符合本校学生会信息管理的系统。更能精准的描绘出个部门的职责和日常办公流程,根据实际的情况进行修改和调整系统的总体更能。在设计管理类系统的时候,我们要结合实际的业务情况进行设计,要设计出符合实际业务流程的要求。因此在设计系统之初,我们需要进行市场调研、需求分析、系统的分析和设计、系统设计实施、系统测试和后期的系统功能模板测试等。在完成这些设计之后还要对系统的界面进行美化处理,制定有效的实施方案,设计出符合市场,有价值的系统,并且能够运用到实际的业务系统当中。
    参考文献[1]周正仁.中职学校团委学生会管理系统的研究与分析[D].硕士学位论文.云南大学,2016.
    [2]叶超.三明学院学生会管理信息系统的研究与分析[D].硕士学位论文.云南大学,2016.
    [3]陈书林,林菡,翁玲敏.学生会管理系统的设计与实现[J].软件,2014.04(4):78-79.
    [4]张红.中职学校学生会管理系统的设计与实现[D].硕士学位论文.厦门大学,2015.
    [5]刘亚姝,严寒冰,黄成.Oracle数据库设计与维护[J].软件,2015.03(3):11-12.
    [6]Michael Kofler.MySQL权威指南 [M].(第三版).北京:人民邮电出版社,2016.12.
    [7]张洪伟.Tomcat Web开发及整合应用[M].北京:清华大学出版社,2016.02.
    [8]段朋鹏,郭庆平.基于Struts 和Hibernate 的在线考试系统[J].中国科技论文在线,2016.11(1):21-21.
    [9]王文婷.高校学生事务管理理论与实践探究[J].中国科技论文在线,2018.10(7):95-95.
    [10]王郑霞,肖来胜.基于Struts的电子商务系统的设计与实现[J].电脑知识与技术, 2016.08(1):105-106.
    [11]张震,杨正球.基于整合了Struts 和Hibernate 的J2EE 架构的用户权限管理系统的设计与实现[J].电脑知识与科技,2016.04(2):98-98.
    [12]穆盼盼.试析学生会的组织结构特征:松散联结基础上的牢固联结性[J].内蒙古财经大学学报,2015.10(3):74-77.
    [13]杨燕,李艳会.高职院校学生会的管理及对策研究[J].湖南邮电职业技术学院学报, 2018.05(1):56-56.
    [14]曾伟仁.网络化背景下学生会管理系统的构建[J].网友世界,2014(19):143-143.
    [15]田娟.基于Grails的学生会工作管理系统研究[J].湖南城市学院学报(自然科学版), 2016.12(4):117-118.
    [16]黄艳峰.在Java语言中实施“案例教学”的研究与探索[J].电脑知识与技术,2017. 06(5):1148-1149.
    [17]崔洋.MySQL数据库应用从入门到精通[J].中国铁道,2015.11(01):27-27.
    [18]金百东,刘德山.Java设计模式及应用案例[M].人民邮电出版社,2017.
    [19]张建军,吴启武.Java课程设计案例精编[M].清华大学出版社,2016.5.
    [20]Joshua Bloch,Effective Java[M].United States of America :Prentice Hall PTR,2015.
    [21]刘中兵.开发突击者:Java web 主流框架开发[J].电脑知识与技术,2016.01:80-95.
    [22]贾志城.王云.JSP程序设计[M].人民邮电出版社,2016.03(2):100-120.
    [23]刘晓华,张健,周慧贞.JSP应用开发详解[J].电脑知识与技术,2017.08:205-220.
    [24]锡德霍姆.基于标准的网页设计技巧与实战[J].2014.09(8):100-101.
    [25]焦辰菲,于林静,霍玉慧.学生工作日常管理系统的开发[J].中国科技论文在线,2014.11(2):180-180.
    [26]朱红,张洪亮.教育信息化保障体系研究[J].中国科技论文在线,2015.08:475-477.
    0 评论 1 下载 2019-07-11 22:25:06 下载需要10点积分
  • 基于java的RPG回合制游戏

    一、工作积累总结1.1 简介该项目是一个回合制RPG游戏,讲述了动物主角对抗人类,自逃出动物园开始,一路与人类对抗,提升能力,并寻找新队友组成团体,逼得人类不得不与之谈判,最终与人类达成了和平协议的故事。玩家可以通过全鼠标点击操控来体验游戏。
    1.2 项目特色
    该项目使用Java语言编写,可以在多个不同平台上运行。界面设计简洁明了,操作简单易懂。拥有丰富的关卡,并且可反复挑战,提升能力,使后续关卡变得容易。拥有丰富的随机装备系统,装备种类多,且拥有自“破烂的”到“传说的”等共七种属性前缀,出现的几率逐级降低。装备可以在商店购买,可刷新当前商店货物,或者在挑战地图时随机掉落。拥有丰富的队伍系统,在挑战地图Area 2每个地区的第一关会固定有一个新成员请求加入,之后的关卡此事件随机出现,可以在基地界面通过上阵及休息指令来安排队伍组成。拥有等级系统,通过反复挑战地图来提升等级,提升能力。拥有完整的剧情,故事情节通过地图上每一个关卡名来揭示,按照Area的顺序进行游戏,即可获得全部故事体验。支持存读档功能,可以分多次完成游戏。
    1.3 项目创新全新的RPG回合制游戏,吸取了经典RPG游戏的基本元素:升级打怪打装备,同时配以 角色养成、队伍搭配等玩法,还有丰富完整的剧情体验,非常新颖。
    二、总体需求分析2.1 角色作为一个RPG游戏,首先的需求便是玩家操控的角色,在此游戏中为各种动物,可随着地图探索的推进而逐渐加入。应该使玩家可以选择上阵队形。
    2.2 敌人其次需要与主角作战的敌人,在此游戏中为世界各地的人类,多为伤害动物者。
    2.3 装备为了增加游戏性,还需要装备系统,应分为不同品质,使玩家乐意花时间去刷装备,增加他们的游戏时间。
    2.4 商店对于不愿意靠运气的玩家,准备商店系统,可直接刷新、购买高品质装备。
    2.5 存读档游戏不可能一口气通关,应提供存读档功能。
    三、系统设计3.1 开始界面
    开始:创建新游戏
    载入:读取先前的存档进度
    帮助:各种按钮操作说明
    退出:离开游戏

    3.2 战斗地图界面
    Area 1 三关新手 难度横向增加
    Area 2 分三个地区每个地区五关 横向难度相同竖向逐渐增加 在每个地区的第一关会固定有一个新成员请求加入,之后的关卡此事件随机出现
    Area 3 终章难度横向增加已被征服的关卡名字变为蓝色,可反复挑战

    3.3 战斗界面
    左上为敌人血量左中为敌人图像 左下为战斗进程描述
    右上为玩家角色血量右中为当前等待进行操作的角色图像 右下为可执行操作
    攻击:当前显示图像角色进行攻击,对象为与其顺序相应的敌人,此人倒下后,选择敌人组中第一个不为空血的进行攻击
    治疗:如果在基地购买了急救包,此时可以使用,为当前角色回复部分生命值,但同时敌人会继续攻击使之掉血
    逃跑:迅速离开战斗,回到地图界面,但会被敌人攻击一次

    3.4 当前出战界面显示当前上阵的角色数据最多三个
    3.5 背包界面
    左侧为背包内存放的装备等物品,点击右键可以进行装备、出售、丢弃等操作
    左下为背包现存物品数及最大容量
    右为队伍成员数据信息

    3.6 商店界面
    左侧每次新游戏随机显示不同品质装备

    购买:花费金钱将当前选中物品添加至背包
    刷新当前商品:随机刷新商店物品。

    右侧为队伍成员数据信息

    为它购买:直接为购买选中物品并给当前角色装备
    修理装备:统一增加当前角色所有装备耐久度
    全部卸下:将当前角色所有装备放入背包


    3.7 基地界面
    左侧为成员信息

    上阵:若当前战斗队伍有空位,则该成员加入队伍,出现在战斗中最多三个
    休息:该成员离开战斗队伍,留在基地

    右侧为医疗室

    治疗:全体成员生命值回复满,消耗金钱
    购买急救包:急救包数量加一,可在战斗中使用


    3.8 选项界面
    继续游戏:关闭选项卡,回到游戏
    保存游戏:将当前游戏数据保存至Save文件夹
    读取存档:读取上一次游戏保存的数据

    四、系统实现4.1 程序系统的结构
    4.2 run类
    创建begin,map,data,bag,shop,base 等静态类对象作为各界面容器,便于跳转Screen centre方法:使游戏界面位于正中央Main方法:完善各框架设置,启动游戏进程
    4.3 Beginning 类
    开始界面的各种按钮:开始、载入、帮助、退出BeginLis监听器类:触发以上按钮点击事件,进行界面跳转
    4.4 Map 类
    各种地图按钮:跳转至相应战斗CreArray方法:根据输入参数创建相应战斗力的敌人组MapLis 监听器类:触发以上按钮点击事件,进行界面跳转
    4.5 Fighting 类
    PrintHP方法:在界面上显示敌我双方的血量、等级等信息CheckAlive 方法:开始战斗时计算我方血量不为零的角色数量MyAttack 方法:我方攻击EnAttack 方法:敌方攻击Drop 方法:通过随机数决定本关是否掉落装备及装备品质oPanel 方法:返回一个含战斗操作按钮的JPanelattackLis 监听器:监听战斗操作,攻击、治疗、逃跑等
    4.6 Data 类
    Wargroup 数组:含当前上阵的角色Money 静态变量:当前持有的金钱线程Description:随时刷新当前角色等级属性、装备数据等CreateDes类:创建一个JPanel 能显示角色各种数据
    4.7 Bag 类
    dataBag类:创建背包界面equipAdd方法:向背包中添加装备Popup方法:返回一个PopupMenu,支持右键装备、出售、丢弃功能dataDes 类:创建角色数据界面CreateTab方法:以JTabbedPane的标签方式创建角色数据界面线程Description:随时刷新当前角色等级属性、装备数据等
    4.8 Shop类
    Store类:创建商店界面buy方法:购买、刷新 使用按钮监听器rollE方法:随机刷新装备品质getEquip:得到按钮复选框中选中的装Character类:创建角色面板createTab方法:创建角色标签线程Description:随时刷新当前角色等级属性、装备数据等BuyLis、FixLis监听器:进行购买及修理装备
    4.9 Base类
    createCharacter方法:创建角色面板Go监听器:控制上下阵AddMember方法:向队伍中加入新成员线程Description:随时刷新当前角色等级属性、装备数据等cureKit类:急救包isFullHealth方法:治疗前检测是否为满血cure、buyKit监听器:治疗及购买急救包
    4.10 属性设定类4.10.1 Animals类
    changeEquip方法:改变对象装备,将换下的放入背包enduranceDown方法:根据攻击次数降低装备耐久attack方法:攻击当前敌人对象print方法:输出属性等数据levelUp方法:以获得的经验来判断是否应该升级子类:Land(Tiger、Lion、Bear、Elephant) Sea(Whale) Sky(Eagle)
    4.10.2 Equipment类
    print方法:输出装备数据changeQuality方法:根据随机数决定生成的装备品质子类:Blank AddATK(Teeth、Claws) AddDEF(Helmet、Breastplate、Kneecap)
    4.10.3 Humen类
    attack方法:攻击当前我方对象setName方法:根据地图上不同地区的参数来修改名字,以产生新种类的敌人子类:HumenZoo HumenLand HumenSea HumenSky HumenEnd
    4.11 ActMenu类
    shutdown方法:隐藏当前所有界面,便于根据需要显示ActLis监听器:根据按钮跳转界面opLis监听器:进行存档、读档、继续游戏的操作
    4.12 S_L类
    Save方法:将队伍成员数据、金钱数、商店货物状态、背包物品、地图进度写入文件Load 方法:读取存档
    1 评论 79 下载 2018-10-22 23:45:45 下载需要3点积分
  • WIN32汇编语言实现超过100位的大数相乘

    一、介绍利用汇编语言实现超过100位的大数相乘。
    二、原理同C语言实现方式差不多,利用字符串数组存大数,然后逐位相称。
    三、结果
    0 评论 1 下载 2019-07-11 14:10:28 下载需要10点积分
  • 基于JAVA和SQL SERVER数据库实现的医院病房信息管理系统

    1 系统设计1.1 设计目标医院病房管理系统是一种以窗体界面为基础的多功能平台,本系统最根本的目的是让使用者与数据库能够通过系统达到交互,以此来进行医院病房的管理等相关操作。管理员可以通过该平台对医生、病人、科室、病房、病床进行增加、删除、修改、查询操作,普通用户可以通过该平台查看修改自己的个人信息、进行病人住院登记、查询病人和床位信息、根据病人的住院日期、出院日期和所住病房的收费标准进行出院结算,然后删除该病人的信息。本系统在全面提高医院的整体工作效率、为病人提供快捷的服务、为医生提供人性化的管理、减轻医院工作人员的负担等方面发挥着重要作用。
    1.2 需求分析信息要求:医生基本信息包括工作证号、密码、姓名、性别、职称、年龄、联系电话、所属科室,病人基本信息包括病历号、姓名、性别、诊断结果、病房号、病床号、主治医生工作证号、联系电话、入院日期、出院日期,科室基本信息包括科室名称、科室地址、科室电话,病房基本信息包括病房号、所属科室、收费标准,病床基本信息包括病房号、病床号、目前状态。
    处理要求:一名医生可以诊治多名病人,一名病人只能被一名医生诊治。一个病房可以住多名病人,一名病人只能住在一个病房。一个科室有多名医生,一个医生只属于一个科室。一个科室包含多个病房,一个病房只属于一个科室。一个病房拥有多张病床,一个病床只能位于一个科室。
    安全性与完整性要求:管理员和医生只有输入正确的工作证号和密码才能登录系统,如果还没有注册,先输入相关信息进行注册。对于管理员,管理主页列出了管理员所能实现的功能,包括对医生、病人、科室、病房、病床的增加、删除、修改、查询,管理员根据需要选择对应的项目。对于用户,即医生,管理主页列出了医生所能实现的功能,包括查看修改自己的个人信息、登记病人基本信息、查询病人和床位信息、根据病人的住院日期、出院日期和所住病房的收费标准进行出院结算,然后删除该病人的信息。为了保证系统的安全性,系统提供对工作证号和旧密码的验证,来修改登录密码。
    1.3 开发和运行环境选择
    开发工具:前台开发语言为Java编程语言
    后台数据库为SQL Server 2014
    运行环境:Windows 10

    2 数据库设计2.1 数据库概念设计根据需求分析,可以确定该系统中的实体、属性和联系之间的关系,并画出如下所示的E-R图。
    实体及属性如图2.1所示。

    病人实体及属性如图2.2所示。

    科室实体及属性如图2.3所示。

    病房实体及属性如图2.4所示。

    病床实体及属性如图2.5所示。

    由该项目的处理需求可知,“医生”和“病人”之间的“治疗”联系为1:n,即一名医生可以诊治多名病人,一名病人只能被一名医生诊治。“病房”和“病人”之间的“入住”联系为1:n,即一个病房可以住多名病人,一名病人只能住在一个病房。“科室”和“医生”之间的“属于”联系为1:n,即一个科室有多名医生,一个医生只属于一个科室。“科室”和“病房”之间的“包含”联系为1:n,即一个科室包含多个病房,一个病房只属于一个科室。“病房”和“病床”之间的“拥有”联系为1:n,即一个病房拥有多张病床,一个病床只能位于一个科室。系统的实体联系图,如图2.6所示。

    2.2 数据库逻辑结构设计2.2.1 关系模式根据转换规则和医院病房管理系统E-R图,可以得到医院病房管理系统的关系模式如下。
    医生(工作证号、密码、姓名、性别、职称、年龄、联系电话、所属科室)为医生实体对应的关系模式,其中工作证号是主码,科室的主码科室名称是医生的外码。
    病人(病历号、姓名、性别、诊断结果、病房号、病床号、主治医生工作证号、联系电话、入院日期、出院日期)为病人实体对应的关系模式,其中病历号是主码,医生的主码工作证号是病人的外码属性,病床的主码病房号、病床号是病人的外码属性。
    科室(科室名称、科室地址、科室电话)为科室实体对应的关系模式,其中科室名称是主码。
    病房(病房号、所属科室、收费标准)为病房实体对应的关系模式,其中病房号是主码,科室的主码科室名称是病房的外码。
    病床(病房号、病床号、目前状态)为病床实体对应的关系模式,其中病房号、病床号是主码。
    2.2.2 结构设计表医生结构设计表如表2.1所示。

    病人结构设计表如表2.2所示。

    科室结构设计表如表2.3所示。

    病房结构设计表如表2.4所示。

    病床结构设计表如表2.5所示。

    2.2.3 数据字典数据项描述如表2.3所示。

    数据结构描述如表2.4所示。

    3 医院病房管理系统详细设计3.1 系统功能医院病房管理系统主要分为用户模块和管理员模块(分为医生、病人、科室、病房、病床信息增删改查功能)。其中用户模块包括查看修改自己的个人信息、进行病人住院登记、查询病人和床位信息、根据病人的住院日期、出院日期和所住病房的收费标准进行出院结算,然后删除该病人的信息。管理员模块包括对医生、病人、科室、病房、病床进行增加、删除、修改、查询操作。
    3.2 数据库以及表的建立医院病房管理系统数据库中包含五张表,分别为医生(Doctor)、病人(Patient)、科室(Department)、病房(Ward)、病床(Bed),相关代码如下。
    CREATE TABLE Doctor (Dno CHAR(10) PRIMARY KEY, Dpassword VARCHAR(15) NOT NULL, Dname CHAR(20) NOT NULL, Dsex CHAR(2) NOT NULL, Dtitle CHAR(10) NOT NULL, Dage SMALLINT NOT NULL, Dtel CHAR(11) NOT NULL, Deptname CHAR(20) NOT NULL, FOREIGN KEY(Deptname) REFERENCES Department(Deptname) );CREATE TABLE Department (Deptname CHAR(20) PRIMARY KEY, Deptaddress CHAR(20) NOT NULL, Depttel CHAR(11) NOT NULL );CREATE TABLE Ward (Wno CHAR(9) PRIMARY KEY, Deptname CHAR(20) NOT NULL, Wcharge INT NOT NULL, FOREIGN KEY(Deptname) REFERENCES Department(Deptname) );CREATE TABLE Bed (Wno CHAR(9), Bno CHAR(9), Bstate CHAR(20) , PRIMARY KEY(Wno,Bno), FOREIGN KEY(Wno) REFERENCES Ward(Wno) );CREATE TABLE Patient (Pno CHAR(10) PRIMARY KEY, Pname CHAR(20) NOT NULL, Psex CHAR(2) NOT NULL, Pdiagnose CHAR(20) NOT NULL, Wno CHAR(9) NOT NULL, Bno CHAR(9) NOT NULL, Dno CHAR(10) NOT NULL, Ptel CHAR(11) NOT NULL, Pindate DATE NOT NULL, Poutdate DATE , FOREIGN KEY(Wno,Bno) REFERENCES Bed(Wno,Bno), FOREIGN KEY(Dno) REFERENCES Doctor(Dno) );
    3.3 连接数据库连接数据库的代码及设置和连接操作的相关代码如下。
    package linkdatabase;package linkdatabase;import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;public class linkdatabase { static Connection connection; public linkdatabase(){ //数据库驱动 String driverName="com.microsoft.sqlserver.jdbc.SQLServerDriver"; //连接的数据库 String url="jdbc:sqlserver://localhost:1433;DatabaseName=HWMS"; String user="sa"; String password="yyl13593519418"; //加载JDBC-MySQL数据库驱动 try { Class.forName(driverName); connection = (Connection) DriverManager.getConnection(url,user,password); System.out.println("数据库连接成功"); } catch(Exception e) { e.printStackTrace(); System.out.println("数据库连接失败:"+e.getMessage()); } } public static Connection getConnection(){ new linkdatabase(); return connection; } public void setConnection(Connection connection){ this.connection = connection; } public static void closeAll(ResultSet rs,PreparedStatement ps,Connection con){ if(rs != null){ try{ rs.close(); }catch(SQLException e){ e.printStackTrace(); } } if(ps != null){ try{ ps.close(); }catch(SQLException e) { e.printStackTrace(); } } if(con != null){ try{ con.close(); }catch(SQLException e){ e.printStackTrace(); } } }}
    3.4 登录系统登录系统为进入系统的首要操作,相关代码如下。
    package Hospitallogin;import java.awt.Button;import java.awt.Color;import java.awt.Cursor;import java.awt.Font;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import javax.swing.ImageIcon;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.JTextField;import Doctorfunction.Main;import Hospitaladmin.admin_frame;import Hospitalresponse.Alter;import Hospitalresponse.Register;import geng.handle.HandleLogin;import geng.model.Login;import linkdatabase.linkdatabase;public class LoginFrame extends JFrame implements ActionListener{ String sql; Login login = new Login(); HandleLogin handleLogin = new HandleLogin(); JLabel l1 = new JLabel("欢迎登陆医院病房管理系统"); JLabel l2 = new JLabel("账号:"); JLabel l3 = new JLabel("密码:"); JLabel l4 = new JLabel("账号不存在!"); JLabel l5 = new JLabel("<HTML><U>"+"注册账号"+"</U></HTML>"); JLabel l6 = new JLabel("<HTML><U>"+"修改密码"+"</U></HTML>"); JTextField t1 = new JTextField(); JTextField t2 = new JTextField(); Button b1 = new Button("登陆"); Button b2 = new Button("取消"); public LoginFrame() { // TODO Auto-generated constructor stub //设置标题 super("欢迎登陆医院病房管理系统");//创建标题为欢迎登陆医院病房管理系统的窗口 setBounds(300,100,910,500);//设置窗口在屏幕上的位置及大小 String path = "lib/login.jpeg"; ImageIcon backgroundimage=new ImageIcon(path);//使标签有图片,用此创建背景图片 JLabel jLabel = new JLabel(backgroundimage);//标签为用户提示信息 jLabel.setBounds(0, 0, this.getWidth(), this.getHeight());//标签在窗口上的位置及大小 JPanel jPanel1 = (JPanel) this.getContentPane();//初始化一个内容面板,这样才可以把内容面板设置成透明的 jPanel1下面是我们要添加的图片,上面是我们的组件 jPanel1.setOpaque(false);//使组件不会显示其中的某些像素,允许组件下面的像素显现出来,即设置透明 jPanel1.setLayout(null); this.getLayeredPane().add(jLabel,new Integer(Integer.MIN_VALUE)); setVisible(true); // 登陆界面配置 l1.setBounds(450, 70, 450, 35); l1.setFont(new Font("宋体", Font.BOLD, 30)); l2.setBounds(470, 140, 70, 25); l2.setFont(new Font("宋体",Font.BOLD,23)); l3.setBounds(470, 200, 70, 25); l3.setFont(new Font("宋体",Font.BOLD,23)); l4.setBounds(120, 200, 150, 20); l4.setFont(new Font("宋体",Font.BOLD,23)); l5.setBounds(730,140,70,25); l5.setFont(new Font("微软雅黑",Font.BOLD,15)); l5.setForeground(Color.blue); l5.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); l5.addMouseListener(new Register()); l6.setBounds(730,200,70,25); l6.setFont(new Font("微软雅黑",Font.BOLD,15)); l6.setForeground(Color.blue); l6.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); l6.addMouseListener(new Alter()); t1.setBounds(540, 140, 160, 25); t1.setFont(new Font("宋体",0,18)); t2.setBounds(540, 200, 160, 25); t2.setFont(new Font("宋体",0,18)); b1.setBounds(540, 260, 70, 30); b1.setFont(new Font("宋体",0,15)); b1.addActionListener(this); b2.setBounds(660, 260, 70, 30); b2.setFont(new Font("宋体",0,15)); b2.addActionListener(this); super.add(l1); super.add(l2); super.add(l3); super.add(l5); super.add(l6); super.add(t1); super.add(t2); super.add(b1); super.add(b2); super.setLayout(null); super.setVisible(true); //当单击窗口右上方的关闭图标时,监视器调用windowClosing方法,如果在该方法中使用System.exit(0)退出程序的运行 super.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { // TODO Auto-generated method stub super.windowClosing(e); System.exit(0); } }); super.setResizable(false); } public static void main(String[] args) { // TODO Auto-generated method stub new LoginFrame(); } @Override //事件源触发ActionEvent事件后,监视器调用接口中的此方法对发生的事件做出处理 public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub Object source = e.getSource();//返回添加事件监听的对象 Connection con = null; PreparedStatement ps = null; ResultSet rs = null; if(source == b1) { String name = t1.getText(); String pass = t2.getText(); Login login = new Login(); login.setDno(name); try { con = linkdatabase.getConnection(); if("".equals(name.trim()) || "".equals(pass.trim())) { JOptionPane.showMessageDialog(null, "请输入完整的登陆信息!","系统提示",JOptionPane.ERROR_MESSAGE); }else if(name.equals("admin") && pass.equals("123456")) { new admin_frame(); super.dispose(); }else { login.setDno(name); login.setDpassword(pass); login = handleLogin.queryVerify(login); if(login.getLoginSuccess() == true) { System.out.println("登录成功了!"); new Main(login); super.dispose(); }else { System.out.println("登录失败了!"); JOptionPane.showMessageDialog(null, "登录失败,请重新登录","系统提示",JOptionPane.WARNING_MESSAGE); } } } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); }finally { linkdatabase.closeAll(rs, ps, con); } } if(source == b2) { System.exit(0); } }}
    4 系统测试以及界面4.1 订书单位信息查询测试测试注册账号,界面如图4.1所示。

    注册账号成功,结果如图4.2所示。

    4.2 病人出院结算测试进入病人出院结算界面,点击查询与结算,得出病人出院费用,结果如图4.3所示。

    结算出院成功,结果如图4.4所示。

    5 总结在本次数据库课程设计中,我设计开发了一个小型的医院病房管理系统,实现了对病人的住院登记、出院结算、信息查询,对医生信息、病人信息、科室信息、病房信息、病床信息的增加、删除、修改、查询的功能。设计过程中曾经遇到了不少难点和问题,如:将界面和后台数据库连接起来时出错;对数据库中信息操作时有时忽略了参照完整性;病人出院结算时无法调用数据库中存储的信息;页面间参数传递实现不了;还出现了一个语法错误,对一些控件的属性及方法不熟悉等。对于上述这些难点,我花了很多时间去解决,查阅数据库教材和理论课的课件、并借来相关书籍辅助学习,注意数据库中各个所建表的主外键约束,上网搜索也让我学到很多知识,还有些问题是与同学之间的相互讨论,最终将难点一一克服。
    2 评论 135 下载 2018-11-06 15:43:53 下载需要5点积分
  • 基于C#实现的电影院售票管理系统

    一、引言1.1选题背景随着互联网和电子商务的快速发展,网上购物已经成了现代人生活中很重要的一种方式,如:数码产品、生活用品、化妆品护肤品等,只要是人们需要到的东西,基本都可以在网上购买。除了购买各种物品,现代人的生活也不再向过去一样单调,除了学习和工作之余,人们的娱乐生活也逐渐丰富,最普遍的娱乐休闲方式之一就是到电影院看电影,那么传统的电影订票窗口显然已经不能满足人们的需要了,所以开发一个电影院网上订票系统是非常必要和可行的。以前传统的电影票订票方法是去电影院的购票窗口查看电影的上映时间、场次、可选座位等信息再进行购票,人们往往需要排队才能买到电影票,这样不仅浪费了人们宝贵的时间,而且电影院工作人员的工作量也很大,对于这种低效率、浪费时间的事情,完全可以以网上购票的方式来改变。
    为了提高劳动的效率、节约成本、提高服务质量,我们小组开发了此款系统,用以方便影院的售票和客户的购买,通过这个系统,可以很快的实现会员注册、登录、购票,后台管理员可以新增影片、排片等基本操作。
    二、需求分析2.1 用户需求需要在网上购买电影票的用户可使用本系统,进行会员的注册登陆之后可以进行网上查询电影、购买电影票等操作,省去了去电影院实体窗口排队买票的繁 琐程序。
    2.2 系统功能分析
    新用户的注册、登录,用户数据能存在后台数据库中
    电影的录入、删除、查询、修改
    电影的排片
    管理员查询会员级别等信息
    会员查询影片信息
    会员购买电影票

    2.3 条件与限制系统可以实现一些基本的购票功能,但系统较简单,尚存在很多缺陷,不能实现完善和全面的功能。
    缺陷:

    首先要使用admin进行登录才能开始注册会员
    购票后无法查看购票信息
    不可以支持选座
    购票时不能通过搜索影片名字等来查找影片

    三、模块设计3.1 系统流程图系统流程图如图一所示:

    系统功能图如图二所示:

    3.2 系统使用指南对于用户
    首先,系统使用者先通过admin登录,进入到新用户注册页面,以管理员的身份为用户注册一个新的会员账号,已注册好的账号密码自动保存在后台数据库中,用户下次可以直接使用已注册的会员账号登录本系统进行电影的查询、购票等操作。
    对于管理员
    首先,管理员可以为新用户注册不同级别的会员账号、查看会员的信息。其次,管理员可在系统后台做电影的录入、删除、查询、修改等基本操作,除此之外,添加好影片后可以对电影进行的排片。
    四、数据库设计及实现4.1 系统E-R图E-R图如图三所示:

    4.2 逻辑结构设计(关系数据库设计)
    顾客(Cus、CusCard、CusType、CusTel(key))
    登陆(UserName、UsePwd、UserType)
    电影(Mname(key)、MBZ、MLanguage、MTYPE、MDirector、MACT、MTime)
    排片(MName(key)、MPrice、MRoom、Mcount、MTime、MBRQ、MERQ)
    上映(ID(key)、MName、MPrice、MRoom、MCount、MTime、MRQ)
    购票(PID(key)、Cname、GPCount、GPJE、MName、SYRQ、FYT、GPRQ、CZY)

    4.3 数据库主要代码及触发器会员信息
    CREATE TABLE [dbo].[Cus]( [CusTel] VARCHAR(50) NOT NULL PRIMARY KEY, [CusName] VARCHAR(50) NOT NULL, [CusCard] VARCHAR(50) NULL, [CusType] VARCHAR(50) NULL)
    触发器
    SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER TRIGGER [dbo].[InsertULogin] on [dbo].[Cus]after insertasdeclare @username varchar(50)declare @userpwd varchar(50)select @username=CusTel from inserted select @userpwd= right(CusCard,6) from inserted insert into ULogin values(@username,@userpwd,'C')
    购票信息
    CREATE TABLE [dbo].[GP]( [PID] VARCHAR(50) NOT NULL PRIMARY KEY, [CName] VARCHAR(50) NOT NULL, [GPCount] INT NULL, [GPJE] FLOAT NULL, [MName] VARCHAR(50) NULL, [SYRQ] VARCHAR(50) NULL, [GPRQ] VARCHAR(50) NULL, [CZY] VARCHAR(50) NULL, [FYT] VARCHAR(50) NULL)
    触发器
    SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER TRIGGER [dbo].[UpdatePP] on [dbo].[GP]after insertasdeclare @MName varchar(50)declare @SYRQ varchar(50)declare @count intselect @MName= MName,@SYRQ=SYRQ,@count=GPCount from inserted update MovieSY set mcount=mcount-@count where MName=@MName and MRQ=@SYRQ
    电影信息
    CREATE TABLE [dbo].[Movie]( [MName] VARCHAR(50) NOT NULL PRIMARY KEY, [MLanguage] VARCHAR(50) NOT NULL, [MDirector] VARCHAR(50) NULL, [MAct] VARCHAR(50) NULL, [MName] INT NULL, [MBZ] VARCHAR(255) NULL, [MType] VARCHAR(50) NULL)
    上映信息
    CREATE TABLE [dbo].[MovieSY]( [ID] INT NOT NULL PRIMARY KEY, [MName] VARCHAR(50) NOT NULL, [MRoom] INT NULL, [MCount] varchar(50) NULL, [MName] INT NULL, [MTime] VARCHAR(50) NULL, [MRQ] VARCHAR(50) NULL)
    排片信息
    CREATE TABLE [dbo].[PP]( [MName] VARCHAR(50) NOT NULL PRIMARY KEY, [MPrice] INT NOT NULL, [MRoom] VARCHAR(50) NULL, [MCount] INT NULL, [MTime] VARCHAR(50) NULL, [MBRQ] VARCHAR(50) NULL, [MERQ] VARCHAR(50) NULL)
    触发器
    SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER TRIGGER [dbo].[InsertPP] on [dbo].[PP]after insertasdeclare @MName varchar(50)declare @BRQ varchar(50)declare @ERQ varchar(50)declare @MTime varchar(50)declare @MRoom varchar(50)declare @MPrice intdeclare @MCount intdeclare @MBRQ datetimedeclare @MERQ datetimedeclare @RQ varchar(50)select @MName= MName,@BRQ=MBRQ,@ERQ=MERQ,@MTime=MTime,@MRoom=MRoom,@MPrice=MPrice, @MCount=MCount from inserted set @MBRQ=CONVERT (datetime,@BRQ)set @MERQ=CONVERT (datetime,@ERQ)while @MBRQ<=@MERQbegin set @rq=CONVERT(varchar(50), @MBRQ, 112)insert into MovieSY values(@MName,@MPrice,@MRoom,@MCount,@MTime,@RQ) set @MBRQ=DATEADD(DAY,1,@MBRQ)endCREATE TABLE [dbo].[MovieSY]( [UserName] VARCHAR(50) NOT NULL PRIMARY KEY, [UserPwd] VARCHAR(50) NOT NULL, [UserType] VARCHAR(50) NULL)
    五、系统设计与实现5.1系统开发环境
    硬件环境

    Intel Pentium 166MHz或以上;内存:需要至少512MHZ;
    软件环境

    运行于Windows2010版的操作系统之上;SQL Server2008数据库;Visual Studio2013;

    5.2 功能模块
    输入功能模块
    查询显示功能模块
    查询、售票功能模块
    登录、注册功能模块

    5.3 系统主要页面展示登录、注册页面

    登陆后的页面

    会员注册页面

    会员信息查询页面

    添加影片页面

    查询修改影片页面

    排片页面

    “排片”页面通过连接数据库,可以搜索影片的名字、导演、主演来选择影片,再输入票价,放映大厅,座位数,放映时间等信息,最后确认排片。
    购票页面

    购票页面通过对获得的已经被排片的电影进行选择而进行购票这一操作。在购票前需填入购票数量、联系电话,系统会自动计算合计金额。之后点击购票按钮则能进行购票操作。但一旦购票成功则不能进行退票操作,也不能查看所购买的电影票。
    数据库页面

    六、主要特色6.1 系统实用性系统首先可以进行新用户的注册,用户数据能存在后台数据库中。管理员可以进行电影的录入、删除、查询、修改,添加好影片后进行电影的排片。退出登录后再使用之前注册的会员登录,可以购买电影票。
    6.2 突出优势和特色(创新点)
    购票时可以看到影片的导演、主演等信息
    用户分为钻石用户,白金用户和普通用户,对用户进行了分类

    7 小结数据库技术课程设计是一次对课堂所学知识的灵活应用,是理论知识与实践的相结合。经过了一周的课程设计,本系统基本达到了当初的设计要求,设计上也基本合理。我们不仅对数据库系统的认识更加深入,同时也掌握了面向实体的系统分析的基本方法,对VS也有了新的认识,也知道了要有坚持不懈,不惧困难的精神,才能取得成功。一个简单的系统,每一个细节都需要在实践中去挖掘并进行进一步的修改完善。本次课设让我们受益匪浅,在分析问题以及解决问题等方面的能力有所提高,也是一次很好的同学之间交流合作的机会。数据库技术的用途很广,还有很多值得我们学习,希望今后能有更多这样的机会。
    6 评论 63 下载 2019-01-01 18:20:12 下载需要18点积分
  • 基于java的学生考试成绩分析程序

    一.系统分析本次试验需要编写一个学生考试成绩分析程序,至少具有这些功能:基本数据输入,能够建立并且输入班级、学生、课程和成绩单的信息,指定特定的班级和课程后,能够输出该班的所有学生的成绩,通过这个方法可以查询学生的成绩,能够对指定的班级和课程的成绩进行以下3种方法的分析,分数文本分析、分数段分析、图形分析。
    对于以上的问题,程序要提供界面,要满足输入输出就要用到GUI的输入输出功能,保存数据就用到文件输入输出,文件保存等功能。
    二.系统设计程序UML图:



    三.系统实现登陆界面:输入用户名和密码,为了方便测试,先设定了一个正确的账号密码。
    初始界面:选择各功能的按键,在不同情况下有不同的图片,作出个个性化的按键的效果。所有的操作界面都在当前的窗口进行,每个功能都是一个JPanel模块。
    学生、班级、课程和成绩单的录入:初始化界面后,先检查录入的数据格式是否正确,是否已经存在,如果之前不存在就先new出个新的变量,再做添加处理,部分要先判断是否重复,并作出相应的提示。当所有条件符合就保存进相应的文档中。
    学生、班级、课程查询:输入相应的信息后,就能查询相关信息,查询到的信息不能随意修改,设为不可键入,初始话reset后要清空所有表格,初始化时有数据是为了方便测试。
    学生成绩分析:做表格不会,用了最简单的文本显示,和基本的图形界面绘图,参照教材做的。首先通过学生的名字和学号在成绩单中找到相应的考试成绩,通过用户的条件进行遍历,找到符合要求的所有学生输出,根据选择的模式输出不同的分析情况。
    四.系统测试程序运行结果及过程截图
    4.1 登录界面
    4.2 初始化界面
    4.3 增加信息



    4.4 查询信息
    4.5 成绩分析


    五.实验总结这次的综合性试验,综合运用面向对象程序设计的设计的思想和方法,采用Java语言编写一个学生考试成绩分析程序,难度适中,对加深面向对象程序设计的认识很有帮助。
    通过这次试验,我对面向对象有了更深入的理解。这次的实验要求虽然都是比较简单的东西,但是合在一起对我这个初学者来说就不是那么简单了,基本的输入输出、图形界面的应用、数据的保存与读取等,都让我绞尽脑汁,多方面寻找帮助。界面方面由于之前做个一个小游戏,这方面就显得比较熟悉,但是数据的存储和读取就比较有难度,因为是初次用java写,于是用了比较原始的方法,通过和同学交流还知道了其他多种方法。由于水平和时间有限,所以做的质量没有想象中的好,这个小程序仍然存在许多方面的不足,需要继续改进。比如界面不够人性化,有些地方可以更加方便用户的使用,比如候选菜单管理,提前显示有哪些班级学生,可以方便用户输入。另外一方面,界面不够统一,后期时间关系就没注意太多细节问题了,图标也可以做得更加好的,更加让人一目了然知道大概功能,提示语句可以和按键合并而不会出现用户一来就点文字而没有反应这个问题。由于程序比较大,到后期就开始复杂了,从中认识到了自己很多的不足,由于一开始没有考虑好,后面出问题导致大部分内容要重做,这是比较痛苦的教训,告诫自己以后做复杂的事前,要做好规划,才不致于导致手忙脚乱。
    这过程中学到了很多,很开心也很纠结,当程序写好后,还是很有成就感的。
    0 评论 3 下载 2019-07-10 11:30:35 下载需要6点积分
  • 基于深度学习的手写数字识别算法Python实现

    摘 要深度学习是传统机器学习下的一个分支,得益于近些年来计算机硬件计算能力质的飞跃,使得深度学习成为了当下热门之一。手写数字识别更是深度学习入门的经典案例,学习和理解其背后的原理对于深度学习的理解有很重要的作用。
    本文将采用深度学习中的卷积神经网络来训练手写数字识别模型。使用卷积神经网络建立合理的模型结构,利用卷积层中设定一定数目的卷积核(即滤波器),通过训练数据使模型学习到能够反映出十个不同手写提数字特征的卷积核权值,最后通过全连接层使用softmax函数给出预测数字图对应每种数字可能性的概率多少。
    本文以学习基于深度学习的手写数字识别算法的过程为线索,由简入深,从最基础的感知器到卷积神经网络,学习和理解深度学习的相关基本概念、模型建立以及训练过程。在实现典型LeNet-5网络结构的同时,通过更改超模型结构、超参数进一步探索这些改变对模型准确率的影响。最后通过使用深度学习框架Keras以MNIST作为训练数据集训练出高识别率的模型并将其与OpenCV技术结合应用到摄像头上实现实时识别数字,使用合理的模型结构,在测试集上识别准确率达到99%以上,在与摄像头结合实际应用中的识别效果达到90%以上。
    关键词:深度学习,卷积神经网络,MNIST,OpenCV
    ABSTRACTDepth learning is a branch of traditional machine learning, thanks to the recent years, computer hardware computing power of the quality of the leap, making the depth of learning has become one of the popular. Handwritten digital recognition is the classic case of advanced learning, learning and understanding the principles behind the depth of learning for the understanding of a very important role.
    In this paper, the convolution neural network in depth learning will be used to train the handwritten numeral recognition model. The convolution neural network is used to establish a reasonable model structure. A certain number of convolution cores (ie, filters) are set in the convolution layer. The training data are used to study the convolution of the model to reflect ten different handwritten digital features Kernel weight, and finally through the full connection layer using soft max function gives the predicted digital map corresponding to the probability of each number of the probability of how much.
    In this paper, we study the basic concepts, model establishment and training process of the depth learning based on the process of learning the handwritten numeral recognition algorithm based on the depth learning. The basic concepts, the model establishment and the training process are studied and understood from the most basic sensor to the convolution neural network. In the realization of the typical LeNet-5 network structure at the same time, by changing the super-model structure, super-parameters to further explore the impact of these changes on the model accuracy. Finally, by using the depth learning framework Keras to MNIST as a training data set to train a high recognition rate model and combine it with OpenCV technology to apply real-time identification numbers to the camera,using a reasonable model structure, the recognition accuracy is achieved on the test set More than 99%, with the camera in the practical application of the recognition effect of more than 90%.
    Key words: deep Learning, convolution neural network, MNIST, OpenCV
    1 绪论1.1 数字识别研究现状早期的研究人员在数字识别[1]这一方向已经取得了不错的成果,如使用K-邻近分类方法,SVM分类方法,Boosting分类方法等。但这些方法多少都会有不足之处,例如K-邻近方法在预测时需要将所有的训练数据集加载至内存,然后用待测数字图片与训练集作对应像素点差的和,最后得出的差值最小的则为预测结果。显然这样的方法在正常的图片准确度上并不可靠,对于待测手写数字的要求也很高。目前识别率最好的模型应该还属基于深度学习的CNN,最典型的例子LeNet-5,美国最早将其商用到识别银行支票上得手写数字[2]。可见基于深度学习的手写数字识别在准确率上是相当可靠。
    1.2 深度学习的发展与现状机器学习[3]发展大致分为两个阶段,起源于浅层学习,发展于深度学习,深度学习是机器学习的一个重要分支。
    在20世纪80年代末期,反向传播算法的应用给机器学习带来了希望的同时也掀起了基于统计模型的机器学习热潮。通过实践,人们成功发现利用反向传播算法可以使一个人工神经网络模型在大量有标签训练样本中学习统计一定的规律,在此之上进而对无标签事物进行预测。该阶段的的网络模型因为只含有一层隐含层的缘故被称之为浅层模型,浅层模型在参数个数、计算单元以及特征表达上有一定瓶颈。90年代,学术界相继提出各种各样的浅层学习模型,如支持向量机(SVM,supportVector Machine)、Boosting、最大熵方法等。这些模型相比当时的神经网络模型不论是在效率上还是在准确率上都有一定提升[4]。
    直到2006年,加拿大多伦多大学教授、机器学习领域泰斗Geoffrey Hinton和他的学生在Ruslan Salakhutdinov在《科学》上发表的一篇关于“deep learning”的综述文章,正式开启了深度学习的浪潮[5]。深度学习火 起来的标志事件是2012年Geoff Hinton的博士生Alex Krizhevsky、Ilya Sutskever使用深度学习在图片分类的竞赛ImageNet上取得了识别结果第一名的好成绩,并且在识别精度上领先于同样使用深度学习进行识别的Google团队。这里的谷歌团队不是一般的团队,而是由机器学习领域的领跑者Andrew Ng和Google神人 Jeff Dean带领下有着他人团队无法企及的硬件资源和数据资源支持的团队,而打败这个顶级团队的仅仅是两个研究深度学习不久的“小毛孩”,这令学术界和工业届哗然的同时,也吸引了工业界对深度学习的大规模投入。Google收购了Hinton的DNN初创公司,并邀请Hinton加入了Google;LeCun加盟Facebook并出任AI实验室主任;百度成立了自己的深度学习研究所,并邀请到了原负责Google Brain的吴恩达。深度学习发展之快令人吃惊,在2016年初谷歌建立的AlphaGo系统在与围棋世界冠军李世石的对弈中,最终AlphaGo以4:1的大比分应得了比赛的胜利。可以看出,人工智能的第三波浪潮也是和深度学习密不可分的。深度学习里最经典的模型是全连接的神经网络、卷积神经网络CNN以及循环神经网络RNN。还有一个非常重要的技术就是深度强化学习技术,而AlphaGo所采用的就是该技术。
    深度学习的成功归功于三大因素——大数据、大模型、大计算。同时这个三个方向也是当前研究的热点。受益于计算能力的提升和大数据的出现,深度学习在现在的条件下可以将模型层次加深到上亿神经元的计算量的等级。GPU对深度学习计算的支持也放低了进行深度学习研究的门槛,使更多的初学研究人员可以踏足这个领域,为这个领域不断注入新鲜血液,不断提出新的思考,开阔新的应用方向。
    深度学习的本质是通过构建多层隐藏层的机器学习模型和大量的训练数据,在训练中不断调整参数以寻找能反应数据集特点的特征,从而提升类似数据的分类或预测准确性。“深度模型”是手段,而“特征学习”是目的。有别于传统的浅层学习,深度学习强调了模型除输入输出层外的隐藏层数量,通常有大于2层以上的隐藏节点。除此之外深度学习突出了特征学习的重要性,通过逐层特征变换,将样本在原空间的特征表示变换到一个新特征空间,从而使分类或预测更加容易。
    深度学习算法中重要的算法之一就是卷积神经网络算法,目前主要应用在图像分类、图像分割、目标检测等相关计算机视觉领域。上文中提及到的2012年取得图片分类的竞赛ImageNet冠军的团队就是使用改进后的卷积神经网络,使得识别准确率达到了质的飞跃。
    1.3 研究意义数字识别已经应用到了生活中的点滴,如停车场停车按车牌号计费,交通电子眼抓拍违章,大规模数据统计,文件电子化存储等。
    阿拉伯数字作为一种全球通用的符号,跨越了国家、文化以及民族的界限,在我们的身边应用非常广泛。数字的类别数目适当,仅有10类,方便对研究方法进行评估和测试。通过研究基于深度学习的手写数字识别方法有助于对深度学习的理解,具有很大的理论实践价值。手写数字识别的方法经验还可以推广应用到其它字符识别问题上,如英文字母的识别。
    本文设计将训练好的卷积神经网络模型与摄像头相结合,实现对摄像头画面中出现的数字实时识别。
    1.4 论文结构在本文基于深度学习的手写数字识别算法实现中,第一章主要对数字识别的研究现状、深度学习的发展与现状及本文的研究意义作以介绍;第二章内容为本文数字识别核心技术卷积神经网络的基本原理;第三章内容为本文采用的深度学习框架Keras相关使用;第四章内容为本文在经典LeNet5结构的基础上进行单一变量改动,以探究不同因素对模型识别率的影响,总结调参经验;第五章内容为对训练好的手写数字识别模型的实际应用,包含了图像处理和数字图像识别两部分。
    2 卷积神经网络基本原理本文采用深度学习中的卷积神经网络实现对手写数字的识别,卷积神经网络是被设计用来处理多维组数据的,如常见的彩色图像就是三个颜色通道组合。手写数字图片是典型的2D型图像数据,使用卷积神经网络可以有效通过训练提取去手写提数字的特征,本章对卷积神经网络的基本原理作以分析。
    2.1 卷积神经网络2.1.1 卷积神经网络概述卷积神经网络(CNN),是人工神经网络的一种。它是一种特殊的对图像识别的方式,属于非常有效的带有前向反馈的网络。
    常规的神经网络不能很好地适应所有的图像,例如在CIFAR-10的训练集中,图片的大小只有32*32*3(32宽32高3颜色通道),那么通过输入层后的第一个隐藏层的神经元将达到3072个。看似可以接受的数字,当隐藏层由一层上升到两层三层甚至更多时,后面隐藏层每一个神经元全连接权值与输入积的加和计算量将膨胀到无法想象。与此同时,除了效率的低下外,大量的参数还会导致过拟合的发生。与常规神经网络不同,卷积神经网络的各层中的神经元是3维排列的:宽度、高度和深度(此处的深度不是网络结构的层数),是一种立体结构。在卷积网络最后的输出层里,会把三维结构的数据转换为在深度方向的一维分类值。
    卷积神经网络诞生的主要目的是为了识别二维图形,它的网络结构对平移、比例缩放、倾斜或其他形式的变形具有高度不变性。卷积神经网络是近些年来发展迅速,备受器重的一种高效识别算法。它的应用范围也不仅仅局限于图像识别领域,也应用到了人脸识别、文字识别等方向。
    2.1.2 卷积神经网络的重要组成部分1.卷积层
    卷积神经网络的核心是卷积层,它产生了网络中大部分的计算。卷积层里最重要的组成就是卷积核。卷积核也可以理解为是一些滤波器集合。每个卷积核在空间上的尺寸都比较小,但是深度和输入数据是一致的。卷积核的大小是个超参数,可以自行选择。卷积核的内容,相当于上一节中全连接神经网络中药更新的权值w,即卷积核就是我们训练卷积神经网络要学习的东西。训练的过程实际上是在寻找能够反映训练数据特征的滤波器。以下图2-1为例,左边的是卷积层的输入image,中间的为卷积核(filter),右边的为卷积后产生的特征图谱(feature map)。卷积层卷积的过程是如图所示从输入的左上角开始,按照卷积核的大小3 3的方框括起相应的元素,与卷积核元素对应位置的元素作积后加和得到特征图谱的第一个元素。方框按一定步幅从左向右从上到下,依次完成卷积,即可得到特征图谱所有的内容。

    2.子采样层
    子采样层也称作池化层在有些文献中也称之为下采样层,在卷积层之间加入子采样层,可以有效减少输入网络中的数据大小,减小规模,控制网络中参数的数量,进而节约计算资源,减少训练所需时间。同时,采样层还能够有效地控制过拟合的出现。最常用的采样方式有两种,一种是Max Pooling,另外一种是Mean Pooling。Max Pooling 是指在算选定的N N尺寸中保留最大的那个作为采样后得样本值。Mean Pooling 是指在算选定的N N尺寸中取样本的平局值作为采样值。研究人员通过不断试验发现,使用MaxPooling的效果好于Mean Pooling,图2-2为2 * 2 大小的Max Pooling采样过程示意。

    2.1.3 权值共享和局部连接权值共享:图像的一部分的统计特性与其他部分是一样的。这也意味着在这一部分学习的特征也能用在另一部分上,所以对于这个图像上的所有位置,都能使用同样的学习特征。
    局部连接:在处理图像这样的高维度输入时,让每个神经元都与前一层中的所有神经元进行全连接是不现实的。相反,让每个神经元只与输入数据的一个局部区域连接。该连接的空间大小叫做神经元的感受野(receptive field),它的尺寸是一个超参数(其实就是滤波器的空间尺寸)。在深度方向上,这个连接的大小总是和输入量的深度相等。需要再次强调的是,对待空间维度(宽和高)与深度维度是不同的:连接在空间(宽高)上是局部的,但是在深度上总是和输入数据的深度一致。
    2.2 神经网络的前向传播和反向传播所有神经网络在训练过程中都存在这两个过程,向前传播计算节点输出,反向传播更新连接权值。
    2.2.1 神经元神经元是组成神经网络的基本单位,如图2-3所示,神经元和感知器在结构上是基本相似的,同样的它们在激活函数上得不同,决定了其输出结果的不同。对于神经元来说,激活函数一般选择为sigmoid函数或者tanh函数或者REUL函数。传统的神经网络激活函数一般选择sigmoid函数或者双曲正切函数 。函数图像如图2-4所示。

    可以看到sigmoid函数的导数可以用sigmoid函数自身来表示。方便计算,这也解释了早期的神经网络会选择sigmoid函数作为激活函数的原因,这是对于早期计算资源的一种妥协。
    2.2.2 神经网络的连接形式神经网络就是多个神经元按一定规则连接在一起。图2-5是一个简单的全连接神经网络。最左边的层叫做输入层,负责接收输入数据;最右边的层叫输出层,可以从这层获取神经网络输出数据;输入层和输出层之间的层叫做隐藏层,因为它们对于外部来说是不可见的。通过上图可以观察到,神经网络一般有以下结构规则:

    同一层的神经元之间没有连接。
    第N层的每个神经元和第N-1层的所有神经元相连(这就是full connected的含义),第N-1层神经元的输出就是第N层神经元的输入。
    每个连接都有一个权值。


    上面这些规则定义了全连接神经网络的结构。事实上还存在很多其它结构的神经网络,比如卷积神经网络(CNN)、循环神经网络(RNN),他们都具有不同的连接规则。
    2.2.3 神经网络的前向传播神经网络的前向传播中,每一层的输入依赖于前一层的输出和两层两层之间连接的权值,如图2-6所示连接的箭头指向为前向传播方向。

    在图2-7中标出以数字1、2、3……对神经元进行编号,输入用x表示,输出用y表示,每条连接的权重用w表示,隐藏层的神经元输出用a表示。前向传播中,要计算当前层的节点输出必须得到前一层的输出,即前层的输出是后层的输入。以激活函数sigmoid为例,由输入层神经元1、2、3获取输入x1, x2, x3仍旧输出x1, x2, x3。如计算a4节点的输出a4=sigmoid(w41X1 + w42X2 + ws3X3 + w4b)中w4b是节点a4的偏置项。同理可以得a5, a6, a7的输出值,得到了隐藏层所有节点的输出值后可以得到最后输出层的输出值,如y1=sigmoid(w84a4 + w85a5 + w86a6 + w87a7 + w8b)。卷积神经网络所采用的前向传播方式与之相似,卷积层与其它层之间的权值在传播过程中改为卷积层的卷积核权值。
    2.2.4 神经网络的反向传播算法神经网络的反向传播是对网络层之间权值得更新过程,层与层之间的权值更新依赖于后一层的输出,反向传播的名字也由此而来。如图2-7所示,反向传播是有输出层向输入层的计算过程。

    反向传播的计算方法以图2-7为例,在上一小节的基础上按序号标注出对应节点的误差项。反向传播算法,字如其名从反方向开始计算,对权值进行更新。在上一节中已经计算了全连接网络的每个节点的输出。这一节从输出层开始,依次计算输出层、和隐藏层每一节点的误差项。输出节点误差项

    i对应相应的节点标号,t表示目标值,y表示节点实际输出值。
    隐藏节点误差项

    其中wki是节点i到下一层节点k的连接权重。权重值得更新依赖于当前节点的输出和下一层对应节点的误差项
    反向传播算法的本质是对链式求导法则的应用,上述的例子中sigmoid函数的求导可以用函数结果本身表示。
    2.3 优化方法——梯度下降梯度下降的方法是目前训练神经网络最常用的一种更新权值的计算方法,其巧妙应用了数学上利用导数求最值的概念。梯度下降具体细分为三种,批梯度下降、随机梯度下降、小批量梯度下降,本节以线性单元为例介绍梯度下降的计算过程。
    线性单元结构如图2-8所示与感知器相比较,替换了激活函数,线性单元将返回一个实数值而不是0,1分类,因此线性单元可以用来解决回归问题,而非分类问题。

    2.3.1 批梯度下降以线性单元为例,设置激活函数为f(x)=x,和感知器的输出结果相似的,因为激活函数得到什么值输出什么值,所以其输出为y=h(x)=w.x+b其中w0仍旧等于b。
    在数学上可以用两个数的方差来表示其相差程度的大小,在这里使用 来训练数据表示通过激活函数后的输出值,用 来表示训练数据所对应的真实标签值,则有:

    把e称作单个样本误差,这里的1/2是用来消除求导后系数2的,并不影响最终结果。当有N个训练数据时,用所有样本的误差和来表示模型的误差E,即

    将上式2代入式3中结合输出函数y化简后得

    此时E(w)称之为目标函数,此函数是关于w的多元二次式。在数学上,我们要求一个函数f(x)的极值点,是对该函数进行求导,当f‘(x)=0时,求得极值点(x0,y0)。对于计算机来说,它可以凭借超强的数据计算能力,通过一次一次怎加或减少x的值把函数的极值点试出来。
    如图2-9所示,随机选取一个点x0,每次迭代更新为x1, x2, x3, …直到找到极小值点。这里要引入梯度的概念,梯度是指向函数值上升最快方向的一个向量。那么我们对梯度取反方向,就能找到函数值下降最快的方向。

    由此得出梯度下降算法的公式

    对于目标函数E(w)来说则为

    最后得

    根据上式来更新w,每次要遍历训练数据中的所有样本进行计算,这种算法叫做批梯度下降。批梯度下降的不足之处在于面对数据量巨大的样本时,由于每次更新都学要遍历所有样本数据,纵使现在的计算机有再强大的计算能力,这也将使得因为计算量异常庞大,而让训练花费更多时间。虽然卷积神经网络的结构特点可以有效降低计算量,但从硬件性能上的限制考虑,本文不采用批梯度下降的方式对权值进行优化。
    2.3.2 随机梯度下降对于精度要求不高的的模型来说,可以使用随机梯度下降,随机梯度下降每次更新w值时只计算一个样本,由于样本的噪音和随机性,并不能保证每一次都是沿着下降的方向更新,但是总体看上去是沿着下降的方向更新的,最后收敛到最小值的附近。随机梯度下降大大提升了训练大规模样本数据的效率。尽管随机梯度下降可以大幅提高模型训练效率,但其波动较大,在有限迭代次数内不能得到稳定的训练结果,故本文不采用该方法对权值进行更新。
    2.3.3 小批量梯度下降随机梯度下在迭代的过程中并不是每次都朝着整体优化的方向,在迭代开始的时候可以很快收敛,但是训练一段时间后收敛会变得很慢。小批量梯度下降结合了批梯度下降和随机梯度下降的优点,使算法的训练过程在提高速度的同时,也保证了最终参数的准确率。本文采用小批量梯度下降的方法对权值进行更新,通过设置合理的批量大小和迭代次数能够在短时间内使模型快速得到优化。
    2.4 小结本章从卷积神经网络的组成结构、模型权值共享和局部连接的特点、网络的前向反向传播过程、以及模型的优化方法等基本原理作以分析。在后续的章节里,将理论应用于实践。
    3 Keras深度学习框架Keras使用简单易上手,只要有Python编程经验即可快速将理论付诸于实现。本文使用深度学习Keras来实现LeNet5的经典模型结构,并在实现经典结构的基础上改变参数,探究不同参数对模型训练的影响,本章对Keras的使用和配置作以介绍。
    3.1 Keras简介Keras是一个有Python编写而成以TensorFlow或Theano 作为后台的深度学习框架。当前作为深度学习框架对于GPU运算的支持是必不可少的,Keras同时支持CPU和GPU。Keras在linux下安装起来非常方便,不像caffe那样需要各种各样的支持库,有一点问题就得重新编译安装。Keras对用户的使用体验支持的相当好,它高度模块化的同时还具有可扩充性。因为是用Python编写的,所以Keras同时适用于Python2和Python3两个版本。Keras的使用更像是搭积木,深度学习里大多数你需要的东西,如网络层、激活函数、优化器、等,它都有对应的API可以进行直接调用。Keras没用单独的模型配置文件,模型的配置、运行、保存都可以写在同一个Python文件中。
    3.2 Keras编程3.2.1 Keras模型构建Keras提供了两种构建模型的方法,一种是序贯模型,另一种是函数式模型。函数式模型应用的范围更加广泛,确切的说序贯模型是函数式模型的一种特殊情况。因此两种模型在有些API的方法上是一样的。序贯模型最容易上手操作,它就像盖楼房那样,从第一层,一层一层按照你所设计的模型结构按顺序从输入层到输出层,依次进行声明即可。这也就意味着模型只有层与层之间的关系,不能存在跨层连接。函数式模型则没有对跨层连接的限制。
    3.2.2 Keras常用函数及用法本文使用的是序贯模型,主要用到的函数有下面这些。

    要开始使用序贯模型建立网络,需要先在Python文件的头部引入Sequential模块,创建Sequential的对象
    为模型添加层,通过创建的对象调用Sequential的add方法依次添加层。使用add添加的第一层需要指定有关输入数据shape的参数,而其后层的可以自动推导出中间数据的shape。
    对训练过程进行配置,使用compile,接收三个参数,分别是优化器、损失函数、指标列表。
    开始训练,使用fit函数,其参数有:

    x:输入数据。如果模型只有一个输入,那么x的类型是numpy array,如果模型有多个输入,那么x的类型应当为list,list的元素是对应于各个输入的numpy array
    y:标签,numpy array
    batch_size:整数,指定进行梯度下降时每个batch包含的样本数。训练时一个batch的样本会被计算一次梯度下降,使目标函数优化一步
    epochs:整数,训练的轮数,每个epoch会把训练集轮一遍
    verbose:日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为每个epoch输出一行记录
    callbacks:list,其中的元素是Keras.callbacks.Callback的对象。这个list中的回调函数将会在训练过程中的适当时机被调用
    validation_split:0~1之间的浮点数,用来指定训练集的一定比例数据作为验证集。验证集将不参与训练,并在每个epoch结束后测试的模型的指标,如损失函数、精确度等。注意,validation_split的划分在shuffle之前,因此如果你的数据本身是有序的,需要先手工打乱再指定validation_split,否则可能会出现验证集样本不均匀
    validation_data:形式为(x ,y)的tuple,是指定的验证集。此参数将覆盖validation_spilt
    shuffle:布尔值或字符串,一般为布尔值,表示是否在训练过程中随机打乱输入样本的顺序。若为字符串“batch”,则是用来处理HDF5数据的特殊情况,它将在batch内部将数据打乱
    class_weight:字典,将不同的类别映射为不同的权值,该参数用来在训练过程中调整损失函数(只能用于训练)
    sample_weight:权值的numpy array,用于在训练时调整损失函数(仅用于训练)。可以传递一个1D的与样本等长的向量用于对样本进行1对1的加权,或者在面对时序数据时,传递一个的形式为(samples,sequence_length)的矩阵来为每个时间步上的样本赋不同的权。这种情况下请确定在编译模型时添加了sample_weight_mode=’temporal’
    initial_epoch: 从该参数指定的epoch开始训练,在继续之前的训练时有用。


    3.3 Keras环境配置Keras在Ubuntu下的环境配置如下,下列命令均在终端中执行。
    1.系统升级
    Sudo apt updateSudo apt upgrade
    2.安装Python基础开发包
    sudo apt install -y python-dev python-pip python-nose gcc g++ git gfortran vim
    3.安装运算加速库
    sudo apt install -y libopenblas-dev liblapack-dev libatlas-base-dev
    4.Keras及相关开发包安装
    sudo pip install -U --pre pip setuptools wheelsudo pip install -U --pre numpy scipy matplotlib scikit-learn scikit-imagesudo pip install -U --pre tensorflow-gpusudo pip install -U --pre tensorflowsudo pip install -U --pre Keras
    5.打开Python解释器 import TensorFlow import Keras 无报错则完成安装
    3.4 小结本章主要对本文采用的深度学习框架Keras两种模型建立方法贯序模型和函数模型、模型的编译和训练所用到的函数参数、使用Keras环境配置中所需的Python基础开发包以及后台TensorFlow的安装作以介绍。本文在下一章中使用Keras实现经典LeNet5结构,并在其基础上作以改动探究不同参数对模型识别率的影响,学习调参经验。
    4 经典LeNet-5实验探究本章以MNIST数据集作为训练和测试数据来源,使用Keras深度学习框架在实现LeNet5的基础上对LeNet5模型结构进行改动以探究不同参数对模型识别率的影响,总结调参经验。
    4.1 数据集MNIST介绍MNIST[7]数据集是一个手写体数字数据集,通过了解这个数据集由四个部分组成。可以分为两大类,一类是训练数据,另一类是测试数据。每种数据包含了数据本身和对应的数据标签。训练集中有60000个用例,测试集中有10000个用例。
    MNIST是由NIST的手写体数字二值化图片的数据库SD3和SD1构成的。NIST最初的设计中,SD3是训练集,SD1是测试集。然而SD3比SD1更清晰,并且更容易识别。原因是SD3是从人口统计局的雇员收集的,而SD1是从中学的学生中收集的。从学习经验中得到有效的结论需要测试集是独立于训练集,并且测试集在完整的样本之中。因此,有必要通过混合NIST的数据来建造一个新的数据库。
    MNIST的训练集是由从SD3中的3万张图片和SD1中的3万张图片组成的。测试集是由从SD3中的5000张图片和SD1中的5000张图片。6万张训练集包含了近似250位写手。并且保证了训练集和测试集的写手是不相交的。
    SD1包含了由500位不同的写手写的58527张图片。比较而言,SD3的数据块是一次排列的,而SD1的数据是杂乱无章的。可以识别出SD1中的写手信息,我们根据识别出来的信息,把500位写手的数据分为两部分,前250位分到训练集中,后250位分到测试集。这样训练集和测试集我们现在都有大概3万张图片。在训练集中再加入SD3的数据,从0开始,使其凑够6万。类似的,在测试集中从SD3第35000张图开始,补充测试集到6万张。

    4.2 LeNet-5实现4.2.1 LeNet-5介绍
    经典LeNet-5包含输入输出层共计有8层,除输入输出两层外的每一层都包含需要通过训练学习的参数。每层有多个特征图谱,每个特征图谱都是通过一种卷积核(滤波器)卷积体现输入的一种特征,每个特征图谱有多个神经元。

    C1层是第一个卷积层,得到的时32*32的数据,包含了6中不同的5*5大小的卷积核,输出28*28的特征图谱。可训练参数共计(5x5+1)x6=156个(每个卷积核有25个参数和一个偏置项参数,共6个卷积核)。
    S2层是一个下采样层,输入为28*28的,采样大小为2*2,通过采样后得到6个14*14的图,加上偏置项每个特征图谱有2个可训练参数,共计12个。
    C3层是第二个卷积层,有16种5*5的卷积核,C3的前6个特征图以S2中3个相邻的特征图子集为输入。接下来6个特征图以S2中4个相邻特征图子集为输入。然后的3个以不相邻的4个特征图子集为输入。最后一个将S2中所有特征图为输入。输出16个10*10的特征图谱。
    S4层是下采样层,采样大小为2*2,通过采样得到16个5*5的图。这层共计32个训练参数。
    C5层是卷积层,卷积核大小5*5,卷积过后形成共计120种卷积结构。每个都与S4的16个输出相连。
    F6层是全连接层,84个节点,共计10164个可训练参数。

    4.2.2 LeNet实现原LeNet-5采用的是32*32的图片数据大小,本文采用的是MNIST数据集,该数据集的单张图片大小为28*28。本文在不改变LeNet-5的整体结构下将LeNet加以实现,模型细节与原paper作者有细微不同,保留了整体层次结构,因为数据输入尺寸大小的不同导致经过两次下采样后的特征图谱尺寸小于5*5无法进行卷积,所以改变C5层卷积核的大小为3*3。卷积层采用的权值初始化方法采用Keras官方推荐的截尾高斯分布初始化,激活函数采用sigmoid函数。最后得全连接层权值初始化采用正态分布初始化方法。所有初始化方法的随机种子采用固定值,方便结果重现和随后探究中控制单一变量进行结果比较。
    代码实现如下:
    # 输入数据的维度img_rows, img_cols = 28, 28# 使用的卷积滤波器的数量nb_filters = 6# 用于 max pooling 的池化面积pool_size = (2, 2)# 卷积核的尺寸kernel_size = (5, 5)# C1 卷积层1 卷积核6个 5*5model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1], border_mode='valid', input_shape=input_shape, kernel_initializer='TruncatedNormal'))model.add(Activation('sigmoid'))# S2 下采样model.add(MaxPooling2D(pool_size=pool_size))# C3卷积层2 16个卷积核 5*5model.add(Convolution2D( 16, kernel_size[0], kernel_size[1], kernel_initializer='TruncatedNormal'))model.add(Activation('sigmoid'))# S4 下采样model.add(MaxPooling2D(pool_size=pool_size))# C5 卷积层3 120个卷积核 3*3model.add(Convolution2D(120, 3, 3, kernel_initializer='TruncatedNormal'))model.add(Activation('sigmoid'))# 转化为一维model.add(Flatten())# F6 全连接层 输出层model.add(Dense(nb_classes, kernel_initializer='random_normal'))model.add(Activation('softmax'))
    模型训练采用克服了批梯度下降和随机梯度下降缺点的小批量梯度下降的参数更新方法。Keras在不设定的情况下,默认对训练数据进行打乱,因为所采用的平台硬件资源限制,该模型采用迭代40批次,每批次更新使用128个样本。
    该模型完成训练后测试准确率达到了98.58%,每次迭代训练和测试率的识别率和损失变化曲线如图4-3所示。

    4.3 模型探究本文将在使用Keras实现经典结构LeNet-5的同时,控制单一变量,在LeNet-5的基础上分别从改变网络结构,卷积核大小和数量、权值初始化方式、激活函数选择这几方面与LeNet5进行比较试验,以掌握一定的调参方法和规则。
    4.3.1 不同网络结构1.实验设计
    在上一节实现的LeNet5的基础上,对模型结构进行改动。直接在原结构S4层的基础上增加5*5的卷积层会导致因为前四层两次下采样而使S4层的输出特征图谱尺寸大小小于5*5无法再次进行卷积,所以CNN1-1直接以新的卷积层代替了S4层的下采样层;CNN1-2在原Lenet5结构上在C5层后添加了按百分之五的概率断开输入神经元的Drop层;CNN1-3在原LeNet5的结构基础上在C5层后添加了新的全连接层。通过使用改变网络结构,探究不同结构的组合对识别率的影响,不同结构对比如表4-1所示。



    网络名称
    层结构










    LeNet5
    Con
    Pooling
    Con
    Pooling
    Con
    Full
    /


    CNN1-1
    Con
    Pooling
    Con
    Con
    Con
    Full
    /


    CNN1-2
    Con
    Pooling
    Con
    Pooling
    Con
    Drop
    Full


    CNN1-3
    Con
    Pooling
    Con
    Pooling
    Con
    Full
    Full



    2.实验结果
    表4-2为不同模型结构经过40轮迭代后,使用测试集测试后的识别率大小,原LeNet5结构的识别率为98.58%,CNN1-1的识别率为98.05%,CNN1-2的识别率为98.49%,CNN1-3的识别率为98.19%。



    网络名称
    LeNet5
    CNN1-1
    CNN1-2
    CNN1-3




    测试识别率
    98.58%
    98.05%
    98.49%
    98.19%



    如图4-4所示为不同结构与LeNet5识别准确率对比折线图,通过对折线图的分析比较,可以看出原LeNet5的识别准确率起点最高,添加了Drop层的CNN1-2其次,添加了卷积层的CNN1-1要通过迭代2次后识别率大幅上升,添加全链接层的CNN1-3因为增加了全连接导致的链接权值数量增加需要迭代5次后才能大幅提高识别的准确率。

    如图4-5所示为不同结构模型与LeNet5损失对比折线图,几种不同模型的损失率与识别率情况相对应,总体上均能在10次迭代以内快速收敛。

    通过表的比较,可以看出不论是添加卷积层、全连接层、还是Drop层,在相同其他条件下,特别是均迭代更新40次的前提下,CNN1-1、CNN1-2、CNN1-3的识别准确率并没有比原LeNet5模型准确率高,均有不同程度的下降。结论是在有限迭代次数内,添加卷积层、Drop层和全连接层,会不同程度降低对测试集识别率,原LeNet5模型结构经典,识别率最高。
    4.3.2 卷积核大小数量1.实验设计
    在LeNet5的基础上进行改动,主要改动卷积核大小和数量。CNN2-1在原LeNet5的基础上将C1和C3层卷积核尺寸大小由55改为33;CNN2-2在原LeNet5的基础上将C3层的卷积核数量由6个改为16个。通过改变卷积核参数,探究卷积核对模型识别率的影响,不同卷积层参数对比如表4-3所示。



    网络名称
    C1
    S2
    C3
    S4
    C5
    F6




    LeNet5
    6*(5*5)
    (2*2)
    6*(5*5)
    (2*2)
    120(3*3)
    10


    CNN2-1
    6*(3*3)
    (2*2)
    6*(3*3)
    (2*2)
    120(3*3)
    10


    CNN2-2
    6*(5*5)
    (2*2)
    6*(5*5)
    (2*2)
    120(3*3)
    10



    2.实验结果
    表4-4为相同模型结构下不同卷积层参数经过40轮迭代后,使用测试集测试后的识别率大小,原LeNet5结构的识别率为98.58%,CNN2-1的识别率为98.25%,CNN2-2的识别率为98.57%。



    网络名称
    LeNet5
    CNN2-1
    CNN2-2




    测试识别率
    98.58%
    98.25%
    98.57%



    如图4-6所示为卷积层不同参数模型识别率变化折线图,通过对折线图的分析,减小卷积核尺寸的大小,会使识别率收敛的起点降低。增加卷积核的数量会使识别率收敛的更快。

    如图4-7所示为卷积层不同参数模型损失变化折线图,通过对折线图的分析,减小卷积核尺寸的大小,会使损失收敛的起点升高;增加卷积核的数量会使损失收敛的更快。

    通过对测试识别率结果进行分析,CNN2-1与LeNet5对比,在其他条件不变的前提下,减小卷积核的大小,明显会使识别率明显下降。CNN2-2与LeNet5对比,在其他条件不变的前提下,增加卷积核的数量,对识别率的影响几乎可以忽略不计,仅降低了0.01%。结论是增加卷积核的数量可以有效提取更多训练集样本的特征,从而提高识别率的收敛速度。
    4.3.2 权值初始化1.实验设计
    如表所示,原LeNet5卷积层采用的权值初始化方式是Keras推荐滤波器使用的Truncated Normal,CNN3-1采用的是权值全0初始化方式;CNN3-2采用的是权值全1初始化方式;CNN3-3采用的是;CNN3-4采用的是。通过改变卷积层的权值初始化方式,探究不同初始化方式对模型识别率收敛速度和准确率的影响,卷积层不同权值初始化方式对比如表4-5所示。



    网络名称
    LeNet5
    CNN3-1
    CNN3-2
    CNN3-3
    CNN3-4




    权值初始化方式
    Truncated Normal
    Zero
    Ones
    Random Normal
    Random Uniform



    2.实验结果
    表4-6为相同模型结构下不同卷积层权值初始化方式经过40轮迭代后,使用测试集测试后识别率大小,原LeNet5结构的识别率为98.58%,CNN3-1的识别率为97.28%,CNN3-2的识别率为8.92%,CNN3-3的识别率为98.41%,CNN3-4的识别率为98.38%。



    网络名称
    LeNet5
    CNN3-1
    CNN3-2
    CNN3-3
    CNN3-4




    测试识别率
    98.58%
    97.28%
    8.92%
    98.41%
    98.38%



    如图4-8所示为卷积层不同权值初始化方式模型识别率折线图,通过对折线图的分析,在其他参数不改变的前提下,CNN3-1的识别率需要经过6次迭代后才快速收敛;CNN3-2的识别率,在40次迭代中一直没有收敛。CNN3-3的识别率与LeNet5识别率收敛过程几乎一致,仅收敛起点比LeNet5略高;CNN3-4的识别率也与LeNet5识别率收敛过程极其相似。

    如图4-9所示为卷积层不同权值初始化方式模型损失折线图,通过对折线图的分析,与识别率的收敛过程相似,采用全1的初始化方式损失居高不下。

    通过对表4-6的分析,CNN3-1卷积层采用权值全0初始化,相比LeNet5在识别准确率上1.3个百分点;CNN3-2卷积层采用全1初始化,相比LeNet5在识别率上大幅降低;CNN3-3卷积层采用初始化方式,相比LeNet5在识别准确率上有略微降低;CNN3-4卷积层采用初始化方式,相比LeNet5在识别准确率上也略微降低。结论是不同于LeNet5的权值初始化方式在其他参数条件不变的前提下会使模型识别率有所降低。在迭代次数规模较小的情况下,不能采用全1对权值进行初始化。
    4.3.3 激活函数选择1.实验设计
    如表所示,LeNet5卷积层采用的是Sigmoid的函数,CNN4-1采用的是Tanh函数,CNN4-2采用的是Reul函数,CNN4-3采用的是Softplus函数,卷积层不同激活函数对比如表4-7所示。



    网络名称
    LeNet5
    CNN4-1
    CNN4-2
    CNN4-3




    卷积层激活函数
    Sigmoid
    Tanh
    Reul
    Softplus



    2.实验结果
    表4-8为相同模型结构卷积层使用不同激活函数经过40轮迭代后,使用测试集测试后识别率大小,原LeNet5结构的识别率为98.58%,CNN4-1的识别率为98.89%,CNN4-2的识别率为98.44%,CNN4-3的识别率为98.62%。



    网络名称
    LeNet5
    CNN4-1
    CNN4-2
    CNN4-3




    测试识别率
    98.58%
    98.89%
    98.44%
    98.62%



    如图4-10所示为卷积层不同激活函数模型识别率折线图,通过对折线图的分析,采用tanh函数作为卷积层激活函数的CNN4-1识别率的收敛起点相当高,通过第一次迭代就已经达到90%以上;采用reul函数作为卷积层激活函数的CNN4-2识别率收敛起点币LeNet5低,但在经过一次迭代后迅速收敛,收敛速度大于LeNet5;采用新激活函数softplus作为卷积层激活函数的CNN4-3,收敛起点和速度都高于LeNet5。

    如图4-10所示为卷积层不同激活函数模型识别率折线图,通过对折线图的分析,卷积层采用Tanh和Softplus作为激活函数的模型损失收敛起点低,卷积层采用Reul函数作为激活函数的模型损失收敛起点高。

    通过表分析可知,在其他参数不改变的前提下,采用tanh函数作为卷积层激活函数的CNN4-1比卷积层采用sigmoid函数的LeNet5在识别率上高出了0.31%。这是出乎意料的结果。CNN4-2采用的是最近学术界推荐替代sigmoid和tanh的reul函数,理论上来说使用reul的效果应该会更好,出乎意料的是它比卷积层采用sigmoid函数的LeNet5识别率低了0.14%;CNN4-3采用的是近期出现的新函数softplus,其识别率比LeNet5高0.04%。结论是在有限迭代次数内,卷积层采用tanh或softplus,能够有效提高识别准确率,并提高识别率收敛的速度。
    4.4 小结本章通过深度学习框架Keras实现了以MNIST数据集作为训练数据的经典LeNet5结构,并通过设计实验探究得出以下结论,LeNet5模型在迭代次数为40次的前提条件下,添加卷积层、drop层、全连接层都会对模型识别率产生负影响;增加卷积层中的卷积核数量可以有效提高模型识别率收敛的速度;在有迭代限次数内采用全1的卷积层权值初始化方式会对模型识别率产生巨大的影响;卷积层激活函数采用Tanh函数可以有效提高模型识别率。
    5 手写数字识别算法应用实践本文将用训练好的高识别率手写数字模型应用到摄像头实现对镜头画面中数字的实时识别。本章将介绍如何使用计算机视觉库OpenCV调用电脑摄像头、找到帧画面中的数字并对数字进行识别前的处理,最后调用训练好的手写数字模型将识别结果在原帧画面中显示出来。
    5.1 OpenCV图像处理部分5.1.1 OpenCV介绍OpenCV是一个开源的跨平台计算机视觉库,它可在Linux、Windows和Mac OS操作系统上运行。因为由C和C++编写,所以它很高效,并且提供了许多其他语言的接口如Python、Ruby、MATLAB等。OpenCV的功能有基本的图像处理如去燥、边缘检测、角点检测、色彩变化等。
    本文将运用部分OpenCV的功能,调取电脑自带的摄像头,对每一帧的画面进行处理,在画面中找到数字并截取出来,调用数字识别模型进行识别,并用矩形框出每个数字把识别结果标注在旁边。
    5.1.2 OpenCV安装配置1.安装依赖包
    依赖包包含了linux程序在安装、运行中所必须的相关编译工具、安装工具等。程序本身并不包含这些需要的库,在不重复造轮子的前提下,程序在运行中相应的功能时会需要调用相应的库。如本文所使用的OpenCV需要对Python不同版本的支持、对图片视频读写的支持等。
    sudo apt-get install --assume-yes build-essential cmake git sudo apt-get install --assume-yes build-essential pkg-config unzip ffmpeg qtbase5-dev python-dev python3-dev python-numpy python3-numpy sudo apt-get install --assume-yes libOpenCV-dev libgtk-3-dev libdc1394-22 libdc1394-22-dev libjpeg-dev libpng12-dev libtiff5-dev libjasper-devsudo apt-get install --assume-yes libavcodec-dev libavformat-dev libswscale-dev libxine2-dev libgstreamer0.10-dev libgstreamer-plugins-base0.10-devsudo apt-get install --assume-yes libv4l-dev libtbb-dev libfaac-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-devsudo apt-get install --assume-yes libvorbis-dev libxvidcore-dev v4l-utils
    2.编译
    在当前目录下创建build文件夹,进入build文件夹,配置编译选项,最后执行编译命令。
    mkdir buildcd build/cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=ON -D WITH_V4L=ON -D WITH_QT=O -D WITH_OPENGL=ON -D WITH_CUBLAS=ON -D CUDA_NVCC_FLAGS="-D_FORCE_INLINES"make -j $(($(nproc) + 1))
    3.安装
    以root权限执行安装命令makeinstall,利用输出重定向,创建OpenCV相关动态链接库配置文件,使用动态库管理命令ldconfig,让OpenCV的相关链接库被系统共享,最后更新系统源。
    sudo make installsudo /bin/bash -c 'echo "/usr/local/lib" > /etc/ld.so.conf.d/OpenCV.conf'sudo ldconfigsudo apt-get update
    4.检查安装
    以root权限执行安装checkinstall,执行checkinstall命令检查安装。
    sudo apt-get install checkinstallsudo checkinstall
    5.确认安装
    进入Python解释器输入“import cv2”无报错即成功安装。
    5.1.3 寻找数字1.方案选择
    要进行数字识别,首先要让程序能够寻找到画面中的数字。安装好的OpenCV中有自带的分类器,但是很不幸的是自带的分类器仅有关于人脸识别方向的,如果是做人脸识别方向的研究使用该分类器将会非常方便。至此,本文需要自己开发一个寻找数字的分类器或程序。有两种方案,一是训练一个关于数字识别的级联分类器,二是直接对画面中的元素进行寻找。方案一训练一个级联分类器并不容易,它需要准备正负两种样本。正样本中全是不同字体数字的图片集合,负样本要求是与数字可能出现的场景中非数字本身的物品图片集合。该方案适用于对识别要求严格的商业级软件开发。方案二相对于方案二适用于比较简单的测试环境,可以容忍一定识别误差。训练级联分类器对于负样本要求的范围广泛,数据量巨大。与深度学习目前所遇到的问题一样,虽然目前有大数据的支持,但是数据的标注代价是巨大的。本文以研究学习为目的且最终测试的环境简单,所以采用第二种方案。
    2.方案实施
    在使用摄像头读取画面时,视频流中的每一帧可以看作为一张图片,如图5-1所示以单张写有数字的图片,代替摄像头读取到的单独一帧。

    先使用cvtcolor()函数对图片进行灰度处理,然后对灰度图进行二次腐蚀处理,可以去除一些细微的无关纹理,处理后效果如图5-2所示可以看到经过二次腐蚀后的图像只能够依稀看到九个数字的痕迹。

    对图片进行二次膨胀处理,是数字在原图的基础上轮廓更加清晰,处理后效果如图5-3所示。

    用膨胀后的图和腐蚀后的图做差,可以得到清晰地数字轮廓,方便后续调用函数提取数字的轮廓信息,处理后如图5-3所示。

    对数字轮廓使用Sobel去噪处理,使轮廓更加清晰,将数字中未连接的部分连接在一起,减小轮廓寻找误差,处理后如图5-4所示。

    利用findContours找到画面中所有轮廓,按设置的像素长宽寻找单个数字轮廓记录其相对坐标及长宽值,最后根据记录的信息在原图中将找到的数字标注出来如图5-5所示。

    函数实现代码:
    def where_num(frame): rois = [] # 灰度处理 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) element = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) # 二次腐蚀处理 gray2 = cv2.dilate(gray, element) gray3 = cv2.dilate(gray2, element) # cv2.imshow("dilate", gray3) # 二次膨胀处理 gray2 = cv2.erode(gray2, element) gray2 = cv2.erode(gray2, element) # cv2.imshow("erode", gray2) # 膨胀腐蚀做差 edges = cv2.absdiff(gray, gray2) # cv2.imshow("absdiff", edges) # 使用算子进行降噪 x = cv2.Sobel(edges, cv2.CV_16S, 1, 0) y = cv2.Sobel(edges, cv2.CV_16S, 0, 1) absX = cv2.convertScaleAbs(x) absY = cv2.convertScaleAbs(y) dst = cv2.addWeighted(absX, 0.5, absY, 0.5, 0) # cv2.imshow("sobel", dst) # 选择阀值对图片进行二值化处理 ret_1, ddst = cv2.threshold(dst, 50, 255, cv2.THRESH_BINARY) # 寻找图片中出现过得轮廓 im, contours, hierarchy = cv2.findContours( ddst, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 在保存的轮廓里利用宽度和高度进行筛选 for c in contours: x, y, w, h = cv2.boundingRect(c) if w > 12 and h > 24: rois.append((x, y, w, h)) return rois
    5.1.4 数字处理在对寻找到的数字进行识别前,还需要进一步对单个数字进行处理。要使训练好的模型能够接收待预测的图片,需要将单个数字处理成与模型训练集数据一样的格式。单个数字截取图应被处理为28*28大小,二值化黑底白字的形式。如图5-6所示为MNIST数据集中的一个样本,图5-7为本文经处理过后的单个数字示例。



    MNIST单个数字示例
    经处理后单个数字示例









    函数代码:
    def resize_image(image): # 单个数字灰度化 GrayImage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 二值化并翻转为黑底白字 ret, thresh2 = cv2.threshold(GrayImage, 120, 255, cv2.THRESH_BINARY_INV) # 给数字增加一圈黑色方框 constant = cv2.copyMakeBorder( thresh2, 20, 20, 20, 20, cv2.BORDER_CONSTANT, value=0) # 调整数字图片尺寸 image = cv2.resize(constant, (28, 28)) return image
    5.2 实现摄像头的手写数字实时识别5.2.1 手写数字识别模型训练结合前文的实验,选择合适的模型结构与参数训练出来的模型测试集上的识别率达到了99%以上,具体结构如下图5-8所示。
    代码如下:
    # 创建贯序模型对象model = Sequential()# 添加卷积层,设置30个尺寸大小为5*5的卷积核,激活函数为relumodel.add(Convolution2D(30, 5, 5,border_mode='valid',input_shape=input_shape))model.add(Activation('relu'))# 添加下采样层model.add(MaxPooling2D(pool_size=pool_size))# 添加drop层,概率设为0.4model.add(Dropout(0.4))# 添加卷积层,设置15个尺寸大小为3*3的卷积核,激活函数为relumodel.add(Convolution2D(15, 3, 3))model.add(Activation('relu'))# 添加下采样层model.add(MaxPooling2D(pool_size=pool_size))# 添加drop层,概率设为0.4model.add(Dropout(0.4))# 添加Flatten使数据一维化model.add(Flatten())# 添加全连接层,设置128个节点,激活函数为relumodel.add(Dense(128))model.add(Activation('relu'))# 添加drop层,概率设为0.4model.add(Dropout(0.4))添加全连接层,设置50个节点,激活函数为relumodel.add(Dense(50))model.add(Activation('relu'))# 添加drop层,概率设为0.4model.add(Dropout(0.4))# 添加全连接层,设置10个节点,激活函数为softmaxmodel.add(Dense(10))model.add(Activation('softmax'))

    5.2.2 模型的保存与调用
    在训练模型的代码中使用model.save(filepath)将Keras训练好的模型和权重保存在一个HDF5文件中,该文件将包含:模型的结构,以便重构该模型;模型的权重训练配置(损失函数,优化器等)优化器的状态,以便于从上次训练中断的地方开始
    使用load_model(filepath)可以加载保存的HDF5文件,并直接对模型进行调用操作

    5.2.3 结果调用训练好的模型,使用model.predict_class()函数对截取出来的单个数字进行识别,将识别结果返回并在原帧画面中标注出来。如图5-9至图5-11所示,本文采取五个不同个人所书写的数字进行测试。



    手写测试结果1
    手写测试结果2








    手写测试结果3
    手写测试结果4






    手写测试结果5







    经测试训练好的手写数字模型能够识别出一定程度畸变的数字,对于不常见的手写体风格不能够做出有效识别。
    5.3 小结本章在前章的实验经验上设计出改进后的手写数字识别模型,在测试集的测试中准确率达到了99%以上。使用计算机视觉库OpenCV实现对摄像头的调用,利用寻找轮廓的方法在摄像头拍摄的帧画面中确定数字的位置并截取,调用训练好的手写数字识别模型对每个数字进行识别,将识别结果在原帧画面中标注返回。
    6 总结深度学习目前在大数据、大计算的支持下引领者新一波的AI热潮。使用MNIST数据集实现卷积神经网络的训练已经成为了深度学习入门的“hello word”。从经典的问题入手学习深度学习,一方面可以很好的入门,另一方面在学习的过程中所遇到的问题大部分通过浏览搜索互联网资源可以得到解决。本文以学习深度学习中重要分支卷积神经网络的过程为线索,由简入深从基本的神经元学起,学习和理解如何对卷积神经网络进行训练。在研究学习训练卷积神经网络的调参优化同时训练出高识别率的手写数字识别模型,并将该模型与OpenCV技术相结合,实现了基于电脑摄像头对画面中手写体数字进行实时识别。通过在对模型参数、结构的实验探究分析,发现并不是对训练集图像的特征提取的越多最终模型识别上得表现就越好,合理组合不同参数,选择合适的训练批次及批次数据大小才能训练出高识别率的模型。通过对模型的实际应用,反映出的问题是虽然在模型在测试集上表现达到近百分百的准确度,但是在应用过程中识别的效果并不完美,有个别数字会在两个结果中间来回跳,这说明理论到实际的应用过程中需要考虑到的实际因素还很多。在生活中我们对于数字精准要求不容闪失,任何一个数字的误差都会导致不可估量的损失。
    在此次毕业设计中我学习了许多知识,从神经网络的原理推到中复习了高等数学的部分知识、从Keras、OpenCV的环境配置中扎实了Linux命令的使用、在使用Keras训练模型的过程中熟练掌握了Python面向对象编程以及使用Matlibplot库绘制实验图像。在将训练好的模型实际应用的过程中锻炼发现问题、解决问题独立思考的能力。通过这次毕业设计,让我对深度学习有了一个清晰地概念,能够将卷积神经网络应用到一些实际问题中,并取得了好的结果。
    参考文献[1] 陈浩翔.手写数字深度特征学习与识别.计算机技术与发展26.7(2016):19-23.
    [2] 张晓.手写数字识别的前景与难点.数码世界1(2016):69-70.
    [3] Andrew Ng.MachineLearning[OL].2016.3.https://www.coursera.org/learn/machine-learning/
    [4] 尹宝才,王文通,王立春.深度学习研究综述[J].北京工业大学学报,2015(1):48-59.
    [5] 郭丽丽,丁世飞.深度学习研究进展[J]. 计算机科学, 2015,42(5):28-33.
    [6] 吴岸城.神经网络与深度学习[M].北京:电子工业出版社,2016.6
    [7] The MNIST Database ofHandwritten Digits[DB].http://yann.lecun.com/exdb/MNIST/
    [8] 赵永科.深度学习21天实战Caffe[M].北京:电子工业出版社,2016.7
    [9] 李丹.”基于LeNet-5的卷积神经网络改进算法.”计算机时代8(2016):4-6.
    [10] Peter Harrington.MachineLearning in Action[M].Manning Publications,2012-4-19
    [11] Andrew Ng,Jiquan Ngiam,ChuanYu Foo,Yifan Mai,Caroline Suen.UFLDL教程[OL].2016.3.http://deeplearning.stanford.edu/wiki/index.php/UFLDL_Tutorial
    [12] Fei-Fei Li,Andrej Karpathy.CS231nConvolutional Neural Networks for Visual Recognition[OL].2016.1.http://cs231n.stanford.edu/
    [13] 吴忠,朱国龙,黄葛峰,等.基于图像识别技术的手写数字识别方法[J]. 计算机技术与发展,2011,21(12):48-51.
    [14] 余凯,贾磊,陈雨强,等.深度学习的昨天, 今天和明天[J]. 计算机研究与发展, 2013,50(9):1799-1804.
    [15] 孙志军, 薛磊, 许阳明, 等. 深度学习研究综述[J]. 计算机应用研究, 2012, 29(8):2806-2810.
    [16] LeCun Y, Bengio Y, Hinton G. Deep learning[J].Nature,2015,521(7553):436-444.
    [17] Krizhevsky A,Sutskever I,HintonG E. Imagenet classification with deep convolutional neuralnetworks[C]//Advances in neural information processing systems.2012:1097-1105.
    2 评论 72 下载 2018-10-03 22:44:16 下载需要13点积分
  • 基于Android和SSM框架实现的学生成绩管理系统APP

    1、项目概述1.1 项目的目的和意义建立学生成绩管理系统,利用手机对学生成绩进行管理,进一步提高现代化水平。使学生能够快速、准确地输入、修改和查询自己的成绩,更好地了解自己的学业成绩,并方便对教师的管理。让学生更快地查询自己的学业成绩。教师可以更快更好地了解学生的学习情况,从而进一步提高学校的教学质量。
    1.2 现状分析学校对学生成绩的管理曾经还停留在使用手工操作上。随着学校规模的扩大,学生人数逐年增加。随着学生成绩管理数据量的不断增加,一些学校不得不依靠不断增加的人力物力来进行学生成绩管理。但是,人工管理存在效率低、易出错、信息检索速度慢、难以为学校管理提供决策信息等缺点。学校不能充分掌握每个学生的学习情况,这不利于学校的教学工作,学校的教学质量一直停滞不前,所以我只想开发一个适用的绩效管理体系,使学生能够充分掌握学业的成绩和课程,以便于学生了解情况。
    2、主要业务流程分析成绩管理系统可以输入课程和成绩数据,并可以完成添加、修改、删除等查询,并根据各种条件基本满足师生的需要。成绩管理系统主要包括学生的基本信息、年龄、电话等方面的信息,内容比较简单。成绩管理系统主要用于学生成绩信息的输入,具有课程注册、成绩查询、学生信息注册等功能。一般来说,它具有编辑、查询、学生成绩管理等功能。
    学生端登陆该系统后,进入个人信息页面可以查看自己的个人信息,进入课程管理页面可以对已选课程的课程成绩查询,显示其学号、科目名称和成绩,进入课程论坛页面可以进入现有话题查看和跟帖,也可以创建新的讨论话题。
    教师端登录系统后可以进入个人信息页面可以查看自己的个人信息,还可以先选择已开放课程,之后进行成绩录入、成绩修改、成绩查询、成绩分析、删除课程的操作,也可以增加新开放的课程。成绩录入先选择需要录入的人数,再添加其学号与成绩。成绩修改先输入需要修改的成绩的学生学号进行查询,然后输入其姓名,科目,任课教师,成绩,然后提交修改。成绩查询可查询已选此门课程的学生的学号、姓名和成绩。成绩分析可以选择分数比例分析图查看饼状统计图,或者选择分段人数分析图查看条状统计图。删除课程就会删除此门开放课程。
    3、需求分析3.1 功能需求
    成绩管理系统可以提供一个完善的登陆界面,使学生或教师都可以通过此窗口登陆
    成绩管理系统可以提供完善的学生信息和课程信息管理界面,学生或管理员可以查看和管理学生信息与课程信息
    成绩管理系统可以提供完善的课程信息管理界面,教师或管理员可以查看和管理课程信息,进行成绩录入、成绩修改、成绩查询、成绩分析
    成绩管理系统有一个后端管理页面,可以作为管理员登陆查看与修改学生信息,教师信息,课程信息和论坛信息

    3.2 非功能需求
    登陆时采用的用户名 和密码都采用MD5算法保护,再存入数据库存储
    该系统能够在android4.0.13以上版本的安卓系统上正常运行

    4、系统功能设计
    5、系统UI设计




























    6、系统数据库设计/*服务器hostname: www.wuyunian.tk密码: wuyunian1998学号:8位数是老师,10位数是本科生*//*学生学号 密码 姓名 入学年份 手机号 */ drop table if exists `student_id`;CREATE TABLE IF NOT EXISTS `student_info`( `id` VARCHAR(100) NOT NULL, `password` VARCHAR(100) NOT NULL, `name` VARCHAR(100) NOT NULL, `year` int not null, `phonenum` varchar(11) not null, PRIMARY KEY ( `id` ))ENGINE=InnoDB DEFAULT CHARSET=utf8;/*老师职工号 密码 姓名 */drop table if exists `teacher_info`;CREATE TABLE IF NOT EXISTS `teacher_info`( `id` VARCHAR(100) NOT NULL, `password` VARCHAR(100) NOT NULL, `name` VARCHAR(100) NOT NULL, `phonenum` varchar(11) not null, PRIMARY KEY ( `id` ))ENGINE=InnoDB DEFAULT CHARSET=utf8;/*课程课程编号 课程名称 任课教师职工号 学生学号 学生成绩*/drop table if exists `subject`;CREATE TABLE IF NOT EXISTS `subject`( `subject_id` VARCHAR(100) NOT NULL, `subject_name` VARCHAR(100) NOT NULL, `teacher_id` VARCHAR(100) NOT NULL, `student_id` VARCHAR(100) , `score` double)ENGINE=InnoDB DEFAULT CHARSET=utf8;/*讨论话题讨论话题编号 讨论的话题 教师职工号 学生学号 老师发言 学生发言*/drop table if exists `discussion`;CREATE TABLE IF NOT EXISTS `discussion`( `discussion_id` int NOT NULL auto_increment, `topic` VARCHAR(100) NOT NULL, `name` VARCHAR(100) NOT NULL, `teacher_id` VARCHAR(100) , `student_id` VARCHAR(100) , `teacher_words` VARCHAR(200) , `student_words` VARCHAR(200) , PRIMARY KEY ( `discussion_id` ))ENGINE=InnoDB DEFAULT CHARSET=utf8;/*插入学生数据 */INSERT INTO student_info (id, password, name,year,phonenum) VALUES("1163710214", "123456", "Anderson",2018,18846135525);INSERT INTO student_info (id, password, name,year,phonenum) VALUES("1163710215", "123456", "刘文佳",2018,15512931688);INSERT INTO student_info (id, password, name,year,phonenum) VALUES("1152625346", "123456", "佳佳大魔王",2018,15512931688);INSERT INTO student_info (id, password, name,year,phonenum) VALUES("1554651223", "123456", "克格勃佳佳",1976,15512931688); /*插入老师数据*/insert into teacher_info(id,password,name,phonenum)values("20181234","123456","奥巴马","18846135525"); insert into teacher_info(id,password,name,phonenum)values("19982356","123456","普京","11913582155"); /*插入课程数据*/insert into subject(subject_id,subject_name,teacher_id,student_id,score)values("cs001","Data constructure And Algorithm","20181234","1163710214",90.6);insert into subject(subject_id,subject_name,teacher_id,student_id,score)values("cs001","Data constructure And Algorithm","20181234","1163710214",90.6);insert into subject(subject_id,subject_name,teacher_id,student_id,score)values("cs002","Software Constructure","19982356","1163710214",85.9);insert into subject(subject_id,subject_name,teacher_id,student_id,score)values("math001","gaoshu","19982356","1163710215",85.9);/*插入讨论数据*/insert into discussion(topic,name,teacher_id,student_id,teacher_words,student_words)values("工业互联网","基于工业互联网的感想","20181234","1163710214","我觉得不行","我觉得ok");insert into discussion(topic,name,teacher_id,student_id,teacher_words,student_words)values("测试大数据导论","基于hadoop进行数据分析","20181234","1163710214","我觉得不行","我觉得ok");insert into discussion(topic,name,teacher_id,student_id,teacher_words,student_words)values("人工智能","价值一亿美元的人工智能代码竟然是用java写的","19982356","1163710214","我觉得不行","我觉得ok");insert into discussion(topic,name,teacher_id,student_id,teacher_words,student_words)values("人工智能","AI","19982356","1163710214","我觉得不行","我觉得ok");
    主要的表

    各个表的结构




    7、系统体系结构设计后端采用SSM框架,采用spring+springmvc+mybatis的技术方案,实现后端快速开发;前端基于Navigation Drawer Activity和LoginActivity两个基础Activity,使用sharedpreferences,HTTP,本地化存储等技术进行开发。

    8、统一接口设计


    序号
    url
    方式
    返回值
    返回格式
    备注




    1
    http://localhost:8080/HITManage/login?id=1163710215&password=123456
    post
    true or false
    json
    登录验证


    2
    http://localhost:8080/HITManage/reqstumsg?id=1163710215
    get
    student_info
    json
    请求学生信息


    3
    http://localhost:8080/HITManage/reqteamsg?id=20160101
    get
    teacher_info
    json
    请求老师信息


    4
    http://localhost:8080/HITManage/reqallsubject
    get
    Arraylist<String>
    json
    请求所有课程名称


    5
    http://localhost:8080/HITManage/reqsubject?subjectname=gaoshu&student_id=1163710215
    get
    subject
    json
    请求某学生某课程的课程信息


    6
    http://localhost:8080/HITManage/reqsubscore?id=1
    get
    Arraylist<Subject_info>
    json
    请求某课程所有的成绩


    7
    http://localhost:8080/HITManage/reqalldis
    get
    Arraylist<String>
    json
    请求所有讨论名称


    8
    http://localhost:8080/HITManage/reqdis?disname=
    get
    Arraylist<discussion>
    json
    请求某讨论所有内容


    9
    http://localhost:8080/HITManage/addStudent?id=116&password&name&year&phonenum
    post
    ?
    ?
    添加学生账号


    10
    http://localhost:8080/HITManage/addScore
    post
    格式:Arraylist<subject>
    json
    添加学生成绩


    11
    http://localhost:8080/HITManage/addDiscussion
    post
    格式:Arraylist<discussion>
    json
    添加讨论信息


    12
    http://localhost:8080/HITManage/reqSubid?subname=gaoshu
    get
    string
    json
    请求某课程的编号


    13
    http://localhost:8080/HITManage/reqSubByTeaId?teacherid=1163710215
    get

    json



    14
    http://localhost:8080/HITManage/newDiscussion?topic=人工智能&name=啥玩意啊
    post
    true or false
    json
    添加讨论圈子


    14
    http://localhost:8080/HITManage/addDiscussion?
    post
    discussion
    json
    添加某话题下的讨论内容


    15
    http://localhost:8080/HITManage/delDiscussion?
    post
    diccussion
    json
    删除某条讨论内容(先不实现)


    16
    http://localhost:8080/HITManage/reqSubByStuId?studentid=1163710215
    get
    status boolean data List<Subject>
    json
    请求某学生的课程信息


    17
    http://localhost:8080/HITManage/modifyPassword?id=1163710215&password=123456
    post
    staues true
    json
    修改密码



    9、其它需要说明的设计要点中文编码问题:由于在前后端传输数据时,若传输中文数据容易变为乱码,因此在前后端进行中文传输时,函数要在开始前进行编码统一。

    10、详细设计与成果先介绍android前端的设计思路,首先设计的是login活动,该活动登陆时读取用户输入的信息,在本地进行加密,加密后送至服务器进行匹配,并返回是否允许登陆的信息。再次登陆时利用sharedpreference存储历史登陆信息。第二个是注册活动,该活动还允许学生注册新的账户与密码,发送至服务器并保存。第三个是修改密码活动,输入用户名,新密码旧密码,以发送至服务器并修改。第四个是显示主页面的活动,通过侧边栏接入更多的功能。第五个是个人信息活动,也是通过请求后端数据库以活动该用户的信息以显示。第六个是学生端的课程信息活动,该活动可以查询自己所有已选课程的成绩,需要通过添加适配器动态地显示多条信息。第七个是教师端的课程信息活动,教师可以增删查改各门课程的成绩,同样是请求后端对数据库进行增删查改,教师端还有一个成绩分析的活动,该活动根据对后端请求所得的特定课程的所有成绩信息进行分段,同样该活动也使用了适配器,然后分别用饼状图和柱状图具体的展示给教师。第八个是论坛讨论功能,先使用一个适配器展示所有的讨论话题,点击一个话题后利用第二个适配器展示所有该话题下的所有讨论内容。
    然后是web管理段的设计思路,该页面相当于将所有存在数据的内容,包括学生信息,教师信息,课程信息,论坛信息,一并的显示于页面上,并且可以自由的增删查改,该页面当然也与后端数据库连接。
    后端采用ssm框架。在后端中有简单的页面:老师界面、学生界面、讨论区界面、课程界面,每个界面实现了基本的增删改查功能。
    在框架中,也贯穿了软件设计过程中的MVC思想。model体现在pojo这个包中,这个包实现了讨论、老师、学生、课程这几个基本类。views体现在web界面的jsp中。control体现在controller这个包中。
    spring利用控制反转和依赖注入,将对象之间的依赖关系交由spring进行控制,避免硬编码所造成的过度程序耦合。
    springMVC实现了利用注解简化了配置,实现可视化。
    mybatis与数据库进行连接,将数据库操作放在xml文件中,避免出现在java代码中,极大地降低了数据库操作语言的书写过程和连接等过程。
    在后端接受来自前端jsp或者android传来的get或者post请求,对请求中的内容进行解析,如json数据、String类型等,调用数据库操作,最后将得到的结果、状态信息等封装到json中返回给请求方。
    11、项目体会了解到了如何将SSM框架应用于后端的开发,在与他人合作编写代码时,要提前商量并确定下来一定的书写规范,可以保证代码的整洁度,也可以为后续的整合以及修改工作提供便利。在编写后端逻辑功能时,要时刻关注前端到后端再到数据库的数值传输,以此来确保模块功能的实现,同时减少代码编写过程中产生的bug。简而言之,代码的书写思路必须要清晰。在android 最初学习阶段,通常会遇到很多问题,Andorid 学习过程中知识点繁多,难以熟练的应用,不经过很长一段时间很难以熟练地运用自己所学的知识。其实Andorid 并不是很难,无非就是布局,Activity 中获取布局,对布局进行传值操作。并且学习Android 开发 fragment ViewPager 适配器是必不可少的,在任意一款app 中都有所应用。
    1 评论 1 下载 2019-07-09 15:15:28 下载需要13点积分
显示 0 到 15 ,共 15 条
eject