分类

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

资源列表

  • 基于JAVA EE的失物招领系统

    摘 要随着社会、经济和科学技术的不断进步发展,快节奏的生活方式让学生在校园生活中频繁出现丢失物品的状况,使学生遭受了经济和精神上的伤害。如今,丢失物品已经成为一个普通存在的问题,追寻一种高效率且有秩序的失物招领管理方式是当前社会共同向往的。失物招领工作信息化管理的实现有了必要性,只有信息化手段的介入,才能成为失物招领的一个方便可行的解决方案。本系统设计了基于JAVA EE开发的嘉园失物招领系统,失主可以通过网络进入到本系统的Web客户端查询自己丢失的物品是否已经发布到失物招领系统上,或者可以发布自己丢失的物品信息,使拾取到物品的人可以联系到失主,捡到物品的人同样可以发布拾取物品信息。管理员通过系统Web管理后台对寻物信息,招领信息,失物类别进行管理。一个良好的信息交流平台,使师生和工作人员能够及时找到失物,给校园生活带来了极大的方便。
    关键词:失物招领,系统设计,Web端,Java语言
    AbstractWith the continuous advancement of society, economy and science and technology, the fast-paced lifestyle has caused students to frequently lose items in campus life, causing students to suffer economic and mental damage. Nowadays, lost items have become a common problem. Pursuing an efficient and orderly management method of lost and found is the common aspiration of the current society. It is necessary to realize the information management of lost and found work. Only the intervention of information technology can become a convenient and feasible solution for lost and found. This system has designed the Jiayuan Lost and Found system based on JAVA EE development. The owner can access the Web client of the system through the network to check whether the lost items have been released to the lost and found system, or can publish the information of their lost items. The person who picks up the item can contact the owner, and the person who picks up the item can also post the items information. The administrator manages the search for information, claim information, and lost property category by web management backstage. A good information exchange platform enables teachers and students and staff to find lost property in time, bringing great convenience to campus life.
    Keywords: lost and found, system design, Web, Java
    引 言在如今信息发达的时代,快节奏的生活方式让学生在校园生活中频繁出现丢失物品的状况,使学生遭受了经济和精神上的伤害;从古至今,丢失物品就是一个普通存在的问题,追寻一种高效率且有秩序的失物招领管理方式是当前社会共同向往的。失物招领工作信息化管理的实现有了必要性,只有信息化手段的介入,才能成为失物招领的一个方便可行的解决方案。一个良好的信息交流平台,使学生失主能够及时找到失物,给校园生活带来了极大的方便。
    本系统采用了基于JAVA EE开发的嘉园失物招领系统,此失物招领系统是为失主和捡到物品的人搭建的一个信息交流平台,失主可以通过网络进入到本系统的Web客户端查询自己丢失的物品是否已经发布到失物招领系统上,或者可以发布自己丢失的物品信息,使拾取到物品的人可以联系到失主;捡到物品的人同样可以发布拾取物品信息;管理员通过系统Web管理后台对寻物信息,招领信息,失物类别进行管理。
    第1章 绪论1.1 项目背景当今,各大高校地域范围广、人口密度大,在校园生活中,学校师生经常来往于教师、图书馆、食堂等场所,随身物品如书籍、钥匙、饭卡、银行卡等生活用品难免容易丢失。即使有时丢失的是一些小物品,却可能对于失主来说有特别的意义和重要性或者包含失主的重要隐私。在信息技术时代,传统寻物招领方式已经不能满足人们的需要。传统张贴寻物启事、招领启事,其效率低、保密性差、管理不集中。易使失主遗忘,难以获取相关信息;从而给失主造成不必要的经济损失,同时也增大了管理人员的工作量。随着信息技术的迅速普及, 校园也慢慢地利用信息化技术进行管理[1]。开发校园失物招领系统,极大地提高认领率,减小失主经济损失,从而能够更好的服务于学校师生和工作人员。
    在国内外,失物招领系统在一些地区已经有了一定了发展,而且各地区有独自的特色的失物招领管理系统。相对于了国内,国外的失物招领系统开发较早,关注性强,用户通过账号密码登录系统查询失物,对于失物采取了现代信息化管理,具备了完善的失物数据库,管理效率高。在亚洲地区,各种失物招领机构遍布,可是依然采用人工管理的方式,其工作量巨大,物品运送规格难度艰巨,而建立一个网络数据库,可以免于失主奔波于各个失物招领机构。我国对于失物招领系统的建设工作也很重视,很多高校和地区同样建立了自己的失物招领管理系统。
    1.2 项目目的和意义开发该项目的目的是为了对于失物招领工作进行更加信息化、系统化、平台化的建设,而拾金不昧可以在一定层面上反映出学生的精神文明素质、道德修养水平、综合素质深度,对于拾金不昧的学生给予表扬和宣传是对当代大学生在道德修养、精神文明上的一种激励,一种正能量的鼓舞,使校园文化建设更加顺畅和谐。开发失物招领管理系统是一件迫在眉睫的事情, 并且该系统是基于网络的, 失主可以在网络上查询和报失以及确认[2]。通过功能模块的优化组合实现可以让失主在网络上发布失物,更加有利于找回自己的物品,拾取者也可发布失物信息,失主通过失物招领网络平台可以确定失物信息并招领,失物招领在线交易平台是为失主与拾获者之间进行失物招领提供的一个平台。有效的减少了工作量,便利了广大的师生及工作人员。失物招领网络平台的开发可以解决校园师生丢失物品的管理, 可以让失物招领部门工作人员高效的管理丢失物品, 降低工作人员的工作量, 以及方便全校师生, 使得师生在丢失物品后能够及时找回[3]。
    1.3 论文主要内容和结构安排本文介绍了基于JAVA EE的嘉园失物招领系统的设计与开发。

    第一章是绪论部分,对失物招领系统大致情况进行了简要介绍,简述了项目背景、项目目的和意义
    第二章是系统设计的技术和开发环境,介绍了系统开发所用到的关键技术,开发使用的语言和使用的开发环境
    第三章是对系统进行了整体的需求分析,工作流程的详细分解,功能模块的整体介绍
    第四章是系统的总体设计和详细设计分解,阐述了系统的各个功能模块的业务逻辑和数据结构
    第五章包括对系统的功能测试,整体研究工作的总结,对系统开发的过程和结果进行总结和展望

    第2章 系统涉及的技术和开发环境2.1 前端2.1.1 HTML超文本标记语言(HyperText Markup Language),标准通用标记语言下的一个应用。是网页制作必备的编程语言。“超文本”就是指页面内可以包含图片、链接,甚至音乐、程序等非文字元素。超文本标记语言的结构包括“头”部分(英语:Head)、和“主体”部分(英语:Body),其中“头”部提供关于网页的信息,“主体”部分提供网页的具体内容。
    2.1.2 CSS正层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。CSS不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式化。
    2.1.3 JqueryjQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。
    2.1.4 AngularJSAngularJS诞生于2009年,由Misko Hevery 等人创建,后为Google所收购。是一款优秀的前端JS框架,已经被用于Google的多款产品当中。AngularJS有着诸多特性,最为核心的是:MVC(Model–view–controller)、模块化、自动化双向数据绑定、语义化标签、依赖注入等等。
    2.2 后端2.2.1 JavaJava是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。
    2.2.2 MySQLMySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件。
    2.2.3 XML语言XML全称是Extensible Markup Language,即可扩展标记语言。XML技术是W3C组织发布的,目前推荐的国家标准是W3C组织于2000年发布的XML1.0规范[4]。
    2.3 开发环境2.3.1 MyEclispeMyEclipse,是在eclipse 基础上加上自己的插件开发而成的功能强大的企业级集成开发环境,主要用于Java、Java EE以及移动应用的开发。MyEclipse的功能非常强大,支持也十分广泛,尤其是对各种开源产品的支持相当不错。
    2.3.2 Navicat PremiumNavicat premium是一款数据库管理工具,是一个可多重连线资料库的管理工具,它可以让你以单一程式同时连线到 MySQL、SQLite、Oracle 及 PostgreSQL 资料库,让管理不同类型的资料库更加的方便。
    第3章 系统需求分析3.1 系统总体功能
    3.2 系统功能概述失物招领系统主要为了让在校师生及工作人员能够便于发布寻物信息和拾取物品的信息,还有通过失物招领系统进行丢失物品的检索等一些问题。大学生课外活动较多, 随身物品较多, 经常活动于不同的场所, 遗失物品的现象时有发生[5]。但是由于没有任何便利的平台来发布失物信息,使得很多人无法获取与之相关的信息,太多的失物,尤其是那些对失主很重要、但对拾得人却毫无价值意义的物品,如有效证件、钥匙,却再也找不回来[6]。这便使传统的失物招领工作中心带来了极大的工作量。而本系统的设计正是让在校师生及工作人员可以快速的对于失物进行检索和发布。
    3.3 系统需求概述失物招领系统服务于校园内的学生、教师和工作人员,该系统运行与校园网内,由失物招领处进行管理维护。失物者通过网络接入Web服务器, 向Web服务器发送各种请求[7]然后发布寻物启事信息,系统针对于每一个寻物启事提供相应的评论功能,其他人员可以访问系统查看各个寻物启事为失物者提供相关信息及线索。失物者在发布寻物启事信息的时候会要求填写管理密码,失物者可以通过该管理密码对相应的启事进行删除、修改操作,如若失物者已经获取了失物的相关线索,可以对该寻物启事进行删除操作,以保证失物者以及线索提供者的信息安全。拾物者可以发布招领启事信息, 拾物者在捡到失物的时候可以访问该系统,发布招领启事信息,填写信息或亦可上传相关图片等待他人认领。失主在失物招领系统中检索到自己的失物可以通过该招领启事信息中的联系人与拾物者联系。拾物者在确认物品已经被失物者领走以后,就可以访问系统将该招领启事信息删除。为了用户的信息安全,本系统对数据进行优化处理,如果发布的启事信息在六个月内未被删除,则启事信息的所有联系方式将成为报名状态,如果一年内未被删除,则启事信息将会被系统自动删除。
    管理员同样可以发布失物招领信息,同时,管理员可以登录失物招领管理后台,用户所有启事发布都会经过管理员审核,只有当管理员审核通过时,启事信息才会发布到系统上。管理员也是可以对失物分类、寻物启事、招领启事进行管理操作。
    3.4 功能需求分析3.4.1 管理员登录模块针对于校园环境的特殊性,管理员一般为校园失物招领处的负责人,只有知道管理员登录用户名和密码才可以进入失物招领管理后台。登录过程中实现安全登录,避免恶意登录、暴力破解或者通过直接输入路径进入失物招领管理后台。
    修改密码,如果管理员要进行密码修改,只有通过安全登录到失物招领后台才可进行修改密码操作,通过输入原密码和两次新密码即可完成修改密码操作。
    登录状态验证内部实现,用于验证管理员是否已经登录为能否正常使用功能的前提条件。
    3.4.2 物品审核模块当用户发布寻物启事或者招领启事时,并不会立即发布到失物招领系统上,而是需要经过管理员通过失物管理后台物品审核模块对于新发布的启事信息进行审核。管理员可以查看新发布启事信息详情,审核通过则发布启事信息,审核不通过则从数据库上删除该启事信息。
    3.4.3 首页展示模块管理员成功登录失物招领管理后台后,则显示失物管理后台首页,首页总共展示四项统计数据,分别为未审核寻物启事信息数量,总发布寻物启事信息数量,未审核招领启事信息数量,总发布招领启事信息数量。管理员可立即看到这四项统计数据,更加方便对于管理员快速对于待审核数据进行审核,提高用户体验性。
    3.4.3 数据统计模块对于失物信息数据的统计,不仅仅只包含首页展示模块中的数据统计。该数据统计模块,同样另外统计了四项数据,分别为寻找中寻物启事信息数量,已失效寻物启事信息数量,寻找中招领启事信息数量,已失效寻物启事数量。
    3.4.4 失物分类模块用户在失物招领系统中,在发布失物信息或者检索失物信息时,其失物分类是通过复选框来进行选择。失物分类的添加、修改、删除等操作则由管理员进行管理更新。
    3.4.5 寻物管理模块管理员对寻物启事信息进行管理,但管理员在失物管理后台不能够进行修改或者添加寻物启事信息,仅能进行查询和删除操作,显示页仅显示部分寻物启事信息,通过查看详情即可查看更多寻物启事信息。
    3.4.5 招领管理模块管理员对招领启事信息进行管理,但管理员在失物管理后台不能够进行修改或者添加招领启事信息,仅能进行查询和删除操作,显示页仅显示部分招领启事信息,通过查看详情即可查看更多招领启事信息。
    3.4.6 失物展示模块失物招领系统的失物展示, 用户进入系统主界面后即可查看到最新发布的失物招领信息,首页仅显示最新一周内发布的失物招领信息,如果首页没有查看到要寻找的物品,可以通过导航栏中的寻物启事或招领启事中进入完整启事信息列表,即可通过精准查询检索到需要寻找的物品。如果用户需要进行快速检索操作,可以进入导航栏通过快速检索输入物品特征进行快速搜索。
    3.4.7 失物添加模块用户通过访问失物招领系统首页即可查看到寻物启事发布、招领启事发布两个按钮,根据需求选择需要发布的信息按钮,进入信息发布页面,信息发布页面中有多条信息需要填写,其中带星号标识的表单是必须填写的。
    3.4.8 失物详情模块通过失物展示模块可以查看失物详情,每个失物展示模块都且仅有一个对应的失物详情链接。失物详情页面显示了该失物的所有信息包括图片。在失物详情模块中可以进行评论操作,管理启事操作。
    3.4.9 失物操作模块在用户发布启事信息时,要求用户填写相应的管理密码,在对启事信息进行相应的修改操作或删除操作时将会用到。用户通过点击管理启事而出现的下拉框中选择删除或修改操作后,输入相应的密码即可进行操作。当用户选择修改操作时,输入正确的管理密码后,则出现弹窗,用户选择需要进行修改的数据进行修改即可完成操作。当用户选择删除操作时,输入正确的密码后,可以进行删除操作,系统会再次提醒用户是否确认删除,用户进行相应的选择即可完成删除操作。
    忘记密码,用户在忘记自己当初设置的管理密码时,可以在填写密码的表单中点击忘记密码链接,则会出现一个弹窗,该弹窗会要求用户输入启事信息相应的信息编号,信息编号在启事详情信息中有显示,发送信息编号后,管理密码会发送到改启事信息用户的预留邮箱,邮箱为用户在添加启事信息时的必填项。
    3.4.10 评论操作模块当其他人员浏览启事信息时,可以对相应的启事信息进行评论。评论主要目的就是提供失物的线索,方便失主可以找回自己的物品。
    3.3 非功能性需求系统非功能性需求主要包括以下几个方面:
    (1)界面需求友好性
    Web模式长期使用时需要保证用户进入系统后可以寻找到主要的关注点,就是直接在首页显示一周内的失物招领信息,在页面变化时添加过渡动画,在加载数据量大的内容时需要显示加载动画,提高人机交互体验性。需要有简洁清晰的界面来形象的显示。
    (2)操作需求准确性
    所有操作应当简便易用,所有涉及数据操作的内容都需要对用户操作进行判断限制,所有关键操作如删除、新增、修改等都需要用户进行确认,防止用户误操作导致数据错误。
    (3)用户体验感
    简洁清晰的页面,整体交互简单直接,各页面之间切换流畅,可保留已打开的页面,所有信息保持时效性,保有充分的用户操作提示信息。
    第4章 系统设计与实现4.1 系统设计目标对于当今校园失物招领工作的独特性,工作量较大,工作繁琐性等特征,同样, 捡到物品的学生也因为缺少相应的平台而难以将物品归还给失主[8]。同学们在丢失物品之后不知道怎么有效找寻丢失的物品,很多的大学的论坛,qq群,微信群等等地方有很多这种消息,但是通过QQ群这些方式发送寻物启事和失物招领的消息受用户权限限制,传播效率并不高[9]。本文主要设计和实现校园失物招领系统。充分利用校园网络坏境,使用校园网,发挥信息化手段的特性,使失物招领信息传播速度快,发布和检索方便实时且支持Web端等特点,最大效率上保证了丢失物品和被拾取物品的信息快速发布,让校园内师生及其工作人员快速得到失物信息。
    4.2 系统总体功能设计模块失物招领管理系统主要分为两个部分,涉及前台和后台,主要的技术是基于Java语言,用户界面是bootstrap框架,可运行于Windows操作系统。主要包括管理员登录模块、失物招领模块、寻物启事模块等,系统整体功能模块划分流程图如下图4-1所示。

    本系统分为两个子系统,分别为Web前台子系统、Web后台子系统,两个子系统使用同一个数据库。Web前台子系统主要是用户使用来发布启事信息、浏览启事信息等操作,Web后台子系统增加了管理员操作部分,具有管理员登录、管理失物类别等操作。
    4.2.1 系统开发环境与平台
    运行环境: windows XP/win7/win8/win10
    开发环境:Windows 10
    使用语言:Java,javascrip
    引用框架:Spring、SpringMVC、Mybatis
    关键工具包:httpclient(调用系统服务)
    开发工具:MyEclipse 2017 CI和Navicat Premium
    数据库:MySQL
    引用开源库:Jquery、日期和时间库、Json解析库和单元测试库等

    4.3 系统架构设计4.3.1 传统架构采用这种架构存在的问题,模块之间耦合度太高,其中一个升级其他都得升级,开发困难,各个团队开发最后都要整合一起,系统的扩展性差,不能灵活的进行分布式部署。
    4.3.2 分布式架构把系统拆分成多个工程,要完成系统的工程需要多个工程协作完成。这种形式叫做分布式。采用这种架构的优点,把模块拆分,使用接口通信,降低模块之间的耦合度。把项目拆分成若干个子项目,不同的团队负责不同的子项目。增加功能时只需要再增加一个子项目,调用其他系统的接口就可以。可以灵活的进行分布式部署。采用这种架构的缺点,系统之间交互需要使用远程通信,接口开发增加工作量。
    4.3.3 系统选用架构本系统采用的架构就是分布式架构,大大降低了系统的耦合度,可以对系统进行灵活的分布式部署。系统的结构主要分成为三层:数据层、服务层和用户层。数据库用于存储数据,使用数据库来实现。用户层通过HttpClient来调用服务层的提供的服务,服务层用于解析用户层的请求并根据数据库的信息处理Web前台客户端的请求。服务层运行于Java虚拟机上,用户层主要运行于Web浏览器上,负责信息的呈现和引导用户进行操作,服务层和数据层直接与数据库进行通信。服务层和用户层之间则通过网络进行通信。

    数据层以数据库的方式来实现,Web前台客户端和Web后台管理端使用的是同一个数据库,因此无需考虑信息同步问题服务层分为数据处理层和网络层,数据处理层从网络层得到用户层发送过来的请求进行处理并将处理结果通过网络层发送至用户层服务层和数据层之间的数据传输通过数据处理使用SQL查询语句和Mybatis框架的使用来访问数据库,数据层返回结果集合到服务层服务层和用户层的数据传输格式需要统一,因此服务层和数据层传输数据时统一使用JSON格式。即发生放将数据转换成JSON格式再发送出来。然后从JSON中提取出所需的数据
    MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。

    Model层主要负责实现具体业务功能的类
    View层是与用户的交互层,负责提交用户的请求和数据,并将后端的响应的结果返回给用户层,同时提供用户提交信息的验证功能
    Controller层负责项目中的业务功能实现流程的管理工作,哪些类来实现具体业务功能,结果在哪显示等由Controller层控制,同时还负责其他两层的通信,协助传递信息和负责重定向与转发操作

    4.4 系统数据库设计4.4.1 管理员登录管理员表中给出了各个属性的数据类型、长度及主外键说明。管理员信息中采用的Spring Security框架默认的BCrypt算法加密存储登录密码。
    BCrypt,是一个跨平台的文件加密工具。由它加密的文件可在所有支持的操作系统和处理器上进行转移。它的口令必须是8至56个字符,并将在内部被转化为448位的密钥,所提供的所有字符都具有十分重要的意义。密码越强大,您的数据就越安全。管理员信息表的设计如表4-1 所示。



    字段名
    说明
    键值
    数据类型
    备注




    id
    管理员编号
    主键
    Bigint(20)
    不为空


    username
    用户名

    varchar(50)
    不为空


    password
    密码

    varchar(100)
    不为空


    phone
    手机号码

    Varchar(20)



    email
    联系邮箱

    varchar(50)



    4.4.2 失物分类当用户添加启事信息或者检索启事信息时,用户将采用下拉框的形式来选择失物分类,因此,失物分类由后台添加,主要有主键和分类名称两个属性组成,失物分类信息表中给出了各个属性的数据类型、长度及主外键说明。失物分类信息表的设计如表4-2 所示。



    字段名
    说明
    键值
    数据类型
    备注




    id
    分类编号
    主键
    Bigint(20)
    不为空


    category_name
    物品分类名称

    varchar(50)
    不为空



    4.4.3 寻物启事寻物信息表除了包含失物所包含的属性数据类型、对应字段、长度、主键外,还包含了外键,表中详细的定义了失物的各类属性名称,还有两个比较特殊的属性,一个是审核状态,两一个是管理密码,审核状态包含0表示未审核,1表示审核通过,2表示审核未通过。寻物启事信息表的设计如表4-3 所示。



    字段名
    说明
    键值
    数据类型
    备注




    id
    启事编号
    主键
    Bigint(20)
    不为空


    category_id
    分类编号
    外键
    Bigint(20)
    不为空


    lost_place
    失物地点

    varchar(50)
    不为空


    lost_time
    丢失时间

    datetime
    不为空


    infoTitle
    信息标题

    varchar(100)
    不为空


    rewards
    悬赏金额

    varchar(100)



    description
    详情描述

    text
    不为空


    images
    物品图片

    varchar(255)



    status
    审核状态

    int(1)
    不为空


    contacts
    联系人

    varchar(255)



    tel
    手机号码

    varchar(50)



    QQ
    QQ号码

    varchar(50)



    email
    联系邮箱

    varchar(50)
    不为空


    address
    联系地址

    varchar(255)



    password
    管理密码

    varchar(20)
    不为空



    4.4.4 招领启事招领启事信息表与寻物招领启事表类似,但是唯一一个不同的招领启事不含有悬赏金额属性,其除了常规的属性名称对应字段、类型长度的定义外,也是同样包含了一个失物分类信息表的外键,说明了外键关联表和其定义。招领启事信息表的设计如表4-4 所示。



    字段名
    说明
    键值
    数据类型
    备注




    id
    启事编号
    主键
    Bigint(20)
    不为空


    category_id
    分类编号
    外键
    Bigint(20)
    不为空


    found_place
    拾物地点

    varchar(50)
    不为空


    found_time
    拾取时间

    datetime
    不为空


    infoTitle
    信息标题

    varchar(100)
    不为空


    description
    详情描述

    text
    不为空


    images
    物品图片

    varchar(255)



    status
    审核状态

    int(1)
    不为空


    contacts
    联系人

    varchar(255)



    tel
    手机号码

    varchar(50)



    QQ
    QQ号码

    varchar(50)



    email
    联系邮箱

    varchar(50)
    不为空


    address
    联系地址

    varchar(255)



    password
    管理密码

    varchar(20)
    不为空



    4.4.5 评论管理基于为了让物品找回能够有多种方式,实现了在查看物品详情信息后可以在详情信息底下留下失物信息,可以在不使用其他方式的情况下以另一种形式通知失主。评论信息表包含常规的属性名称对应字段、类型长度的定义。评论信息表的设计如表4-5 所示。



    字段名
    说明
    键值
    数据类型
    备注




    id
    启事编号
    主键
    Bigint(20)
    不为空


    goods_id
    物品编号

    Bigint(20)
    不为空


    comment_text
    评论内容

    text
    不为空


    comment_time
    评论时间

    datetime
    不为空



    4.4.6 详情信息当我们查看失物的基本信息后,想要深入的了解失物的详情信息时,便可以点击失物进入详情信息页面,详情信息表包含常规的属性名称对应字段、类型长度的定义。详情信息表的设计如表4-6 所示。



    字段名
    说明
    键值
    数据类型
    备注




    id
    启事编号
    主键
    Bigint(20)
    不为空


    goods_id
    物品编号

    Bigint(20)
    不为空


    publish_time
    发布时间

    datetime
    不为空


    page_view
    浏览次数

    int(11)
    不为空


    status
    启事状态

    int(1)
    不为空



    4.5 Web管理后台功能模块实现4.5.1 登录模块的设计与实现登录模块的设计,众所周知想要对Web资源和其他后端内部信息进行保护,最好的办法莫过于Filter,要想对方法调用进行保护,最好的办法莫过于AOP。所以Spring Security框架在我们进行用户认证以及授予权限的时候,通过各种各样的拦截器来控制权限的访问,从而实现安全。所以,我们设计了Web管理后台的安全登录,采用了Spring Security框架具体实现。
    登录模块的实现,一个能够为基于Spring的企业应用系统提供声明式的安全防问控制解决方式的安全框架,简单说是对访问权限进行控制,应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。 spring security的主要核心功能为 认证和授权,所有的架构也是基于这两个核心功能去实现的。下图4-2就是权限认证未通过登录状态效果图。

    管理员输入正确的用户名和密码成功经过Spring Security框架权限认证后直接进入首页,登录后页面如下图4-3成功登录效果图。

    管理员安全登录系统之后,如若想要修改密码,可通过界面点击修改密码按钮,按标准填写原密码与新密码即可完成操作。下图4-4为修改密码效果图。

    4.5.2 启事审核模块的设计与实现启事审核的设计,关于这模块的设计是为了防止用户恶意刷数据,还有用户发布的数据存在问题等一些问题,导致数据库无效数据的大量堆积,造成用户的体验感极低,网站的负荷、数据库的压力过大。那么,我们应该考虑一种从最优的角度去避免这样的情况发生,就是每次用户发布的寻物启事信息或者招领启事信息都经过管理员审核,虽然从另一种角度来看,增加了失物招领处的工作量,但是利大于弊,保证了用户发布的失物信息的质量和有效性。
    启事审核的实现,了解了启事审核模块的目的和整体设计,关于启事审核模块的实现,首先,寻物启事信息表和招领启事信息表都有一个status属性字段,其中当status值为0时,为未审核状态,当status值为1时,为审核通过状态,而当status值为2时,为审核未通过状态。
    我们默认用户发布的寻物启事信息或者招领启事信息的status值为0,失物招领后台管理系统将会拦截所有审核状态status值为0的数据,要求进行审核,才能发布到失物招领前台客户端。拦截的数据通过管理员经过严格审核之后,审核状态status值为1的数据则放行,而审核状态status值为2的数据则将其从后台数据库删除。下图4-5为启事审核流程图,图4-6为启事审核效果图。


    4.5.3 失物分类管理模块的设计与实现失物分类管理模块的设计,用户在失物招领系统中,在发布失物信息或者检索失物信息时,其失物分类并不是自己填写而是通过复选框来进行选择,所有失物类别的数据由后台进行管理。
    失物分类管理模块的实现,主要实现了对失物分类的增加、删除、修改与查询,失物可批量删除,查询数据方面通过输入分类名称进行模糊查询相关数据。显示数据方面实现了分页显示,管理员可以设置一页显示的数量等。下图4-7为分类管理效果图。

    4.5.4 寻物启事管理模块的设计与实现寻物启事管理模块的设计,首先考虑到保证用户数据的安全性等其他问题,失物招领后台管理不允许对用户的启事信息进行修改操作,添加失物信息则在失物招领前台客户端实现。所以,后台仅实现了对于启事信息的删除和查询操作。招领启事管理模块类似于此。
    寻物启事管理模块的实现,对于启事信息分页显示,实现了批量删除操作,考虑删除操作的危险性,使用layer弹窗框架显示警示提醒。查询数据实现精准查询,用户可以选择失物分类,选择日期开始时间,日期结束时间,关键字进行查询。日期组件选择了angular ui-bootstrap日期控件,引入了中文文件,方便用户操作。下图4-8为启事信息管理模块效果图。

    4.5.5 数据统计模块的设计与实现数据统计模块的设计,数据统计的首要就是简要明了,让管理员能够清晰的统计数据信息,失物招领管理后台的数据统计主要设计了已失效招领启事数据统计,已失效寻物启事数据统计,寻找中招领启事数据统计,寻找中寻物启事数据统计。
    数据统计模块的实现,通过前端请求数据,后端响应的数据以echarts数据饼状图图形化的形式展示,ECharts,缩写来自Enterprise Charts,商业级数据图表,一个纯Javascript的图表库,可以流畅的运行在PC和移动设备上,兼容当前绝大部分浏览器(IE6/7/8/9 /10/11,chrome,firefox,Safari等),底层依赖轻量级的Canvas类库ZRender,提供直观,生动,可交互,可高度个性化定制的数据可视化图表。创新的拖拽重计算、数据视图、值域漫游等特性大大增强了用户体验,赋予了用户对数据进行挖掘、整合的能力。ECharts为百度的推出一款相对较为成功的开源项目,总体上来说有这样的一些优点,ECharts容易使用,ECharts支持按需求打包,ECharts开源支持中国地图功能。下图4-9为数据统计效果图。

    4.6 Web前台客户端功能模块实现4.6.1 失物招领首页设计与实现失物招领的首页设计主要以美观简洁易操作为主旨,通过首页导航栏可进入寻物启事、招领启事、发布信息和快速检索等页面,下图4-10为失物招领首页效果图,图4-11为最新一周寻物招领启事资讯效果图。
    g)

    4.6.2 快速检索模块的设计与实现为了让用户快速查找到目标、提升用户的搜索体验和输入效率,本系统实现了搜索关键字智能提示。下图4-12为快速检索效果图。

    4.6.3 启事信息发布的设计与实现用户发布启事信息时,部分信息为必填项,其余选填,启事添加实现了添加图片插件BootStrap FileInput和日期选择插件angular ui-bootstrap,两者样式非常美观,提升了用户的体验感。下图4-13为启事信息发布效果图。

    4.6.4 启事详情信息的设计与实现通过查看物品启事时,可点击查看详情信息页面,可进入物品详情页面,在物品详情页面可以查看物品的所有信息,包括详情信息浏览次数、物品图片、物品详情页面评论信息、物品详情描述、管理启事操作等。下图4-14为物品详情信息效果图,图4-15为物品详情信息页面评论信息效果图。


    4.6.5 管理启事的设计与实现管理启事主要设计了删除启事功能、修改启事功能与忘记密码操作功能。当用户发布寻物启事信息或招领启事信息时,会要求用户必须填写管理密码,这在用户对其发布的启事信息进行修改操作或删除操作时使用,用户必须输入正确的管理密码才能进行此项操作,如若用户忘记密码,可通过点击忘记密码链接后弹窗输入启事信息编号,则管理密码将会发送到当用户发布寻物启事信息或招领启事信息时要求用户必须填写的邮箱上,用户收到邮箱信息信息即可得到管理密码。下图4-16为管理启事效果图,图4-17为忘记密码操作效果图,图4-18为修改启事信息效果图。



    第5章 系统测试与结果分析失物管理系统的测试主要是为了保证系统各功能模块的正常运行,保证系统能满足功能,并且防止在用户进行操作时放置出现不在系统限制的范围内,需要对系统进行一些功能测试,目的在于发现错误和不满足需求的部分,并对发现的问题进行修复。
    5.1 系统测试环境选择
    客户端硬件:PC
    客户端软件环境:Windows 10
    数据库:MySQL
    版本控制:GIT

    5.2 测试计划系统完成后,需要对其进行各功能模块进行测试,下面以寻物启事管理模块为例,进行测试计划。寻物启事模块具体如表5-1所示。



    功能
    输入
    输出




    新增寻物启事
    点击发布寻物启事信息
    跳转到寻物启事发布页面,显示待填写表单。



    输入必填信息




    点击发布按钮
    提示操作结果,刷新页面


    启事信息审核
    点击审核处理
    弹出启事审核弹窗,显示启事信息



    点击审核结果选项
    提示操作结果,刷新待审核启事信息表


    修改寻物启事
    点击启事详细信息,点击管理启事,输入管理密码,点击修改启事
    弹出待修改启事所有信息弹窗并回显图片



    输入修改信息




    点击修改按钮
    提示操作结果,刷新页面


    搜索寻物启事
    选择搜索条件,输入搜索关键字




    点击搜索按钮
    显示所需的寻物启事信息


    删除寻物启事
    选择需删除寻物启事或全选本页寻物启事




    点击删除按钮
    提示操作结果,刷新页面



    5.3 测试用例测试用例主要由以下几张表构成为寻物启事管理模块测试。新增寻物启事功能如表5-2所示,审核寻物启事功能测试如表5-3,搜索寻物启事功能测试如表5-4所示,修改寻物启事功能测试如表5-5所示,删除寻物启事功能测试如表5-6所示。
    表5-2 新增寻物启事功能测试



    测试用例
    Test01




    测试项目
    新增寻物启事


    输入
    1. 点击发布寻物启事按钮 2. 点击选择失物分类 3. 寻物启事信息必填项 4. 点击选择图片 5. 点击选择日期 6. 点击发布按钮


    执行步骤
    1. 进入失物招领首页 2. 点击发布寻物启事按钮 3. 进入寻物启事发布页 4. 选择失物分类为“宠物” 5. 选择图片并上传“宠物图片” 6. 选择丢失日期为“2019-3-5” 7. 输入寻物启事信息必填项 8. 点击提交按钮


    预计输出
    1. 正确完成填写所有必填项,显示“发布成功”弹窗,选择返回首页,或继续发布信息。 2. 若填写发生错误,提示错误信息。



    表5-3 审核寻物启事功能测试



    测试用例
    Test02




    测试项目
    审核寻物启事


    输入
    1、 点击寻物审核 2、 选择寻物启事点击审核处理 3、 点击审核结果(审核通过或未通过)按钮


    执行步骤
    1、 进入失物招领管理后台首页 2、 首页显示未审核寻物启事数量 3、 点击物品审核选择寻物启事审核 4、 选择要审核的寻物启事点击审核处理 5、 浏览审核寻物启事 6、 点击审核通过按钮


    预计输出
    1、 审核通过,提示“审核通过”,刷新待审核寻物启事列表,列表中审核的寻物启事消失,审核通过的寻物启事成功发布。



    表5-4 搜索寻物启事功能测试



    测试用例
    Test03




    测试项目
    搜索寻物启事


    输入
    1. 选择失物分类 2. 选择开始日期 3. 选择结束日期 4. 关键字 5. 点击搜索按钮


    执行步骤
    1. 进入寻物启事页面 2. 选择失物分类为“钱包” 3. 选择开始日期为“2019-3-1” 4. 选择结束日期为“2019-3-12” 5. 输入关键字“粉色钱包” 6. 点击搜索按钮


    预计输出
    1、显示寻物启事失物分类为钱包,日期范围在2019-3-1到2019-3-12,物品特征为粉色钱包的记录。



    表5-5 修改寻物启事功能测试



    测试用例
    Test04




    测试项目
    修改寻物启事功能测试


    输入
    1、 输入管理密码 2、 点击前往修改 3、 修改失物地点 4、 修改丢失日期 5、 点击确认修改


    执行步骤
    1、 选择寻物启事 2、 点击查看详情 3、 点击管理启事 4、 选择修改启事 5、 输入管理密码 6、 点击前往修改 7、 修改失物地点为“主五#402” 8、 修改丢失日期为“2019-03-03” 9、 点击确认修改


    预计输出
    1、 提示修改成功,并刷新寻物启事详情页面,修改信息成功显示到寻物启事详情页面。 2、 发生错误,寻物启事详情未发生改变,提示错误信息。



    表5-6 删除寻物启事功能测试



    测试用例
    Test05




    测试项目
    删除寻物启事功能测试


    输入
    1. 点击管理启事 2. 点击删除按钮 3. 进入删除页面 4. 输入管理密码 5. 点击确认删除按钮


    执行步骤
    1. 进入寻物启事详情页面 2. 点击管理启事 3. 点击删除按钮 4. 进入删除页面 5. 输入管理密码“123456” 6. 点击确认删除按钮 7. 弹窗提示确认操作 8. 点击确定按钮


    预计输出
    1. 提示“删除成功”,刷新失物招领首页,选择的寻物启事已被删除掉 2. 提示“密码错误请重新输入”,重新输入。



    5.4 测试结果与分析通过一系列的功能测试,所有模块的测试结果与预计输出一致,符合预期的功能需求。
    结 论通过对校园失物招领所碰到的实际问题的具体分析,联系国内外失物招领网站的特征,开发和设计了失物招领系统。该系统不仅融合了校园信息化工作的特征,将传统的失物招领工作信息化,网络化,依靠全校学生的力量就能够很快地找到所失之物, 从而减少经济及精神损失, 规范学校的校风校貌, 有利于创建一个“无遗”的和谐校园[10]。
    本文主要阐明了失物招领系统的设计与实现,从该项目的背景,到该系统开发所用的技术框架和系统运行环境,再到系统的需求分析和功能的详细描述和实现过程。本系统主要重点部分在于启事信息的发布和查询浏览,通过对启事信息模块化的显示,使用户浏览更加便利,顺应了当前校园坏境下对系统的要求和实际需求,通过系统网络化的方式可以提高系统在校园坏境下的使用率,可以真正的提高校园寻回失物的机会。
    失物招领系统实现了启事信息发布、启事信息的快速查询、启事信息的精准查询、启事信息的审核功能、启事信息的数据统计等功能。通过本系统可以大大缓解高校失物招领工作中的一些繁复流程,提升了效率,有一定的应用和推广价值[11]。
    参考文献
    [1]吴江平.高校失物招领管理系统的研究与分析[J].科技广场, 2015年11期:32-35.
    [2]董伟东.失物招领系统的建立[J].计算机光盘软件与应用, 2014年01期: 251-252.
    [3]谭伟,林俊存.基于JSP的高校失物招领网络平台的设计与实现[J].电子世界, 2016年21期:109-110.
    [4]唐志婧.基于Android的校园失物招领平台的设计与实现[D].内蒙古自治区:内蒙古大学,2017.
    [5]周梦萍.基于J2EE的高校失物招领系统的开发设计[J].福建电脑,2018年04期:125-126.
    [6]陈玲.遗失物招领付费之研究[J].成都理工大学学报(社会科学版), 2016年01期:34-38.
    [7]刘莹.校园失物招领公益性管理系统[J].福建电脑, 2017年11期:128.
    [8]邹骅.基于微信公众平台的校园失物招领系统设计[J].河北软件职业技术学院学报,2017年03期:228.
    [9]查玉华,胡开华,张玉静.基于Web的校园寻物网站设计[J].电脑知识与技术, 2016年32期:49-50.
    [10] 张瑾,马皎,史伶丽,丁学翠,董莉霞.校园失物招领管理网页的开发[J]. 机电信息,2018年33期:118-119.
    [11]高越.高校失物招领系统的设计与实现[D].吉林省:吉林大学,2017.
    11 评论 299 下载 2020-06-07 09:48:33
  • 基于JSP的小区物业管理系统设计与实现

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

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

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

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

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

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

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

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



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




    I01-1
    房产编号
    id
    no
    主键


    I01-2
    备注信息
    beizhu
    yes
    备注


    I01-3
    时间
    createtime
    yes
    添加时间


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


    I01-5
    结构
    fangwujiegou
    yes
    房屋结构


    I01-6
    门牌号
    menpaihao
    yes
    门牌号


    I01-7
    面积
    mianji
    yes
    房屋面积


    I01-8
    设备
    shebei
    yes
    设备


    I01-9
    住址
    zhuzhi
    yes
    住址


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


    I01-11
    投诉编号
    id
    no
    主键


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


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


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


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


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


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


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


    I01-19
    维修编号
    id
    no
    主键


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


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


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


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


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


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


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


    I01-27
    业主编号
    Id
    no
    主键


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


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


    I01-30
    业主姓名
    huzhuxingming
    yes
    姓名


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


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


    I01-33
    业主住址
    zhuzhi
    yes
    住址


    I01-34
    用户编号
    id
    no
    主键


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


    I01-36
    用户密码
    password
    yes
    密码


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


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


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


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


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


    I01-42
    缴费编号
    id
    yes
    主键


    I01-43
    备注
    beizhu
    yes
    备注


    I01-44
    费用
    feiyong
    no
    费用


    I01-45
    费用周期
    feiyongzhouqi
    yes
    周期


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


    I01-47
    缴费类型
    leixing
    yes
    类型


    I01-48
    缴费时间
    shoufeishijian
    yes
    时间


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


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


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




    数据流编号:D1—01

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

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

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

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

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

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

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

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

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

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


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

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

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



    名称
    类型

    备注




    id
    bigint(20)
    no
    主键


    beizhu
    varchar(255)
    yes
    备注


    createtime
    datetime
    yes
    添加时间


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


    fangwujiegou
    varchar(255)
    yes
    房屋结构


    menpaihao
    varchar(255)
    yes
    门牌号


    mianji
    varchar(255)
    yes
    房屋面积


    shebei
    varchar(255)
    yes
    设备


    zhuzhi
    varchar(255)
    yes
    住址


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



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



    名称
    类型

    备注




    id
    bigint(20)
    no
    主键


    beizhu
    varchar(255)
    yes
    备注


    createtime
    datetime
    yes
    添加时间


    feiyong
    varchar(255)
    yes
    费用


    feiyongzhouqi
    varchar(255)
    yes
    费用标题


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


    leixing
    varchar(255)
    yes
    缴费类型


    shoufeishijian
    datetime
    yes
    收费时间


    shoufeizhuangtai
    varchar(255)
    yes
    缴费状态


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


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



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



    名称
    类型

    备注




    id
    bigint(20)
    no
    主键


    chulifankui
    varchar(255)
    yes
    处理反馈


    chulijieguo
    varchar(255)
    yes
    处理结果


    content
    varchar(255)
    yes
    投诉内容


    createtime
    datetime
    yes
    添加时间


    title
    varchar(255)
    yes
    投诉标题


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


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



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



    名称
    类型

    备注




    id
    bigint(20)
    no
    主键


    chulifankui
    varchar(255)
    yes
    处理反馈


    chulijieguo
    varchar(255)
    yes
    处理结果


    content
    varchar(255)
    yes
    维修内容


    createtime
    datetime
    yes
    添加时间


    title
    varchar(255)
    yes
    维修标题


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


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



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



    名称
    类型

    备注




    id
    bigint(20)
    no
    主键


    dianhuahaoma
    varchar(255)
    yes
    电话号码


    huzhufz
    varchar(255)
    yes
    业主身份证


    huzhuxingming
    varchar(255)
    yes
    姓名


    ruzhushijian
    varchar(255)
    yes
    入住时间


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


    zhuzhi
    varchar(255)
    yes
    住址



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



    名称
    类型

    备注




    id
    bigint(20)
    no
    主键


    createtime
    datetime
    yes
    添加时间


    password
    varchar(255)
    yes
    密码


    role
    int(11)
    no
    用户权限


    truename
    varchar(255)
    yes
    真实姓名


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


    username
    varchar(255)
    yes
    用户名


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



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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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



    动作
    期望结果
    实际情况




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


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


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


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



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

    1 概述1.1 课程设计目的加深TCP/IP协议的理解,掌握TCP四次握手机制,同时熟悉socket编程。
    1.2 课程设计内容实现一个端口扫描器:

    支持多进程/线程
    能对单个指定主机进行扫描或扫描指定网段内的主机
    能扫描特定的部分端口或对指定的端口段内的端口进行逐个扫描
    能够显示所开放端口的服务名称

    1.3 运行环境
    操作系统:Windows 7及以上版本系统
    开发环境:Microsoft Visual Studio 2013

    2 系统分析与设计2.1 原理概述端口扫描有好几种,但其中TCP connect扫描是最基本的扫描,我们可以利用系统提供的connect()用来与每一个目标计算机的端口进行连接。如果端口处于侦听状态,那connect()就能成功。否则,这个端口即是不可用的,也就是说没有提供服务。这个技术的一个最大的优点是,你不需要任何权限。系统中的任何用户都有权利使用这个调用。另一个好处就是速度,如果对每个目标端口以线性的方式,使用单独的connect()调用,那么将花费相当长的时间,使用者可以通过多线程同时打开多个套接字来加速扫描。使用非阻塞I/O允许设置一个低的时间用尽周期,同时观察多个套接字。但这种方法的缺点是很容易被察觉,并且被防火墙将扫描信息包过滤掉。目标计算机的Logs文件会显示一连串的连接和连接出错消息,并且能很快使它关闭。
    2.2 程序流程图
    说明:扫描器可实现对单个主机单个端口的扫描也可实现对网段内主机和范围内端口进行逐个扫描,因此操作时要注意是单个主机扫描还是多个IP地址扫描,以及扫描端口范围。确定扫描IP和扫描端口后点击开始即可对相应IP下的端口进行侦听,并返回端口状态,如果端口开放则同时返回端口服务,扫描结束后线程停止。
    2.3 主要数据结构private string ipStart; // 起始IP地址private string ipEnd; // 终点IP地址private int portStart; // 开始端口private int portEnd; // 结束端口private int numThread=20; // 分配的线程数,默认最小为20private int overTime; // 超时限制private Thread t; // 定义一个线程private Thread scanthread; // 端口扫描线程private bool[] done = new bool[65536]; List<string> str; // 扫描结果集
    2.4 主要算法设置好IP地址和端口范围后,开辟线程,开始扫描:
    利用PingReply对象试探目标主机,如果超时则表示不可达,否则连通,显示端口扫描状态,如果端口开放,显示服务。
    2.5 主要函数说明// 界面初始化函数private void Form1_Load(object sender, EventArgs e); // 开始按钮函数private void button1_Click(object sender, EventArgs e);// 扫描IP地址线程public void wait();// 判断端口状态函数,返回(open或closed)public string State(int i);// 根据开放端口号返回具体服务public string Service(int i);// 扫描端口线程public void Scan(object Point);// 停止按钮事件函数private void button2_Click(object sender, EventArgs e);// 关于按钮事件函数private void button3_Click(object sender, EventArgs e);// 超时设置函数private void trackBar1_Scroll(object sender, EventArgs e);// 点选按钮函数private void checkBox2_CheckedChanged(object sender, EventArgs e);
    3 用户使用手册端口扫描器主界面

    运行程序系统进入主界面,主界面中主要包括以下布局:IP地址设置、端口范围设置、线程数设置、Ping超时时间限制、扫描进度、显示扫描结果、开始停止和关于按钮。
    扫描单个主机或单个端口
    当需要扫描单个主机或者单个端口是,需要点选“扫描单个主机”、“扫面单个端口”选框,这时IP范围设置和端口范围设置各自的第二个编辑框变为只读属性,无法再填写相应字段。

    设置线程数和超时限制
    由于多线程,可以分配多个线程,但为了避免消耗过多资源导致主机奔溃建议1-30;超时限制可通过TrackBar滑动选择,默认为10-30s,注意下方的编辑框是只读属性。

    开始、停止、关于按钮
    设置好需要扫描的IP和端口后,点击开始按钮,即可进行扫描,点击停止,将线程挂起,扫描结束。点击关于按钮,弹出个人信息及软件反馈地址。

    显示扫描结果
    通过richTextBox控件显示扫描结果找出开放端口,ListBox控件动态显示扫描结果,包括扫描IP地址,端口号,端口状态(closed、open),以及开放端口服务名称。

    4 心得体会与总结4.1 心得体会如图:对主机就127.0.0.1进行测试,符合预期结果。


    根据计算机网络知识,可以看到通过对单个主机和网段内的多个主机进行端口扫描都得到了正确结果。创建一个socket,通过TCP connect()测试该主机的某个端口是否能够连通,获得该端口的状态,如果open则获知它的服务。
    当然由于采用TCP connect()方法,不可避免的有它的缺陷,因为大量无需权限的访问,容易被防火墙过滤掉,因此可以进行这方面的改进。可以采用TCP SYN扫描、TCP FIN扫描、TCP反向ident扫描、FTP返回攻击等。
    4.2 总结通过这次课程设计,一方面我熟悉了C#方面基本的网络编程和socket编程,同时对TCP连接的过程有了更深入的理解,包括封装API的调用,握手机制等。为了解决这一过程中遇到的问题,除了课本还查阅了很多资料,对网络编程也有了不少的心得,总得来说收获满满!
    5 评论 118 下载 2018-11-05 15:37:28
  • 基于JSP和SQL Server的网上花店销售系统的设计与实现

    摘 要随着时代的快速发展,我们的生活已经离不开计算机网络,而电子商务的快速发展正在改变着人们的生活方式。随着各种网上购物平台的不断兴起,人们早已习惯了不用出门就买到自己需要的东西。但是针对鲜花销售这方面的网络平台还很少,因此设计一个网上花店销售系统很有前景。
    网上花店销售系统采用JSP+Servlet+JavaBean的MVC模式,将数据对象、业务逻辑以及用户界面分离。该系统分为用户和管理员两个角色。用户注册登录后可以浏览鲜花,浏览公告,购买鲜花,管理员登录后可以对系统进行管理和维护。
    网上花店销售系统对于用户来说操作方便,满足了用户随时随地购买鲜花的需求,不仅为用户节省了时间,还提高了用户的购买效率。对于花店老板而言,不仅提高了销售效率还降低了时间和人工成本。
    关键词:销售系统;JSP;MVC;网上花店
    AbstractWith the rapid development of the times, our lives have been inseparable from the computer network, and the rapid development of e-commerce is changing people’s way of life. With the continuous rise of a variety of online shopping platform, people have long been accustomed to buy their own needs do not have to go out. But for the sale of flowers on the network platform is still very small, so the design of an online florist sales system is promising.
    Online flower florist system using JSP + Servlet + Javabean MVC model, the data object, business logic and user interface are separate. The system includes two roles: user and administrator. After registering, user can browse the flowers, browse the announcement, buy flowers, Administrators can manage and maintain the system after logging.
    Online florist sales system for the user is easy to operate, It fulfills the needs of users to buy flowers anytime and anywhere.This system not only saves user’s time, but also improve the user’s purchasing efficiency. For the flower shop owner, this system not only improve the sales efficiency but also reduce the time and labor costs.
    Key words: sales system; JSP; MVC; online florist
    1 绪论1.1 现状分析鲜花销售行业最初是鲜花销售商个体进行实体销售,后来经过发展形成了鲜花进入批发市场再进行分销的形式。传统的鲜花销售模式是以实体花店为主体,直到后来由于网络的迅速发展,电子商务的介入使鲜花销售发生了很大的变化。随着人们生活水平的提高以及对生活品质的要求,鲜花销售行业发展的前景也越来越好。目前,很多大的鲜花销售品牌已经开始了鲜花的网上销售,方便了消费者购买鲜花的需求,节约了大量的时间。但很多个体鲜花销售商的鲜花销售依然不够景气,还停留在传统花店的状态。这样不仅消费者必须亲自进入花店进行购买,再加上鲜花包装等一系列工序,浪费了大量的时间,而且鲜花销售商也会由于实体销售的缺陷降低销售额。另外,传统花店销售由于地域性的约束和客户范围的划分,使得传统花店的客户受到限制。因此发展网上花店销售系统就显得比较重要,也比较有前景。这样能扩展鲜花消费市场,实现利润增长。网上花店销售系统的实现不仅缩短了鲜花上市时间,节约了成本,方便了消费者购买,方便管理员管理,节约了大量时间和大量的人力物力,还增强了人们之间的感情交流等。
    1.2 研究意义传统的实体鲜花销售存在很多的限制,该系统致力于满足用户随时随地在网上挑选购买鲜花的需求。对于花店老板而言,可以提高工作效率,使网上鲜花管理工作系统化、规范化、自动化,提高整个购买鲜花流程的效率,使总体水平上升到一个新的高度。与传统花店相比,网上花店有其不可比拟的优势。首先网上花店的运营成本较低,职员人数较少,也不需要很大的运营场地。其次网上花店有传播信息迅速、容量大、范围广、可交互等特点。不仅如此,网上花店的建立,可以更好的满足消费者的需求。通过这种网络工具为消费者带来方便,同时促进浏览此网站用户的购买欲,提高销售效率。
    网上花店系统给用户提供了一整套完整的网上鲜花订购流程,使用户足不出户直接进行网上购物,给消费者带来了很大的方便。随着人类社会的发展,人际交往变得越来越重要。在这个繁忙的社会,人们很少有时间能见面交流感情,在特殊的日子里送给好友一束鲜花是用于联络感情的很好方式,因此受到广大消费者的欢迎。与此同时,商家也不再需要在商店里被动的等待顾客,完全可以坐在家里就轻松的卖出自己的商品,获得利润。计算机的存储与快速查询功能大大提高了网上花店管理的效率,并且还提高了查询并购买鲜花的精确度。方便快速的操作,不仅可减少从前的漏洞,还可以减少因工作的冗余出现的错误,更重要的是该系统的操作非常简单,推广起来比较容易。
    1.3 研究方法网上花店销售系统将采用瀑布模型的方式,先对目前鲜花销售的情况进行概述,然后对开发系统的环境以及技术进行简要介绍,之后对开发网上花店销售系统进行可行性分析、需求分析、总体设计、详细设计、编程实现以及测试直到实现最终理想的效果。本文将详细阐述整个实现过程。
    2 系统的开发环境及技术简介2.1 系统开发环境简介2.1.1 MyEclipse简介MyEclipse企业级工作平台作为对Eclipse IDE的扩展,它的功能体现在可以在数据库和JavaEE的开发、发布、应用程序服务器的整合方面极大的提高工作效率。MyEclipse几乎包括了目前所有主流开源产品的专属Eclipse开发工具,它作为功能丰富的JavaEE集成开发环境,在功能方面包括了完备的编码、调试、测试和发布,十分完整地支持HTML、Struts 2、Spring、JSP、CSS、JavaScript、Servlet、Hibernate、JDBC数据库链接工具等。JavaEE模型;Web开发工具;EJB开发工具;应用程序服务器的连接器;JavaEE项目部署服务;数据库服务;MyEclipse整合帮助是MyEclipse的7类特征。在Eclipse中,对于以上每一种功能上的类别都存在相应的功能部件,以及一系列可以用来实现它们的插件。MyEclipse这种结构上的模块化为它带来了很多优势,可以让开发人员在基本不影响其他模块的前提下,可以单独的扩展和升级任一模块。
    2.1.2 Tomcat简介Tomcat服务器是一个免费的开放源代码的Web应用服务器。运行时占用的系统资源小;扩展性好;支持负载平衡与邮件服务等开发应用系统常用的功能这几个特点使得其很受编程人员的喜欢。任何一个编程人员都可以更改它或在其中加入新的功能,因此Tomcat服务器还在不断的改进和完善中。 Tomcat是一个小型的轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是调试和开发JSP程序的第一选择。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache服务器,可利用它响应对HTML页面的访问请求。实际上Tomcat部分是Apache服务器的扩展,但它是独立运行的,所以当你运行Tomcat时,它实际上是作为一个与Apache独立的进程单独运行的。
    2.1.3 SQL Server简介SQL Server 是一个关系数据库管理系统,常用的有SQL Server 2000,SQL Server 2005,SQL Server 2008等版本。SQL Server 2008是微软公司2008年推出的数据库产品。它紧密结合了微软公司的各类主要产品,与Windows操作系统、Office办公软件、Visual Studio开发平台的最新技术进行了衔接。其各项指标在同类产品中都堪称优秀,而且图形化的管理界面十分便于学习与使用。SQL Server 2008具有很多新的特点,它是可信任的,使得公司可以以很高的安全性、可靠性和可扩展性来运行他们最关键任务的应用程序。它是高效的,使得公司可以降低开发和管理他们的数据基础设施的时间和成本。它是智能的,提供了一个全面的平台,可以在你的用户需要的时候给他发送观察和信息。
    2.2 系统开发技术简介2.2.1 JSP简介JSP全称Java Server Pages,是一种动态网页开发技术。JSP页面由HTML代码和嵌入其中的Java代码所组成。服务器在页面被客户端请求以后对这些Java代码进行处理,然后将生成的HTML页面返回给客户端的浏览器。Servlet是JSP的技术基础,而且大型的Web应用程序的开发需要Servlet和JSP配合才能完成。JSP具备了Java技术简单易用的特点,完全地面向对象,具有平台无关性、主要面向因特网且安全可靠。简单的理解,JSP就是HTML页面+Java代码,但是JSP中能写的内容还不止这些,可以包含HTML标签,CSS,JavaScript,JAVA代码,EL表达式,引入并使用其他标签库,例如JSTL标签库、Struts 2标签库等。浏览器可以直接运行HTML页面,但是不能直接运行JSP页面,JSP是需要在拥有JSP引擎的服务器中运行的,例如Tomcat服务器。所以JSP是运行在服务器端的,运行完之后,把动态生成的HTML页面再使用IO流写回给浏览器,浏览器接收并且解析后再呈现出来效果。JSP的生命周期分为编译阶段,初始化阶段,执行阶段,销毁阶段。
    2.2.2 Javabean简介JavaBean 是一种Java语言写成的可重用组件。为了编写JavaBean,类必须是特定的和公共的,并且具有无参数的构造器。JavaBean通过提供一个符合一致设计模式的公共方法公开内部域的成员属性。众所周知,属性名与此模式相一致,其他java类可以通过自省机制发现和操纵这些JavaBean的属性。用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBean程序或者应用来使用这些对象。用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。JavaBean可分为两种:一种是有用户界面的JavaBean;还有一种是没有用户界面,主要负责处理事务(如数据运算,操纵数据库)的JavaBean。JSP通常访问的是后一种JavaBean。JavaBean是可复用的平台独立的软件组件,开发者可以在软件构造器工具中对其直接进行可视化操作。一个JavaBean由3部分组成:属性、方法、事件。
    2.2.3 Servlet简介Servlet是一个基于JAVA技术的Web组件,运行在服务器端,由Servlet容器所管理,用于生成动态的内容,Servlet是平台独立的Java类,编写一个Servlet实际上就是按照Servlet规范编写一个Java类,Servlet被编译为平台独立的字节码,可以被动态地加载到支持 Java技术的Web服务器中运行。Servlet容器也叫Servlet引擎,是Web服务器或者应用服务器的一部分,用户在发送请求和响应之上提供网络服务,Servlet不能独立运行,必须被部署到Servlet容器中,由容器实例化和调用Servlet的方法,Servlet容器在Servlet的生命周期内包含和管理Servlet。Servlet是单实例多线程的运行方式,每个请求在一个独立的线程中运行,提供服务的Servlet实例只有一个Servlet 具有可升级性,能响应更多的请求,因为Servlet容器使用一个线程而不是操作系统进程,线程占用的资源要小,Servlet使用标准的API,被更多的Web服务器所支持。Servlet使用Java语言编写,拥有更多的Java程序语言的优点,Servlet可以访问Java平台丰富的类库,使得各种应用的开发更为容易,Servlet容器给Servlet提供额外的功能。
    2.2.4 JDBC简介对系统来说数据库连接应该说是最为重要的部分,Java中连接数据库的技术是JDBC。JDBC作为一种用于执行SQL语句的Java API,具备为多种关系数据库提供统一访问的功能,JDBC是由一组用Java语言编写的类和接口组成的。为了达到可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序的目的,JDBC提供了一种基准。众所周知,JDBC API、JDBC驱动程序和JDBC驱动程序管理器是JDBC的三个部分,即可以通过Java.sql包来提供JDBC API,JDBC API上仅仅设计为了利用数据库而提供的类的接口,提供JDBC驱动的软件商来实际完成这个接口。当JDBC API制作的程序进行数据调用时,JDBC驱动发挥它的作用,实际连接数据库并且进行相应的处理, JDBC API的接口类也由JDBC驱动提供。
    两层模型(C/S)和三层模型(B/S)同样都是JDBC API支持数据库访问的。在两层模型(C/S)中,Java Applet或应用程序与数据库会直接进行对话,与所访问的特定数据库管理系统进行通讯时需要一个JDBC驱动程序,数据库收到被用户送来的SQL语句,而用户将会收到其被送回的结果。客户机/服务器配置指的是数据库可以位于另一台计算机上,用户通过网络连接到上面。其中客户机就是我们平时常说的用户的计算机,而服务器是我们常说的提供数据库的计算机,网络是Internet。在三层模型(B/S)中,服务的”中间层”先是收到命令,然后由服务的“中间层”将SQL语句交给数据库,数据库需要对SQL语句进行处理并将所得结果送回到中间层,最后用户将会收到中间层所得的结果。JDBC是用于直接调用SQL命令的“低级”接口。它在这方面的功能极佳,相比其它的数据库,它连接API易于使用,与此同时它也被设计成为了一种基础接口,高级接口和工具可以建立在它之上。很明显,JDBC具有如下优点:JDBC支持不同的关系数据库,JDBC使得开发人员不需要再使用复杂的驱动器调用命令和函数,可以将常用的JDBC数据库连接封装成一个类等。
    2.2.5 SQL语言简介SQL全称是结构化查询语言(Structured Query Language),SQL语言结构简洁,功能强大,简单易学。SQL语言是高级的非过程化编程语言,允许用户在高层数据结构上工作。它不要求用户指定对数据的存放方法,也不需要用户了解具体的数据存放方式,所以具有完全不同底层结构的不同数据库系统, 可以使用相同的结构化查询语言作为数据输入与管理的接口。SQL语言语句可以嵌套,这使它具有极大的灵活性和强大的功能。SQL语言不仅是一个功能强大的通用的关系数据库标准语言,而且还是一种介于关系演算和代数之间的语言,其功能之强大体现在查询、操纵、定义和控制这四个方面。SQL语言包含以下六个部分:

    数据查询语言
    数据操作语言
    事务处理语言
    数据控制语言
    数据定义语言
    指针控制语言

    作为非过程化的语言,SQL一次只对一个记录进行处理,自动对数据提供导航。SQL不对单个记录进行操作,它不仅可对记录集进行操作,还允许用户在高层的数据结构上工作。对于所有SQL语句,输入的是接受集合,输出的是返回集合。SQL的集合特性允许一条SQL语句的结果作为另一条SQL语句的输入。SQL可用于所有用户的DB活动模型,这里所指的用户包括系统管理员、数据库管理员、 应用程序员、决策支持系统人员以及许多其它类型的终端用户等。基本的SQL命令简单易学,一般情况下只需很少时间就能学会,即使是高级的命令在几天也内便可掌握。SQL语言则将所有任务统一在了一种语言中。用户之所以可将使用SQL的技能从一个关系数据库管理系统转到另一个,是因为所有主要的关系数据库管理系统都支持SQL语言。
    3 可行性研究3.1 经济可行性经济可行性,主要考虑的是系统开发涉及到的一些相关费用问题,企业是否可以支撑这些费用,通常来分析,软件系统开发主要包括的费用有设备购买费用,人员开发成本,设备维护更新成本,以及其他零散费用等,这些费用中,人员开发费用相对较高,但是本次系统开发规模小,周期短,所设计的开发费用不高,因此企业不必担心此方面问题。再则就是设备购买费用,一般保持电脑,交换机,网络,服务器等,这些都是一次性购买,费用也不高。因此,对于企业来讲,问题不大,经济上可以接受。通过对现已存在的相关系统进行调查,开发该系统所需的相关资料可以由此采集。同时所需的应用软件、系统硬件也便于获得,因此该系统开发成本不高。在引进该系统之后,不可否认,与传统方式相比可以节省不少人力、物力及财力,因为它的确具有效率高、质量高、成本低以及实用性高的特点。所以,站在经济的角度来讲,网上花店销售系统被认定为是可行的。
    3.2 技术可行性技术可行性主要分析技术条件能否顺利完成开发工作,硬、软件能否满足开发者的需要等。首先,系统采用的是JAVA开发技术,这项技术比较全面,实用广泛,没有实现不了的功能需求;其次该网站采用了SQL Server2008数据库,它能够处理大量数据,同时保持数据的完整性并提供许多高级管理功能,它的灵活性、安全性和易用性为数据库编程提供了良好的条件;最后开发工具,采用的是MyEclipse,工具中具有框架函数等,可以直接引用。因此,系统的软件开发平台已成熟可行。硬件方面,科技飞速发展的今天,硬件更新的速度越来越快,容量越来越大,可靠性越来越高,价格越来越低,其硬件平台完全能满足此系统的需要。
    3.3 操作可行性操作可行性主要是考虑系统完成后,用户使用的是否便利,是否可以达到用户的操作要求。该系统界面设计充分考虑浏览用户的习惯,鲜花信息浏览,公告浏览,鲜花搜索,用户注册,用户登录,用户挑选鲜花加入购物车,用户将购物车的鲜花生成订单,用户查看订单,用户管理个人信息等功能操作方便。除此之外,对于管理员而言,管理界面一目了然,对于系统的管理和维护也很容易。更重要的是所有网页设计清新、简洁、合理,不会让用户感到视觉疲劳,可操作性强。
    3.4 法律可行性法律可行性主要是看新系统的开发会不会在社会上或政治上引起侵权,有无违法问题。网上花店销售系统开发过程中所有技术资料都是合法的;在开发过程中是不存在知识产权问题的;未抄袭其他系统,故不存在侵犯版权问题;开发过程中不会涉及任何法律责任。
    4 需求分析4.1 数据描述4.1.1 数据流图数据流图简称DFD,它从数据传递和加工角度,以图形方式来表达系统的逻辑功能、数据在系统内部的逻辑流向和逻辑变换过程,是结构化系统分析方法的主要表达工具及用于表示软件模型的一种图示方法。网上花店销售系统的数据流图如图4-1所示。

    在该数据流图中方框表示数据的原点或终点,原点和终点是系统之外的实体。椭圆表示变换数据的处理,也称之为加工,它对数据流进行某些操作或变换。箭头表示数据流,数据流是数据在系统中的运行方向。双杠表示数据存储文件,是用来暂时存储数据的。网上花店销售系统的实体有两个,分别为用户和管理员,用户对应于在网上购买鲜花的顾客,管理员对应于网上花店的老板。此系统中的加工对于用户来说有浏览鲜花、查看分类、管理用户信息、管理购物车、生成并查看订单、查看公告,对管理员来说有鲜花管理、分类管理、用户管理、订单管理、公告管理。此系统中的数据存储包括鲜花信息、分类信息、用户信息、购物车信息、订单信息和公告信息,在实际的实现中应该将这些信息存储在对应的表里,虽然鲜花信息、分类信息、用户信息、订单信息和公告信息是用户和管理员共享的,但是由于权限的不同用户对于鲜花信息、分类信息以及公告信息只有查看的权限,管理员对于这些信息有增、删、改的权限。在数据流图中反映为加工的不同。
    用户在系统中可以浏览鲜花、查看分类、管理用户信息、管理购物车、生成并查看订单、查看公告,本系统中用户数据流图如图4-2所示。

    管理员在系统中可以进行鲜花管理、分类管理、用户管理、订单管理、公告管理,其中管理员可以对鲜花、分类和公告进行添加、修改、查看和删除,对用户进行查看和删除,对订单进行查看和处理。本系统中管理员数据流图如图4-3所示。

    4.1.2 数据字典数据字典是指对数据的数据项、数据结构、数据流、数据存储、处理逻辑、外部实体等进行定义和描述,其目的是对数据流程图中的各个元素做出详细的说明。图4-1中数据流条目如下所示:

    用户信息=用户ID+用户名+密码+姓名+角色+手机号+地址
    鲜花信息=鲜花ID+鲜花名+鲜花图片+上架时间+分类ID+分类名+价格+是否推荐+点击数+鲜花销量+鲜花描述
    公告信息=公告ID+标题+内容+添加时间
    分类信息=分类ID+分类名称
    购物车信息=购物车ID+用户ID+鲜花ID+鲜花名+价格+购买数量
    订单信息=订单ID+订单状态+用户ID+用户姓名+用户手机+收货地址+订单详情+订单号+备注+生成时间+总价

    根据数据流条目得到数据项条目如表4-1所示。



    名称
    类型
    长度
    别名




    id
    int
    11
    用户ID


    username
    varchar
    255
    用户名


    password
    varchar
    255
    密码


    xingming
    varchar
    255
    姓名


    role
    int
    11
    角色


    dianhua
    varchar
    255
    手机号


    dizhi
    varchar
    255
    地址


    id
    int
    11
    鲜花ID


    pname
    varchar
    255
    鲜花名


    imgpath
    varchar
    255
    鲜花图片


    createtime
    varchar
    255
    上架时间


    fname
    varchar
    255
    分类名


    jiage
    double

    价格


    tuijian
    varchar
    255
    是否推荐


    dianjishu
    int
    11
    点击数


    xiaoliang
    int
    11
    鲜花销量


    miaoshu
    text

    鲜花描述


    id
    int
    11
    公告ID


    biaoti
    varchar
    255
    标题


    neirong
    text

    内容


    shijian
    varchar
    255
    添加时间


    id
    int
    11
    分类ID


    fname
    varchar
    255
    分类名称


    id
    int
    11
    购物车ID


    shuliang
    int
    11
    购买数量


    id
    int
    11
    订单ID


    status
    varchar
    255
    订单状态


    xiangqing
    text

    订单详情


    orderid
    varchar
    255
    订单号


    beizhu
    varchar
    255
    备注


    shijian
    varchar
    255
    生成时间


    zongjia
    double

    总价



    4.1.3 系统IPO图IPO图是输入—处理—输出图(Input-Process-Output)的简称。基本形式是画三个方框,在左边框中列出有关输入数据,在中间框内列出主要处理,在右边框中列出产生的输出数据。网上花店销售系统的输入数据主要是用户信息以及鲜花信息,处理主要针对用户、鲜花分类、鲜花详情、购物车以及订单,输出数据对应于处理过程。该系统IPO图如图4-4所示。

    4.2 功能需求4.2.1 功能划分本网上花店销售系统主要分为前台操作和后台管理两部分。

    前台操作

    前台作为与用户直接交互的界面,在考虑功能的同时,也考虑了操作的简洁和方便性,目的是让大多数不太懂电脑操作的用户也能轻松的享受该系统带来的便利前台主要功能包括:首页(主界面)、鲜花搜索、鲜花分类、花店公告、鲜花浏览、用户注册、用户登录、订购鲜花、查看购物车、查看订单等
    后台管理

    后台管理考虑了花店管理的操作简单方便后台主要功能包括:分类管理、鲜花管理、公告管理、订单管理、用户管理

    4.2.2 功能描述
    首页(主界面):提供简洁美观的主界面,界面陈列系统提供功能,用户和管理员通过选择各个功能来达到自己所需的目的
    用户注册:新用户通过填写注册表单,将自己的详细信息输入并提交系统,系统会通过与数据库的连接以及表单限定的格式来检查合法性。注册成功后可以进行订购等其他功能
    用户登录:用户通过输入“用户名”和“密码”进行登录,系统会通过与数据库的连接来检查合法性,如果存在则登录成功继续接下来的功能,如果不存在则返回登录界面
    鲜花浏览:用户可以通过选择该功能看到本系统鲜花的详细介绍
    加入购物车:用户可以通过该功能选择自己要购买的鲜花并放入购物车,在购物车也可以进行数量的修改并且生成订单。但要首先登录才可以实现该功能
    生成订单:用户可以把购物车里的鲜花下订单
    查看订单:用户可以查询自己的订单,但首先必须登录
    修改个人信息:用户可以修改个人资料
    管理员分类管理:管理员可以对系统首页的分类进行增加、查看、修改、删除
    管理员鲜花管理:管理员可以对系统首页的鲜花进行增加、查看、修改、删除
    管理员公告管理:管理员可以对系统首页的公告进行增加、查看、修改、删除
    管理员订单管理:管理员可以对用户的订单进行查看、处理
    管理员用户管理:管理员可以对系统已经注册的用户进行查看、删除

    4.3 性能需求网上花店销售系统在日常处理中的响应速度为秒级,达到实时要求,以及时反馈信息。在进行统计分析时,根据所需数据量的不同而从秒级到分钟级,原则是保证操作人员不会因为速度问题而影响工作效率。系统处理的准确性和及时性是系统的必要性能。在系统设计和开发过程中,要充分考虑系统当前和将来可能承受的工作量,使系统的处理能力和响应时间能够满足用户对信息处理的求。由于网上花店销售系统的查询功能对于整个系统的功能和性能完成举足轻重,作为系统的很多数据源,其准确性很大程度上决定了网上花店销售系统的成败。在系统开发过程中,必须采用一定的方法保证系统的准确性。用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用Java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBean程序或者应用来使用这些对象。用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。当操作发生变化时,一些功能同样能够实现。因为在实现各项功能时了,把功能划分成了不同的模块,各模块之间互不干扰,而且JavaBean都采用类的形式,每个功能都封装成一个类,当运行环境发生变化时,对程序会有一些影响,但打上补丁就可以继续运行了。总体上讲,本系统具有一定的自适应性。
    4.4 运行需求
    硬件条件:英特尔酷睿2 CPU、1GB 内存、20GB以上硬盘的PC机
    软件条件:Windows 7操作系统

    当系统遇到问题时,首先查看运行环境是否更改;如果更改,只修复运行环境即可;若未更改,查看系统中各个模块之间的接口是否有问题,可通过调试改正错误。数据库最严重的问题是数据库损坏,此时最好是从备份恢复数据库。如果是由于存储问题导致部分数据库文件损坏,但数据库还可以连接,这种情况采用导出数据库的表结果和数据的方法来恢复数据库。解决数据库的性能问题,可以从以下方面入手,检查数据库的配置,如缓冲池,排序堆等是否处理;检查数据库是否收集过统计信息,准确的统计信息对语句优化起着重要的作用;对sql语句进行优化;查看是否有系统资源瓶颈。
    4.5 其他需求网上花店销售系统是直接面对使用人员的,而使用人员往往对计算机并不是非常熟悉。这就要求系统能够提供良好的用户接口,易用的人机交互界面。要实现这一点,就要求系统应该尽量使用用户熟悉的术语和中文信息的界面。针对用户可能出现的使用问题,要提供足够的在线帮助,缩短用户对系统熟悉的过程。网上花店系统中涉及到的数据是相当重要的信息,系统要提供方便的手段供系统维护人员进行数据的备份,日常的安全管理,系统意外崩溃时数据的恢复等工作。
    5 总体设计5.1 系统功能模块设计网上花店销售系统一共分为前台和后台两大模块,两个模块之间虽然在表面上是相互独立的,但是在对数据库的访问上是紧密相连的,各个模块访问的是同一个数据库,只是所访问的表不同。
    网上花店销售系统的前台功能模块分为:

    鲜花展示模块:鲜花展示模块主要是向用户展示网上花店的鲜花,主要分为鲜花搜索和鲜花分类两个子模块。用户可以通过鲜花搜索直接查询自己想要了解的鲜花,也可以通过鲜花分类查找某一类的鲜花
    公告展示模块:公告展示模块是管理员发布的与网上花店系统相关的公告信息,可以包括系统的使用或者最新的优惠活动等。用户登录系统后,可以查看公告信息,以此来最快的了解系统
    购买鲜花模块:购买鲜花模块主要是完成用户在网上的购物的流程。购买鲜花模块分为加入购物车和生成订单两个子模块
    用户管理模块:用户管理模块分为用户注册、用户登录、用户修改信息三个子模块

    网上花店销售系统前台功能模块图如图5-1所示。

    用户进行购买鲜花时,先进行注册,然后进行登录,登录系统后用户可以浏览鲜花,把需要购买的鲜花加入购物车,把购物车的鲜花生成订单。用户购买鲜花时序图如图5-2所示。

    网上花店销售系统的后台功能模块分为:

    分类管理模块:分类管理模块主要是实现管理员对系统分类的管理,使得用户可以按照分类挑选鲜花,方便了用户的挑选,管理员通过这个模块可以向系统添加新的分类,查看已有的分类,修改已有的分类,删除旧的分类
    鲜花管理模块:鲜花管理模块主要是实现管理员对系统鲜花的管理,该模块对整个系统至关重要。管理员通过这个模块可以向系统添加新的鲜花,查看已有的鲜花,修改已有的鲜花,删除旧的鲜花
    订单管理模块:订单管理模块主要是实现管理员对系统订单的管理,管理员通过这个模块可以查看用户下的订单并对订单做出相应的处理
    公告管理模块:公告管理模块主要是实现管理员对系统公告的管理,这样用户进入系统后可以通过浏览公告获取网上花店销售系统的最新资讯,并且可以在最短的时间内对系统有基本的了解。管理员通过这个模块可以向系统添加新的公告,查看已有的公告,修改已有的公告,删除旧的公告
    用户管理模块:用户管理模块主要是实现管理员对已注册用户的管理,管理员通过这个模块可以查看用户的信息或者删除用户

    网上花店销售系统后台功能模块图如图5-3所示。

    5.2 数据库设计5.2.1 概念结构设计描述概念模型的有力工具是E-R模型,E-R模型是用E-R图来描述现实世界的概念模型。E-R模型包括实体、属性、实体之间的联系等。接下来将用E-R图对网上花店销售系统进行概念结构设计,包括各实体间的E-R图及各实体的详细属性E-R图。其中实体型用矩形表示,矩形框内写明实体名。属性用椭圆形表示,并用无向边将其与相应的实体型连接起来。联系用菱形表示,菱形框内写明联系名,并用无向边分别与有关实体型连接起来,同时在无向边旁标上联系的类型。
    本网上花店销售系统的实体有管理员,用户,公告,订单,分类,鲜花。下面将分别设计各实体的E-R图。
    用户E-R图如图5-4所示。

    在该E-R图中,对于用户实体,用户可以浏览公告,因此用户实体和公告实体是浏览关系,用户可以选购鲜花,因此用户实体和鲜花实体是选购关系,用户可以查看分类,因此用户实体和分类实体是查看关系,用户可以管理自己的购物车,因此用户实体和购物车实体是管理关系,用户可以查看自己的订单,因此用户实体和订单实体是查看关系,用户在系统中是被管理员管理的,因此用户和管理员是被管理的关系。
    管理员E-R图如图5-5所示。

    在该E-R图中,对于管理员实体,管理员可以对系统的公告、订单、分类、鲜花进行管理,对已注册的用户进行管理,因此它与其他实体的关系都是管理关系。
    用户实体的属性有ID、用户名、密码、姓名、角色、手机号、地址。用户详细属性E-R图如图5-6所示。

    鲜花实体的属性有ID、鲜花名、鲜花图片、上架时间、分类ID、分类名、价格、是否推荐、点击数、鲜花销量、鲜花描述。鲜花详细属性E-R图如图5-7所示。

    公告实体的属性有ID、标题、内容、添加时间。公告详细属性E-R图如图5-8所示。

    分类实体的属性有ID、分类名称。分类详细属性E-R图如图5-9所示。

    购物车实体的属性有ID、用户ID、鲜花ID、鲜花名、价格、购买数量。购物车详细属性E-R图如图5-10所示。

    订单实体的属性有ID、订单状态、用户ID、用户姓名、用户手机、收货地址、订单详情、订单号、备注、生成时间、总价。订单详细属性E-R图如图5-11所示。

    5.2.2 逻辑结构设计逻辑结构设计的任务就是把概念结构设计阶段设计好的基本E-R图转换为与选用数据库管理系统产品所支持的数据模型相符合的逻辑结构。数据库设计时注意保证在整个系统运行和业务操作过程中,数据库都能便于访问和查询,同时还需要考虑到要尽量节省数据库操作时的响应时间,尽可能的提高数据库对程序和业务请求的响应速度。
    根据概念结构设计阶段的E-R图,设计数据库表结构如下。
    t_Fenlei分类表
    该表存放分类ID及分类名称。t_Fenlei分类表如表5-1所示。



    名称
    类型
    长度
    备注




    id
    int
    11
    主键


    fname
    varchar
    255
    分类名称



    t_Product鲜花表
    该表存放鲜花信息,主要包括鲜花名、鲜花图片、上架时间、价格、鲜花销量、鲜花描述等信息。分类表和该表相关联,因此表中还包含了分类ID以及分类名。t_Product鲜花表如表5-2所示。



    名称
    类型
    长度
    备注




    id
    int
    11
    主键


    pname
    varchar
    255
    鲜花名


    imgpath
    varchar
    255
    鲜花图片


    createtime
    varchar
    255
    上架时间


    fenleiid
    varchar
    255
    分类ID,外键


    fname
    varchar
    255
    分类名


    jiage
    double

    价格


    tuijian
    varchar
    255
    是否推荐


    dianjishu
    int
    11
    点击数


    xiaoliang
    int
    11
    鲜花销量


    miaoshu
    text

    鲜花描述



    t_Gonggao公告表
    该表存放公告信息,主要包括标题、内容、添加时间。t_Gonggao公告表如表5-3所示。



    名称
    类型
    长度
    备注




    id
    int
    11
    主键


    biaoti
    varchar
    255
    标题


    neirong
    text

    内容


    shijian
    varchar
    255
    添加时间



    t_Gouwuche购物车表
    该表存放购物车ID、以及用户ID、鲜花ID、鲜花名、价格、购买数量。t_Gouwuche购物车表如表5-4所示。



    名称
    类型
    长度
    备注




    id
    int
    11
    主键


    userid
    int
    11
    用户ID,外键


    pid
    int
    11
    鲜花ID,外键


    pname
    varchar
    255
    鲜花名


    jiage
    double

    价格


    shuliang
    int
    11
    购买数量



    t_User用户表
    该表中存放用户的基本信息,普通用户和管理员共用此表,主要包括用户ID、用户名、密码、姓名、角色、手机号、地址信息。普通用户和管理员通过角色的值进行区分, 0表示普通用户,1表示系统管理员。t_User用户表如表5-5所示。



    名称
    类型
    长度
    备注




    id
    int
    11
    主键


    username
    varchar
    255
    用户名


    password
    varchar
    255
    密码


    xingming
    varchar
    255
    姓名


    role
    int
    11
    角色


    dianhua
    varchar
    255
    手机号


    dizhi
    varchar
    255
    地址



    t_Dingdan订单表
    该表存放订单ID、订单状态、以及关联表里的用户ID、用户姓名等信息。t_Dingdan订单表如表5-6所示。



    名称
    类型
    长度
    备注




    id
    int
    11
    主键


    status
    varchar
    255
    订单状态


    userid
    int
    11
    用户ID 外键


    xingming
    varchar
    255
    用户姓名


    dianhua
    varchar
    255
    用户手机


    dizhi
    varchar
    255
    收货地址


    xiangqing
    text

    订单详情


    orderid
    varchar
    255
    订单号


    beizhu
    varchar
    255
    备注


    shijian
    varchar
    255
    生成时间


    zongjia
    double

    总价



    6 详细设计与实现根据总体设计部分对于功能模块的划分,在详细设计中采用JSP+Servlet+Javabean的MVC模式,其中系统的显示由JSP页面完成,用Javabean封装对象,业务的逻辑处理由Servlet完成,对于数据库的操作写在dao包的文件里。
    6.1 系统对象的设计与实现系统中总共包括七个对象,分别为用户,管理员,公告,鲜花,类别,购物车和订单。系统的类图如图6-1所示。

    在实现过程中将这七个对象封装成bean对象,其中管理员和用户的封装对象内容相同,故二者共用一个对象,用属性role进行区分,0表示用户,1表示系统管理员。六个对象对应于代码中的Dingdan.java,Fenlei.java,Gonggao.java,Gouwuche.java,Product.java,User.java。以User.java为例,关键代码如下:
    public class User { private int id;//主键 private String username;//用户名 private String password;//密码 private String xingming;//姓名 private int role;//用户角色 0表示用户,1表示系统管理员 private String dianhua;//手机 private String dizhi;//收货地址}
    6.2 系统首页的设计与实现该系统首页页面风格简单明了,上边横条可以选择注册和登录,左侧有鲜花搜索,鲜花分类,销量排行榜以及花店公告,用户可以根据自己的需求浏览相关内容。页面右侧是鲜花列表,用户可以通过点击相应的链接查看详情或者加入购物车。首页页面的设计如图6-2所示。

    具体的实现过程是:index.jsp文件主要包括鲜花列表部分,在index.jsp页面引入黄色横条的head.jsp以及左侧的left.jsp。
    6.3 系统前台功能的设计与实现6.3.1 用户注册模块的设计与实现用户注册需要填写相应的信息,主要包括用户名、密码、确认密码、姓名、收货地址以及手机号码。用户注册页面的设计如图6-3所示。

    该页面对应代码中的register.jsp,该页面对输入的每一个数据都有格式上的要求,用户名不能为空且必须是数字,字母或者下划线,密码不能为空且至少6位,确认密码要和密码一致,姓名,收货地址以及手机号都不能为空,手机号码还要符合正确的格式。当用户进行注册时,页面首先会对输入的数据格式进行检验,若输入错误会有相应的提示。除此之外,当用户输入正确的格式的数据之后,点击了注册按钮,系统会在数据库进行比对,若用户名已经被注册,系统也会弹出相应的提示,若用户名还未注册则将数据插入数据库,提示注册成功并跳转到首页。具体的实现过程是在IndexServlet.java中对注册进行逻辑处理,在UserDao.java中对数据库进行操作。
    该页面关键代码如下:
    <form action="indexServlet/register" method="post" onsubmit="return checkform()"> <label>用户名:</label> <input type="text" class="form_input" name="username" id="usernameid" /> <label>密码:</label> <input type="password" class="form_input" name="password" id="passwordid"/> <label>确认密码:</label> <input type="password" class="form_input" name="password2" id="password2id"/> <label>姓名:</label> <input type="text" class="form_input" name="xingming" id="xingmingid"/> <label>收货地址:</label> <input type="text" class="form_input" name="dizhi" id="dizhiid"/> <label>手机:</label> <input type="text" class="form_input" name="dianhua" id="dianhuaid"/> <input type="submit" class="form_submit" value="注册" /></form>
    用户在注册时,第一不能有空值,第二两次密码的输入要一致,第三各项数据的格式要正确。除此之外,用户名不可以是已经注册过的。用户注册程序流程图如图6-4所示。

    6.3.2 用户登录模块的设计与实现用户登录需要填写用户名以及密码,登录页面的设计如图6-5所示:

    该页面对应代码中的login.jsp,用户名和密码都不能为空,否则页面会进行相应的提示,当输入用户名和密码点击登录之后,系统会在数据库中查找,若有匹配的数据则提示登录成功并跳转到首页,否则提示用户名或密码不正确。具体的实现过程是在IndexServlet.java中对登录进行逻辑处理,在UserDao.java中对数据库进行操作。
    该页面关键代码如下:
    <form action="indexServlet/login" method="post" onsubmit="return checkform()"><label>用户名:</label><input type="text" class="form_input" name="username" id="usernameid" /><label>密码:</label><input type="password" class="form_input" name="password" id="passwordid"/><input type="submit" class="form_submit" value="登录" /></form>
    用户在登录时,用户名和密码要一致,如果正确才可以登录成功,否则登录失败需要重新输入登录信息。用户登录程序流程图如图6-6所示。

    6.3.3 公告浏览模块的设计与实现用户在首页可以浏览花店公告,通过点击花店公告的标题可以查看花店公告的详细信息。花店公告页面以及公告详情页面设计如图6-7以及6-8所示。
    花店公告页面

    公告详情页面

    具体的实现过程是,当用户点击花店公告的标题时,通过IndexServlet.java的gonggaoupdate方法获取对象,然后通过GonggaoDao.java对数据库进行操作,最后将对象传到gonggao.jsp页面。
    公告详情页面关键代码如下:
    <form action="${url }" method="post" onsubmit="return checkform()"><div class="form"><div class="form_row"><label>公告标题:</label>${bean.biaoti }</div><div class="form_row"><label>内容:</label>${bean.neirong }</div><div class="form_row"><label>发布时间:</label>${bean.shijian }</div><div class="form_row"><input type="button" class="form_submit" value="返回" onclick="javascript:history.go(-1);"/> </div> <div class="clear"></div></div></form>
    6.3.4 鲜花列表模块的设计与实现用户在系统首页的鲜花列表可以浏览鲜花,鲜花列表包括鲜花名,图片,分类名,鲜花价格,以及查看详情和加入购物车两种操作。点击查看详情后页面会跳转到鲜花信息详情页面。鲜花列表页面以及鲜花信息详情页面如图6-9以及6-10所示。
    鲜花列表页面

    鲜花信息详情页面

    鲜花列表页面对应代码中的index.jsp,鲜花信息详情页面对应代码中的product.jsp,具体实现方式是当用户点击查看详情时,在IndexServlet.java中用productupdate方法进行具体处理,之后把对象传到product.jsp页面。当用户点击鲜花列表或鲜花信息详情页面的加入购物车时,如果用户已经登录,那么系统跳转到我的购物车页面。否则,系统会提示用户先登录并跳转到登录页面。
    6.3.5 用户购物车模块的设计与实现我的购物车页面,包括鲜花名,单价,购买时间,小计。用户可以修改购买数量或者删除购物车里的东西,也可以点击链接跳转到订单页面。我的购物车页面设计如图6-11所示。

    我的购物车页面对应代码中的gouwuchelist.jsp,当用户点击鲜花列表或鲜花信息详情页面的加入购物车时,在IndexServlet.java中用gouwucheadd2方法进行添加商品到购物车操作,在GouwucheDao.java里对数据库进行操作,将所选鲜花数据插入数据库。我的购物车页面的变更删除分别用IndexServlet.java的gouwucheupdate2方法和gouwuchedelete方法实现。
    6.3.6 用户订单模块的设计与实现我的订单页面,包括订单号,收货人姓名,订单状态,生成时间,总价,以及查看订单详情的操作。用户也可以查看和搜索自己的订单。我的订单页面如图6-12所示。

    我的订单页面对应代码中的orderlist.jsp,查询订单的操作在indexServlet/orderlist中实现,查看订单详情的操作在indexServlet/dingdanupdate3中实现,其中对数据库的操作在DingdanDao.java中完成。
    6.3.7 用户信息管理模块的设计与实现用户可以在个人信息页面对自己的信息进行管理,主要是对姓名,手机号以及收货地址的更改,可以在修改密码页面进行密码的修改。用户信息页面的设计与修改密码的设计如图6-13以及6-14所示。
    个人信息页面

    修改密码页面

    个人信息页面对应代码中的userupdate.jsp,修改密码页面对应代码中的passwordupdate.jsp,修改个人信息在是在indexServlet/userupdate2中完成的,修改密码是在indexSe rvlet/passwordupdate2中完成的,操作数据库的部分在UserDao.java中完成。
    6.4 系统后台功能的设计与实现6.4.1 系统后台页面的设计与实现管理员登录成功后会进入系统后台页面,主要包括左侧的主菜单以及中间的欢迎页面。主菜单包括,分类管理,鲜花管理,公告管理,订单管理,用户管理。系统后台页面如图6-15所示。

    管理员在此页面可以通过点击左侧主菜单进行相应的管理。关键代码如下:
    <ul> <li><a href="<%=basePath2 %>manageServlet/fenleilist" >分类管理</a></li> <li><a href="<%=basePath2 %>manageServlet/productlist" >鲜花管理</a></li> <li><a href="<%=basePath2 %>manageServlet/gonggaolist" >公告管理</a></li> <li><a href="<%=basePath2 %>manageServlet/dingdanlist" >订单管理</a></li> <li><a href="<%=basePath2 %>manageServlet/userlist" >用户管理</a></li></ul>
    6.4.2 分类管理功能的设计与实现管理员通过此功能可以查看、修改、删除已经存在的分类,也可以增加新的分类。该系统分类管理页面如图6-16所示。

    分类管理页面对应代码中的fenleilist.jsp,添加新分类以及查看和修改分别对应fenl eiadd.jsp,fenleiupdate3.jsp,fenleiupdate.jsp,管理员进行操作时,系统通过在ManageSer vlet.java中的方法实现,对数据库的操作在FenleiDao.java中实现。
    6.4.3 鲜花管理功能的设计与实现管理员通过此功能可以查看、修改、删除已经存在的鲜花,也可以增加新的鲜花。该系统鲜花管理页面如图6-17所示。

    鲜花管理页面对应代码中的productlist.jsp,添加新商品对应productadd.jsp,上传图片对应productupdate5.jsp,查看和修改分别对应productupdate3.jsp,productupdate.jsp,管理员进行操作时,系统通过在ManageServlet.java中的方法实现,对数据库的操作在ProductDao.java中实现。
    6.4.4 公告管理功能的设计与实现管理员通过此功能可以查看、修改、删除已经存在的公告,也可以增加新的公告。该系统公告管理页面如图6-18所示。

    公告管理页面对应代码中的gonggaolist.jsp,添加新公告对应gonggaoadd.jsp,查看和修改分别对应gonggaoupdate3.jsp,gonggaoupdate.jsp,管理员进行操作时,系统通过在ManageServlet.java中的方法实现,对数据库的操作在GonggaoDao.java中实现。
    6.4.5 订单管理功能的设计与实现管理员通过此功能可以查看和处理订单。该系统订单管理页面如图6-19所示。

    订单管理页面对应代码中的dingdanlist.jsp,查看订单详情对应dingdanupdate3.jsp,管理员进行操作时,系统通过在ManageServlet.java中的方法实现,对数据库的操作在DingdanDao.java中实现。
    6.4.6 用户管理功能的设计与实现管理员通过此功能可以查看和删除用户。该系统用户管理页面如图6-20所示。

    用户管理页面对应代码中的userlist.jsp,管理员进行查询用户和删除用户操作的时候,系统通过在ManageServlet.java中的方法实现,对数据库的操作在UserDao.java中实现。
    7 系统的调试与测试7.1 程序调试调试是在测试发现错误之后排除错误的过程。调试的目的是为了解决存在的错误,即对错误定位、分析并找出原因改正错误,因此调试也称为纠错。软件调试是一项具有很强技巧性的工作,调试是一个通过外部表现找出原因的思维分析过程。常用的调试技术是消去原因法,即通过思考,分析列出发生错误的所有可能原因,逐个排除,最后找出真正的原因。试探法、归纳法、折半查找法、演绎法都属于消去原因法。
    7.2 程序测试7.2.1 测试的内容功能测试:用户注册登录后进行鲜花选购、查看公告等功能,与此同时查看数据库内容是否同步更改,若更改成功则说明程序正确,反之说明程序错误。同理以管理员身份进行登录,对公告、用户等进行查看更改,查看数据库的变化。

    链接测试:在点击菜单按钮之后,查看跳转的页面是否正确
    极限测式:可以通过频繁登录与退出数据库这类频繁的操作来对系统进行测试等

    7.2.2 测试用例根据系统的功能,测试用例为以下几方面:

    用户的注册和登录以及退出,管理员的登录以及退出
    用户浏览鲜花,将鲜花加入购物车,对购物车的鲜花数量进行更改,生成订单,提交订单,查看订单,修改个人信息
    管理员对分类、鲜花、公告进行增、删、改、查,对订单和用户进行查、删

    具体的测试细节为:

    用户注册测试:用户注册时,填写各项信息,首先是各项信息空值的测试,其次是各项数据的数据格式的测试
    用户及管理员登录测试:用户及管理员登录时只需填写用户名和密码,因此测试时主要对用户名和密码的匹配性进行测试
    用户及管理员退出测试:用户和管理员的退出主要是通过点击“退出系统”按钮,因此实际测试中只需测试用户点击按钮后是否能够正确跳转
    浏览鲜花测试:浏览鲜花时用户可以点击查看详情去获取鲜花的详细信息,因此实际测试中只需测试用户点击按钮后是否能够正确跳转到相应的鲜花详情页面
    加入购物车测试:鲜花列表以及鲜花详情页面都有包含加入购物车功能,因此实际测试中需要在两个页面都测试用户点击按钮后是否能够正确跳转到购物车页面
    管理购物车测试:在购物车页面,用户可以对购物车里的鲜花数量进行更改,可以删除购物车里的鲜花,因此实际测试中需对这两方面进行测试
    生成订单测试:用户点击生成订单页面会跳转到确认订单收货信息页面,因此实际测试中要测试用户点击链接后能否正确跳转
    提交订单测试:用户提交订单后会跳转到订单页面,因此实际测试中要测试用户点击提交按钮后页面能否正确跳转以及数据库信息是否相应改变
    用户管理个人信息测试:用户可以更改自己的姓名、收货地址和手机,更改后数据库数据会有相应改变,因此实际测试中要测试用户点击提交按钮后页面能否正确弹出更改成功的信息以及数据库信息是否相应改变
    管理员分类管理测试:管理员在网上花店后台对于分类的管理主要是对分类的增加、修改、查询和删除,因此实际测试中要测试管理员进行查询操作时是否能正确显示查询信息,管理员进行增加、修改和删除操作时前台显示的分类是否改变以及数据库中的分类数据是否相应的改变
    管理员鲜花管理测试:管理员在网上花店后台对于鲜花的管理主要是对鲜花的增加、修改、查询和删除,因此实际测试中要测试管理员进行查询操作时是否能正确显示查询信息,管理员进行增加、修改和删除操作时前台显示的鲜花是否改变以及数据库中的鲜花数据是否相应的改变
    管理员公告管理测试:管理员在网上花店后台对于鲜花的管理主要是对公告的增加、修改、查询和删除,因此实际测试中要测试管理员进行查询操作时是否能正确显示查询信息,管理员进行增加、修改和删除操作时前台显示的公告是否改变以及数据库中的公告数据是否相应的改变
    管理员订单管理测试:管理员在网上花店后台对于订单的管理主要是对订单的查询和处理,因此实际测试中要测试管理员进行查询操作时是否能正确显示查询信息,管理员进行处理操作时订单是否显示已处理并且数据库中的订单数据是否相应的改变
    管理员用户管理测试:管理员在网上花店后台对于用户的管理主要是对用户的查询和删除,因此实际测试中要测试管理员进行查询操作时是否能正确显示查询信息,管理员进行删除操作时数据库中的用户数据是否相应的删除

    7.2.3 测试结果通过上一小节对测试细节的分析,对系统进行相应的测试,具体的测试结果如表7-1、表7-2以及表7-3所示。
    在表中有四项内容:

    名称:指测试的对象
    操作:指测试过程中进行的操作方法
    预期结果:指对测试操作产生结果的预测
    实际结果:指实际对系统进行测试时产生的结果

    登录注册测试结果



    名称
    操作
    预期结果
    实际结果




    用户注册测试
    在注册表单输入各种格式的数据
    格式正确则注册成功,反之失败
    同预期


    用户登录测试
    在登录表单输入未注册和已注册数据
    与数据库数据一致则登录成功,反之失败
    同预期


    管理员登录测试
    在登录表单输入正确数据及错误数据
    与数据库数据一致则登录成功,反之失败
    同预期


    用户退出测试
    点击退出系统
    正确退出
    同预期


    管理员退出测试
    点击退出系统
    正确退出
    同预期



    用户操作测试结果



    名称
    操作
    预期结果
    实际结果




    浏览鲜花测试
    点击首页的鲜花列表相应链接
    跳转到相应鲜花界面
    同预期


    加入购物车测试
    点击加入购物车按钮
    跳转正确并且数据库相应改变
    同预期


    管理购物车测试
    对购物车内容进行增、删
    跳转正确并且数据库相应改变
    同预期


    生成订单测试
    点击生成订单按钮
    跳转正确
    同预期


    提交订单测试
    点击提交订单按钮
    跳转正确并且数据库相应改变
    同预期


    管理个人信息测试
    修改个人信息并提交
    跳转正确并且数据库相应改变
    同预期



    管理员操作测试结果



    名称
    操作
    预期结果
    实际结果




    分类管理测试
    在分类管理界面进行增删改查
    跳转正确并且数据库相应改变
    同预期


    鲜花管理测试
    在鲜花管理界面进行增删改查
    跳转正确并且数据库相应改变
    同预期


    公告管理测试
    在公告管理界面进行增删改查
    跳转正确并且数据库相应改变
    同预期


    订单管理测试
    在订单管理界面进行查看和处理
    跳转正确并且数据库相应改变
    同预期


    用户管理测试
    在用户管理界面查看和删除用户
    跳转正确并且数据库相应改变
    同预期



    结论完成了网上花店销售系统的设计,系统前台实现了用户在线浏览所有鲜花,按需求搜索相关鲜花,浏览系统公告以及注册登录后对鲜花选购的操作和购物结束后对订单信息的查看。系统后台实现了管理员对鲜花、分类、公告、订单、用户的管理。
    所设计系统中有一些优点,第一系统安全性高,本系统使用者分为管理员和用户两个角色,当其登录系统时,对其身份进行严格认证;第二采用隔离与访问控制,本系统根据用户的工作需求来分析,对用户权限进行了严格的控制,比如,用户只能浏览鲜花信息而不能修改,系统管理员就可以添加、删除、修改鲜花信息;第三操作简便,该系统本着方便易用的目的进行设计,无论是管理员还是用户都不需要具备专业的计算机知识,只要懂得计算机的一些基本操作,就可以轻松的对花店进行使用,这样做更加贴近用户,使用户使用方便,提高用户的体验。
    但本系统也有一些不足,比如界面相对比较简单,功能相对有限。所以该系统还可以继续完善。
    参考文献[1] 万常选,刘云生. 电子商务的技术及其应用[J]. 计算机工程与应用. 2002(07) .
    [2] 王知强,郑炜. 基于UML的动态企业建模的研究与实现[J]. 哈尔滨商业大学学报(自然科学版). 2005(02) .
    [3] 文灿华,张伟. 基于JSP的网上商城的设计与实现[J]. 电脑知识与技术. 2010(31) .
    [4] 鲁晓东,李育龙,杨健编著.JSP软件工程案例精解[M]. 电子工业出版社, 2005.
    [5] 杨学瑜等编著.JSP入门与提高[M]. 清华大学出版社, 2002.
    [6] 张琳. 网上购物系统的设计与开发[J]. 科技信息(学术研究). 2007(24).
    [7] 陈春蓉. 网上购物系统的设计与开发[J]. 软件导刊. 2009(08).
    [8] 万华. 基于JSP的网上购物系统的实现[J]. 现代计算机(专业版). 2002(10).
    [9] Enhancing Java server availability with JAS. Reinhard Klemm,Navjot Singh. Software. Practice \& Experience . 2001.
    [10] D.C.Ghita.JavaScript Generators. Studia Universitatis Babes-Bolyai:Series Informatica . 2010.
    [11] Jeffrey A Hoffer,Joey F. George.Modern SystemsAnalysis and Design. 2003.
    31 评论 398 下载 2020-08-03 19:01:00
  • 基于Android Studio实现的新闻APP

    一、作业题目实现一个安卓新闻类App,最低支持安卓系统版本为5.1(minSdkVersion 为API 16 https://developer.android.com/guide/topics/manifest/uses-sdk-element.html )
    二、作业描述互联网科技的发展让新闻的传播从报纸、广播、电视等方式发展到了网页以及最近几年兴起的手机app客户端,人们获取新闻的方式变得异常容易。手机上的新闻app让大家随时随地掏出手机即可看天下事,手机新闻app不再是一个简简单单的新闻获取工具,许多app已经利用数据挖掘构建出了新闻推荐引擎,为用户提供个性化、更有价值的新闻,例如今日头条、天天快报等。
    现在让我们也来尝试一下做一个新闻app!本次大作业的任务就是实现一款新闻获取的工具类软件,其中新闻数据采用的是腾讯网的rss,同学们根据相关rss数据和作业要求利用课上所学的Java和android开发知识实现一个新闻客户端即可。
    三、接口描述本次大作业需要开发的系统结构如图1所示,实现了新闻内容的抓取和存储;客户端从服务器拉取新闻,是学生需要完成的部分,包括新闻频道获取、展示和管理,新闻列表的获取、展示以及刷新,新闻收藏、分享等。
    中文新闻所用的rss为:http://rss.qq.com/index.html ,需要简单了解rss相关知识。
    四、具体实现4.1 新闻列表4.1.1 UIAPP主界面布局xml如下:
    <android.support.design.widget.CoordinatorLayout <android.support.design.widget.AppBarLayout <android.support.v7.widget.Toolbar/ > <android.support.design.widget.TabLayout/ > </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager/></android.support.design.widget.CoordinatorLayout>
    其中CoordinatorLayout用于协调布局中的部件的滑动,AppBarLayout用于显示标题并添加菜单,ViewPager用于显示新闻列表。
    ViewPager中包含多个Fragment,每个Fragment布局xml如下:
    <android.support.v4.widget.SwipeRefreshLayout <android.support.v7.widget.RecyclerView/></android.support.v4.widget.SwipeRefreshLayout>
    其中SwipeRefreshLayout用于添加下拉刷新操作,RecyclerView中以垂直线性布局的方式显示新闻条目。
    RecyclerView中的新闻条目布局xml如下:
    <LinearLayout android:orientation="vertical"> <TextView android:id="@+id/title"/> <LinearLayout android:orientation="horizontal"> <TextView android:id="@+id/source"/> <TextView android:id="@+id/datetime"/> </LinearLayout></LinearLayout>
    即每个条目分为两行,第一行为新闻标题,以较大字体显示,第二行为新闻来源和发布时间,分别位于第二行左侧和第二行右侧,以较小字体显示。
    4.1.2 功能实现新闻列表中主要实现了以下功能:
    下拉刷新获取新的新闻该功能通过重载SwipeRefreshLayout中的onRefresh()功能实现。用户下拉页面会自动调用onRefresh()函数,app后台向服务器申请新闻数据,并更新后台的新闻列表;随后会调用Fragment的Adapter的notifyDataSetChanged函数,更新UI界面上所显示的数据。
    上拉加载更多旧的新闻该功能通过给RecyclerView添加SrollListener监测用户下拉动作,当列表下拉至接近最下端时,会向后台申请更多新闻数据,并调用notifyDataSetChanged函数更新UI界面上的数据。
    新闻列表本地存储该功能通过使用SQLiteOpenHelper类为app添加后台数据库,并在向服务器申请更新数据时将更新的数据放入数据库中。在app开启时会从数据库中取出新闻数据加载到内存中。
    新闻是否看过的灰色标记该功能通过新闻列表中ViewHolder的onClick函数实现。当用户点击某一新闻条目时,会更改该条目的颜色为灰色。同时,阅读标记也会被更新到数据库中,下一次打开程序时灰色标记不会消失。
    新闻搜索该功能通过主页面上的Menu中的条目点击实现。点击Menu中的search条目会弹出AlertDialog搜索框。搜索功能通过对后台新闻数据进行搜索实现,并将搜索到的新闻显示在search Fragment上。









    搜索示例1
    搜索示例2



    新闻分类添加和删除操作该功能通过主页面上的Menu中的条目点击实现。点击Menu中的category条目会弹出多选框,对需要的category进行选中即可。用户选中后点击确定,调用函数对后台选中category的数据进行更新,并调用notifyDataSetChanged函数添加和清除相关页面。

    4.1.3 工作难点与亮点
    页面布局,使用了比较新的控件,需要学习的东西较多。在协调TabLayout和ViewPager中碰到较多问题,包括标题不显示,ViewPager显示空白等
    数据加载,FragmentStatePagerAdapter使用较复杂。碰到了更新后台数据前台不刷新,以及删除Fragment后页面错位的问题。通过上网查阅资料,重载getItemPosition函数得以解决。此外使用了Loader类,对数据进行加载和更新
    新闻分类和删除操作中,对Fragment的重构析构操作较多,碰到了一些问题

    4.2 分享功能4.2.1 实现方式通过调用Android自带的原生分享功能Active_Send实现。由于微信SDK的问题,在同时分享文本与图片上遇到一些问题:微信6.6.7版本以后无法再使用”Kdescription”进行图片与文本的共同分享。
    4.2.2 工作难点与亮点图片URL获得方法通过针对不同版本的android系统,重载不同的WebView的shouldInteruptRequest方法,在WebView加载网页时获取所加载资源的URL,并通过URL的所含字段判断是否为图片类型,从而直接获取图片URL。
    图片下载与选择问题通过BitmapFactory类对图片通过URL进行下载并保存。在保存过程中需要动态申请外存权限,申请过程写在了重载的onCreate函数中。
    Uri传输问题保存图片后,由于android较高版本对权限的控制,需要使用FileProvider类对图片URI进行获取并分享。
    4.3 收藏功能4.3.1 实现方法通过为每一个NewsItem类添加一个favorite成员变量,记录每一条NewsItem是否被收藏过。收藏内容记录在本地,并可以通过服务器进行同步。
    4.3.2 工作难点与亮点数据更新问题在设置收藏的时候,需要对页面进行实时刷新以便显示出最新添加的收藏。此外,需要避免数据重复的问题。
    4.4 新闻推荐4.4.1 实现方法通过对用户阅读过的新闻与收藏的新闻进行记录,为每一个阅读与收藏记录赋予不同的权重,通过加和判断出用户对各分类的喜好顺序,排序后为用户更多推荐未阅读过的喜好顺序靠前的分类的新闻。

    4.5 新闻评论4.5.1 实现方法通过获取用户手机mac地址将评论上传到服务器,服务器端判断是否登录,并决定显示mac地址或用户名。新闻评论自动与服务器同步。
    4.5.2 实现难点与亮点同步评论过程中需要对mac地址进行判断。评论显示布局需要设计。









    评论示例1
    评论示例2



    4.6 服务器设计4.6.1 实现方法在服务器端使用Java语言写了一个多线程服务器,接收用户端的不同请求,包括注册,登录,刷新新闻,收藏新闻,同步收藏,同步评论等。并实现了新闻的mac地址记录缓存,服务器端保存功能,避免了新闻的遗漏。
    注册,登录在服务器端使用mysql数据库记录用户数据,在注册时判断用户名是否存在并返回成功或失败信息;在登录时判断用户名密码是否匹配,并记录登录的mac地址以便后续使用时无需再次登录。
    刷新新闻服务器端每5分钟爬取一次各分类的rss界面获取最新的新闻信息。客户端申请更新新闻时将最近的50条新闻传送给客户端,客户端可以判断传输的新闻是否已存在,并将新的新闻更新到UI界面中。
    收藏新闻服务器端记录每一个登录用户的收藏信息。客户端登录后自动同步收藏信息,并且接收客户端新建的收藏条目。客户端刷新页面后自动再次同步收藏信息。
    4.6.2 工作难点与亮点服务器与客户端同步服务器与客户端同步时为多线程,避免了多个客户端的阻塞。
    服务器本地存储服务器本地创建mysql数据库对信息进行保存。
    mac地址获取与缓存客户端通过MacAddressFetcher类获取手机mac地址。由于android权限限制,获取方法较为复杂。

    五、总结与心得在本次新闻app项目的制作过程中,我学习到了android编程的相关知识和面向google编程的能力,也感受到了人在DDL面前的巨大潜力。7天的时间从不懂android编程到编出一个能够使用的新闻app,也让我自己很惊讶。但也由于时间关系和评分要求,所做出的app界面并不美观,也希望助教谅解。
    附注
    实验手机型号:小米6
    系统版本:MIUI10 8.8.23开发版,Android 8.0.0
    24 评论 385 下载 2020-04-07 09:57:40
  • 基于C语言实现的操作系统银行家算法

    一、选题背景这次课程设计要求完成一个资源管理系统,掌握使用银行家算法管理系统资源分配的工作原理。深入认识在多道程序系统中合理资源分配的重要性,加深死锁有关概念的理解。模拟实现银行家算法对系统资源进行分配,以防止死锁的出现。本课题肯定不可能实现对实际操作系统的资源管理,而是通过对模拟资源数据的处理,检测银行家算法在防止死锁出现的作用。
    二、方案论证模拟实现银行家算法对系统资源进行分配,以防止死锁的出现。本课题肯定不可能实现对实际操作系统的资源管理,而是通过对模拟资源数据的处理,检测银行家算法在防止死锁出现的作用。先对用户提出的请求进行合法性检查,即检查请求的是不大于需要的,是否不大于可利用的。若请求合法,则进行试分配。最后对试分配后的状态调用安全性检查算法进行安全性检查。若安全,则分配,否则,不分配,恢复原来状态,拒绝申请。
    三、实验环境
    Windows操作系统
    VS 2013
    C语言

    四、设计思想及实验步骤4.1 设计思想先对用户提出的请求进行合法性检查,即检查请求的是不大于需要的,是否不大于可利用的。若请求合法,则进行试分配。最后对试分配后的状态调用安全性检查算法进行安全性检查。若安全,则分配,否则,不分配,恢复原来状态,拒绝申请。
    4.2 银行家算法中的数据结构可利用资源向量Available。这是一个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态改变。如果Available[j]=K,则表示系统中现有Rj类资源K个。
    最大需求矩阵Max。这是一个 的矩阵,它定义了系统中 个进程中的每一个进程对 类资源的最大需求。如果Max[I,j]=K,则进程i需要Rj类资源的最大数目为K。
    分配矩阵Allocation。这也是一个 的矩阵,它定义了系统中每一类资源当前已分配给每一个进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已经分得Rj类资源的数目为K。
    需求矩阵Need。这也是一个 的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成任务。
    即:
    int M ; // 总进程数int N ; // 资源种类int ALL_RESOURCE[W]; // 各种资源的数目总和int Max[W][R]; // 最大需求矩阵,M个进程对N类资源最大资源需求int Available[R]; // 可利用资源向量,int Allocation[W][R];// 分配矩阵,各个进程M已经得到N类资源的资源数int Need[W][R]; // M个进程还需要N类资源的资源量int Request[R]; // 进程的请求资源个数
    以上三个矩阵间存在下述关系:

    4.3 银行家算法bank()设Request i是进程Pi的请求向量,如果Requesti[j]=K,表示进程Pi需要K个Rj类型的资源。发出请求后,系统按下述步骤进行检查:

    (1)检查申请量是否不大于需求量。如果Request i[j]<=Need[i,j],便转向步骤(2);否则认为出错,因为他所需要的资源数已经超过它所宣布的最大值。
    (2)检查申请量是否小于系统中的可利用资源数量。如果Requesti[j]<=Available[i,j],便转向步骤(2);否则认为尚无足够资源,Pi必须等待。
    (3)若以上两个条件都满足,则系统试探着将资源分配给申请的进程,并修改下面数据结构中的数值:

    Available[j]=Available[j]-Request[j];Allocation[k][j]=Allocation[k][j]+Request[j];Need[k][j]=Need[k][j]-Request[j];

    (1)试分配后,系统执行安全性算法,调用safe()函数检查此次资源分配后系统是否处于安全状态。若安全,才正式将资源分配给进程,以完成本次分配,并将安全序列打印出来;否则本次试探分配作废,恢复原来的资源分配状态,让该进程等待。
    4.4 安全性算法safe()
    (1)设置两个向量

    工作向量:Work,它表示系统可提供给进程继续运行所需要的各类资源数目,它含有m个元素,在执行安全性算法开始时,Work: =AvailableFinish,它表示系统是否有足够资源分配给进程,使之运行完成。开始时先做Finish[i]:=false;当有足够的资源分配给进程时,再令Finish[i]:=true
    (2)从进程集合中找到一个满足下述条件的进程

    Finish[i]:=false;Need[i,j]<=Work[j];若找到,执行步骤(3),否则,执行步骤(4)
    (3)当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行



    (4)如果所有的进程Finish= true都满足,则表示系统处于安全状态;否则系统处于不安全状态
    五、程序的基本结构框图和流程图5.1 程序结构功能图
    5.2 流程图
    六、实例运行结果及分析



    七、总结银行家算法就是一个分配资源的过程,使分配的序列不会产生死锁。此算法的中心思想是:按该法分配资源时,每次分配后总存在着一个进程,如果让它单独运行下去,必然可以获得它所需要的全部资源,也就是说,它能结束,而它结束后可以归还这类资源以满足其他申请者的需要。
    通过这两周的课程设计,我依然学到了很多的实用性知识。对以前学习到的知识又进行了巩固,除了更深的了解这个算法,还对C语言进行了复习,让我获益匪浅。在本次的课程设计过程,我也遇到了很多这样或那样的问题,但是通过我上网查资料,去图书馆借书,以及向老师和同学请教,最终把问题给解决了,这样又锻炼了我实际动手操作能力。
    2 评论 274 下载 2019-06-07 11:51:23
  • 基于Jsp和MySQL实现的学生选课系统

    1.功能需求
    管理员能够实现学生基本信息的录入、修改、删除等操作,其中学生信息包括学号、姓名、性别、专业等信息
    管理员能够实现课程的录入、修改、删除等功能,其中课程信息包括课程号、课程名、课程图片、学分等
    管理员可以查看学生选课信息,并可以进行添加选课学生和删除选择该课程的学生等操作
    有汇总功能,管理员首页可以查看没门课程的选课人数
    学生能实现选课功能,每个学生可以在首页浏览课程信息,并可以进行选课操作,其中课程信息包括学分、上课地点、课程编号、授课教师、课程名等信息

    2.表结构和表关系E-R图

    管理员表 t_admin

    班级表 t_class

    课程表 t_course


    学生表 t_student

    教师表 t_techaer

    3.功能分析3.1 用户模块3.1.1 用户登录功能

    当用户输入用户ID和密码点击登录进行登录,登录成功跳转首页,登录失败跳转回登录页面并回显用户信息以及提示信息
    不同类别的用户登录成功后进入不同的首页,拥有不同的功能


    难点

    验证码存session,登录的时候拿到表单提交的验证码和session中的进行比较
    不同类别的用户首页显示不同页面,通过jstl中的条件判断,不同用户存不同的值到作用域中,前台不同值显示不同页面

    3.1.2 用户注销用过点击注销,清session跳转登录页面即可。
    3.2 管理员模块3.2.1 查看个人信息前台点击→后台查询session中的个人信息→填充到指定页面位置:

    3.2.2 添加新的管理员前台提交数据到后台,数据库的添加操作:

    3.2.3 添加学生前台提交数据到后台,数据库的添加操作:

    3.2.4 获取所有学生
    前台提交数据到后台,数据库的查询操作
    查询功能,前台提交条件到后台,数据库的条件查询操作


    3.2.5 添加课程前台提交数据到后台,数据库的添加操作:

    3.2.6 查询课程
    前台提交数据到后台,数据库的查询操作
    提交按钮,给老师设置课程,前台提交数据到后台,数据库的添加操作


    3.2.7 添加教师前台提交数据到后台,数据库的添加操作:

    3.2.8 获取所有教师前台提交数据到后台,数据库的查询操作。

    点击修改,前台提交数据到后台,数据库的更新操作
    点击删除,前台提交数据到后台,数据库的删除操作


    难点

    数据库的联表操作
    分页功能的实现,主要就是后台SQL的limit筛选语句

    3.3 教师模块3.3.1 查看个人信息前台点击→后台查询session中的个人信息→填充到指定页面位置:

    3.3.2 评分前台提交数据到后台,数据库的更新操作:

    3.3.3 查看任课课程前台提交数据到后台,数据库的查询操作:

    难点

    数据库联表操作
    3.4 学生模块3.4.1 查看个人信息**前台点击→后台查询session中的个人信息→填充到指定页面位置:

    3.4.2 选课前台提交数据到后台,数据库的添加操作:

    3.4.3 查看已选课程
    前台提交数据到后台,数据库的查询操作
    取消课程操作,前台提交数据到后台,数据库的删除操作

    1 评论 6 下载 2021-08-16 10:50:24
  • 基于JAVA和TCP SOCKET实现的P2P的局域网即时通信系统

    一、设计要求
    掌握P2P原理
    实现一个图形用户界面局域网内的消息系统。
    功能:建立一个局域网内的简单的P2P消息系统,程序既是服务器又是客户,服务器端口(自拟服务器端口号并选定)

    用户注册及对等方列表的获取:对等方A启动后,用户设置自己的信息(用户名,所在组);扫描网段中在线的对等方(服务器端口打开),向所有在线对等方的服务端口发送消息,接收方接收到消息后,把对等方A加入到自己的用户列表中,并发应答消息;对等方A把回应消息的其它对等方加入用户列表。双方交换的消息格式自己根据需要定义,至少包括用户名、IP地址发送消息和文件:用户在列表中选择用户,与用户建立TCP连接,发送文件或消息
    用户界面:界面上包括对等方列表;消息显示列表;消息输入框;文件传输进程显示及操作按钮或菜单

    二、软件开发工具及运行环境
    软件开发工具

    编程语言:Java开发环境:EclipseJDK版本:1.8操作系统:windows 10
    运行环境

    操作系统无关性:Windows、Linux、Mac OS X下安装了Java的运行环境JRE即可运行

    三、程序开发的基础知识3.1 学习Socket和TCP的基本原理和通信机制3.1.1 TCP连接电脑能够使用联网功能是因为电脑底层实现了TCP/IP协议,可以使电脑终端通过无线网络建立TCP连接。TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上。
    建立起一个TCP连接需要经过“三次握手”:

    第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手
    握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”。(过程就不细写了,就是服务器和客户端交互,最终确定断开)
    3.2 SOCKET原理3.2.1 套接字(socket)概念套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
    应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。
    3.2.2 建立socket连接建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。
    套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

    服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求
    客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求
    连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求

    3.3 SOCKET连接与TCP连接创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。
    3.4 主要运用知识
    Java socket编程Java GUI编程Java继承和事件绑定Java异常与捕获
    四、总体设计4.1 设计思路4.1.1 经典的TCP通信服务器客户端架构服务器有一个服务器等待用户连接的线程,该线程循环等待客户端的TCP连接请求。一旦用ServerSocket.accept()捕捉到了连接请求,就为该TCP连接分配一个客户服务线程,通过该消息传递线程服务器与客户端通信。服务器发送消息通过该客户服务线程的方法在主线程完成,而接收消息全部在客户服务线程中循环接收并处理。
    客户机能发起一个向服务器的socket连接请求,一旦收到服务器成功响应连接请求,客户机便为这个socket分配一个消息接收线程,否则关闭该socket。和服务器任务分配类似,发送消息作为非常用方法在主线程中完成,而接收消息在消息接收线程中不停刷新并作相应处理。
    4.2 统一ASCII码级文本传输协议为了实现客户机对服务器命令的响应、服务器对客户机需求的解读以及客户机与客户机之间的消息传递,我为服务器和客户端之间通信定义了一组文本传输协议。协议属于变长文本传输协议,用@作为各字段分隔符,所有消息的首节一定是消息类型,方便解析。协议定义了以下按发送方分类的消息格式:


    4.3 MVC分层模式Model-View-Controller是经典的应用程序开发设计模式,它讲究数据管理、界面显示和用户交互、程序维护管理分别封装在MVC三种类中,够成松耦合关系。本次课程设计中我也利用MVC的设计思路,独立了Model类User用于保存客户机用户信息,DefaultListModel模型类用于储存在线用户队列;将View单独放在一个包中,Controller监听用户操作事件,反映给Model类处理并在View中更新。
    MVC的思想即是M和V之间不要直接产生联系,业务逻辑均封装在MC中,而V仅仅负责显示。本实验为V类绑定了各自的Listener监听用户操作,在C中完成业务逻辑处理,保存并更新User和DefaultListModel,最后再显示到UI界面上。
    4.4 concurrentHashMap管理线程队列和用户列表concurrentHashMap是java.util.concurrent包中定义的多线程安全的哈希表,利用哈希表管理线程队列和用户列表可以快速索引,多线程安全也保证了多个用户服务线程之间共享资源的数据一致性。
    4.5 程序流程图
    4.6 关键数据结构4.6.1 User模型类
    构造方法
    有两个,一个是用独立的name和IP实例化一个User,另一个是用name%IP拼接而成的字符串实例化User
    只读字段
    name和ipAddr均是private的,给他们配置一个只读的getter
    description()用户描述
    返回name%IP拼接而成的字符串,用以代表一个独立的用户

    4.6.2 ServerView类
    UI相关的方法
    构造函数中的initUI()大部分是设置UI界面,其中用到了GridLayout和BorderLayout。用serviceUISetting(false)把所有连接状态才起作用的button和textField全部关闭了(false改为true开启他们,并关闭所有设置相关的button和textField)

    4.6.3 ServerMain类
    startServer()开启服务器方法———startButton绑定
    先检查maxClientNum和port的合法输入,如果不合法弹出出错窗口并退出。接着初始化管理客户服务线程队列的并发哈希表clientServiceThreads,初始化监听客户机连接请求的serverSocket,并且初始化和开启一个监听连接请求的线程。最后有一些差错处理以及服务器log日志
    请求监听线程ServerThread类
    isRunning作为线程运行标志位控制线程存活,线程start后会调用的函数run()里完成了监听逻辑。如果开启则一直循环,serverSocket.accept()是阻塞的,线程不会运行直到有其他线程/进程向其请求Socket连接。这也是我下面提到的一个bug的原因:accept()阻塞了线程它一直在等待,仅仅用标志位来结束线程并不能使之跳出阻塞状态(还没有循环到下一次while的判断),因此我在closeThread()中强行关闭serverSocket会报出一个异常!
    收到连接请求后accept()返回一个socket,这个socket用于和请求连接的客户机通信。至此时TCP建立连接3次握手已经完成,全部被serverSocket类封装起来了。获取了通信socket之后检查服务器在线人数是否已满,向客户机发送一个登陆成功或失败的消息。若在线人数未满连接成功,则为客户机分配一个clientServiceThread线程专门用于发送和接受客户机的TCP包。
    监听客户机消息的ClientServiceThread线程类
    该类比较庞大,我挑重点介绍。
    关键字段
    private Socket socket;private User user;private BufferedReader reader;private PrintWriter writer;private boolean isRunning;
    分别保存了通信socket、当前连接用户Model、绑定在socket输入流上的BufferedReader、绑定在socket输出流上的PrintWriter以及线程运行控制标志位isRunning。reader用来读取客户机消息输入,readLine方法也是阻塞的,直到客户机有消息发送过来。writer有一个写缓冲区,有flush()函数强制发送消息并刷新缓冲区,我把写消息封装在sendMessage(String)中。
    初始化
    初始化中先绑定reader和writer到socket响应流,在判断用户socket请求发送的消息格式是否正确(不正确线程将不能执行)。接着向所有已上线的用户通知一遍这个新用户上线了,发送通知需要遍历整个服务线程队列并发送文本传输协议中定义的各式的通知。注意到这时候该服务线程并没有加入到服务线程队列中,是在初始化完成之后加入的。
    通知了其他用户这个新客户机上线后,再告诉该客户机现在已经有哪些用户在线了,这也是用协议中的格式发送通知即可。这里用到了StringBuffer类,多字符串连接时该类比String的+的效率要高。
    线程run
    收到客户机消息后判断消息类型,若是LOGOUT通知客户机下线,则向所有其他客户端进程发送该用户下线的信息,并删除model类里的该用户对象和线程队列里的该线程。
    如果是消息则交与dispatchMessage(String)方法专门分发消息。
    分发消息方法dispatchMessage(String)
    该方法解析MSG类消息的to字段,根据to字段选择是将消息发给特定用户还是直接群发。发给特定用户的话根据to字段(userDescription)做索引,快速从服务线程队列找出服务该用户客户机的线程来发送信息。
    其他
    绑定时间如stopServer关闭服务器和sendAll群发消息都比较直白便省略介绍,主要需要注意一下其中的差错控制。关闭服务器还需要更新UI控制逻辑。
    说明
    ServerMain类虽然通过ClientServiceThread里的writer发送消息,并且也是调用封装在这个Thread内部类中的,但是调用writer来sendMessage并不是一定在该线程内完成的(该线程内指的是run()里的while循环内部),sendMessage是非阻塞的我们没有必要专门在线程中执行。ClientServiceThread主要工作是收听各个客户端向服务器发送的消息。

    4.6.4 ClientView类Client和Server稍微有点不一样,只有一个辅助线程MessageThread用于接收服务器消息。由于只需要绑定在一个socket上,所以writer和reader只有一个,是直接属于Client实例的字段。

    UI相关方法
    构造函数里的init和Server中几乎完全一样,这部分属于代码复用。注意需要多绑定一个监听器:
    javax.swing.event.ListSelectionListener类用来监听用户选择JList框里的条目,JList框里固定一个所有人的项(点击选中表示消息发送给所有人,默认发送给所有人,目标对象下线后也是自动把对象转变成所有人),其他则是在线用户。点击这些列表项时触发一个选择事件,通过判断index来判断用户的选择,并更新模型记录sendTarget和UI中messageToLabel显示的text。

    4.6.5 ClientMain类
    connect连接到服务器
    差错检测这里没有判断IP地址合法性,判断也不是很麻烦。用户输入合法时,根据服务器IP地址和端口实例化一个socket,这个socket用于将来和服务器通信。获取客户机本地IP地址并用这个IP地址实例化,通过socket给服务器发送一条自己用户信息(name和IP)的消息表示请求。发送完毕后立即开启MessageThread等待服务器的回应。
    MessageThread接受服务器消息线程
    reader.readLine()阻塞读取服务器消息。一直忘记介绍StringTokenizer类,这里说明一下。StringTokenizer类通过一个String和一个分割字符串实例或一个tokenizer,通过分割得到一系列记号流通过tokenizer.nextToken()获取这些记号字符串。不难发现其作用和String.split(String)一样也是做字符串分割,但是其效率显著优于split方法(百度搜索两者比较会有较详细的性能分析)。
    根据tokenizer返回的记号流我们来判断消息类型:
    服务器关闭:向服务器发送一个下线信息,关闭socket, write和read,清空记录Model,最后退出线程。
    服务器错误:log错误类型,啥也不干进入下一轮循环。
    登陆信息:
    成功:log成功,进入下一轮循环。
    失败:log失败,关闭socket, write和read,清空记录Model,最后退出线程。

    五、关键代码 private class ClientServiceThread extends Thread { private Socket socket; private User user; private BufferedReader reader; private PrintWriter writer; private boolean isRunning; private synchronized boolean init() { try { reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); writer = new PrintWriter(socket.getOutputStream()); String info = reader.readLine(); StringTokenizer tokenizer = new StringTokenizer(info, "@"); String type = tokenizer.nextToken(); if (!type.equals("LOGIN")) { sendMessage("ERROR@MESSAGE_TYPE"); return false; } user = new User(tokenizer.nextToken()); sendMessage("LOGIN@SUCCESS@" + user.description() + "与服务器连接成功!"); int clientNum = clientServiceThreads.size(); if (clientNum > 0) { //告诉该客户端还有谁在线 StringBuffer buffer = new StringBuffer(); buffer.append("@"); for (Map.Entry<String, ClientServiceThread> entry : clientServiceThreads.entrySet()) { ClientServiceThread serviceThread = entry.getValue(); buffer.append(serviceThread.getUser().description() + "@"); //告诉其他用户此用户在线 serviceThread.sendMessage("USER@ADD@" + user.description()); } sendMessage("USER@LIST@" + clientNum + buffer.toString()); } return true; } catch(Exception e) { e.printStackTrace(); return false; } } public ClientServiceThread(Socket socket) { this.socket = socket; this.isRunning = init(); if (!this.isRunning) { logMessage("服务线程开启失败!"); } } public void run() { while (isRunning) { try { String message = reader.readLine(); // System.out.println("recieve message: " + message); if (message.equals("LOGOUT")) { logMessage(user.description() + "下线..."); int clientNum = clientServiceThreads.size(); //告诉其他用户该用户已经下线 for (Map.Entry<String, ClientServiceThread> entry : clientServiceThreads.entrySet()) { entry.getValue().sendMessage("USER@DELETE@" + user.description()); } //移除该用户以及服务器线程 listModel.removeElement(user.getName()); clientServiceThreads.remove(user.description()); close(); return; } else { //发送消息 dispatchMessage(message); } } catch(Exception e) { e.printStackTrace(); } } } public void dispatchMessage(String message) { StringTokenizer tokenizer = new StringTokenizer(message, "@"); String type = tokenizer.nextToken(); if (!type.equals("MSG")) { sendMessage("ERROR@MESSAGE_TYPE"); return; } String to = tokenizer.nextToken(); String from = tokenizer.nextToken(); String content = tokenizer.nextToken(); logMessage(from + "->" + to + ": " + content); if (to.equals("ALL")) { //send to everyone for (Map.Entry<String, ClientServiceThread> entry : clientServiceThreads.entrySet()) { entry.getValue().sendMessage(message); } } else { //发送给某一个人 if (clientServiceThreads.containsKey(to)) { clientServiceThreads.get(to).sendMessage(message); } else { sendMessage("ERROR@INVALID_USER"); } } } public void close() throws IOException { this.isRunning = false; this.reader.close(); this.writer.close(); this.socket.close(); } public void sendMessage(String message) { writer.println(message); writer.flush(); } public User getUser() { return user; } }
    六、测试6.1 运行ServerMain和ClientMain本程序支持单服务器多客户端,我打开了1个Server和2个Client作为演示。进程开启后界面如下:


    服务器和客户端在未开启/连接的状态下无法发送消息只能修改配置,而在开启/连接状态下无法修改配置只能发送消息,UI逻辑均由开启/连接状态决定。
    服务器配置中可以修改监听端口和人数上限,开启后接收所有来自客户端的消息,模仿解析包动作进行转发,服务器可以群发消息。
    客户端可以设置自己的名字、服务器IP和服务器端口(默认均是192.168.1.154本地IP和端口6666)。客户端连接后可以在在线用户列表中选择所有人或其他在线用户发送消息。其他用户上下线信息在在线用户列表和聊天消息框中都有提示。
    6.2 开启服务器并登陆客户端下图是第二位登陆的用户杨劲登录时,从服务器接受其他用户,显示在左侧在线用户列表中。

    6.3 服务器群发消息
    6.4 客户端群发消息客户端 选择 所有人,并发送消息:

    客户端 收到了消息,并标记为群发:

    6.5 客户端发送私聊消息:客户端 和 客户端 私聊:


    6.6 客户端下线客户端下线时所有在线用户收到其下线消息,在线列表中不再出现此用户:
    客户端 下线,通知服务器,服务器转发其下线消息:

    客户端 收到 下线通知,左侧在线列表中已经没有下线的用户了:

    七、开发过程中遇到的问题及解决办法本次完成这个课程设计还是花了不少精力和时间,由于对于Java网络编程这一块并不是很擅长,开发过程中老是遇到各种大大小小的问题,例如一开始不太清楚tokenizer.nextToken()的意思以及用法, 在参考了一些书籍以及百度各种关于网络编程的文章,才得以顺利完成本次课设。
    八、程序中待解决的问题及改进方向程序可能还存在不少小bug,后期有时间再进行修复。目前发现的一个Bug是服务器关闭时,我关了服务器接收Socket请求的线程并close了该ServerSocket,但是该线程仍然继续执行了一次ServerSocket.accept()。我尝试用了synchronized方法并判断ServerSocket是否关闭,但这个异常还是会出现。我捕捉了该异常,仅仅printStackTrace而没有做其他错误处理,幸运的是这小Bug并不影响服务器关闭,所有客户端都能正确的接收服务器关闭的消息。希望以后有时间能把这个错误给改过来。
    10 评论 246 下载 2018-11-29 09:34:27
  • 基于PHP和MySQL实现的网页聊天系统

    一、网站总体设计1.1 网站设计主题.随着互联网的发展,使得通过网络实现人与人之间的联系沟通变得越来越重要。当你的朋友或者家人不在身边时,而思念的情感之浓,聊天软件更加方便;当你与同事共同探讨工作问题时,聊天软件更加方便。所以聊天软件很重要。为我们的生活提供了太多方便。
    1.2 网站功能要求1.2.1 网站功能结构图设计一个简易的网页聊天软件。该系统将完成注册用户、用户登录、和添加好友、实现群聊,本系统的功能模块图如图 1-1 所示。

    1.2.2 网站扩展功能
    实现删除用户完成用户个人详细资料添加
    二、网站数据库设计2.1 MySQL 介绍MySQL 是一种关系型管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据妨碍一个大仓库中,这样就增加了速度并提高了灵活性。
    MySQL 所使用的 SQL 语言是用于访问数据库的最常用标准语言。由于其提价小、速度快、总体拥有的成本低,尤其是开源码这一特点,一般中小网站开发都选择 MySQL。
    2.2 数据库详细设计2.2.1 数据库设计网页聊天系统,需要完成用户的登录注册,聊天信息缓存,用户信息。
    2.2.2 数据表设计2.2.2 用户表 chat_user
    表功能:保存用户登录和个人信息表结构

    2.2.2 聊天信息表 chat_message
    表功能:保存用聊天内容表结构

    2.2.3 表间关系
    三、网站界面实现3.1 Dreamweaver 介绍Adobe Dreamweaver,简称“DW”,中文名称 “梦想编织者”,最初为美国公司开发 [1] ,2005 年被收购。DW 是集制作和管理网站于一身的所见即所得编辑器。利用对 、、等内容的支持,和可以在几乎任何地方快速制作和进行。
    3.2 网站界面设计3.2.1 登录界面界面功能描述
    完成用户的登录和注册
    界面效果图

    界面操作流程

    部分核心代码
    header("content-type:text/html;charset=utf-8");$userName = $_POST['userName'];$userPwd = $_POST['userPwd'];clude_once("./Tools/phpTools.php");$sql = "select * from chat_user where userName = '$userName' and userPass = '$userPwd'";$arr = mysqli_excute_select($sql);if(count($arr) > 0) { header('location:./chat.php'); session_start(); $_SESSION['info'] = $arr[0];} else { echo "账号或者密码错误,请<a href='login.html'>重新登录</a>";}
    3.2.2 登录界面界面功能描述
    群聊界面
    界面效果图

    界面操作流程
    在输入框中输入需要发送的信息,然后点击发送。点击消息选择撤回
    部分核心代码
    header('content-type:text/html;charset=utf-8');session_start();$userId = $_SESSION['info']['Id'];$messageContent = $_POST['messageContent'];include_once "./Tools/phpTools.php";$sql="insertintochat_message(user_id,content)values('$userId','$messageCont ent')";$arr = mysqli_excute_zsg($sql);var_dump($arr);if($arr > 0) { header("location:./chat.php");} else { echo "发送失败";}
    3.2.3 登录界面界面功能描述
    所有用户界面
    界面效果图

    界面操作流程
    查看所有的好友信息
    部分核心代码
    <table class="table table-bordered table-striped"><thead><tr><th width='15%'>序号</th><th width='15%'>姓名</th><th width='15%'>密码</th><th width='55%'>头像</th></tr></thead><tbody><?phpheader("contentg-type:text/html;charset=utf-8");include "./Tools/phpTools.php";$sql = "select * from chat_user";$arr = mysqli_excute_select($sql);// var_dump($arr);for($i=0; $i<count($arr); $i++): ?> <tr> <td><?php echo $arr[$i]['Id']?></td> <td><?php echo $arr[$i]['userName']?></td> <td><?php echo $arr[$i]['userPass']?></td> <td> <img src="./images/icon/<?php echo $arr[$i]['userIcon']?>" alt=""> </td> </tr> <?php endfor;?></tbody></table></div></body>
    五、测试和总结5.1 测试和调试成功实现群聊

    输入错误的用户密码后提示登录错误要求重新登录

    5.2 系统存在的问题由于本系统知识一个小课题作业,存在很多的不足,安全性,多用户的并发性,交互体验感不足,界面不够美化。
    5.3 总结运用的技术本系统主要运用的技术 PHP、JavaScript、MySQL、jQuery,文件上传。
    5.4 收获及心得体会PHP 吸收了、和的特点,利于学习,使用,主要适用于开发领域。PHP 独特的混合了、、以及自创的语法。它可以更快速地执行。用 PHP 做出的与其他的相比,是将嵌入到(下的一个应用)文档中去执行,执行效率较高;PHP 还可以执行后代码,编译可以达到和代码运行,使代码运行更快。
    在完成这个课题的学习后,加深了我对与 PHP 技术的理解和运用能力,是自己学习了一门新的编程语言。
    2 评论 6 下载 2021-05-28 12:26:08
  • 基于JSP+Servlet+MySQL校园二手交易平台

    摘 要本系统采用JSP/servlet技术,是使用Java编程语言编写的一套校园网二手交易平台软件。系统采用的是最近几年流行的B/S开发模式,以互联网方式运行,服务器端只需要安装本系统,而客户端用户只要可以上网,就可以非常方便快捷的通过浏览器访问系统,浏览和发布二手交易信息,免去了传统的C/S模式下复杂的安装、配置、维护等操作。同时由于使用面向对象的Java语言,所以本系统也具有Java语言的面向对象、与平台无关、安全性高、稳定性高、多线程等特性,以及Java语言对网络编程技术的支持。使得本系统具有很高的使用价值。
    系统开发采用了实现MVC模式的Web应用组件:Struts,实现数据持久化功能的ORM组件:Hibernate,用JSP+HTML+JavaScript进行界面处理,数据库采用比较稳定的MySQL 5.0,并用JDBC进行数据库访问。
    关键词:JSP,Struts,Hibernate,MySQL,二手交易平台
    ABSTRACTThis system is a set of platform software of the campus-wide system secondhand transaction. It adopts the JSP/J2EE technique, and programmed with Java programming language. It also adopts the B/S development mode, which is based on Web and popularize in recent years. It runs in internet ways. Only when the server install this system and the client can visit it, browse and release some secondhand conveniently and speedily when they go on-line. And so it dispenses with such operation as the complicated installing, installment and support in traditional C/S mode. At the same time, it uses the Java language which towards the OOP(object-oriented programming).So the system has the specific property of towarding OOP, irrelevant with the platform ,the Java language’s support to the network programming technique makes the system have high practical value.
    The System using the components of Web applications: Struts to achieve MVC model, using the ORM components: Hibernate to achieve data persistence features, using JSP + HTML + JavaScript to Show page. using Relatively stable database MySQL 5.0, and use JDBC to visit.
    KEY WORDS: JSP,Struts,Hibernate,MySQL,Campus Secondhand Merchandise
    1 系统分析1.1 开发背景随着全世界互联网技术的不断发展,各种基于互联网技术的网络应用不断涌现,网络技术正在不断的深入人们的生活。人们从Internet上获取信息、享受生活、交流感情、网上工作等。Internet正在迅速改变着人们的生活方式。
    经过我国改革开放多年以后,随着与国际社会的接轨,各种资源的商品化已经逐渐成为了我们这个社会的代名词。在这这情势下,校园二手商品资源也已极大的丰富起来,如何解决一类问题,争取最大利用率的交流这类商品的信息便是一个存在中的问题。本毕业设计便是解决该问题的。
    1.2 目的和要求在当前社会上,许多的各种类型的电子商务类网站纷纷建立,可以很大程度上的解决人们信息资源的闭塞以及地域上的限制。作为大学校园,伴随着学生的购买能力的提高和每年的升学和毕业,也存在的许多各种类型的二手商品,由于信息交流的落后,很多只限于于校园公告栏或者请人代为宣传的方式进行交易。这种方式有很多局限性和偶然性,并不能满足二手商品畅通交流的要求。于是一种新的二手商品信息交流的方式出现了,就是基于Web的校园网二手商品交易系统。通过这个系统,可以发现每一个校园网用户都是系统的主人,大家可以非常方便的发布自己的信息,浏览别人的发布的信息,还可以对各种二手商品信息作出横向比较,作出自己的最佳选择。由此可见,该系统只是一个交流二手商品信息的平台,与一般的电子商务类网站又有本质的区别。
    1.3 可行性研究设计这样一个系统,从根本上解决了传统的校园二手信息发布交流方式的弊端,使得校园各种二手商品信息得到了有效的整合,方便了广大用户。且拥有的客户通常只是大学校园网的用户,所有系统规模上来讲不会很大,从经济上来说,由于选择的开发工具和服务器几乎全部为免费的开源软件,并且由于是开发成本较低的基于Web的B/S模式,而非成本费用相对较高的C/S模式,所以从经济上来讲是可行的。从技术上来说,由于是基于Web的,可以相对比较容易面对用户的实际需求而开发。而在现今,各种网络应用的开发已经相当成熟,出现了几大主流的开发语言和工具,都可以非常有效的支持开发这样一个系统。同时作为本系统,也有许多成功的电子商务类网站的经验可以借鉴,所以从技术的角度来说,也是可行的。从运行上来说,由于客户端仅仅只是需要一个浏览器,通过浏览器来登陆系统,而服务器端也只需要一台服务器,服务器要求一个数据库环境和一个网络应用开发的环境,实现起来比较容易,所以从运行上来说是可行的。同时这样一个系统,在系统管理员合法管理和用户的自觉配合下,不会违规进行任何的不法的活动和交易,发布具有危害性和不适宜的信息,也不存在任何非法牟利的行为,在法律上也是可行的。在各种可行性研究保证和基于用户需求要求下,开发系统的方案经过不断论证和假设,确定出了一个最佳方案。
    2 开发技术及开发环境2.1 Java语言简介Java语言是美国Sun公司于1995年推出的一种简单的、面向对象的、分布式的、可解释的、键壮的、安全的、结构的、中立的、可移植的、性能很优异的多线程的、动态的语言。其前身为OAK语言,是SUN公司为一些消费性电子产品而设计的一个通用环境。他们最初的目的只是为了开发一种独立于平台的软件技术。经过Sun公司的工程师的不懈努力以及全世界无数的编程爱好者的使用,Java终于发展成为今天这样一个集桌面(J2SE)、网络(J2EE)、移动平台(J2ME)应用为一体的功能强大的编程语言。目前Java由于其平台无关及分布式特性,最重要的应用是在网络应用上[1]。
    2.2 J2EE技术介绍J2EE技术是Java网络应用的技术,广泛应用于企业级的应用。它是由一套规范(shannin,2001)和建立在J2SE平台上的应用编程接口(API)组成。J2EE拥有Sun公司提供免费开发工具,称为J2EE软件开发工具包(Software Development Kit,SDK )( http://java.sun.com/j2ee )。J2EE技术是一种Java网络应用技术的组合,包含有远程方法调用(Remote Method Invocation,RMI)、Java消息服务(Java Message Service,JMS)、JavaMail等通信服务,JDBC、Java命名和目录接口(Java naming and Directory Interface,JNDI)、Java连接器体系结构(Java Connector Architecture,JCA)、Java事务API/Java事务服务(JTA/JTS)、XML处理API等通用服务以及Servlet、Java服务器页面(JSP)、企业级JavaBean(EJB)等组件技术。任何J2EE的实现都必须要在其特定容器中实现。
    2.3 Servlet/JSP技术Servlet是JSP技术的基础,JSP本身就是预先被编译成Servlet,然后再运行的,而且大型的Web应用程序的开发需要Java Servlet和JSP配合才能完成。 Servlet其实和传统的CGI程序和ISAPI、NSAPI等Web程序开发工具的作用是相同的,在使用Java Servlet以后,用户不必再使用效率低下的CGI方式,也不必使用只能在某个固定Web服务器平台运行的API方式来动态生成Web页面。许多Web服务器都支持Servlet,即使不直接支持Servlet的Web服务器也可以通过附加的应用服务器和模块来支持Servlet。JSP(JavaServer Pages)是一种基于Java的脚本技术。在JSP 的众多优点之中,其中之一是它能将 HTML 编码从 Web 页面的业务逻辑中有效地分离出来。用 JSP 访问可重用的组件,如 Servlet、JavaBean 和基于 Java 的 Web 应用程序。JSP 还支持在 Web 页面中直接嵌入 Java 代码。可用两种方法访问 JSP 文件:浏览器发送 JSP 文件请求、发送至 Servlet 的请求。

    JSP 文件访问 Bean 或其它能将生成的动态内容发送到浏览器的组件
    发送至 Servlet 的请求生成动态内容,并调用 JSP 文件将内容发送到浏览器。该访问使得将内容生成从内容显示中分离出来更为方便

    JSP最大的优点在于其与平台无关性,具有“一次编写,处处运行”的特点。
    2.4 MVC 简介模型-视图-控告器(MVC)是20世纪80年代Smalltalk-80出的一种软件模式,现在已经被广泛使用。

    模型(Model):模型是应用程序的主体部分。模型表示业务数据,或者业务逻辑
    视图(View):视图是应用程序中用户界面相关的部分,是用户看到并与之交互的界面
    控制器(Controller):控制器的工作就是根据用户的输入,控制用户界面显示和更新模型对象的状态

    典型的MVC模式所包含的模块、每个模块的功能以及模块之间的关系如图2-1所示[2]:

    MVC模式的出现不仅实现的功能模块和显示模块的分离,同是赛马场还提高了应用系统的可维护性、可扩展性、可移植性和组件的可利用性。
    在早期的程序中,如果不注意对数功能和显示的解耦合,常常估导致程序的复杂及难以维护,像VB,Delphi等RAD程序都有这种问题。甚至现在有C#,Java有时候也会出现把业务逻辑写在显示模块中的现象。
    尽管MVC设计模式很早的提出了,但在Web项目的开发中引入MVC却是步履艰难。主要原因是在早期的Web项目开发中,程序语言和Html的分离一直难以实现,CGI程序以字条串输出的形式动态的生成html内容。直到基于J2EE的JSP Model2问世时才得以改观。它用JSP技术实现视图的功能,用Servlet技术实现控制器的功能,用JavaBean实现模型的功能。JSP Model2 结构如图2-2所示:

    在Model 2这种框架结构中,Servlet作为控制器负责处理用户的请求以及创建JSP页面中所有要使用的Bean对象,并且还要根据用户的请求来返回到不同的JSP页面。
    在使用Model 2开发框架时,一定要保证在JSP页面中不能包含任何的业务处理逻辑。它只是简单地得到对象或者在Servlet中创建的Bean,然后通过这些动态的内容来生成动态显示的页面。
    Struts 本质上就是在Model 2的基础上实现一个MVC架构,它只有一个中心控制器,采用定制转向的URL并采用Action来处理逻辑。
    2.5 Struts 技术Struts是一个为开发基于模型(Model)-视图(View)-控制器(Controller)(MVC)模式的应用架构的开源框架,是利用Java Servlet和JSP构建Web应用的一项非常有用的技术。首先事件是指从客户端页面(浏览器)由用户操作触发的事件,Struts使用Action来接受浏览器表单提交的事件,这里使用了Command模式,每个继承Action的子类都必须实现一个方法execute。
    struts重要的表单对象是ActionForm,它代表了一种应用,这个对象中至少包含几个字段,这些字段是Jsp页面表单中的input字段,因为一个表单对应一个事件,所以,当我们需要将事件粒度细化到表单中这些字段时,也就是说,一个字段对应一个事件时,单纯使用Struts就不太可能,当然通过结合JavaScript也是可以转弯实现的。
    Struts是一个基于Sun J2EE平台的MVC框架,主要是采用Servlet和JSP技术来实现的。Struts把Servlet、JSP、自定义标签和信息资源(message resources)整合到一个统一的框架中,开发人员利用其进行开发时不用再自己编码实现全套MVC模式,极大的节省了时间。
    Struts包含了一组想相互协作的类、Servlet和JSP标记,它们共同组成了一个可重用的MVC模板。通过定义可以看出,Struts是Web应用的开发框架,Struts包含丰富的标记库和独立于该框架工作的实用程序类。图2-3 显示了Struts的基本结构。

    通过图 2¬-3可以看出,采用Struts框架结构的Web应用程序主要由控制器、业务逻辑、模型和视图组成。其中的控制器、模型和视图为Struts框架的主要组成部分,而事务逻辑则是我们需要实现的系统业务逻辑处理部分。
    2.6 Hibernate 技术2.6.1 应用程序的分层体系结构随着计算机应用软件的发展,应用程序逐渐由单层体系结构发展为多层体系结构。其中,三层结构是目前典型的一种应用软件结构。

    表述层:提供与用户交互的界面,如GUI(图形用户界面),web页面等
    业务逻辑层:负责各种业务逻辑,直接访问数据库,提供对业务数据的保存、更新、删除和查询操作
    数据库层:负责存放管理应用的持久性业务数据

    三层结构的特点:所有下层向上层提供调用的接口,具体实现细节对上层透明。层与层之间存在自上而下的依赖关系,即上层会访问下层的API,但下层不依赖于上层。
    分离出的持久化层封装了数据访问细节,为业务逻辑层提供了面向对象的API[2]。
    持久(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的数据存储在关系型的数据库中,当然也可以存储在磁盘文件中、XML数据文件中等等。
    持久层(Persistence Layer),即专注于实现数据持久化应用领域的某个特定系统的一个逻辑层面,将数据使用者和数据实体相关联。
    三层软件结构如图2-4所示:

    数据库的读写是一个很耗费时间和资源的操作,当大量用户同时直接访问数据库的时候,效率将非常低,如果将数据持久化就不需要每次从数据库读取数据,直接在内存中对数据进行操作,这样就节约了数据库资源,而且加快了系统的反映速度。增加持久化层提高了开发的效率,使软件的体系结构更加清晰,在代码编写和系统维护方面变得更容易。特别是在大型的应用里边,会更有利。同时,持久化层作为单独的一层,人们可以为这一层独立的开发一个软件包,让其实现将各种应用数据的持久化,并为上层提供服务。从而使得各个企业里做应用开发的开发人员,不必再来做数据持久化的底层实现工作,而是可以直接调用持久化层提供的API。
    2.6.2 Hibernate的应用及API简介Hibernate是一种Java语言下的对象关系映射解决方案。它是一种自由、开源的软件。它用来把对象模型表示的对象映射到基于SQL的关系模型结构中去,为面向对象的领域模型到传统的关系型数据库的映射,提供了一个使用方便的框架。
    Hibernate不仅管理Java类到数据库表的映射(包括从Java数据类型到SQL数据类型的映射),还提供数据查询和获取数据的方法,可以大幅度减少开发时人工使用SQL和JDBC处理数据的时间。
    Hibernate对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。Hibernate可以应用在任何使用JDBC的场合,它既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用。最具革命意义的是,Hibernate可以在应用EJB(EnterpriseJavaBeans是Java应用于企业计算的框架)的J2EE架构中取代CMP,完成数据持久化的重任。
    Hibernate使用 Java 反射机制 而不是字节码增强程序来实现透明性。Hibernate 的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。Hibernate支持各种关系数据库,从一对一到多对多的各种复杂关系。Hibernate核心接口如图2-5所示:

    2.7 开发环境及环境配置2.7.1 Java/JSP系统环境开发及测试的系统环境,我选择了Microsoft Windows Advanced Server 2000。由于其本身就是为服务器版的,适合用于搭设成为服务器端。要开发JSP,首先必须要求有Java环境,我选择了JavaTM Platform, Standard Edition 6 Development Kit。
    作为JSP的容器,选择了目前非常流行的Tomcat 6.0。而IDE工具则选择了Eclipse(MyEclips)。
    2.7.2 JSP环境的安装和环境变量的设置
    首先安装JDK,安装Tomcat
    接下来配置环境变量:右键点击“我的电脑”,在弹出的菜单中点“属性”,在系统特性里选择“高级”,找到“环境变量”,点击进入后,“系统变量”就是我们需要设置的地方

    新建变量CATALINA_HOME,变量值为:D:\apache-tomcat-6.0.18新建JAVA_HOME变量,然后在变量值中输入以下内容:C:\Program Files\Java\jdk1.6.0_12编辑path变量,在原有的变量值后添加JDK的BIN目录:%JAVA_HOME%\bin;%CATALINA_HOME%\BIN

    2.7.3 Eclipse开发工具Eclipse平台体系结构主要由5部分组成,分别是平台运行库、工作区、工作台、团队支持和帮助。
    在运行时内核是整个架构的核心,其他部件都是以插件方式来实现的。Eclipse采用动态加载机制,即只有需要的才加载,这样可以降低启动时间,提高资源使用效率。
    工作空间插件即所谓的工作区,主要负责管理用户资源,例如用户创建项目的管理、文件变更等,并负责通知其他插件关于资源变更的信息。
    工作台插件是Eclipse 提供的用户界面。它使用标准窗口工具包(SWT)和一个更高级的API(JFace)构建的。SWT是Java的Swing/AWT的非标准替代者,JFace则以SWT为基础,但更易于使用。
    团队支持插件负责提供版本控制和配置管理支持。它允许用户根据需要添加视图,并与允许用户使用的任何版本控制系统交互。
    帮助插件允许以HTML文件形式添加文档,并提供了一个附加的导航结构以便用户使用帮助功能搜索相关信息。
    2.7.4 Tomcat服务器Tomcat是Sun的JSWDK(Java Server Web Development Kit)中Servlet的运行环境(servlet容器)。Tomcat是Apache Jakarta软件组织的一个子项目,Tomcat是一个JSP/Servlet容器,它是在SUN公司的JSWDK(Java Server Web Development Kit)基础上发展起来的一个JSP和Servlet规范的标准实现,使用Tomcat可以体验JSP和Servlet的最新规范。经过多年的发展,Tomcat不仅是JSP和Servlet规范的标准实现,而且具备了很多商业Java Servlet容器的特性,并被一些企业用于商业用途[4]。
    Tomcat目录如下:
    Tomcat_home|---bin Tomcat:存放启动和关闭tomcat脚本|---conf Tomcat:存放不同的配置文件(server.xml和web.xml)|---doc:存放Tomcat文档|---lib/japser/common:存放Tomcat运行需要的库文件(JARS)|---logs:存放Tomcat执行时的LOG文件|---src:存放Tomcat的源代码|---webapps:Tomcat的主要Web发布目录(包括应用程序示例)|---work:存放jsp编译后产生的class文件2.8 数据库开发工具选择及配置目前数据库的开发工具,大、中、小型的有很多,比如Oracle、MS SQL Server2000、DB2、MySQL、Access等等许多关系数据库,在系统开发初期,我用SQL server2000 进行数据库连接,因为可以于Windows 2000服务器系统很好的兼容,并且对大并发访问有很好支持,功能强大且使用简单,然而在后期的开发中,由于经常更换设计环境,而且自己用到Hibernate,对软件有一定要求,每次系统移植都要花很多时间配置环境,所以又更换了移植性很好的MySQL做数据库。
    MySQL是一个小型关系型数据库管理系统,被广泛地应用在Internet上的中小型网站中。由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,许多中小型网站为了降低网站总体拥有成本而选择了MySQL作为网站数据库。
    与其他的大型数据库例如Oracle、DB2、SQL Server等相比,MySQL自有它的不足之处,如规模小、功能有限(MySQL Cluster的功能和效率都相对比较差)等,但是这丝毫也没有减少它受欢迎的程度。对于一般的个人使用者和中小型企业来说,MySQL提供的功能已经绰绰有余,而且由于MySQL是开放源码软件,因此可以大大降低总体拥有成本[3]。
    在本系统中,对MySQL的配置最重要是数据库字符编码设置,因为数据库的录入的大多是中文字符,默认编码为GBK会减少许多操作,配置如下:
    default-character-set=gbk3 系统需求分析及设计3.1 系统需求分析3.1.1 系统功能需求本系统主要面向于大学校园网用户,依托校园网提供给这些用户一个发布和交流二手商品信息的平台。在大学校园里,存在着很多的二手商品,但是由于信息资源的不流通以及传统二手商品信息交流方式的笨拙,导致了很多仍然具有一定价值或者具有非常价值的二手商品的囤积,乃至被当作废弃物处理。现在通过校园网进入到本系统,可以方便快捷的发布和交流任何二手商品的信息,并且可以通过留言方式进行深一步的交流。由于每个大学的校园网都基本篇布校园的每一个地方,因此,只要宣传得当,理论上来说,每一个人都可以让他所发布的信息让全校所了解,争取到了信息资源的最大化利用。
    系统完成的主要功能有:用户设置功能、发布信息功能、信息管理功能、搜索信息功能,留言功能,及系统管理功能,具体业务功能包括如下:

    用户注册:学生可利用自已学号进行注册,注册实现实名制
    用户登录:只有登录用户才能进行信息发布。管理员登录后可以进行系统管理
    发布信息:普通用户和管理员登录后都可以发布信息
    修改信息:普通用户可以修改自己发布的信息,管理员可以修改所有信息
    删除信息:普通用户可以删除自己发布的信息,管理员可以删除所有信息
    浏览信息:游客、普通用户和管理员可以浏览所有发布的信息
    搜索信息:游客、普通用户和管理员可以用关键字搜索所有发布的信息。普通用户可以搜索自己发布的所有信息
    发表留言:普通用户和管理员登录后都可以对发布信息进行留言
    查看留言:游客、普通用户和管理员都可以查看发布信息的留言
    删除留言:管理员可以删除留言
    添加二手指南:管理员可以添加二手指南
    查看二手指南:游客、普通用户和管理员都可以查看二手指南
    修改二手指南:管理员可以修改二手指南
    删除二手指南:管理员可以删除二手指南

    3.1.2 系统界面要求由于系统主要面向大学生,系统界面要求不能过古板,要能体现大学校园的自由,创新。系统界面设计应体现人性化,界面清晰简捷,操作简单流畅,提高管理效果。不需要任何专业培训,不需要配备专门的电脑操作人员,无电脑知识一样运用自如。关键在于系统的框架式设计简单明晰。
    3.2 概要设计3.2.1 系统体系结构设计本系统是一个典型的三层应用——浏览器通过Web服务器实现对数据库的各种操作。图3-1 展示了整个系统的体系结构。

    在这个系统体系结构中,并不是直接JDBC来访问数据库和进行数据库中相关表的操作,而是通过一系列持久层的Java对象来完成数据库的操作。
    映射文件相当于持久层的Java对象和数据库的表之间的桥梁,它所描述的是这两都之间的对应关系。而且,持久层的Java对象和数据库表之间的关系也是一一对应的。
    3.2.2 系统功能模块设计系统主要设计了用户设置功能、发布信息功能、信息管理功能、搜索信息功能,留言功能,及系统管理功能模块。

    用户设置功能:主要是用户注册必须填写所要求的个人资料,完成个人资料登入
    发布信息功能:主要是为已注册用户的服务,登陆的用户可以即时发布自己的二手商品信息,立刻就能浏览到。这是本系统的主要功能
    信息管理功能:是帮助已发表信息的的用户管理自身发布的二手商品信息的同时也管理短消息信息。此项功能也主要是服务于注册用户
    搜索信息功能:是面向所有登陆到本系统的人员的,采用模糊查询的方法,遍历所有二手商品信息,搜索出浏览者感兴趣的内容
    留言功能:是对某一二手商品信息进行留言,还可以查看该信息的其他留言
    系统管理功能:是系统管理员对系统所有信息资源进行统一管理的一个模块

    系统功能结构如图3-2所示:

    3.2.3 功能设计的目标与原则本二手交易平台的主要目的是服务于学生,方便学生进行网上交易。其原则是做到界面友好,操作简单且可靠。
    具体做到:

    架构清晰,界面友好美观,简捷,实用性强
    动态式信息发布:为充分展现网站的时实性,二手交易平台采用动态网页技术实现内容发布
    提供多种信息搜索及查看方式。全面自动化管理
    全面整合买家和卖家之间的信息,提供一个交流沟通的平台
    可用性,目标系统功能齐全,能够完全满足业务需求

    3.3 数据库设计3.3.1 数据库需求分析对于数据库的需求主要体现在对数据库的提交信息、更新信息、删除信息、保存信息等。这些信息的存在都取决于各个功能模块的对信息的需求。通过对功能模块的具体操作,实现对数据库中信息的输入和输出。所以,针对各个功能模块的需求,设计如下的数据表和数据结构:

    Maste 类表:用于实现平台用户我实名制及平台基本信息

    学院信息:包括学院编号,学院名,描述等班级信息:包括班级编号,班级名,学院编号,描述等学生信息:包括学号,姓名,班级编号,学院编号等类型信息:包括类型编号,类型名,类型描述等交易地区信息:包括地区编号,地区名,地区描述等
    Temp 类表:用于实现平台各模块

    用户信息:包括用户编号、用户名、密码、学号,及用户的其它相关信息等商品信息:商品编号、信息标题、信息内容,发布信息的用户,信息相关内容等商品留言信息:包括留言编号、商品信息编号、留言内容等

    3.3.2 数据库概念结构设计概念模型是对于信息世界的建模,是现实世界到信息世界的抽象,是数据库设计人员和用户之间进行交流的语言。它具有简洁明晰、易于理解和修改、便于向各种数据模型转换,从而生成相应的逻辑模式。
    概念设计的目的是要确定系统的概念模型,因为概念模型是数据库系统的核心和基础,所以概念设计是数据库设计的关键。
    3.3.3 数据库逻辑表设计数据库的概念结构设计完毕后,现在可以将上面的数据库概念结构转化为某种数据库所支持的实际数据模型,也就是数据库的逻辑结构。
    在本次设计开发中,考虑到系统的规模,以及系统的功能、稳定性、性能和效率等方面,特别的对系统可移植性的考虑,我使用MySQL数据库系统。
    依照3.3.1中的数据库需求分析设计各数据库表,各个表中都用ID做主键,困为用到Hibernate自动生成主键,所以这里主键ID类型设置为VARCHAR(50)。其它字段也都有各自的约束条件。
    各个表的具体逻辑结构如下:
    学院表 (m_dep)



    字段名
    数据类型
    约束条件
    说明




    ID
    VARCHAR(50)
    Primary Key
    学院编号


    DEP_NAME
    VARCHAR(10)
    UNIQUE
    学院名


    DEP_DESC
    varchar(100)
    NOT NULL
    学院描述



    班级表(m_class)



    字段名
    数据类型
    约束条件
    说明




    ID
    VARCHAR(50)
    Primary Key
    班级编号


    DEP_ID
    VARCHAR(50)
    Foreign Key
    学院编号


    CLASS_NAME
    VARCHAR(10)
    UNIQUE
    班级名


    CLASS_DESC
    varchar(100)
    NOT NULL
    班级描述



    学生表(m_student)



    字段名
    数据类型
    约束条件
    说明




    ID
    VARCHAR(12)
    Primary Key
    学号


    CLASS_ID
    VARCHAR(50)
    Foreign Key
    班级编号


    STU_NAME
    VARCHAR(10)
    UNIQUE
    学生姓名


    sex
    TINYINT(3)
    NOT NULL
    学生性别



    交易地区表(m_area)



    字段名
    数据类型
    约束条件
    说明




    ID
    VARCHAR(50)
    Primary Key
    地区编号


    AREA_NAME
    VARCHAR(10)
    UNIQUE
    地区名


    AREA_DESC
    varchar(100)
    NOT NULL
    地区描述



    信息类型表(m_type)



    字段名
    数据类型
    约束条件
    说明




    ID
    VARCHAR(50)
    Primary Key
    类型编号


    TYPE_NAME
    VARCHAR(10)
    UNIQUE
    类型名


    TYPE_DESC
    varchar(100)
    NOT NULL
    类型描述



    二手指南表(t_article)



    字段名
    数据类型
    约束条件
    说明




    ID
    VARCHAR(50)
    Primary Key
    指南编号


    TITLE
    VARCHAR(10)
    UNIQUE
    指南标题


    CONTENT
    varchar(8000)
    NOT NULL
    指南内容



    用户表(t_user)



    字段名
    数据类型
    约束条件
    说明




    ID
    VARCHAR(50)
    Primary Key
    用户编号


    USERNAME
    VARCHAR(10)
    UNIQUE
    用户名


    PASSWORD
    varchar(100)
    NOT NULL
    用户密码


    STU_ID
    VARCHAR(50)
    Foreign Key
    学号


    BIRTHDAY
    DATETIME
    NOT NULL
    生日


    PHOTO
    SMALLINT(5)
    NOT NULL
    照片


    QUESTION
    VARCHAR(100)
    NOT NULL
    注册问题


    ANSWER
    VARCHAR(100)
    NOT NULL
    注册答案


    EMAIL
    VARCHAR(50)
    —-
    EMAIL


    QQ
    VARCHAR(20)
    —-
    QQ


    CREATE_TIME
    DATETIME
    NOT NULL
    注册时间


    STATUS
    TINYINT(3)
    NOT NULL
    状态


    ROLE
    TINYINT(3)
    NOT NULL
    权限



    信息表(t_message)



    字段名
    数据类型
    约束条件
    说明




    ID
    VARCHAR(50)
    Primary Key
    信息编号


    MESSAGE_TITLE
    VARCHAR(50)
    UNIQUE
    信息标题


    TYPE_ID
    VARCHAR(50)
    Foreign Key
    信息类型


    AREA_ID
    VARCHAR(50)
    Foreign Key
    交易地区


    OLD_VALUE
    SMALLINT(5)
    NOT NULL
    新旧值


    PRICE
    DECIMAL(10,0)
    NOT NULL
    商品价格


    R_USER
    VARCHAR(10)
    NOT NULL
    联系人


    R_PHONE
    VARCHAR(50)
    NOT NULL
    联系电话


    R_EMAIL
    VARCHAR(50)
    —-
    EMAIL


    MESSAGE_DESC
    VARCHAR(200)
    NOT NULL
    信息详情


    MESSAGE_PHOTO
    VARCHAR(50)
    —-
    信息图片


    CREATE_TIME
    DATETIME
    NOT NULL
    新增日期


    FLAG
    TINYINT(3)
    NOT NULL
    信息标志


    TOP_VALUE
    INTEGER
    NOT NULL
    人气值


    CREATE_USER_ID
    VARCHAR(50)
    Foreign Key
    发布用户



    3.3.4 数据库逻辑结构设计对于maste表,它们都是做为别的表的外键而存在的。本系统数据库逻辑可分为两部分,一部分实现用户的实名制:实名制需要校方学生纪录,而学生又有以学院、班级,每个用户对应一个学生,其逻辑模型如图3-3所示:

    第二部分实现商品信息关联,每个商品都有商品类型、交易地区和发布用户,每个商品有多个留言,而每个留言又有发表用户,其逻辑模型如图3-4所示:

    3.4 数据库访问设计数据库访问是指对数据库进行操作,本系统使用Hibernate完成数据库表与java对象映射,并用HibernateSessionFactory进行数据库访问。
    3.4.1 数据库表模型设计所有数据库表中都有编号做为主键,在java类库中用BaseModel.java完成模型对象的基类。在BaseModel类中,属性id 做为所有表的主键,equals(Object o)是重写的父类方法,只要字符串内容相同,对象就相同;toString用于规范对象的打印格式。
    本系统包含的业务模型有:交易地区(Area),商品类型(Type),二手指南(Article),学院(Department),班级(Clazz),学生(Student),用户(User),信息(Message),留言(Comment),它们都对应于数据库中某张表。这些Java模型对象的数据类型与数据库表相对应,并都继承BaseModel,所有Model类的UMR如图3-5所示:

    3.4.2 Hibernate数据库访问配置Hibernate配置文件主要用于配置hibernate连接数据库的参数以及其它一些hibernate在运行时需要使用的各种参数的值。配置如图3-6所示:

    Hibernate是你的应用程序里连接数据库的那层,所以它需要连接用的信息。连接(connection)是通过一个也是由我们配置的JDBC连接池(connection pool)来完成的。Hibernate的发布包里包含了许多开源的(open source)连接池,但在我们例子中使用Hibernate内置的连接池。
    3.4.3 定义映射文件映射文件用于描述持久层对象以及它们的属性和数据库中的表和表的字段之间的对应关系,完成java对象和数据库中表的数据的相互转化,这里只介绍用户对象的映射配置。
    文件清单如下:
    <?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="cn.lee.market.model"> <class name="User" table="T_USER" schema="dbo" catalog="market_1"> <id name="id" type="string"> <column name="ID" length="50" /> <generator class="uuid.hex" /> </id> <many-to-one name="MStudent" class="Student" fetch="select"> <column name="STU_ID" length="50" not-null="true" /> </many-to-one> <property name="username" type="string"> <column name="USERNAME" length="50" not-null="true" /> </property> <property name="password" type="java.lang.String"> <column name="password" length="50" not-null="true" /> </property> <property name="birthday" type="timestamp"> <column name="BIRTHDAY" length="23" not-null="true" /> </property> <property name="photo" type="integer"> <column name="PHOTO" not-null="true" /> </property> <property name="question" type="string"> <column name="QUESTION" length="50" not-null="true" /> </property> <property name="answer" type="string"> <column name="ANSWER" length="50" not-null="true" /> </property> <property name="telephone" type="string"> <column name="TELEPHONE" length="50" /> </property> <property name="email" type="string"> <column name="EMAIL" length="50" /> </property> <property name="qq" type="string"> <column name="QQ" length="50" /> </property> <property name="create_time" type="timestamp"> <column name="CREATE_TIME" length="23" not-null="true" /> </property> <property name="status" type="integer"> <column name="STATUS" not-null="true" /> </property> <property name="role" type="integer"> <column name="ROLE" not-null="true" /> </property> <set name="TMessages" inverse="true"> <key> <column name="CREATE_USER_ID" length="50" not-null="true" /> </key> <one-to-many class="Message" /> </set> <set name="TComments" inverse="true"> <key> <column name="USER_ID" length="50" not-null="true" /> </key> <one-to-many class="Comment" /> </set> </class></hibernate-mapping>
    在hibernate-mapping标签(tag)之间, 含有一个class元素。所有的持久化实体类都需要一个这样的映射,来把类对象映射到SQL数据库里的表。id元素是标识符属性的声明,name=”id” 声明了Java属性的名字 - Hibernate会使用getId()和setId()来访问它。 column属性则告诉Hibernate, 我们使用market_1表的哪个字段作为主键。嵌套的generator元素指定了标识符生成策略,在这里我们指定uuid.hex。
    3.4.4 Hibernate Session工厂该类主要用于方便地提供Hibernate的初始化以及Hibernate的sessioon和事务的处理,HibernateSessionFactory类的结构如图3-7所示:

    在此简要介绍一下使用Hibernate进行数据库操作的过程,使用Hibernate进行持久化操作主要需要以下步骤:

    创建Configuration对象:进行配置文件的装载操作,读取所有的映射文件并进行解析
    创建 SessionFactory对象:通过创建好的Configuration对象可以创建一个SessionFactory对象的实例,它是产生Session对象的工厂,它在整个应用中是唯一的
    创建Session对象实例:Session对象类似于数据库的连接对象,可以理解为与数据库建立的一个连接,这个连接可以进行数据库的其它操作
    开始一个事务
    进行持久化操作:读取或保存java对象
    结束事务:在操作完成后要进行显示的结束事务的操作
    关闭Session:类似于释放数据库的连接

    3.4.5 定义和实现Hibernate DAO在完域模型的定义和配置工作后,要完成HibernateDAO的定义和实现。
    首先定义DAO接口,使用的接口的编程方法,可以在方法调用者和方法具体实现之间建立一个屏障,即它们不存在任何的关联,一边的修改不会影响另一边的正确运行。在本系统中,DAO接口(IBaseHibernateDAO)只有一个方法:返回Session对象。
    然后实现DAO接口,每个方法的实现,这里只介绍UserDAO、MessageDAO、CommentDAO这三个类的关系如图3-8所示:

    3.4.6 Hibernate Filter的实现在Web应用中,通过Filter来进行Hibernate事务管理并不仅仅出于处理方便,在本系统中,采用了面向对象的设计方法,每个Message对象都持有一个User对象的实例来表示这个二手信息的发布者,这与传统的结构化开发有很在区别。在结构化的开发方法中,Message对象中的属性应该是与信息存储表中的字段一一对应的,那么它就应该创建一个持有用户ID的属性来表示信息的的发布者。而在该系统中,我使用User类作为Message的属性。在面向对象的方法中,只需取得页面中需要显示的Message对象就可以了。
    通过上面获取对象的不同方法可以看出,采用面向对象的方法可以在很大程度上减少进行持久化操作所要进行的编码工作。而对于Message对象所持有的User对象则会由持久层(本系统用的是Hibernate)自动去完成相应的读取操作。
    在本系统中,通过Filter的机制,将一个用户请求中所做的所有持久化操作看成一个事务。当然,如果某个业务确实需要将这个请求分解成多个事务,那么也就可以在业务实现的方法中自选进行事务的提交可者回滚操作。也就是说,整个用户请求都是在一个Session中完成的,在响应用户请求之前会自动开始一个Session和事务。在处理完用户请求直到页面输出完毕后才提交当前的事务和关闭用户的Session。这样,就可以确保应用随时都可以通过Hibernate来获取相关对象的信息。
    另外在本系统的Filter中还进行了字符编码的控制,在每次用户请求中都将字符转化为GBK,以确保信息的正确保存。本系统用到的Filter关键代码如下:
    字符编码转化
    request.setCharacterEncoding("GBK");
    Hibernate事务处理
    session.beginTransaction();chain.doFilter(request, response);session.getTransaction().commit();
    完成Filter类后,要对该Filter进行配置和部署,Filter的配置和部署工作是在WEB-INF目录下的Web.xml中配置的,相关配置代码如下:
    <filter> <filter-name>hibernateFilter</filter-name> <filter-class>cn.lee.market.filter.HibernateFilter</filter-class></filter><filter-mapping> <filter-name>hibernateFilter</filter-name> <url-pattern>/*</url-pattern></filter-mapping>
    4 系统功能模块的实现在本章内,将为大家详细说明系统功能模块的具体实现,系统主要使用了JSP、Javascript、Java、HTML以及DHTML语言等综合处理页面信息的显示和各个功能模块功能的设计,以及通过Hibernate对数据库的操作,完成了一个动态的校园二手交易平台。
    4.1 系统主页设计4.1.1 主页显示设计系统主页是面向平台的所有访问者,注册用户和非注册用户都可以进入到系统主页面,查看相关的二手信息及二手指南。主页面由平台Logo、登录框、搜索框和各种类型的最新二手信息列表组成。主页面效果如图4-1所示:

    4.1.2 主页后台设计系统主页面显示了最新各种类型的二手信息和二手信息top排行,这些都在进入主页前放入request,还有搜索条件中的分类下拉列表和交易地区下拉列表需要放入session中供以后使用。这些操作在IndexAction中实现,相关代码如下:
    查询各种类型的二手信息,放入request,供主页面显示:
    List typeList = tDao.findAllType();for(Type type:(List<Type>)typeList){ List<Message> typeMessage = (List<Message>)mDao.getTypeMessages(type.getId()); messageMap.put(type.getId(), typeMessage); typeMap.put(type.getId(), type.getType_desc());}request.setAttribute("messageMap", messageMap);
    查询所有分类,所有交易地区放入session,用于搜索框下拉列表及其它操作:
    request.getSession().setAttribute("typeMap", typeMap);List areaList = aDao.findAllArea();for(Area area:(List<Area>)areaList){ areaMap.put(area.getId(), area.getArea_desc());}request.getSession().setAttribute("areaMap", areaMap);
    按人气将信息排序后放入TopMessageList,供主页面显示:
    List<Message> TopMessageList = mDao.findByTop_value2();request.getSession().setAttribute("TopMessageList", TopMessageList);
    4.2 系统登录功能设计由于游客、普通用户、管理员限不同,系统实现登录功能,为普通用户、管理员的特殊操作提供接口。
    登录流程简单描述为输入->验证->返回主页。本系统为登录表单设计了ActionForm,在Action只须对接收到的ActionForm进行验证,验证其是否为用户、用户权限等,并根据不同验证结果进行相应操作。登录Struts配置如图4-2所示:

    登录成功后,普通用户、管理员都将在主页面显示用户的基本信息,并提供信息管进,发布信息,修改个人资料和用户注销的链接。登录成功效果图如图4-3所示:

    4.3 系统搜索功能设计系统搜索时也用ActionForm(searchConditionForm)接收搜索表单,在Action中用Dao对象操作ActionFromr返回搜索结果,搜索Struts配置如图4-4所示:

    Dao对searchConditionForm的操作代码如下:
    public List findBySearchCondition(SearchConditionForm searchConditionForm) { String keyword = searchConditionForm.getKeyword(); String typeid = searchConditionForm.getTypeid(); int flag = searchConditionForm.getFlag(); String areaid = searchConditionForm.getAreaid(); try { String queryString = "from Message where (message_title like '%" + keyword +"%'" +"or message_desc like '%" + keyword +"%')"; if(typeid!=null&&!"allType".equals(typeid)) queryString += " and MType = '"+ typeid +"'"; if(flag==1||flag==0) queryString += " and flag = "+ flag +""; if(areaid!=null&&!"allArea".endsWith(areaid)) queryString += " and MArea = '"+ areaid +"'"; queryString += " order by id desc"; System.out.println(queryString); Query queryObject = getSession().createQuery(queryString); return (List)queryObject.list(); } catch (RuntimeException re) { log.error("get failed", re); throw re; }}
    搜索结果的显示实现了分页显示功能,搜索效果如图4-5所示:

    在该系统中,页面中所有信息列表的显示均使用JSTL标签进行处理,这里仅对搜索结果显示的代码作一下分析,关键代码如下:
    <c:forEach items="${searchMessageList }" var="message" begin="${first }"end="${last }"><TR align=middle><TD> <c:if test="${message.flag == 0 }">[出售]</c:if> <c:if test="${message.flag == 1 }">[求购]</c:if></TD><TD style="WIDTH: 40%"><A href="${ctx}/message.do?messageid=${message.id }">${fn:substring(message.message_title,0,20) }${fn:length(message.message_title) le 20?"":"..."}</a></TD><TD>${message.MArea.area_desc} </TD> <TD><fmt:formatDate value="${message.create_time}" type="date" dateStyle="medium"/></TD> <TD> ${message.old_value }成新</TD><TD>${message.price }RMB</TD><TD>${message.top_value }</TD></TR></c:forEach>
    说明:searchMessageList是从Action中返回的信息列表,在此用C标签进行循环打印,字段值的输出使用EL表达式,使页面代码简洁,容易理解,修改[4]。
    4.4 用户注册功能设计本系统用户注册实现了学生实名制,注册前要先同意平台协议,然后在注册输入界面输入相关信息,系统收集到用户注册人信息,验证通过后注册成功,进入注册成功页面。
    4.4.1 用户注册页面设计注册页面包括表单和表单验证。注册页面所涉及的表单元素如表4-1所示:



    名称
    元素类型
    重要属性
    含义




    Username
    Text
    maxLength=16 onblur=”checkUsernameFormat(this)”
    平台帐号


    stu_id
    Text
    maxLength=12
    学号


    Birthday
    Text
    onclick=”GetCalendar(this,’birthday’);” src=”../images/calendar/calendar.gif”
    生日


    email
    Text
    前台验证: isEmail(this)
    E-mail


    password
    password
    maxLength=20
    密码


    repassword
    password
    maxLength=20
    确认密码


    question
    Text
    id=txtTipQuestion
    密码问题


    answer
    Text
    id=txtTipAnswer
    密码答案



    注册表单提交前使用javascript脚本进行验证,核心代码如下:
    if(!checkUsernameFormat(f.username)) return false; if(!isNumeric(f.stu_id,'学号格式不正确!')) return false; if(!isEmail(f.email)) return false; if(f.repassword.value != f.password.value){ alert('两次输入的密码不相同!'); f.repassword.value=""; f.password.value=""; f.password.focus(); return false; } if(!isNotEmpty(f.question, '密码查询问题不能为空!')) return false; if(!isNotEmpty(f.answer, '密码查询答案不能为空!')) return false; return true;
    注册验证效果如图4-6所示:

    4.4.2 用户注册后台设计用户注册后台操作在Action中进行,后台实现了将用户信息插入数据库并将新注册用户以及用户权限放入session。用户注册Struts配置如图4-7所示:

    4.5 发布、修改信息设计信息的发布和修改是该系统的最主要功能,只有注册用户或管理员才有权限进行信息发布,普通用户只能修改自己发布的信息,管理员可以修改所有信息。
    信息的发布和修改共用了同一个页面,页面中包含表单和表单验证。表单通过ActionForm接收,在Action中对表单的操作根据信息编号参数值判断执行发布或修改。
    信息发布页面效果如图4-8:

    信息表单元素如表4-2所示:



    名称
    元素类型
    重要属性
    含义




    postForm
    from
    action=”post.do” method=”post” onsubmit=”return(post_check(this))”
    表单


    messageid
    hidden
    —-
    信息编号


    message_title
    Text
    maxLength=30
    信息标题


    old_value
    DropDown
    onclick=”GetCalendar(this,’birthday’);” src=”../images/calendar/calendar.gif”
    新旧程度


    flag
    DropDown
    —-
    交易类型


    typeid
    DropDown
    遍历${typeMap } value=”${type.key }”
    所属类别


    areaid
    DropDown
    遍历${areaMap } value=” ${area.key }”
    交易地区


    price
    Text
    maxLength=10
    物品价格


    r_user
    Text
    maxLength=10
    联系人


    r_email
    Text
    maxLength=20
    E-mail


    r_phone
    TEXTAREA
    —-
    联系方式


    message_desc
    TEXTAREA
    —-
    物品简介


    submit
    submit
    value=”提交”
    提交按钮


    reset
    reset
    value=”重置”
    重置按钮



    信息发布、修改的具体操作在Action中进行,Action中首先验证是否为用户,非用户则弹出消息返回主页,反之执行相应操作。信息发布、修改Struts配置如图4-9所示:

    4.6 信息管理设计信息管理分为普通用户个人信息管理和管理员会员信息管理。管理页面显示了要管理信息的重要信息,并提供链接可进入详细信息页面。每个信息都有修改、删除按钮。这里只介绍个人信息管理页面,页面效果如图4-10所示:

    4.7 信息留言设计登录用户可以对信息进行留言,留言会立刻显示在信息详细下面。留言输入界面显示有登录用户的相关信息(用户名和邮箱),这些信息会连同留言表单内容传入Action中进行插入操作。留言界面效果如图4-11所示:

    留言成功后返回到信息详细页,信息最后显示该信息的所有留言,效果如图4-12所示:

    4.8 二手指南设计二手指南是平台为用户提供的二手帮助指南,游客和普通用户都只能对其进行浏览操作。二手指南的增加,修改,删除都是管理员来操作。在该模块,因为二手指南只有标题和内容两个字段,所有没有必要用ActionForm来接收表单,操作仍然写在Action中。
    5 总结本次毕业设计工作在最初选题过后,我选择了JSP,它是真正的跨平台,实现动态功能的一种技术。JSP+Servlet+JavaBeans/EJB,能够让人非常简单方便地构建安全高速的WEB应用。同时可以通过JDBC(Java DataBase Comnectivity)接口,访问几乎所有数据库,并且可以使用数据库连接池技术,有效控制连接数,确保系统的正常运转。从发展的眼光来看,JSP的前途一片光明。在数据库的选择上,我也使用近些年发展很好的MySQL,充分实现系统的跨平台性。
    在这个系统开发过程中,我对Hibernate的学习从零开始,作过许多小测试。每次的新发现我都运用到这个系统中,在运用中,对它的掌握也更加熟练。还是系统运用Struts框架,在该系统的开发过程中,参阅了很多相关的书籍,特别的Apache官方网站的帮助文档,不仅解决了很多问题,也提高了自己的英文水平。系统中所有的页面,我都争取只写显示代码,用到了JSTL标签和EL表达式,使页面上代码简捷,易懂,易改。
    9 评论 135 下载 2020-07-31 16:55:17
  • 基于Java.Swing实现的俄罗斯方块

    1.项目简介1.1 背景分析俄罗斯方块,相信很多80、90后的小伙伴都玩过,也是当年非常火的游戏,当年读中学的时候,有一个同学有这个游戏机,大家都很喜欢玩,这个游戏给当时的我们带来了很多欢乐,时光飞逝,感慨颇多!人终归是要长大的,回忆再美好,日子也一去不复返了,以前我们只会玩游戏,心里想自己能做一个出来多牛逼啊,长大后,成为程序员的我们有能力自己写游戏玩,我想这就是成长吧!

    玩过这个游戏机的小伙伴看到这个图,应该对这个机器多少有些感情,毕竟带给了我们很多的欢乐!
    这次利用周末的时间,去写了一个俄罗斯方块Java版本,感觉碰撞判断这个地方有点难处理,确实花了不少时间!
    1.2 效果图这里界面做的感觉不是很好看,但我觉得问题不大,功能到位就好!

    1.3 实现思路
    画布1: 用来绘制静态东西,比如游戏区边框、网格、得分区域框、下一个区域框、按钮等,无需刷新的部分
    画布2: 用来绘制游戏动态的部分,比如 方格模型、格子的移动、旋转变形、消除、积分显示、下一个图形显示等

    2.代码实现2.1创建窗口首先创建一个游戏窗体类GameFrame,继承至JFrame,用来显示在屏幕上(window的对象),每个游戏都有一个窗口,设置好窗口标题、尺寸、布局等就可以。
    /* * 游戏窗体类 */public class GameFrame extends JFrame { public GameFrame() { setTitle("俄罗斯方块");//设置标题 setSize(488, 476);//设定尺寸 setLayout(new BorderLayout()); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//点击关闭按钮是关闭程序 setLocationRelativeTo(null); //设置居中 setResizable(false); //不允许修改界面大小 }}
    2.2 画布1创建面板容器BackPanel继承至JPanel。
    /* * 背景画布类 */public class BackPanel extends JPanel{ BackPanel panel=this; private JFrame mainFrame=null; //构造里面初始化相关参数 public BackPanel(JFrame frame){ this.setLayout(null); this.setOpaque(false); this.mainFrame = frame; mainFrame.setVisible(true); }}
    再创建一个Main类,来启动这个窗口。
    public class Main { //主类 public static void main(String[] args) { GameFrame frame = new GameFrame(); BackPanel panel = new BackPanel(frame); frame.add(panel); frame.setVisible(true);//设定显示 }}
    右键执行这个Main类,窗口建出来了。

    2.3 创建菜单及菜单选项创建菜单
    private void initMenu(){ // 创建菜单及菜单选项 jmb = new JMenuBar(); JMenu jm1 = new JMenu("游戏"); jm1.setFont(new Font("仿宋", Font.BOLD, 15));// 设置菜单显示的字体 JMenu jm2 = new JMenu("帮助"); jm2.setFont(new Font("仿宋", Font.BOLD, 15));// 设置菜单显示的字体 JMenuItem jmi1 = new JMenuItem("开始新游戏"); JMenuItem jmi2 = new JMenuItem("退出"); jmi1.setFont(new Font("思源宋体", Font.BOLD, 15)); jmi2.setFont(new Font("思源宋体", Font.BOLD, 15)); JMenuItem jmi3 = new JMenuItem("操作说明"); jmi3.setFont(new Font("思源宋体", Font.BOLD, 15)); JMenuItem jmi4 = new JMenuItem("失败判定"); jmi4.setFont(new Font("思源宋体", Font.BOLD, 15)); jm1.add(jmi1); jm1.add(jmi2); jm2.add(jmi3); jm2.add(jmi4); jmb.add(jm1); jmb.add(jm2); mainFrame.setJMenuBar(jmb);// 菜单Bar放到JFrame上 jmi1.addActionListener(this); jmi1.setActionCommand("Restart"); jmi2.addActionListener(this); jmi2.setActionCommand("Exit"); jmi3.addActionListener(this); jmi3.setActionCommand("help"); jmi4.addActionListener(this); jmi4.setActionCommand("lost"); }
    实现ActionListener并重写方法actionPerformed

    actionPerformed方法的实现


    2.4 绘制游戏区域绘制游戏区域边框
    //绘制边框private void drawBorder(Graphics g) { BasicStroke bs_2=new BasicStroke(12L,BasicStroke.CAP_ROUND,BasicStroke.JOIN_MITER); Graphics2D g_2d=(Graphics2D)g; g_2d.setColor(new Color(128,128,128)); g_2d.setStroke(bs_2); RoundRectangle2D.Double rect = new RoundRectangle2D.Double(6, 6, 313 - 1, 413 - 1, 2, 2); g_2d.draw(rect);}
    绘制右边辅助区域(积分、下一个、按钮等)
    //绘制右边区域边框private void drawBorderRight(Graphics g) { BasicStroke bs_2=new BasicStroke(12L,BasicStroke.CAP_ROUND,BasicStroke.JOIN_MITER); Graphics2D g_2d=(Graphics2D)g; g_2d.setColor(new Color(128,128,128)); g_2d.setStroke(bs_2); RoundRectangle2D.Double rect = new RoundRectangle2D.Double(336, 6, 140 - 1, 413 - 1, 2, 2); g_2d.draw(rect); //g_2d.drawRect(336, 6, 140, 413);}
    在BackPanel 中重写paint 方法,并调用刚才两个区域绘制方法。


    绘制得分区域和下一个区域
    //绘制积分区域private void drawCount(Graphics g) { BasicStroke bs_2=new BasicStroke(2L,BasicStroke.CAP_ROUND,BasicStroke.JOIN_MITER); Graphics2D g_2d=(Graphics2D)g; g_2d.setColor(new Color(0,0,0)); g_2d.setStroke(bs_2); g_2d.drawRect(350, 17, 110, 80); //得分 g.setFont(new Font("宋体", Font.BOLD, 20)); g.drawString("得分:",380, 40);}//绘制下一个区域private void drawNext(Graphics g) { BasicStroke bs_2=new BasicStroke(2L,BasicStroke.CAP_ROUND,BasicStroke.JOIN_MITER); Graphics2D g_2d=(Graphics2D)g; g_2d.setColor(new Color(0,0,0)); g_2d.setStroke(bs_2); g_2d.drawRect(350, 120, 110, 120); //得分 g.setFont(new Font("宋体", Font.BOLD, 20)); g.drawString("下一个:",360, 140);}
    绘制网格(15列 20行)
    //绘制网格private void drawGrid(Graphics g) { Graphics2D g_2d=(Graphics2D)g; g_2d.setColor(new Color(255,255,255,150)); int x1=12; int y1=20; int x2=312; int y2=20; for (int i = 0; i <= ROWS; i++) { y1 = 12 + 20*i; y2 = 12 + 20*i; g_2d.drawLine(x1, y1, x2, y2); } y1=12; y2=412; for (int i = 0; i <= COLS; i++) { x1 = 12 + 20*i; x2 = 12 + 20*i; g_2d.drawLine(x1, y1, x2, y2); }}
    在paint方法中调用

    创建游戏右边区域的一个暂停按钮
    //初始化private void init() { // 开始/停止按钮 btnStart = new JButton(); btnStart.setFont(new Font("黑体", Font.PLAIN, 18)); btnStart.setFocusPainted(false); btnStart.setText("暂停"); btnStart.setBounds(360, 300, 80, 43); btnStart.setBorder(BorderFactory.createRaisedBevelBorder()); this.add(btnStart); btnStart.addActionListener(this); btnStart.setActionCommand("start");}

    此时基本布局已经完成了。
    2.5 画布2GamePanel 继承至 JPanel 并重写 paint 方法修改Main类,将画布2也放到窗口中
    public class Main { //主类 public static void main(String[] args) { GameFrame frame = new GameFrame(); BackPanel panel = new BackPanel(frame); frame.add(panel); GamePanel gamePanel = new GamePanel(frame); panel.setGamePanel(gamePanel); frame.add(gamePanel); frame.setVisible(true);//设定显示 }}
    2.6 画布2绘制一个小方块因为游戏区域被分成了一个个的小格子,每个小格子就是一个单位,整个网格就是一个15,、20的二维数组。于是第一行第一个元素,用数组下标来表示就是 0,0 、第一行第二个元素就是0、1 这样就好办了,我们创建一个Block类,设置坐标和宽高即可绘制方块(宽高为固定20,与网格对应)。
    package main;import java.awt.Graphics;public class Block { private int x=0;//x坐标 private int y=0;//y坐标 private GamePanel panel=null; public Block(int x,int y,int mX,int mY,GamePanel panel){ this.x=x; this.y=y; this.panel=panel; } //绘制 void draw(Graphics g){ g.fillRect(12+x*20, 12+y*20, 20, 20); } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; }}
    实例化这个类,并在paint方法中调用draw绘制方法。
    private void init() { x=0; y=0; curBlock = new Block(x, y,this);}@Overridepublic void paint(Graphics g) { super.paint(g); if(curBlock!=null){ curBlock.draw(g); }}

    在Block类加入移动方法 两个参数 boolean xDir, int step xDir 布尔值:true表示横向移动,false表示向下移动 step是步数:当xDir为true,我们设定为 1 和 -1 横向移动1表示向右,-1表示向左移动;当xDir为true为false,向下移动为1(因为不能向上移动)。
    //移动 void move(boolean xDir, int step){ if(xDir){//X方向的移动,step 正数向右 负数向左 x += step; }else{//向下运动 y += step; } panel.repaint(); }
    GamePanel添加键盘事件
    //添加键盘监听private void createKeyListener() { KeyAdapter l = new KeyAdapter() { //按下 @Override public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); switch (key) { //空格 case KeyEvent.VK_SPACE: break; //向上 case KeyEvent.VK_UP: case KeyEvent.VK_W: break; //向右 case KeyEvent.VK_RIGHT: case KeyEvent.VK_D: if(curBlock!=null) curBlock.move(true, 1); break; //向下 case KeyEvent.VK_DOWN: case KeyEvent.VK_S: if(curBlock!=null) curBlock.move(false, 1); break; //向左 case KeyEvent.VK_LEFT: case KeyEvent.VK_A: if(curBlock!=null) curBlock.move(true, -1); break; } } //松开 @Override public void keyReleased(KeyEvent e) { } }; //给主frame添加键盘监听 mainFrame.addKeyListener(l);}
    于是我操作一波

    2.7 创建图形七种图形

    如上图,如果我们以标红的小方块为原点(0,0)那我们分析一下图形其他几个方块的位置。

    比如上面图形,红色框住的为(0,0)的话,那最前面的那个是不是(-1,0),因为 y 他们是一样的,只要 x 往左边移动一个位置。以此类推,第3个应该是(1,0),第4个是(2,0)。

    此图形呢,标红的为(0,0),它正下方的那个应该是(0,1),它右边那个是(1,0),它右下角的那个应该是(1,1) 于是我们可以设计一个Data类,专门存储7种图形的位置信息,分别对应前面图的7种模型
    public class Data { public static List datas = new ArrayList(); static void init(){ int[][] data1 = {{-1,0},{0,0},{1,0},{1,1}}; datas.add(data1); int[][] data2 = {{-1,0},{0,0},{1,0},{2,0}}; datas.add(data2); int[][] data3 = {{-1,0},{-1,1},{0,0},{1,0}}; datas.add(data3); int[][] data4 = {{-1,0},{0,0},{0,1},{1,1}}; datas.add(data4); int[][] data5 = {{0,0},{0,1},{1,0},{1,1}}; datas.add(data5); int[][] data6 = {{-1,1},{0,0},{0,1},{1,0}}; datas.add(data6); int[][] data7 = {{-1,0},{0,0},{0,1},{1,0}}; datas.add(data7); }}
    2.8 创建模型类其中创建的时候,随机从Data类里面7个数据里面取到一个,生成一个图形,根据对应二维数组作为下标来创建小方块。
    public class Model { private int x=0; private int y=0; private GamePanel panel=null; private List blocks = new ArrayList(); boolean moveFlag=false; public Model(int x,int y,GamePanel panel){ this.x=x; this.y=y; this.panel=panel; createModel(); } private void createModel() { Random random = new Random(); int type = random.nextInt(7);//1-7种模型 int[][] data= (int[][])Data.datas.get(type); Block block=null; int mX=0; int mY=0; for (int i = 0; i < 4; i++) { mX = data[i][0]; mY = data[i][1]; block = new Block(x, y, mX , mY, panel); blocks.add(block); } }}
    Block也要稍微做些变动需要加入偏移坐标值,来设定4个小方块的相对位置

    GamePanel类中实例化的就是Model类了,同时绘制的也是
    curModel = new Model(x,y,this);@Overridepublic void paint(Graphics g) { super.paint(g); //当前模型 if(curModel!=null){ List blocks = curModel.getBlocks(); Block block=null; for (int i = 0; i < blocks.size(); i++) { block = (Block)blocks.get(i); block.draw(g); } }}
    我这里设定创建Model的时候x为7,y为3,于是:

    图形创建好了,怎么去移动这个图形呢 很简单就是键盘移动的时候,改成调用Model类的move方法了,此方法里面就是循环模型的4个Block实例,每个小块调用自己的move方法即可:


    2.9 模型旋转变形旋转万能公式 x=-y y=x 这里的x、y指的是Data类里面二维数组的值,也就是 Block中的偏移值
    在Block中添加变形方法:
    //变形 public void rotate() { //旋转万能公式 x=-y y=x int x = mX; mX = -mY; mY = x; }
    Model中添加变形方法,就是循环4个Block实例 这里加入了预变形方法,就是要先判断能否变形,比如变形会出边界,会碰到别的方块,则不让变形。
    //旋转void rotate(){ boolean flag = true;//允许变形 Block block=null; for (int i = 0; i < blocks.size(); i++) { block = (Block)blocks.get(i); if(!block.preRotate()){ //有一个不让变形就不能变形 flag = false;//不能变形 break; } } if(flag){ for (int i = 0; i < blocks.size(); i++) { block = (Block)blocks.get(i); block.rotate(); } } panel.repaint();}

    2.10 方块累计当图形触底或者接触往下接触到其他方块时,会累计在下面,并且创建新的图形出来。public Block[][] blockStack = new Block[15][20]; 这个二维数组用来存储累计的方块 图形触底后,会根据每个小block实例的位置一一对应插入到blockStack这个二维数组中。

    在paint方法中加入累积块的绘制
    //累计块 Block bott = null; for (int i = 0; i < 15; i++) { for (int j = 0; j < 20; j++) { bott = (Block)blockStack[i][j]; if(bott!=null ){ bott.draw(g); } } }
    2.11 方块消除和积分从当前撞击的模型中取出y坐标(注意去重)。2.将y进行排序,让位置小的排在前面,也就是如果消除两行的话要先消上面的那行。2.消除当前行采用的是数据替换,从当前行开始,上一行的数据往下一行赋值,当前行就等于被消除了。3.积分处理。
    //消除处理private void clear() { Block block = null ; int num=0; int y=0; List hasDoList=new ArrayList(); List clearList=new ArrayList(); for (int i = 0; i < blocks.size(); i++) { block = (Block)blocks.get(i); y = block.getY() + block.getmY(); if(y<0 || y>19) continue; if(!hasDoList.contains(y)){ hasDoList.add(y); if(block.clear()){ clearList.add(y); num++; } } } if(num==1){ panel.curCount+=100; }else if(num==2){ panel.curCount+=300; }else if(num==3){ panel.curCount+=600; }else if(num==4){ panel.curCount+=1000; } //执行格子的消除动作 if(num>0){ Collections.sort(clearList); doClear(clearList); }}//执行消除void doClear(List l){ int y=0; for (int i = 0; i < l.size(); i++) { y = Integer.parseInt(String.valueOf(l.get(i))); clearClock(y); }}void clearClock(int y){ Block[][] stack = panel.blockStack; Block block=null; for (int i = 0; i < 15; i++) { for (int j = 19; j >= 0; j--) {//从最下面往上 if(y>=j&&j>0){//消除行和上方的行,全部往下移动,即这行等于上一行的数据 block = stack[i][j-1]; if(block!=null){ block.setY(block.getY()+1); } stack[i][j]=block; }else if(j==0){//第一行,清空 stack[i][j]=null; } } }}
    积分规则:1行100分、2行300分、3行600分、4行1000分

    2.12 显示下一个这个其实不难:1.创建好当前模型的时候,同时创建好下一个模型,并绘制出来;2.当前模型触底累计后,把下一个模型设置为当前模型。3.同时创建一个新模型做为下一个模型。
    //创建模型 public void createModel(int type) { if(type==0){//游戏刚开始时 curModel = new Model(x,y,this); nextModel = new Model(x,y,this); }else{//游戏运行中 curModel = nextModel; nextModel = new Model(x,y,this); } }
    在paint方法中绘制‘下一个’,在右边的下一个区域显示
    //下一个模型 if(nextModel!=null){ List blocks = nextModel.getBlocks(); Block block=null; for (int i = 0; i < blocks.size(); i++) { block = (Block)blocks.get(i); block.drawNext(g); } }2.13 加入自动向下线程,并启动//游戏线程,用来自动下移private class GameThread implements Runnable { @Override public void run() { while (true) { if("start".equals(gameFlag)){ curModel.move(false, 1); } try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } } }}

    5.最后加入积分、按键控制、游戏结束、重新开始等就完成了
    /** 软件的启动方法 action:动作,活动 */ public void action(){ // randomOne 工厂方法,用于生成方块 // 工厂方法:用于创建对象的方法 tetromino = Tetromino.randomOne(); nextOne = Tetromino.randomOne(); // wall[10][4] = new Cell(2,4,T); state = RUNNING; KeyListener l = new KeyAdapter(){ public void keyPressed(KeyEvent e) { //按键按下 int key = e.getKeyCode(); switch(state){ case RUNNING:processRunningKey(key); break; case PAUSE:processPauseKey(key); break; case GAME_OVER:processGameOverKey(key); break; } //re重新 paint绘制 重绘:尽快执行paint Tetris.this.repaint(); } }; //Tetris 是面板类型 l 监听 面板的动作 this.addKeyListener(l); this.setFocusable(true); //request 请求 Focus 焦点 this.requestFocus(); //在action方法中添加 timer = new Timer(); TimerTask task = new TimerTask() { public void run() { //下落速度控制逻辑 speed = 40-(score/1000); speed = speed<=1? 1: speed; level = 41-speed; if(index % speed==0){ if(state==RUNNING){ softDropAction(); } } index ++; repaint(); } }; timer.schedule(task, 10, 10); } /** 在Tetris类中添加方法 */ protected void processGameOverKey(int key) { switch(key){ case KeyEvent.VK_Q: System.exit(0);break; case KeyEvent.VK_S: wall=new Cell[ROWS][COLS]; tetromino = Tetromino.randomOne(); nextOne = Tetromino.randomOne(); score = 0; lines = 0; index=0; state = RUNNING; } } protected void processPauseKey(int key) { switch(key){ case KeyEvent.VK_Q: System.exit(0);break; case KeyEvent.VK_C: state=RUNNING; index = 1; break; } } /** 处理Running状态的按键情况 */ protected void processRunningKey(int key){ switch(key){ case KeyEvent.VK_RIGHT:moveRightAction();break; case KeyEvent.VK_LEFT:moveLeftAction();break; case KeyEvent.VK_DOWN:softDropAction();break; case KeyEvent.VK_UP:rotateRightAction();break; case KeyEvent.VK_Z:rotateLeftAction();break; case KeyEvent.VK_SPACE:hardDropAction();break; case KeyEvent.VK_Q:System.exit(0);break; case KeyEvent.VK_P:state=PAUSE;break; } }
    0 评论 0 下载 2021-10-17 11:07:11
  • 基于java.swing实现的发送邮件的小程序

    1.项目简述该项目是一个通过Java实现的发送邮件的小程序,该小程序具有发送普通邮件,带附件邮件的功能。
    1.1技术栈
    Java基础
    JavaFX
    Mail包使用

    1.2 功能描述实现发送普通邮件,带附件邮件的功能。
    1.3 预览效果运行截图

    1.4 项目结构说明
    项目结构说明

    .idea:存放项目的配置信息,包括历史记录及版本控制等信息。
    META-INF:存放类信息的文件夹
    out:运行输出文件
    src:源代码文件夹

    MainSenSystem:邮件发送小程序项目controller:FXML文件的控制器类MainFrameController.java:主界面的控制器类,是界面的事件处理方法SendAcountOptionFrameController.java:本地账户的设置界面,设置本人账户的账号、密码和服务器
    images:项目所需要使用到的图片资源
    properties:项目索要用到的配置文件

    data.properties:项目的配置文件,即将账户设置保存在该配置文件中tools:一些工具类
    JavaFXTools.java:JavaFX的操作工具类SimpleTools.java:一些要用到的公共方法
    view:FXML视图文件
    MainApp.java:主类,含start方法,即启动该项目

    邮件发送器.iml:是intellij idea的工程配置文件,由该软件创建项目后默认产生

    2.实现主界面和设置界面2.1 创建一个基于maven的JavaFX项目第一步:首先创建一个maven项目

    第二步:设置GroupId和ArtifactId
    GroupId为:com.mycom.myapp
    ArtifactId为:mailsendsystem

    第三步:设置项目名称和项目路径

    第四步:按照如下图创建文件夹

    第五步:创建两个fxml文件,分别名为:MainFrame.fxml和SendAccountOptionFrame.fxml。

    可以看到有红色错误,先不用管。
    注意:出现红色的原因是fxml界面文件没用同controller类相关联。

    第六步:设计MainFrame.fxml

    界面效果如下:

    2.2 实现fxml内容其中MainFrame.fxml内容如下:
    <?xml version="1.0" encoding="UTF-8"?><?import javafx.geometry.Insets?><?import javafx.scene.control.*?><?import javafx.scene.layout.*?><?import javafx.scene.web.HTMLEditor?><AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="641.0" prefWidth="719.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.mycom.myapp.mailsendsystem.controller.MainFrameController"> <children> <VBox alignment="CENTER" prefHeight="641.0" prefWidth="719.0"> <children> <HBox alignment="CENTER_RIGHT" prefHeight="100.0" prefWidth="200.0"> <children> <Button fx:id="optionButton" mnemonicParsing="false" onAction="#do_optionButton_event" text="设置"/> </children> </HBox> <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" spacing="50.0"> <children> <Label text="收信人:"/> <TextField fx:id="addresseeTextField" prefHeight="30.0" prefWidth="507.0" promptText="请输入收件人邮箱:"/> </children> <padding> <Insets left="50.0"/> </padding> </HBox> <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" spacing="50.0"> <children> <Label text="主 题:"/> <TextField fx:id="subjectTextField" prefHeight="30.0" prefWidth="504.0" promptText="请输入邮件主题:"/> </children> <padding> <Insets left="50.0"/> </padding> </HBox> <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" spacing="100.0"> <children> <Button fx:id="addAppendixButton" mnemonicParsing="false" onAction="#do_addAppendixButton_event" text="添加附件"/> <Label fx:id="appendixNameLabel"/> </children> <padding> <Insets left="50.0"/> </padding> </HBox> <HBox alignment="CENTER" prefHeight="377.0" prefWidth="715.0"> <children> <HTMLEditor fx:id="contentHTMLEditor" htmlText="<html><head></head><body contenteditable="true"></body></html>" prefHeight="309.0" prefWidth="632.0"/> </children> </HBox> <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0"> <children> <Label fx:id="addresseeLabel"/> </children> <padding> <Insets left="50.0"/> </padding> </HBox> <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="50.0"> <children> <Button fx:id="sendButton" mnemonicParsing="false" onAction="#do_sendButton_event" text="发送"/> <Button fx:id="resetButton" mnemonicParsing="false" onAction="#do_resetButton_event" text="重置"/> <Button fx:id="exitButton" mnemonicParsing="false" onAction="#do_exitButton_event" text="退出"/> </children> </HBox> </children> </VBox> </children></AnchorPane>
    可以直接将上面的代码复制到MainFrame.fxml中,当然也可以自己设计界面,熟练使用SceneBuilder。
    注意:里面的组件对象和事件方法可以自己用SceneBuilder打开查看,在这里就不一一列举。
    复制过去仍然会报错,因为还没有将其与controller类关联起来。同理,SendAccountOptionFrame.fxml界面效果如下:

    其源代码如下:
    <?xml version="1.0" encoding="UTF-8"?><?import javafx.scene.control.*?><?import javafx.scene.layout.*?><AnchorPane prefHeight="516.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.mycom.myapp.mailsendsystem.controller.SendAccountOptionFrameController"> <children> <VBox prefHeight="516.0" prefWidth="448.0"> <children> <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="50.0"> <children> <Label text="发件人:"/> <TextField fx:id="addresserTextField" promptText="请输入发件人邮箱:"/> </children> </HBox> <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="50.0"> <children> <Label text="密码:"/> <PasswordField fx:id="passwordField" promptText="请输入密码或授权码:"/> </children> </HBox> <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="50.0"> <children> <Label text="服务器:"/> <TextField fx:id="serverTextField" promptText="请输入服务器:"/> </children> </HBox> <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="50.0"> <children> <Button fx:id="saveButton" mnemonicParsing="false" onAction="#do_saveButton_event" text="保存"/> <Button fx:id="cancelButton" mnemonicParsing="false" onAction="#do_cancelButton_event" text="取消"/> </children> </HBox> </children> </VBox> </children></AnchorPane>
    对于报错仍然忽略。
    接下来在controller创建一个名为MainFrameController的类,其中的内容即对界面的事件处理。那么如何获取其组件对象和事件处理方法呢?
    选中MainFrame.fxml文件,右键用SceneBuilder打开。然后View——>Show Sample Controller Skeleton

    复制打开面板中的内容到MainFrameController.java中,全部覆盖。其中报错有两个,分别是包路径错误以及未导入类错误。最后修改成功不报错的代码如下:
    /** * 主界面控制器 * @author lck100 */public class MainFrameController { public void initialize() { // 初始化按钮图标 simpleTools.setLabeledImage( new Labeled[]{ optionButton, sendButton, resetButton, exitButton, addAppendixButton}, new String[]{ "src/main/resources/images/option.png", "src/main/resources/images/send.png", "src/main/resources/images/reset.png", "src/main/resources/images/exit.png", "src/main/resources/images/appendix.png"}); } @FXML void do_optionButton_event(ActionEvent event) { // 加载设置界面 new MainApp().initSendAccountOptionFrame(); } @FXML void do_addAppendixButton_event(ActionEvent event) { File selectedFile = simpleTools.getSelectedFile(); selectedFilePath = selectedFile.getAbsolutePath(); appendixNameLabel.setText(selectedFile.getName()); } @FXML void do_sendButton_event(ActionEvent event) throws UnsupportedEncodingException, MessagingException { Map dataMap = simpleTools.readReturnMap("src/main/resources/properties/data.properties"); String addresser = (String) dataMap.get("addresser"); String addressee = addresseeTextField.getText(); String subject = subjectTextField.getText(); String content = contentHTMLEditor.getHtmlText(); String password = (String) dataMap.get("password"); // 1.创建参数配置, 用于连接邮件服务器的参数配置 Properties properties = new Properties(); properties.setProperty("mail.transport.protocol", "smtp"); properties.setProperty("mail.smtp.host", (String) dataMap.get("server")); properties.setProperty("mail.smtp.auth", "true"); // 2.根据配置创建会话对象,用于和邮件服务器交互 Session session = Session.getInstance(properties); session.setDebug(true); // 3.创建一封邮件 MimeMessage message = null; if (selectedFilePath.equals("")) { message = createSimpleMimeMessage(session, addresser, addressee, subject, content); } else { message = createConflexMimeMessage(session, addresser, addressee, subject, content, selectedFilePath); } // 4.根据Session获取邮件传输对象 Transport transport = session.getTransport(); // 5.使用邮箱账号和密码连接邮件服务器,这里认证的邮箱必须与message中的发件人邮箱一致,否则报错 transport.connect(addresser, password); // 6.发送邮件,发到所有的收件地址,message.getAllRecipients()获取到的是在创建邮件对象时添加的所有的收件人、抄送人、密送人 transport.sendMessage(message, message.getAllRecipients()); // 7.关闭连接 transport.close(); } @FXML void do_resetButton_event(ActionEvent event) { JavaFXTools javaFXTools = new JavaFXTools(); javaFXTools.reset(addresseeTextField, subjectTextField); javaFXTools.reset(contentHTMLEditor); javaFXTools.reset(appendixNameLabel); } @FXML void do_exitButton_event(ActionEvent event) { // 退出程序 System.exit(0); }
    同理,在controller下创建一个名为SendAccountOptionFrameController的类。
    好,界面弄好了,现在就是启动程序了。在运行之前,先解决fxml文件中错误。

    将MainFrame.fxml文件中的 fx:controller=”MainSendSystem.controller.MainFrameController “修改成 fx:controller=”com.mycom.myapp.mailsendsystem.controller.MainFrameController” 。
    同时还有将SendAccountOptionFrame.fxml文件中的 fx:controller=”MainSendSystem.controller.SendAccountOptionFrameController” 改成 fx:controller=”com.mycom.myapp.mailsendsystem.controller.SendAccountOptionFrameController” 。
    好的,报错解决,下面就是最后一步,创建一个启动类启动该程序了。
    在mailsendsystem包创建一个MainApp类。
    public class MainApp extends Application { private Stage primaryStage; @Override public void start(Stage primaryStage) { this.primaryStage = primaryStage; // 设置标题 this.primaryStage.setTitle("邮件发送器"); // 在程序启动的时候加载主界面 initMainFrame(); } /** * 加载主界面 */ public void initMainFrame() { try { // 加载FXML界面文件 FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("/view/MainFrame.fxml")); Parent root = loader.load(); // 实例化场景 Scene scene = new Scene(root); // 将场景设置到舞台 primaryStage.setScene(scene); // 展示舞台 primaryStage.show(); } catch (IOException e) { e.printStackTrace(); } } /** * 加载设置界面 */ public void initSendAccountOptionFrame(){ try { // 加载FXML文件 FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("/view/SendAccountOptionFrame.fxml")); Parent root = loader.load(); // 实例化舞台 Stage stage = new Stage(); // 设置标题 stage.setTitle("设置"); // 设置该界面不可缩放 stage.setResizable(true); // 设置该界面总是处于最顶端 stage.setAlwaysOnTop(true); // 设置模态窗口,该窗口阻止事件传递到任何其他应用程序窗口 stage.initModality(Modality.APPLICATION_MODAL); // 设置主容器为主界面舞台 stage.initOwner(primaryStage); // 实例化场景 Scene scene = new Scene(root); // 将场景设置到舞台上 stage.setScene(scene); // 获取SendAccountOptionFrameController控制器 SendAccountOptionFrameController controller = loader.getController(); // 设置SendAccountOptionFrameController类的stage controller.setStage(stage); // 展示舞台 stage.showAndWait(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { launch(args); }}
    点击运行,效果如下:

    3.设置按钮图标、重置和退出功能3.1 打开设置界面只能打开主界面,看到主界面的一些组件,当点击“设置”按钮的时候,不会弹出设置界面。
    在MainApp.java中添加一个initSendAccountOptionFrame()方法,内容如下:
    /** * 加载设置界面 */ public void initSendAccountOptionFrame(){ try { // 加载FXML文件 FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("/view/SendAccountOptionFrame.fxml")); Parent root = loader.load(); // 实例化舞台 Stage stage = new Stage(); // 设置标题 stage.setTitle("设置"); // 设置该界面不可缩放 stage.setResizable(true); // 设置该界面总是处于最顶端 stage.setAlwaysOnTop(true); // 设置模态窗口,该窗口阻止事件传递到任何其他应用程序窗口 stage.initModality(Modality.APPLICATION_MODAL); // 设置主容器为主界面舞台 stage.initOwner(primaryStage); // 实例化场景 Scene scene = new Scene(root); // 将场景设置到舞台上 stage.setScene(scene); // 获取SendAccountOptionFrameController控制器 SendAccountOptionFrameController controller = loader.getController(); // 设置SendAccountOptionFrameController类的stage controller.setStage(stage); // 展示舞台 stage.showAndWait(); } catch (IOException e) { e.printStackTrace(); } }
    该方法是用来加载FXML资源文件并对加载成功的界面进行一些设置。
    接下来就是在设置按钮的事件监听器方法中启动该方法,因此在MainFrameController.java类中的将do_optionButton_event内的内容换成如下:
    @FXML void do_optionButton_event(ActionEvent event) { // 加载设置界面 new MainApp().initSendAccountOptionFrame(); }
    刚才在MainApp类有一个红色报错,那是因为在SendAccountOptionFrameController类并没有定义stage。
    因此在SendAccountOptionFrameController类添加如下代码:
    private Stage stage; public void setStage(Stage stage) { this.stage = stage; }
    这个设置是为了获得该界面的场景,在取消按钮事件中会用到它来关闭界面。
    运行程序,点击主界面右上角的设置按钮,将打开如下界面:

    3.2 设置按钮图标在很多软件中按钮都是有图标,便于识别。
    对比如下两个界面,回发现有图标的好看得多,而且更容易明白这个按钮的具体功能是什么。

    在本项目中需要设置图标的组件分别是发送按钮、重置按钮、退出按钮、添加附件按钮、设置按钮、保存按钮和取消按钮。

    首先设置主界面的各个按钮的图标。
    在MainFrameController添加一个initialize()方法
    public void initialize() { // 初始化按钮图标 simpleTools.setLabeledImage( new Labeled[]{ optionButton, sendButton, resetButton, exitButton, addAppendixButton}, new String[]{ "src/main/resources/images/option.png", "src/main/resources/images/send.png", "src/main/resources/images/reset.png", "src/main/resources/images/exit.png", "src/main/resources/images/appendix.png"}); }
    initialize()方法是JavaFX提供的,不是自定义的方法,该方法用来在控制器中初始化一些配置。
    在这里初始化了各个按钮的图标。设置按钮图标的方法是定义在SimpleTools类中的setLabeledImage()方法,该方法有两个参数,第一个参数是按钮数组,第二个参数是与之对应的要设置图片的路径。

    接下来就是设置界面的图标设计了,同理SendAccountOptionFrameController类中添加如下方法来初始化图标设置:
    public void initialize() { // 初始化图标设置 new SimpleTools().setLabeledImage( new Labeled[]{saveButton, cancelButton}, new String[]{"src/main/resources/images/save.png", "src/main/resources/images/cancel.png"}); }

    3.3 实现重置功能重置即将各输入框清空。
    在MainFrameController类中的do_resetButton_event()方法中添加如下代码:
    @FXML void do_resetButton_event(ActionEvent event) { JavaFXTools javaFXTools=new JavaFXTools(); javaFXTools.reset(addresseeTextField, subjectTextField); javaFXTools.reset(contentHTMLEditor); javaFXTools.reset(appendixNameLabel); }
    代码解释说明:

    JavaFXTools是自定义在tools包的工具类,里面是重载的不同参数的reset()方法
    需要重置的有:收信人输入文本框、主题输入文本框、附件显示标签以及内容编辑器HTMLEditor

    效果图如下:

    3.4 退出功能退出功能在本项目其实有两个:主界面的退出按钮的退出和设置界面的取消按钮的退出。其中退出按钮的退出即结束程序,可使用 System.exit(0);。因此在do_exitButton_event()方法添加如下内容:
    @FXML void do_exitButton_event(ActionEvent event) { // 退出程序 System.exit(0); }
    其二就是设置界面的取消按钮,取消按钮只是退出当前设置界面,而不是结束程序,因此就需要用到前面传过来的stage了。
    在SendAccountOptionFrameController.java类中的do_cancelButton_event方法添加如下代码:
    @FXML void do_cancelButton_event(ActionEvent event) { // 退出当前设置界面 stage.close(); }
    好了,这节的功能实现了,需要注意的是工具类中的方法是如何实现的,理解有助于去自定义适合更复杂场景的工具方法。还有一个难点就是取消按钮的功能实现,虽然代码简单,但是实现逻辑需要注意,这其间传输设置stage的过程。
    4.完成邮件信息的保存设置4.1 properties配置因此首先在properties创建一个名为data的properties文件。

    properties文件的保存数据是通过键值对的方式。
    如下:即key=value的方式,“#”是注释。

    在SendAccountOptionFrameController类中的do_saveButton_event()方法添加如下代码:
    @FXML void do_saveButton_event(ActionEvent event) { // 获取发件人邮箱 String addresser = addresserTextField.getText(); // 发件人登录密码 String password = passwordField.getText(); // 服务器,这里使用的是smtp.163.com,是网易邮箱的第三方服务器 String server = serverTextField.getText(); // 实例化一个Map Map dataMap = new HashMap(); // 将键值保存在Map中 dataMap.put("addresser", addresser); dataMap.put("password", password); dataMap.put("server", server); // 调用SimpleTools的dataWriteProperties()方法将输入写入properties文件中 new SimpleTools().dataWriteProperties("src/main/resources/properties/data.properties",dataMap); }
    代码解释:

    首先从设置界面的输入框中获取用户填入的数据
    然后实例化一个Map用来保存从界面传来的数据
    最后调用SimpleTools类中的工具方法dataWriteProperties(String fileName,Map<String,String> map);里面有两个参数,第一个参数是保存数据的properties文件的路径;第二个参数保存了键值对数据的map集合
    而dataWriteProperties(String fileName,Map<String,String> map);是在SimpleTools类自定义的,主要是properties.setProperty(String key,String value)方法向properties文件中写入键值对的

    dataWriteProperties()方法的代码如下:
    /** * 操作结果:生成属性文件 * * @param fileName 文件路径 * @param maps 数据集合 */ public void dataWriteProperties(String fileName, Map<String, String> maps) { Properties properties = new Properties(); try { File file = new File(fileName); if (!file.exists()) { file.createNewFile(); } // 写入文件 for (String key : maps.keySet()) { properties.setProperty(key, String.valueOf(maps.get(key))); } FileOutputStream fos = new FileOutputStream(file); properties.store(fos, null);//store(...)指定的流仍保持打开状态 fos.flush(); fos.close();// 关闭流 } catch (IOException e) { e.printStackTrace(); } }

    打开data.properties文件内容如下:

    将这些配置保存在properties文件中后,当你再次点击设置按钮打开后,发现界面如下:

    发现界面中的输入框是空的,这对用户体验并不好,因为他们并不知道他们的配置去哪里了,也不可能每次去打开data.properties文件查看,也或者如果再次点击保存按钮就使设置成了空。
    因此在SendAccountOptionFrameController.java中的initialize()方法添加如下代码(将下面的代码直接替换initialize()方法即可):
    public void initialize() { // 初始化图标设置 new SimpleTools().setLabeledImage( new Labeled[]{saveButton, cancelButton}, new String[]{"src/main/resources/images/save.png", "src/main/resources/images/cancel.png"}); // 从data.properties文件中读取配置 Map dataMap = new SimpleTools().readReturnMap("src/main/resources/properties/data.properties"); String addresser = (String) dataMap.get("addresser"); String password = (String) dataMap.get("password"); String server = (String) dataMap.get("server"); addresserTextField.setText(addresser); passwordField.setText(password); serverTextField.setText(server); }
    再次运行即可看到界面的输入框有内容了。

    5.发送邮件功能5.1 导入包依赖由于发送邮件需要使用mail包,因此maven在这里终于发挥作用了 ,在pom.xml中添加如下内容为mial的依赖:
    <dependencies> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.7</version> </dependency> </dependencies>
    导入依赖成功

    由于是使用第三方工具发送邮件,因此使用邮箱的登录密码可能发送邮件并不会成功,因此就需要获取使用第三方服务器的授权码。
    5.2 获取授权码第一步:登录网易邮箱(这里以网易邮箱作例)
    设置——>POP3/SMTP/IMAP

    第二步:开启授权码设置

    第三步:发送短信

    第四步:设置授权码

    第五步:设置成功


    5.3 发送邮件在MainFrameController.java中添加如下方法:
    /** * 操作结果:创建一个邮件发送对象 * * @param session * @param sendMail 发信人 * @param receiveMail 收信人 * @param subject 邮件主题 * @param content 邮件内容 * @return * @throws UnsupportedEncodingException */ public MimeMessage createSimpleMimeMessage(Session session, String sendMail, String receiveMail, String subject, String content) throws UnsupportedEncodingException, javax.mail.MessagingException { // 1.创建一封邮件 MimeMessage mimeMessage = new MimeMessage(session); // 2.From:发件人 mimeMessage.setFrom(new InternetAddress(sendMail, sendMail, "UTF-8")); // 3.To:收件人(可以增加多个收件人、抄送、密送) mimeMessage.setRecipients(MimeMessage.RecipientType.TO, new InternetAddress[]{new InternetAddress(receiveMail , receiveMail, "UTF-8")}); // 4.邮件主题 mimeMessage.setSubject(subject, "UTF-8"); // 5.Content:邮件正文(可以用HTML标签) mimeMessage.setContent(content, "text/html;charset=UTF-8"); // 6.设置发件时间 mimeMessage.setSentDate(new Date()); // 7.保存设置 mimeMessage.saveChanges(); return mimeMessage; }
    然后将MainFrameController.java中的do_sendButton_event()方法添加为:
    @FXML void do_sendButton_event(ActionEvent event) throws UnsupportedEncodingException, MessagingException { Map dataMap = simpleTools.readReturnMap("src/main/resources/properties/data.properties"); String addresser = (String) dataMap.get("addresser"); String addressee = addresseeTextField.getText(); String subject = subjectTextField.getText(); String content = contentHTMLEditor.getHtmlText(); String password = (String) dataMap.get("password"); // 1.创建参数配置, 用于连接邮件服务器的参数配置 Properties properties = new Properties(); properties.setProperty("mail.transport.protocol", "smtp"); properties.setProperty("mail.smtp.host", (String) dataMap.get("server")); properties.setProperty("mail.smtp.auth", "true"); // 2.根据配置创建会话对象,用于和邮件服务器交互 Session session = Session.getInstance(properties); session.setDebug(true); // 3.创建一封邮件 MimeMessage message = createSimpleMimeMessage(session, addresser, addressee, subject, content); // 4.根据Session获取邮件传输对象 Transport transport = session.getTransport(); // 5.使用邮箱账号和密码连接邮件服务器,这里认证的邮箱必须与message中的发件人邮箱一致,否则报错 transport.connect(addresser, password); // 6.发送邮件,发到所有的收件地址,message.getAllRecipients()获取到的是在创建邮件对象时添加的所有的收件人、抄送人、密送人 transport.sendMessage(message, message.getAllRecipients()); // 7.关闭连接 transport.close(); }
    代码处理完成后,开始测试发送邮件功能。
    运行程序,输入一些文字进行测试:

    点击“发送”按钮发送邮件。
    发送成功会有类似如下的控制台输出:

    打开我的QQ邮箱(发件人是用的QQ邮箱),接收邮件成功。

    到此,发送邮件功能完成。
    注意:自行设置发件人的邮箱和密码。
    6.添加附件发送功能要想发送附件,就需要获取文件的路径。
    在SimpleTools类中添加如下方法获取JavaFX的文件选择器的文件路径:
    /** * 操作结果:获取文件选择器所选中的文件 * * @return File 文件选择器选中的文件 */ public File getSelectedFile() { String selectedFilePath = ""; //实例化文件选择器 FileChooser fileChooser = new FileChooser(); //打开文件选择框 File result = fileChooser.showOpenDialog(null); // 选择文件的路径 if(result!=null){ selectedFilePath = result.getAbsolutePath(); } return new File(selectedFilePath); }
    在MainFrameController类中定义一个变量selectedFilePath来放置选择的文件路径。
    private String selectedFilePath="";
    在do_addAppendixButton_event()方法添加如下内容获取选中文件路径:
    @FXML void do_addAppendixButton_event(ActionEvent event) { File selectedFile = simpleTools.getSelectedFile(); selectedFilePath = selectedFile.getAbsolutePath(); appendixNameLabel.setText(selectedFile.getName()); }
    将do_sendButton_event方法的内容修改成如下内容即既能发送普通邮件又能发送带附件的邮件:
    @FXML void do_sendButton_event(ActionEvent event) throws UnsupportedEncodingException, MessagingException { Map dataMap = simpleTools.readReturnMap("src/main/resources/properties/data.properties"); String addresser = (String) dataMap.get("addresser"); String addressee = addresseeTextField.getText(); String subject = subjectTextField.getText(); String content = contentHTMLEditor.getHtmlText(); String password = (String) dataMap.get("password"); // 1.创建参数配置, 用于连接邮件服务器的参数配置 Properties properties = new Properties(); properties.setProperty("mail.transport.protocol", "smtp"); properties.setProperty("mail.smtp.host", (String) dataMap.get("server")); properties.setProperty("mail.smtp.auth", "true"); // 2.根据配置创建会话对象,用于和邮件服务器交互 Session session = Session.getInstance(properties); session.setDebug(true); // 3.创建一封邮件 MimeMessage message = null; if (selectedFilePath.equals("")) { message = createSimpleMimeMessage(session, addresser, addressee, subject, content); } else { message = createConflexMimeMessage(session, addresser, addressee, subject, content, selectedFilePath); } // 4.根据Session获取邮件传输对象 Transport transport = session.getTransport(); // 5.使用邮箱账号和密码连接邮件服务器,这里认证的邮箱必须与message中的发件人邮箱一致,否则报错 transport.connect(addresser, password); // 6.发送邮件,发到所有的收件地址,message.getAllRecipients()获取到的是在创建邮件对象时添加的所有的收件人、抄送人、密送人 transport.sendMessage(message, message.getAllRecipients()); // 7.关闭连接 transport.close(); }
    现在功能实现了,进行测试


    打开我的QQ邮箱,查看发送邮件的结果。

    发送带附件的邮件成功。
    控制台会输出类似日志。
    0 评论 0 下载 2021-10-17 10:59:40
  • 基于java.swing实现的取色器

    1.项目简述该项目是一个通过Java来实现的屏幕取色的小程序。
    将介绍从创建到打包exe程序的全部过程。
    1.1 功能描述
    通过鼠标实现向屏幕取色
    实现RGB与HEX颜色之间的转换

    1.2 运行截图
    项目结构截图

    1.3 项目结构说明
    .idea:存放项目的配置信息,包括历史记录及版本控制等信息。
    src

    mainjava:项目所使用的Java文件com.mycom.myapp.colorpicker:该项目的主要Java文件
    Main.java:主界面类Style:界面样式类Test:程序主类测试Utils:项目方法类

    resources:项目所使用的各种资源文件,如图片等

    images:该项目所用到的图片资源
    test
    java:项目的测试文件
    target:存放项目构建后的文件和目录、jar包、war包及编译的class文件,由Maven构建时产生
    pom.xml:包含了Maven项目的各种信息,如项目名称、版本、项目id、项目间的依赖关系、编译环境等项目信息
    取色器.iml:是intellij idea的工程配置文件,由该软件创建项目后默认产生

    2.实现主界面使用IDEA创建一个Maven项目。
    其中:

    groupId:com.mycom.myapp
    artifactId:colorpicker
    version:1.0-SNAPSHOT

    在src/main/java目录下创建com.mycom.myapp.colorpicker包,并在colorpicker包创建Main类。

    在Main类中主要是主界面的代码,分析主界面图可知,主界面由一个拆分面板构成,拆分面板左侧是取色器面板,右侧是颜色的HEX格式与16进制格式的相互转换面板。
    主窗体代码如下:
    public class Main { private JFrame mainFrame; private JSplitPane splitPane; private JPanel showColorPane, showValuePane, settingPane, descriptionPane, changePane, rgbToHexPane, rgbTextFieldPane, transformButtonPane, transformButtonPane2, hexToRgbPane, hexTextFieldPane; private JButton startColorPickerButton, rgbToHexButton, hexToRgbButton; private JTextArea textArea, hexTextArea, rgbTextArea; private JLabel RLabel, GLabel, BLabel, HEXLabel, descriptionLabel; private JTextField RTextField, GTextField, BTextField, HEXTextField, rTextField, gTextField, bTextField, hexResultTextField, inputHexTextField, rResultTextField, gResultTextField, bResultTextField; private JCheckBox checkBox; private Box vbox; /** * 得到一个主窗体对象 * * @return 返回得到的JFrame */ public JFrame mainFrame() { // 实例化一个主窗体对象 mainFrame = new JFrame(); // 设置窗体的标题 mainFrame.setTitle("取色器"); // 设置窗体的尺寸大小 mainFrame.setSize(900, 450); // 设置窗体的不允许用户自由调整大小 mainFrame.setResizable(false); // 设置窗体的图标(注意图标路径问题) mainFrame.setIconImage(Toolkit.getDefaultToolkit().createImage("src/main/resources/images/colorpicker.png")); // 创建拆分面板作为主面板 splitPane = new JSplitPane(); // 设置分隔条上折叠/展开按钮的显示 splitPane.setOneTouchExpandable(true); // 设置当拖动分隔条时连续重绘组件 splitPane.setContinuousLayout(true); // 设置分隔条的位置 splitPane.setDividerLocation(mainFrame.getWidth() / 2); // 设置拆分面板的左侧组件为取色器面板 splitPane.setLeftComponent(getColorPickerPane()); // 设置拆分面板的右侧组件为转换面板 splitPane.setRightComponent(getChangePane()); // 调用设置的样式 setFrameAllConponentStyles(); // 将拆分面板设为主窗体的内容面板 mainFrame.setContentPane(splitPane); // 设置窗体的关闭方式 mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 返回主窗体 return mainFrame; }
    在colorpicker包创建Test类用来启动主窗体,其中内容如下:
    public class Test { public static void main(String[] args) { new Main().mainFrame().setVisible(true); }}
    点击运行,运行的结果如下:

    而取色器面板的方法getColorPickerPane的代码改成如下内容:
    /** * 设置取色器的面板内容 * * @return 返回设置好的取色器面板 */ private Box getColorPickerPane() { vbox = Box.createVerticalBox(); // 实例化一个显示取色的面板 showColorPane = new JPanel(); // 设置该面板的布局方式 showColorPane.setLayout(new BorderLayout()); // 创建一个启动取色功能的按钮 startColorPickerButton = new JButton("取色"); // 创建一个文本域来显示取到的颜色 textArea = new JTextArea(10, 25); // 设置文本域不可编辑 textArea.setEditable(false); // 设置文本域默认背景颜色 textArea.setBackground(Color.BLACK); // 设置文本域无边界 textArea.setBorder(null); // 将按钮添加到面板中并设置显示在北部位置 showColorPane.add(startColorPickerButton, BorderLayout.NORTH); // 将文本域添加到面板中并设置显示到中部位置 showColorPane.add(textArea, BorderLayout.CENTER); // 将面板添加到vbox中 vbox.add(showColorPane); // 实例化一个显示RGB值和HEX值的面板 showValuePane = new JPanel(); // 设置面板的布局方式为流动布局 showValuePane.setLayout(new FlowLayout()); // 创建R标签 RLabel = new JLabel("红(R):"); // 创建R文本框 RTextField = new JTextField(2); // 创建G标签 GLabel = new JLabel("绿(G):"); // 创建G文本框 GTextField = new JTextField(2); // 创建B标签 BLabel = new JLabel("蓝(B):"); // 创建B文本框 BTextField = new JTextField(2); // 创建HEX标签 HEXLabel = new JLabel("HEX:"); // 创建HEX文本框 HEXTextField = new JTextField(6); // 将上面这些组件添加到面板中 showValuePane.add(RLabel); showValuePane.add(RTextField); showValuePane.add(GLabel); showValuePane.add(GTextField); showValuePane.add(BLabel); showValuePane.add(BTextField); showValuePane.add(HEXLabel); showValuePane.add(HEXTextField); // 将面板添加到vbox中 vbox.add(showValuePane); // 创建一个设置面板 settingPane = new JPanel(); // 设置面板的边界 settingPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY, 2, true), "设置", TitledBorder.LEFT, TitledBorder.TOP, new Font("微软雅黑", Font.PLAIN, 16), BLACK)); // 创建一个复选框,默认被勾选 checkBox = new JCheckBox("总是在最上层", false); // 设置复选框的字体 checkBox.setFont(new Font("微软雅黑", Font.PLAIN, 16)); // 将复选框添加到面板中 settingPane.add(checkBox); // 将该面板添加到vbox中 vbox.add(settingPane); // 创建一个说明面板 descriptionPane = new JPanel(); // 设置面板的边界 descriptionPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY, 2, true), "说明", TitledBorder.LEFT, TitledBorder.TOP, new Font("微软雅黑", Font.PLAIN, 16), BLACK)); // 创建一个说明标签 descriptionLabel = new JLabel(); // 设置标签内容 descriptionLabel.setText("按下Alt键取色,可以直接在剪贴板复制RGB颜色"); // 设置标签字体 descriptionLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16)); // 将标签添加到面板中 descriptionPane.add(descriptionLabel); // 将该面板添加到vbox中 vbox.add(descriptionPane); /** * 复选框状态改变监听器 */ checkBox.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { // 判断复选框是否被选中 if (checkBox.isSelected()) { // 设置主窗体置于最上层 mainFrame.setAlwaysOnTop(true); } else { // 取消主窗体置于最上层 mainFrame.setAlwaysOnTop(false); } } });
    运行一下,运行结果如下:

    而转换面板方法getChangePane代码改成如下内容:
    /** * 设置转换面板的面板内容 * * @return 返回设置好的转换面板 */ private JPanel getChangePane() { // 创建一个转换面板 changePane = new JPanel(); // 设置面板的布局方式为网格布局 changePane.setLayout(new GridLayout(2, 1)); // 创建一个rgb转hex的面板 rgbToHexPane = new JPanel(); // 设置面板布局方式为边界布局 rgbToHexPane.setLayout(new BorderLayout()); // 设置面板的边界 rgbToHexPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY, 2, true), "RGB颜色代码转化成16位颜色", TitledBorder.LEFT, TitledBorder.TOP, new Font("微软雅黑", Font.BOLD, 16), RED)); // 创建一个放置输入RGB值文本框的面板 rgbTextFieldPane = new JPanel(); // 创建R文本框 rTextField = new JTextField(2); // 创建G文本框 gTextField = new JTextField(2); // 创建B文本框 bTextField = new JTextField(2); // 将R,G,B文本框添加到面板中 rgbTextFieldPane.add(rTextField); rgbTextFieldPane.add(gTextField); rgbTextFieldPane.add(bTextField); // 将该面板添加到rgbToHexPane中 rgbToHexPane.add(rgbTextFieldPane, BorderLayout.NORTH); // 创建一个文本域来显示颜色 hexTextArea = new JTextArea(6, 6); // 设置文本域不可编辑 hexTextArea.setEditable(false); // 将文本域添加到rgbToHexPane中 rgbToHexPane.add(hexTextArea, BorderLayout.CENTER); // 创建一个转换结果面板 transformButtonPane = new JPanel(); // 创建一个转换按钮 rgbToHexButton = new JButton("转换"); // 创建一个显示HEX值的文本框 hexResultTextField = new JTextField(5); // 添加rgbToHexButton和hexResultTextField到transformButtonPane中 transformButtonPane.add(rgbToHexButton); transformButtonPane.add(hexResultTextField); // 将transformButtonPane添加到rgbToHexPane中 rgbToHexPane.add(transformButtonPane, BorderLayout.SOUTH); // 将rgbToHexPane添加到转换面板 changePane.add(rgbToHexPane); // 创建一个hex转成rgb的面板 hexToRgbPane = new JPanel(); // 设置面板的布局方式为边界边界 hexToRgbPane.setLayout(new BorderLayout()); // 设置面板的边界 hexToRgbPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY, 2, true), "十六位颜色代码转化成RGB颜色", TitledBorder.LEFT, TitledBorder.TOP, new Font("微软雅黑", Font.BOLD, 16), RED)); // 创建一个输入hex的文本框面板 hexTextFieldPane = new JPanel(); // 创建一个输入hex的文本框 inputHexTextField = new JTextField(6); // 将文本框添加到文本框面板中 hexTextFieldPane.add(inputHexTextField); // 将hexTextFieldPane添加到hexToRgbPane中 hexToRgbPane.add(hexTextFieldPane, BorderLayout.NORTH); // 创建一个显示颜色的文本域 rgbTextArea = new JTextArea(); // 设置文本域不可编辑 rgbTextArea.setEditable(false); // 将rgbTextArea添加到hexToRgbPane中 hexToRgbPane.add(rgbTextArea, BorderLayout.CENTER); // 创建转换按钮面板transformButtonPane2 transformButtonPane2 = new JPanel(); // 创建转换按钮 hexToRgbButton = new JButton("转换"); // 创建R结果显示文本框 rResultTextField = new JTextField(2); // 创建G结果显示文本框 gResultTextField = new JTextField(2); // 创建B结果显示文本框 bResultTextField = new JTextField(2); // 将这些文本框和按钮添加到transformButtonPane2中 transformButtonPane2.add(hexToRgbButton); transformButtonPane2.add(rResultTextField); transformButtonPane2.add(gResultTextField); transformButtonPane2.add(bResultTextField); // 将transformButtonPane2添加到hexToRgbPane中 hexToRgbPane.add(transformButtonPane2, BorderLayout.SOUTH); // 将hexToRgbPane添加到转换面板 changePane.add(hexToRgbPane); /** * 为rgbToHexButton添加活动监听器 */ rgbToHexButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 获取文本框的R,G,B值被转换成整型 int R = Integer.parseInt(rTextField.getText()); int G = Integer.parseInt(gTextField.getText()); int B = Integer.parseInt(bTextField.getText()); // 在hexTextArea显示要转换的颜色 hexTextArea.setBackground(new Color(R, G, B)); // 显示转换成功的HEX值 hexResultTextField.setText(new Utils().rgbToHex(R, G, B)); } }); /** * 为hexToRgbButton添加活动监听器 */ hexToRgbButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 获取输入的HEX值 String text = inputHexTextField.getText(); // 获取转换后的Color对象 Color color = new Utils().hexToRgb(text); // 显示转换的颜色 rgbTextArea.setBackground(color); // 显示转换的结果R,G,B rResultTextField.setText(String.valueOf(color.getRed())); gResultTextField.setText(String.valueOf(color.getGreen())); bResultTextField.setText(String.valueOf(color.getBlue())); } }); // 返回设置好的转换面板 return changePane; }
    点击运行,效果图如下:

    3.实现具体功能由于需要对界面的组件进行一些操作,所以应该定义一些变量在方法之外,以便整个类能够进行调用,其实并没有什么改变。
    其中Main.java的内容如下:
    public class Main { private JFrame mainFrame; private JSplitPane splitPane; private JPanel showColorPane, showValuePane, settingPane, descriptionPane, changePane, rgbToHexPane, rgbTextFieldPane, transformButtonPane, transformButtonPane2, hexToRgbPane, hexTextFieldPane; private JButton startColorPickerButton, rgbToHexButton, hexToRgbButton; private JTextArea textArea, hexTextArea, rgbTextArea; private JLabel RLabel, GLabel, BLabel, HEXLabel, descriptionLabel; private JTextField RTextField, GTextField, BTextField, HEXTextField, rTextField, gTextField, bTextField, hexResultTextField, inputHexTextField, rResultTextField, gResultTextField, bResultTextField; private JCheckBox checkBox; private Box vbox; /** * 得到一个主窗体对象 * * @return 返回得到的JFrame */ public JFrame mainFrame() { // 实例化一个主窗体对象 mainFrame = new JFrame(); // 设置窗体的标题 mainFrame.setTitle("取色器"); // 设置窗体的尺寸大小 mainFrame.setSize(900, 450); // 设置窗体的不允许用户自由调整大小 mainFrame.setResizable(false); // 设置窗体的图标(注意图标路径问题) mainFrame.setIconImage(Toolkit.getDefaultToolkit().createImage("src/main/resources/images/colorpicker.png")); // 创建拆分面板作为主面板 splitPane = new JSplitPane(); // 设置分隔条上折叠/展开按钮的显示 splitPane.setOneTouchExpandable(true); // 设置当拖动分隔条时连续重绘组件 splitPane.setContinuousLayout(true); // 设置分隔条的位置 splitPane.setDividerLocation(mainFrame.getWidth() / 2); // 设置拆分面板的左侧组件为取色器面板 splitPane.setLeftComponent(getColorPickerPane()); // 设置拆分面板的右侧组件为转换面板 splitPane.setRightComponent(getChangePane()); // 调用设置的样式 setFrameAllConponentStyles(); // 将拆分面板设为主窗体的内容面板 mainFrame.setContentPane(splitPane); // 设置窗体的关闭方式 mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 返回主窗体 return mainFrame; } /** * 设置取色器的面板内容 * * @return 返回设置好的取色器面板 */ private Box getColorPickerPane() { vbox = Box.createVerticalBox(); // 实例化一个显示取色的面板 showColorPane = new JPanel(); // 设置该面板的布局方式 showColorPane.setLayout(new BorderLayout()); // 创建一个启动取色功能的按钮 startColorPickerButton = new JButton("取色"); // 创建一个文本域来显示取到的颜色 textArea = new JTextArea(10, 25); // 设置文本域不可编辑 textArea.setEditable(false); // 设置文本域默认背景颜色 textArea.setBackground(Color.BLACK); // 设置文本域无边界 textArea.setBorder(null); // 将按钮添加到面板中并设置显示在北部位置 showColorPane.add(startColorPickerButton, BorderLayout.NORTH); // 将文本域添加到面板中并设置显示到中部位置 showColorPane.add(textArea, BorderLayout.CENTER); // 将面板添加到vbox中 vbox.add(showColorPane); // 实例化一个显示RGB值和HEX值的面板 showValuePane = new JPanel(); // 设置面板的布局方式为流动布局 showValuePane.setLayout(new FlowLayout()); // 创建R标签 RLabel = new JLabel("红(R):"); // 创建R文本框 RTextField = new JTextField(2); // 创建G标签 GLabel = new JLabel("绿(G):"); // 创建G文本框 GTextField = new JTextField(2); // 创建B标签 BLabel = new JLabel("蓝(B):"); // 创建B文本框 BTextField = new JTextField(2); // 创建HEX标签 HEXLabel = new JLabel("HEX:"); // 创建HEX文本框 HEXTextField = new JTextField(6); // 将上面这些组件添加到面板中 showValuePane.add(RLabel); showValuePane.add(RTextField); showValuePane.add(GLabel); showValuePane.add(GTextField); showValuePane.add(BLabel); showValuePane.add(BTextField); showValuePane.add(HEXLabel); showValuePane.add(HEXTextField); // 将面板添加到vbox中 vbox.add(showValuePane); // 创建一个设置面板 settingPane = new JPanel(); // 设置面板的边界 settingPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY, 2, true), "设置", TitledBorder.LEFT, TitledBorder.TOP, new Font("微软雅黑", Font.PLAIN, 16), BLACK)); // 创建一个复选框,默认被勾选 checkBox = new JCheckBox("总是在最上层", false); // 设置复选框的字体 checkBox.setFont(new Font("微软雅黑", Font.PLAIN, 16)); // 将复选框添加到面板中 settingPane.add(checkBox); // 将该面板添加到vbox中 vbox.add(settingPane); // 创建一个说明面板 descriptionPane = new JPanel(); // 设置面板的边界 descriptionPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY, 2, true), "说明", TitledBorder.LEFT, TitledBorder.TOP, new Font("微软雅黑", Font.PLAIN, 16), BLACK)); // 创建一个说明标签 descriptionLabel = new JLabel(); // 设置标签内容 descriptionLabel.setText("按下Alt键取色,可以直接在剪贴板复制RGB颜色"); // 设置标签字体 descriptionLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16)); // 将标签添加到面板中 descriptionPane.add(descriptionLabel); // 将该面板添加到vbox中 vbox.add(descriptionPane); /** * 复选框状态改变监听器 */ checkBox.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { // 判断复选框是否被选中 if (checkBox.isSelected()) { // 设置主窗体置于最上层 mainFrame.setAlwaysOnTop(true); } else { // 取消主窗体置于最上层 mainFrame.setAlwaysOnTop(false); } } }); /** * 给startColorPickerButton按钮添加键盘事件监听器 */ startColorPickerButton.addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent e) { // 键入某个键 } @Override public void keyPressed(KeyEvent e) { // 释放某个键 } @Override public void keyReleased(KeyEvent e) { // 按下某个键 // 当按下Alt键时触发事件 if (e.getKeyCode() == 18) { try { // Robot 可以模拟鼠标和键盘的输入。基于给定屏幕设备创建一个Robot Robot robot = new Robot(); // 获取鼠标在屏幕中移动的坐标位置 Point mousePoint = MouseInfo.getPointerInfo().getLocation(); // 获取鼠标所在位置的X值 int X = mousePoint.x; // 获取鼠标所在位置的Y值 int Y = mousePoint.y; // 获取指定屏幕坐标处的像素颜色 Color pixelColor = robot.getPixelColor(X, Y); // 分别获取Color的R,G,B值 int R = pixelColor.getRed(); int G = pixelColor.getGreen(); int B = pixelColor.getBlue(); // 分别将获取到的R,G,B及HEX值显示在界面中 RTextField.setText(String.valueOf(R)); GTextField.setText(String.valueOf(G)); BTextField.setText(String.valueOf(B)); HEXTextField.setText("#" + Integer.toHexString(R) + Integer.toHexString(G) + Integer.toHexString(B)); // 对取得的颜色进行显示 textArea.setBackground(new Color(R, G, B)); // 把RGB值复制到剪贴板中直接使用 // 获取系统的剪贴板 Clipboard systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); // 对RGB值进行封装 StringSelection stringSelection = new StringSelection(R + "," + G + "," + B); // 把文本内容设置到系统剪贴板 systemClipboard.setContents(stringSelection, null); } catch (AWTException e1) { e1.printStackTrace(); } } } }); // 返回设置好的vbox return vbox; } /** * 设置转换面板的面板内容 * * @return 返回设置好的转换面板 */ private JPanel getChangePane() { // 创建一个转换面板 changePane = new JPanel(); // 设置面板的布局方式为网格布局 changePane.setLayout(new GridLayout(2, 1)); // 创建一个rgb转hex的面板 rgbToHexPane = new JPanel(); // 设置面板布局方式为边界布局 rgbToHexPane.setLayout(new BorderLayout()); // 设置面板的边界 rgbToHexPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY, 2, true), "RGB颜色代码转化成16位颜色", TitledBorder.LEFT, TitledBorder.TOP, new Font("微软雅黑", Font.BOLD, 16), RED)); // 创建一个放置输入RGB值文本框的面板 rgbTextFieldPane = new JPanel(); // 创建R文本框 rTextField = new JTextField(2); // 创建G文本框 gTextField = new JTextField(2); // 创建B文本框 bTextField = new JTextField(2); // 将R,G,B文本框添加到面板中 rgbTextFieldPane.add(rTextField); rgbTextFieldPane.add(gTextField); rgbTextFieldPane.add(bTextField); // 将该面板添加到rgbToHexPane中 rgbToHexPane.add(rgbTextFieldPane, BorderLayout.NORTH); // 创建一个文本域来显示颜色 hexTextArea = new JTextArea(6, 6); // 设置文本域不可编辑 hexTextArea.setEditable(false); // 将文本域添加到rgbToHexPane中 rgbToHexPane.add(hexTextArea, BorderLayout.CENTER); // 创建一个转换结果面板 transformButtonPane = new JPanel(); // 创建一个转换按钮 rgbToHexButton = new JButton("转换"); // 创建一个显示HEX值的文本框 hexResultTextField = new JTextField(5); // 添加rgbToHexButton和hexResultTextField到transformButtonPane中 transformButtonPane.add(rgbToHexButton); transformButtonPane.add(hexResultTextField); // 将transformButtonPane添加到rgbToHexPane中 rgbToHexPane.add(transformButtonPane, BorderLayout.SOUTH); // 将rgbToHexPane添加到转换面板 changePane.add(rgbToHexPane); // 创建一个hex转成rgb的面板 hexToRgbPane = new JPanel(); // 设置面板的布局方式为边界边界 hexToRgbPane.setLayout(new BorderLayout()); // 设置面板的边界 hexToRgbPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY, 2, true), "十六位颜色代码转化成RGB颜色", TitledBorder.LEFT, TitledBorder.TOP, new Font("微软雅黑", Font.BOLD, 16), RED)); // 创建一个输入hex的文本框面板 hexTextFieldPane = new JPanel(); // 创建一个输入hex的文本框 inputHexTextField = new JTextField(6); // 将文本框添加到文本框面板中 hexTextFieldPane.add(inputHexTextField); // 将hexTextFieldPane添加到hexToRgbPane中 hexToRgbPane.add(hexTextFieldPane, BorderLayout.NORTH); // 创建一个显示颜色的文本域 rgbTextArea = new JTextArea(); // 设置文本域不可编辑 rgbTextArea.setEditable(false); // 将rgbTextArea添加到hexToRgbPane中 hexToRgbPane.add(rgbTextArea, BorderLayout.CENTER); // 创建转换按钮面板transformButtonPane2 transformButtonPane2 = new JPanel(); // 创建转换按钮 hexToRgbButton = new JButton("转换"); // 创建R结果显示文本框 rResultTextField = new JTextField(2); // 创建G结果显示文本框 gResultTextField = new JTextField(2); // 创建B结果显示文本框 bResultTextField = new JTextField(2); // 将这些文本框和按钮添加到transformButtonPane2中 transformButtonPane2.add(hexToRgbButton); transformButtonPane2.add(rResultTextField); transformButtonPane2.add(gResultTextField); transformButtonPane2.add(bResultTextField); // 将transformButtonPane2添加到hexToRgbPane中 hexToRgbPane.add(transformButtonPane2, BorderLayout.SOUTH); // 将hexToRgbPane添加到转换面板 changePane.add(hexToRgbPane); /** * 为rgbToHexButton添加活动监听器 */ rgbToHexButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 获取文本框的R,G,B值被转换成整型 int R = Integer.parseInt(rTextField.getText()); int G = Integer.parseInt(gTextField.getText()); int B = Integer.parseInt(bTextField.getText()); // 在hexTextArea显示要转换的颜色 hexTextArea.setBackground(new Color(R, G, B)); // 显示转换成功的HEX值 hexResultTextField.setText(new Utils().rgbToHex(R, G, B)); } }); /** * 为hexToRgbButton添加活动监听器 */ hexToRgbButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 获取输入的HEX值 String text = inputHexTextField.getText(); // 获取转换后的Color对象 Color color = new Utils().hexToRgb(text); // 显示转换的颜色 rgbTextArea.setBackground(color); // 显示转换的结果R,G,B rResultTextField.setText(String.valueOf(color.getRed())); gResultTextField.setText(String.valueOf(color.getGreen())); bResultTextField.setText(String.valueOf(color.getBlue())); } }); // 返回设置好的转换面板 return changePane; }
    这个项目需要实现的功能有如下几个:

    从屏幕中取色并显示在界面中同时显示它的RGB值和HEX值
    “总是在最上层”复选框的实现
    点击【转换】按钮将RGB颜色代码转化成16进制颜色
    点击【转换】按钮将16进制颜色转化成RGB颜色值

    实现取色在这个项目中最主要的是取色的实现:
    在Main.java中的getColorPickerPane方法中添加如下代码:
    /** * 给startColorPickerButton按钮添加键盘事件监听器 */ startColorPickerButton.addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent e) { // 键入某个键 } @Override public void keyPressed(KeyEvent e) { // 释放某个键 } @Override public void keyReleased(KeyEvent e) { // 按下某个键 // 当按下Alt键时触发事件 if (e.getKeyCode() == 18) { try { // Robot 可以模拟鼠标和键盘的输入。基于给定屏幕设备创建一个Robot Robot robot = new Robot(); // 获取鼠标在屏幕中移动的坐标位置 Point mousePoint = MouseInfo.getPointerInfo().getLocation(); // 获取鼠标所在位置的X值 int X = mousePoint.x; // 获取鼠标所在位置的Y值 int Y = mousePoint.y; // 获取指定屏幕坐标处的像素颜色 Color pixelColor = robot.getPixelColor(X, Y); // 分别获取Color的R,G,B值 int R = pixelColor.getRed(); int G = pixelColor.getGreen(); int B = pixelColor.getBlue(); // 分别将获取到的R,G,B及HEX值显示在界面中 RTextField.setText(String.valueOf(R)); GTextField.setText(String.valueOf(G)); BTextField.setText(String.valueOf(B)); HEXTextField.setText("#" + Integer.toHexString(R) + Integer.toHexString(G) + Integer.toHexString(B)); // 对取得的颜色进行显示 textArea.setBackground(new Color(R, G, B)); // 把RGB值复制到剪贴板中直接使用 // 获取系统的剪贴板 Clipboard systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); // 对RGB值进行封装 StringSelection stringSelection = new StringSelection(R + "," + G + "," + B); // 把文本内容设置到系统剪贴板 systemClipboard.setContents(stringSelection, null); } catch (AWTException e1) { e1.printStackTrace(); } } } });
    代码解释说明:

    通过对startColorPickerButton按钮添加键盘事件监听器来对当按下Alt键后的事件处理
    可以通过e.getKeyChar()获取键盘按下的字符;通过e.getKeyCode()获取键盘按下键对应的数值
    Robot,机器人。Robot 的主要目的是便于 Java 平台实现自动测试,也可以模拟鼠标和键盘的输入
    MouseInfo.getPointerInfo().getLocation()可以得到鼠标在电脑屏幕中的当前坐标位置
    通过Robot的getPixelColor(X,Y)方法来得到当前位置的像素颜色,就这样实现了取色
    下面的代码就是将获取到的颜色显示在界面

    运行程序,效果图如下:

    实现总是在最上层接下来是实现复选框的【总是在最上层】的功能。
    在getColorPickerPane()方法中添加如下代码:
    /** * 复选框状态改变监听器 */ checkBox.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { // 判断复选框是否被选中 if (checkBox.isSelected()) { // 设置主窗体置于最上层 mainFrame.setAlwaysOnTop(true); } else { // 取消主窗体置于最上层 mainFrame.setAlwaysOnTop(false); } } });
    代码解释说明:

    通过对checkBox添加状态改变监听器来实现如果复选框被勾选则使主窗体处于最上层,否则不
    判断复选框checkBox是否被选中通过JCheckBox的isSelected()方法来得到,被选中返回true,否则返回false
    使窗体处于最上层其实是使JFrame处于最上层,所以是设置JFrame的setAlwaysOnTop()方法实现的,其中参数是boolean类型,是true则使其处于最上层,否则不

    产生的效果图如下:

    实现RGB转HEX接下来就是实现RGB和HEX之间的转换。
    在colorpicker包下新建一个Utils类,该类用来放置一些在整个项目中要用到的方法。
    先讲将RGB转换成HEX的实现。
    在Utils类中添加如下一个方法:
    public class Utils { /** * 将三位RGB值转换成HEX格式 * @param R 十进制的R值 * @param G 十进制的G值 * @param B 十进制的B值 * @return 返回转换成功HEX格式的字符串 */ public String rgbToHex(int R,int G,int B){ return "#"+Integer.toHexString(R)+Integer.toHexString(G)+Integer.toHexString(B); }
    该方法就是将RGB转换成HEX的方法,在主界面中的【转换】按钮直接调用这个方法即可。
    为getChangePane()方法添加如下代码:
    /** * 为rgbToHexButton添加活动监听器 */ rgbToHexButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 获取文本框的R,G,B值被转换成整型 int R = Integer.parseInt(rTextField.getText()); int G = Integer.parseInt(gTextField.getText()); int B = Integer.parseInt(bTextField.getText()); // 在hexTextArea显示要转换的颜色 hexTextArea.setBackground(new Color(R, G, B)); // 显示转换成功的HEX值 hexResultTextField.setText(new Utils().rgbToHex(R, G, B)); } });
    代码解释说明:

    RGB到HEX的转换是通过触发【转换】按钮的点击事件监听器来实现的,而具体的转换则是调用的Utils类中的rgbToHex()方法来完成的
    值得注意的是,从文本框获取的是字符串类型的值,而不是我们所需要的整型,因此需要进行转换

    运行程序,测试结果如下:

    实现HEX转RGB说完了将RGB转换成HEX,接下来将如何将HEX转换成RGB。
    同样地,在Utils.java中添加如下方法:
    /** * 操作结果:将HEX格式字符串转换成Color对象 * @param hex HEX格式字符串 * @return Color 转换完成的颜色对象 */ public Color hexToRgb(String hex){ String rHex=hex.substring(1,3); String gHex=hex.substring(3,5); String bHex=hex.substring(5,7); int R=Integer.parseInt(rHex,16); int G=Integer.parseInt(gHex,16); int B=Integer.parseInt(bHex,16); return new Color(R,G,B); }
    在Main.java中的getChangePane()方法中添加如下代码:
    /** * 为hexToRgbButton添加活动监听器 */ hexToRgbButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 获取输入的HEX值 String text = inputHexTextField.getText(); // 获取转换后的Color对象 Color color = new Utils().hexToRgb(text); // 显示转换的颜色 rgbTextArea.setBackground(color); // 显示转换的结果R,G,B rResultTextField.setText(String.valueOf(color.getRed())); gResultTextField.setText(String.valueOf(color.getGreen())); bResultTextField.setText(String.valueOf(color.getBlue())); } }); // 返回设置好的转换面板 return changePane; }
    代码解释说明:

    HEX到RGB的转换是通过触发【转换】按钮的点击事件监听器来实现的,而具体的转换则是调用的Utils类中的hexToRgb()方法来完成的
    其中文本框的setText()方法中的参数是字符串类型,而通过Color对象分别得到的R,G,B值都是整型,也都需要使用String.valueOf()方法进行转换

    运行程序,测试效果图如下:

    4.界面简单装饰查看运行效果图,会发现界面比较丑,字迹模糊,文本框小。

    在colorpicker包下创建一个Styles类,专门来放置一些设置的样式。
    设置按钮的样式在Styles类中添加如下方法:
    /** * 设置按钮的样式 * * @param buttons 按钮组 */ public void setButton(JButton... buttons) { for (JButton button : buttons) { // 设置按钮的字体 button.setFont(new Font("微软雅黑", Font.PLAIN, 20)); // 设置当鼠标放在按钮上的样式 button.setCursor(new Cursor(Cursor.HAND_CURSOR)); // 设置按钮的前景色 button.setForeground(Color.BLACK); // 设置按钮的背景色 button.setBackground(new Color(221, 232, 243)); // 设置按钮获取焦点后不显示线框 button.setFocusPainted(false); } }
    再在主界面类Main中添加一个setFrameAllConponentStyles()方法:
    其中内容如下:
    /** * 设置界面一些组件的样式 */ private void setFrameAllConponentStyles() { Styles styles = new Styles(); // 设置按钮的样式 styles.setButton(startColorPickerButton, hexToRgbButton, rgbToHexButton); // 设置文本框的样式 styles.setTextField(RTextField, GTextField, BTextField, HEXTextField, rTextField, gTextField, bTextField, hexResultTextField, inputHexTextField, rResultTextField, gResultTextField, bResultTextField); // 设置标签的样式 styles.setLabel(RLabel, GLabel, BLabel, HEXLabel, descriptionLabel); }}
    把上面的工作做完后还是没有把这些样式用起来,因为虽然写好了实现方法,但是该方法还没有被调用。
    在Main类的mainFrame()方法中添加如下内容:
    // 调用设置的样式 setFrameAllConponentStyles();
    好了,样式已经成功调用,那么来看看效果怎么样:

    看起来按钮的效果确实好了许多。
    设置文本框的样式在Styles.java中添加如下方法:
    /** * 设置文本框的样式 * * @param textFields 文本框组 */ public void setTextField(JTextField... textFields) { for (JTextField textField : textFields) { // 设置文本框显示字体 textField.setFont(new Font("微软雅黑", Font.PLAIN, 18)); // 设置文本框前景色 textField.setForeground(Color.BLUE); // 设置文本框背景色 textField.setBackground(Color.WHITE); // 设置文本框最小尺寸 textField.setMinimumSize(new Dimension(3, 5)); // 设置文本框选中文本时文本颜色 textField.setSelectedTextColor(Color.BLUE); } }
    文本框样式的方法写好后,就是为所有的文本框使用该样式,在Main.java中的setFrameAllConponentStyles()方法中添加如下内容:
    // 设置文本框的样式 styles.setTextField(RTextField, GTextField, BTextField, HEXTextField, rTextField, gTextField, bTextField, hexResultTextField, inputHexTextField, rResultTextField, gResultTextField, bResultTextField);
    运行程序,看下成果:

    设置标签的样式在Styles.java中添加setLabel()方法设置标签的样式,如下:
    /** * 设置标签的样式 * * @param labels 标签组 */ public void setLabel(JLabel... labels) { for (JLabel label : labels) { label.setFont(new Font("微软雅黑", Font.PLAIN, 19)); label.setForeground(Color.BLACK); } }
    接着在Main.java中的setFrameAllConponentStyles()方法中添加如下内容:
    // 设置标签的样式 styles.setLabel(RLabel, GLabel, BLabel, HEXLabel, descriptionLabel);
    运行程序,查看效果图:

    尽管不是非常好看,但是比一开始建立的界面要好看一些。而本项目的代码部分也基本完成了,接下来就是打包成jar和exe了。
    5.使用Maven打包jar文件IDEA默认打包方式在介绍Maven打包之前先说明下IDEA默认打包方式:
    第一步:打开IDEA->File->Project Structure…。或者使用快捷键:Ctrl+Alt+Shift+S

    第二步:选中Artifacts选项卡,然后点击上面的加号(+),选择第一项JAR展开后,选择【From modules with dependencies…】

    第三步:配置打包相关

    第四步:得到输出路径,然后点击【OK】

    第五步:选择【Build】,然后是【Build Artifacts…】

    第六步:生成jar包

    第七步:查看生成包,到刚才输出路径的位置去查看生成的jar包。

    第八步:运行该包,效果图如下。

    6.总结在本项目中,可以发现就主界面一个界面就有非常多的组件,而在Styles类已经对组件样式统一写方法进行设置了,但是还是比较麻烦,如果项目中界面很多,那么光设置样式就是一件很麻烦的事情,会充斥着大量重复代码,如需修改或单独设置某一个组件的样式,又是很麻烦,那么如何解决呢?这个问题留在下一个项目吧!
    0 评论 0 下载 2021-10-17 10:47:06
  • 基于SSM架构的网络租车系统

    摘 要随着网络应用的兴起,人们的生活也因此发生了翻天覆地的变化。人们开始利用计算机来解决我们生活中的实际问题,由此诞生了许多互联网产业,同时也有不少传统服务业已经向互联网服务业进行改变,利用网络技术为人们的生活提供更优质的服务。
    本文首先介绍了开发项目使用的框架以及所用插件,对其的优势进行了介绍。然后是本项目的需求分析,主要讲述了本项目中各个角色以及其所拥有的功能和权限。其次是本项目的数据库设计,包括每个字段的类型和长度以及说明。然后是本系统的详细开发流程,展示了项目中的主要页面及主要代码。最后是将对系统进行一些测试,将测试结果进行展示。
    关键词:SSM框架;JAVA技术;租车系统
    AbstractWith the rise of web applications, people’s lives have undergone earth-shaking changes. People began to use computers to solve practical problems in our lives. Many Internet industries have been born. At the same time, many traditional service industries have changed the Internet service industry and used network technologies to provide people with better services.
    This article first introduced the framework used by the development project and the plug-ins used, and introduced its advantages. This is followed by an analysis of the needs of this project. It mainly describes the various roles in this project and their own functions and permissions. Followed by the database design of this project, including the type and length of each field and description. This is followed by a detailed development process for the system, showing the main pages and major codes in the project. Finally, some tests will be performed on the system and the test results will be displayed.
    Keywords: SSM Framework; JAVA Technology; Car Rental System
    1.绪论1.1 课题来源在学校期间,自己通过在老师的指导下完成了一个简易的租车网页,仅仅是将数据库中数据用表格展示,并输入车辆数和天数后完成租车。在公司实习期间,接触到了spring + srpingmvc + mybatis(以下简称SSM)的JavaWeb框架,发现其操作流程清晰,代码不冗杂。经过一段时间的工作积累,决定将以前做的租车系统进行优化,使用SSM框架,maven技术来做一个小型租车网站。
    1.2 课题背景在互联网产业迅速发展的今天,一些线下产业正在被侵蚀,所以需要向互联网企业转型,这样才能不被时代所淘汰。
    而作为租车行业,需要提高商家的知名度。这样用户才能更好的了解商家和车辆信息,以及对比价格。现在每个城市都还存在一些小型租车公司,他们没有一个统一的平台,传播度不高,普及的用户不广。对于不了解地方的外地游客来说,并不能获取租车的信息。所以说开发一个租车系统将各个城市中的线下租车公司进行资源整合。对用户来说,可以更清晰的了解租车公司的车辆信息,以及商家位置,方便了用户。对商家而言,将自己的信息放到网络上,用户可以更加了解自己的店铺,可以提高知名度,也可以更快捷的为用户服务。这正是本项目开发的目的和意义所在。
    1.3 系统设计的目标基于SSM框架的网络租车系统,其开发主要包括前台页面数据的展示,后台是基于MySQL数据库的restful api开发,利用ajax请求api将数据展示在前台页面。

    用户邮箱注册与验证码登陆:用户注册后需要通过邮箱所发邮件链接进行激活,激活成功后才能登陆,否则会提示未激活。当用户选中车辆需要租赁时会需要用户登陆
    查看用户基本信息:修改用户密码,上传用户头像等
    车辆信息展示:使用轮播图展示车辆图片,展示基本车辆信息,使用百度地图api展示商家位置
    商家信息展示:展示基本商家信息,展示商家下的车辆。使用百度地图api展示商家位置
    邮件提醒:用户成功租赁车辆后会向用户和商家发送邮件提醒商家和用户
    车辆管理:上传车辆,修改车辆
    商家管理:上传商家,修改商家
    管理员管理:设置管理员,删除管理员

    2.系统可行性分析2.1 经济可行性由于本次开发所运用技术都是免费开源的技术或者框架,不存在版权收费问题。而且这个项目是JavaWeb项目,开发完成后仅需将war包放到服务器上并且搭配一个域名就可完成一个网站的搭建。用户通过手机或电脑都可以进行访问,不需要很强的配置。而商家上传车辆也仅需要一个电脑和车辆图片,就可完成上传,对于电脑配置也没有很大的要求。所以本系统在经济上就有完全的可行性。
    2.2 技术可行性一个项目是否可以完成开发,还是要看技术是否能达到要求。
    由于在学校期间学习了Jsp,Oracle等技术,对于前台页面的开发还是可以完成的。然后又经过一段时间的实习,学到了更加优秀的技术,并且接触到ssm框架。使自己的眼界和技能都提升了一大步。Mysql和oracle在基本操作上的差异不是很大,而且在公司实习也是用的mysql,并且mysql体积小。经过比较最后决定使用mysql作为数据库。前台页面主要是利用jsp,并且利用bootstrap,jQuery,arttemplter,validform等js插件完成前台页面简洁,优美,功能强大的数据展现。后台部分由于采用了框架,所以对功能实现了分层,使得各个代码之间的逻辑清晰,代码简洁明了。所以掌握的技术还是可以完成整个系统的开发,在技术上也具有可行性。
    2.3 操作可行性操作可行性是指系统开发完成并上线后,用户和商家对于本系统的掌握程度。
    由于本系统整体页面简洁,不冗杂,操作按钮清晰,用户浏览清晰。操作简单。
    商家也仅需会基本的计算机操作,就可完成车辆上传等操作。所以操作上具有可行性。
    2.4 维护可行性一个系统是否能够长远运行,需要有人一直维护系统,对出现的简单错误进行修改,对一些复杂性的错误及时提醒。
    本系统在开发时运用了log4g进行了错误日记记录,维护人员可以根据错误日记信息快速找到错误点,进行判断修改。所以在维护上具有可行性。
    3.关键技术介绍3.1 软件环境软件环境是一个程序的运行土壤,开发程序时需要就要设定好的,如果环境错误或缺失很容易造成系统崩溃或运行错误。

    操作系统:Window10专业版
    Jdk:1.8.0
    服务器:apache-tomcat-9.0.6
    数据库:MySQL 5.7
    系统开发工具:IntelliJ IDEA 2017.2.6

    3.2 开发技术简介本软件系统开发所用到的技术:MySQL 、Java、JavaScrapt、jQuery、Sping、Spring MVC、MyBatis、Maven。
    3.2.1 Java简介Java是一种广泛使用的计算机编程语言,拥有跨平台、面向对象、泛型编程的特性。
    由于是将源码编译成class字节码文件,最后由jvm虚拟机来解释执行字节码文件。所以具有“一次开发,到处运行”的跨平台特性。
    3.2.2 JavaScrapt简介JavaScirpt一种高级编程语言,是一种基于原型,函数先行的语言。
    JavaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能。
    基本特点:

    是一种解释性脚本语言(代码不进行预编译)
    主要用来向HTML页面添加交互行为
    可以直接嵌入HTML页面,但写成单独的js文件有利于结构和行为的分离

    常用来完成以下任务:

    嵌入动态文本于HTML页面
    对浏览器事件作出响应
    读写HTML元素
    在数据被提交到服务器之前验证数据
    检测访客的浏览器信息
    控制,包括创建和修改等

    3.2.3 jQuery简介jQuery是一套跨浏览器的JavaScript库,简化了HTML与JavaScript直接的操作,是目前最受欢迎的JavaScript库。
    jQuery的语法设计使得很多基本操作变得容易,如选择DOM节点、操作文档对象,创建动画效果、处理事件、以及开发Ajax程序。并且有良好的扩展性,可以基于jQuery开发许多插件。
    3.2.4 MySQL简介MySQL拥有体积小、速度快、稳定性高等特点,对于一些数据量不是特别大的中小型网站而言MySQL是最佳的数据库。工作模式是基于客户机/服务器结构。并且有良好的跨平台特性,能够在大部分操作系统上运行。
    基本特点:

    为多种編程语言提供了API
    支持多线程,充分利用CPU资源,支持多用户
    优化的SQL查询算法,有效地提高查询速度
    可以处理拥有上千万条记录的大型数据库

    3.2.5 Spring简介主要解决业务逻辑层和其他各层的松耦合问题,所以整个系统都是面向接口的编程思想。并且采用控制反转(Inversion of Control,IoC)原则的配置管理。使组件应用程序更加方便快捷。
    3.2.6 Spring MVC简介MVC:(Model-view-controller)模式是软件工程中一种常见的软件架构模式,把软件系统总体分为三个大模块:模型(Model)、视图(View)和控制器(Controller)。

    视图层:只是负责页面的渲染,布局和数据的展示。只需通过向后台请求数据就可完成展现。不再考虑后台数据逻辑的处理
    控制层是将视图层发送的请求拦截,再根据不同场景及数据要求调用不同的处理方法
    模型层:主要是后台逻辑处理,针对不同业务场景或需求制定不同的算法,处理不同的数据进行拼装。实现不同的功能

    3.2.7 MyBatis 简介Mybatis是一个Java持久化的框架,它通过XML描述符或注解把对象与存储过程或SQL语句关联起来。与其他类似的对象关系映射框架不同的是,Mybatis并不是将Java对象与数据库表关联,而是将Java方法与Sql语句关联。
    3.2.8 Maven简介Maven:一个软件项目管理及自动构建。
    Maven是一个项目管理和整合的工具。Maven为开发者提供了一套完整的构建生命周期框架。开发团队基本不用花多少时间就能自动完成工程的基础构建配置,因为Maven使用了一个标准的目录结构和一个默认的构建生命周期。在创建报告、检查、构建和测试自动配置时,Maven可以让开发者的工作变得更简单。
    3.3 应用插件简介本软件系统开发所用到的插件:Validform验证表单插件、bootstrap框架、autoComplate自动补充插件,arttemplete模板插件、dialog弹出框插件、idcode插件。
    3.3.1 Validform表单验证用于前台表单页面的校验,并且可以自定义校验类型,以及已有的限定规则,使得表单校验变得很简单。
    3.3.2 bootStrap框架Bootstrap,来自 Twitter,是目前很受欢迎的前端框架。Bootstrap 是基于 HTML、CSS、JavaScript 的,它简洁灵活,使得 Web 开发更加快捷。 它由Twitter的设计师Mark Otto和Jacob Thornton合作开发,是一个CSS/HTML框架。Bootstrap提供了优雅的HTML和CSS规范,它即是由动态CSS语言Less写成。Bootstrap一经推出后颇受欢迎,一直是GitHub上的热门开源项目,包括NASA的MSNBC(微软全国广播公司)的Breaking News都使用了该项目。国内一些移动开发者较为熟悉的框架,如WeX5前端开源框架等,也是基于Bootstrap源码进行性能优化而来。
    3.3.3 autoComplete自动填充搜索关键字输入后,会将符合条件的结果以特定格式展现在输入框下方。
    3.3.4 arttemplate 模板插件art-template 是一个简约、超快的模板引擎。
    特性:

    拥有接近JavaScript渲染极限的性能
    调试友好:语法、运行时错误日志精确到模板所在行;支持在模板文件上打断点
    支持Experss、Koa、Webpack
    支持模板继承与子模板

    3.3.5 dialog 弹出框插件弹出框,相比于原生的alert()方法更美观,可自定义标题和按钮,也可设定回调事件。
    3.3.6 idcode 验证码插件验证码插件。相比于后台的验证码,前台验证码具有速度快,不受网络速度的限制的优势。
    4.系统概要设计4.1 需求分析用户总体分为三种:普通用户,管理员,超级管理员。

    超级管理员:是网站的负责人,可以新建商家,并可以对商家信息进行修改,也可以删除违法或不再继续运营的商家。也可以上传车辆,但是需要指定商家
    管理员:商家的负责人,可以上传车辆,商家指定为自己所在的商家。也可以修改车辆,通过条件筛选车辆。删除不再继续租赁的车辆
    用户:浏览车辆,根据条件筛选车辆,登录成功后租赁车辆。用户注册时没有头像,有一个默认头像,进入个人信息页面后可以修改自己的头像。并修改自己的用户名

    这三种身份都是用户,都需要注册,超级管理员是预先设定的。所以数据库中需要一个用户表,然后一个字段说明用户级别。一个表存储商家下的管理员。
    4.1.1 用户需求分析图
    4.1.2 管理员需求分析图
    4.1.3 超级管理员需求分析图
    4.2 数据库设计数据库名:car_project
    表名:car 车辆表



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




    1
    car_id
    Varchar
    255




    Java的uuid随机生成


    2
    car_brand
    Varchar
    255




    车辆品牌


    3
    car_name
    Varchar
    255




    车辆名称


    4
    car_type
    Varchar
    255




    车辆类型


    5
    car_image
    Varchar
    255




    车辆图片,多张图片之间用“,”拼接


    6
    car_price
    Decimal
    10
    2



    价格


    7
    car_amount
    Int
    10




    数量


    8
    car_people
    Int
    10




    载人数


    9
    car_good
    Decimal
    10




    载货量


    10
    car_info
    Varchar
    255




    车辆描述信息


    11
    rent_count
    Int
    10




    租赁次数


    12
    shop_id
    Varchar
    255




    商家id


    13
    car_milage
    Decimal
    10




    里程数


    14
    car_time
    Date





    购买时间


    15
    user_id
    Varchar
    255




    上传者id



    表名:user 用户表



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




    1
    user_id
    Varchar
    255




    用户的标识,注册时随机生成的字符串


    2
    user_count
    Varchar
    255




    登录账号


    3
    user_name
    Varchar
    255




    用户的名称


    4
    user_email
    Varchar
    255




    用户的邮箱地址


    5
    user_password
    Varchar
    255




    用户密码


    6
    user_registration
    Date
    10
    2



    注册时间


    7
    is_active
    int
    10



    0
    是否激活,用户注册后需通过邮件激活


    8
    rent_count
    int
    10



    0
    租赁次数


    9
    user_image
    varchar
    10



    Default.png
    用户头像


    10
    is_admin
    int
    255



    0
    0 用户,1管理员,2 超级管理员



    表名:shop 商家表



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




    1
    shop_id
    varchar
    255




    商家id


    2
    shop_name
    varchar
    255




    商家名称


    3
    shop_phone
    int
    11




    商家联系方式


    4
    shop_email
    varchar
    255




    商家邮箱


    5
    shop_location
    varchar
    255




    商家位置


    6
    jingdu
    decimal
    10
    7



    位置的经度


    7
    weidu
    decimal
    10
    7



    位置的纬度



    表名:order订单表



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




    1
    order_id
    varchar
    255




    订单id


    2
    user_id
    varchar
    255




    用户id


    3
    shop_id
    varchar
    255




    商家id


    4
    car_id
    varchar
    255




    车辆id


    5
    price
    decimal
    10
    2



    价格


    6
    order_time
    date





    订单时间



    表名:admin管理员表



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




    1
    id
    varchar
    255




    id


    2
    user_id
    varchar
    255




    用户id


    3
    shop_id
    varchar
    255




    商家id



    5.系统详细设计5.1 用户注册与登陆5.1.1 用户注册用户注册页面

    用户登录代码

    用户登录后根据用户等级跳转到不同页面,同时将用户的头像地址,id,用户昵称,等级存放到cookies中。
    用户注册如图4所示需要邮箱地址,因为邮箱是联系商家或用户的一个主要方式。并且在失去焦点后会向后台发送校验请求。校验邮箱、用户名是否被注册。确定密码失去焦点后会自动校验与第一次输入密码是否一致。验证码失去焦点后会自动校验与图片内文字是否一致。校验全部通过后完成注册。
    完成注册后,系统会自动向注册邮箱发送一封激活账户的邮件,用户点击邮件内的链接可以将账户进行激活。
    5.1.2 用户激活用户通过邮件内的链接点击进行是如图6所示的页面。

    出现这样的页面,则标识该用户已经成功激活。并且在3秒后会自动跳转到登录页面。
    5.1.3 用户登陆
    用户在页面点击进入或激活成功后会进入登录页面。
    表单中也用到了Validform表单校验,用来检测用户名是否存在、密码是否与数据库中存储的密码是否一致、验证码是否与图片内文字是否一致。通过后会跳转到首页,并且在点击租赁车辆时如果未登录,也会跳转到登录页面。
    用户登录成功后会向cookies中存储信息,这样在不同页面也可以检查到用户是登录状态。
    5.2 头部栏与底部栏本软件系统中其他页面都通过:
    <jsp:include page=”public/header.jsp”></jsp:include><jsp:include page=”public/footer.jsp”></jsp:include>
    命令将头部栏和底部栏引入到其他页面。
    5.2.1 头部栏
    未登录时头部栏如图8所示,显示的是登录注册按钮,当登录后会变成图9所示,头部栏展示用户头像和用户昵称,以及注销按钮。

    输入框可对车辆和商家进行搜索,搜索结果如图11所示。关键字可以从车辆的品牌、类型、名称来搜索。也可通过商家名称进行搜索。

    如图10所示,对输入框设置键盘抬起事件。并设置一个0.8秒的延迟。设置延迟主要是为了减少搜索次数,如果不设置延迟,在一些输入法或系统下会将每次按键都发送一次请求,设置后会将0.8秒后的输入框内文字进行查询。这样会减少查询次数,减少等待时间。然后根据返回数据的不同对前台的内容设置不同的格式。最后将查询到的数据展示。

    5.2.2 底部栏底部栏主要展示的是开发者信息,以及版权信息。并且加入了邮件的超链接。
    <a href=mailto:ytulnj@163.com>
    点击超链接会自动调用电脑的邮件发送程序,来给指定的邮箱发送邮件。
    5.3 首页首页是一个网站的主页面,是一个网站的脸面,首页的好坏足够影响系统在用户心中的形象。所以要求首页简洁大方,逻辑清晰,可操作性良好。本网站的首页头部和底部嵌入了头部栏和底部栏。中间放入了一个轮播图,展示商家或网站的广告。再向下则是筛选条件,通过筛选条件确定下面的车辆展示。 筛选条件中有车辆品牌,车辆类型,车辆价格等条件。并且车辆价格也可用户自己输入。如果选择错误也可通过重置按钮取消选择。并且三个条件可以联合查询。如果在该查询条件下没有车辆会提示,该查询条件下没有车辆。 下面车辆框展示车辆的图片,车辆的名称、品牌、价格、剩余车辆、租赁次数,以及商家的名称。鼠标移入后会显示边框,提醒用户正在查看的车辆。点击商家名称也可进入商家信息页面。点击车辆框进入车辆信息页面。

    5.4 详细页面车辆详情页和商家详情页都是在detail.jsp展示。通过地址栏中的参数,如果是carId则是展示车辆详情页面,如果是shopId则是展示商家详情页面。
    在详情页会调用百度地图的api将商家位置展示在地图上,并且会定位到用户位置,然后在地图上展现用户到商家的驾车路线。

    传参为商家的经纬度,然后将商家经纬度进行标识在地图中,并设置为15级别的地图大小。并开启地图的鼠标滑轮滚动。然后定位用户位置,将用户位置与商家位置设置为起点和终点,最后驾车路线就会展示在地图中。
    5.4.1 车辆详情页面
    通过车辆id查询车辆信息,以表格形式展现在页面上,车辆图片以轮播图的形式进行播放展示,右侧为租赁车辆的输入框,可以输入租赁的天数以及辆数。如果输入车辆数大于剩余数量则校验不通过。并且如果用户未登录会弹出提示框,提示用户登录,然后跳转到登录页面。
    下方是展示该车辆所在的商家的一些基本信息。
    然后是相同车型的车辆展示,并且限制了数量在20辆以内。
    5.4.2 商家详情页面
    通过商家id进行查询,将基本信息以表格形式进行展现,右侧通过百度地图展示商家位置。下面展示该商家下的车辆进行展示。
    5.5 用户页面由与将不同身份的用户都放到一个页面下展示,并且根据身份不同需要展示的页面内容是不一样的。登录成功后,会在后台存储包括用户id、昵称、头像、身份级别等信息返回前台。前台接受到数据后会向cookies中存储用户信息。包括用户id,用户昵称,用户头像等。使得在不同标签中都可以检测到用户的状态。

    如图16所示,用户在进入用户页面时会根据用户的等级来决定模板,这样就可以让不同身份的用户看到不同的信息。
    5.5.1 普通用户
    用户头像开始是一个默认图片,用户可进入页面自行修改。并且可以进行修改昵称和密码。然后又显示的是一些不可编辑的信息,包括注册时间,邮箱,登录账号和租赁次数等。最后会将租赁的记录展示出来,并且做了限制,只显示最近的20条记录。在租赁记录中点击车辆名称和商家名称都可以进入到车辆或商家的详情页。
    5.5.2 普通管理员
    普通管理员是作为商家下的管理人员,可以进行上传车辆、编辑车辆和删除车辆的操作。点击上传车辆按钮会进入到上传车辆页面,并且上传车辆页面表单中的商家名称固定为所在商家的名称且不可编辑。删除车辆可以单个删除也可通过多选按钮进行批量删除。在删除时会弹出提示框,提醒此操作是危险操作。点击车辆名称可以进入编辑车辆页面。
    5.5.3 超级管理员
    超级管理员作为网站的负责人,可以设置新建商家、编辑商家和删除商家。点击新建商家可以进入新建商家页面。点击商家列表中的商家名称可以进入编辑商家页面。通过删除按钮可以删除单个或批量删除商家,删除时会弹出提示框,提醒此操作是危险操作。
    同时超级管理员也可以为商家设置管理员。由于管理员也是一个用户,所以管理员也需要进行注册并且进行激活。在输入框通过搜索用户账号进行搜索,并且会对输入的关键字进行查询。在搜索商家名称时也可通过关键字进行提示筛选。当用户账号和商家名称输入完成之后点击设置会将输入的用户设置为输入的商家下的管理员。同时超级管理员也有上传车辆的权限,但是点击上传车辆按钮进入上传车辆页面商家名称为空,需要手动输入。原则上超级管理员是不会对车辆进行操作。
    5.6 车辆页面上传车辆和编辑车辆都是在car.jsp页面完成,通过后面是否带参数判断是编辑车辆还是上传车辆。
    由于车辆需要图片来进行展示,所以会有车辆图片的编辑操作,但是不能确定管理员会上传几张图片,所以设定一个按钮,点击后会打开文件框来上传图片,并限制最大数量。在上传图片时可以会操作失误,图片错误,所以需要预览和删除功能。在编辑车辆页面还需要将之前的图片进行展示,如果数量等于最大数量则不允许继续上传,不然则可以继续上传图片,也可对之前的图片进行删除操作。

    5.6.1 上传车辆页面
    点击上传图片按钮会弹出上传文件窗口,并且可以将上传的图片在右侧进行预览。并且在图片下方有一个删除按钮,点击删除后可以将图片删除,这样可以避免点击失误,并且如果对图片不满意可以将其删除。并且限制了最多只能上传6张图片。
    上传成功后会显示如图22所示页面。点击继续上传后可以跳转到上传车辆页面,否则会在3秒后回到首页。

    5.6.2 编辑车辆页面
    可以将以前上传的图片进行删除,也可修改其他基本信息。但是租赁次数是没法修改的。
    修改完成后会出现提示页面并自动返回到首页。
    5.7 商家页面新建商家和编辑商家都是在shop.jsp页面完成,通过判断是否带参数来确定是新建商家还是编辑商家。
    5.7.1 新建商家页面
    商家需要的属性有商家名称,商家联系方式,商家邮箱,商家位置,商家经纬度。
    其中商家名称、商家联系方式、商家邮箱、商家位置都不能重复。商家联系方式作为用户联系商家的方式,商家邮箱作为用户成功租赁车后系统自动向商家发送邮件的地址,商家位置是作为一个商家具有线下实体店的主要信息。商家经纬度主要是作为百度地图标识商家位置的主要参数。
    5.7.2 编辑商家页面超级管理员点击商家名称后进入编辑商家页面,展示商家的基本信息,输入框不可编辑,并且改变了输入框的样式,让输入框只有下边框。点击编辑按钮后输入框可编辑,显示边框。

    5.8 错误页面错误页面主要是对系统可以出现的错误进行预测并设置其错误后显示的页面。本系统主要设置了404错误和500错误后显示的页面。
    5.8.1 404页面
    当地址栏输入的地址不存在时,会自动拦截到404页面,中间会有一个动画效果,并且右侧有个消息框,点击里面的回到首页可以回到系统的首页。
    5.8.2 500错误页面
    并不会将错误信息进行展示,只是拦截,并展示这个页面。
    5.9 后台代码说明
    后台逻辑层次分为controller、dao、data、service、util五个包。Controller层是作为前台与后台的链接,起到拦截调用分发的作用。Dao层是对数据库的操作,主要是对数据库操作的方法,其中一个java接口对于一个相同名称的xml文件,在xml中编写sql。Data层是对数据库中表的映射,一个数据库的表对应一个类文件。Service中是主要逻辑的编写,其中service文件夹中还有一个impl文件夹,在service中编写接口,在impl中具体对方法进行实现。这样暴露接口后其他人员查看不到具体逻辑的实现。Util文件夹中是一些其他操作类,比如邮件发送,图片存储等方法
    6.系统测试6.1 后台代码测试结构如图29所示:

    测试类主要是对后台程序是否能够正常连接数据库,逻辑操作是否正确,方法能否被正确调用进行测试。主要是对dao层和service层进行测试。Dao层主要是看数据库操作结果是否正确。Service层主要是看逻辑操作是否正确。
    6.2 程序运行测试6.2.1 注册注册页面测试图

    用户收到邮件页面

    用户激活页面

    用户信息校验成功。并且注册邮箱会收到一份邮件,点击链接后会将用户激活。
    6.2.2 登录用户未激活页面

    如果账号未激活,会出现提示信息。
    6.2.3 修改头像测试
    点击更好头像后会出现文件框,选择图片后可以实现图片预览,不点击保存是无法更换成功的,只能将图片展示。点击保存后,保存按钮消失,头部栏的头像也会发生改变。
    6.2.4 租赁车辆测试
    当租赁数量大于剩余车辆时会提示数量错误。

    当未登录时会弹出提示框提示用户需要登录。

    用户登录后再进行选择会提示所租车辆名称和天数,辆数以及价格。点击结算后系统会自动向用户和商家发送邮件进行提醒。
    总结毕业设计主要是对大学期间所学知识的检验,将所学知识转换成项目实战。这个项目也是将自己从学校学到的知识和从公司学到的知识进行融合,利用ssm框架完成一个小型网站的开发。从题目的选取、整个项目的需求分析、数据库设计、页面设计、具体代码实现、系统测试这些不管是整体架构还是琐碎细节都需要自己来进行实现。这整个过程让我受益匪浅。
    整体开发过程中遇到的错误还是很多的,但是经过自己的思考、网络资源的提示、同学老师的帮助,这些困难还是被一一克服了。
    这个系统还有很多可以改进的地方,比如手机号验证码等、通过浏览器或ip地址定位进行导航、用户登录使用第三方账号比如QQ或微信。这也是以后需要完善的地方。
    参考文献[1] 梁弼.SSH框架整合技术研究及应用[J].西安文理学院学报:自然科学版,2011,14(3):16-19.
    [2] 陈夫真.基于SSM的某高校教室管理信息系统的设计与实现[D].苏州:苏州大学,2012.
    [3] 张锦煌,吴丽娟,梁舒婷.基于SSM整合框架开发的项目管理系统[J].电脑知识与技术,2015,11(11):103-105.
    [4] 孙卫琴. Java面向对象编程[M]:北京:电子工业出版社, 2006.7 .168-172
    [5] 阎宏. Java与模式[M]:北京:电子工业出版社, 2002.10..88-96
    [6] 孙卫琴等著.基于MVC的Java Web设计与开发.北京:电子工业出版社,2012
    [7] 陈雄华,林开雄,文建国.精通Spring 4.x:企业应用开发实战[M].北京:电子工业出版社,2017.1
    [8] 张海藩.软件工程导论[M].北京:清华大学出版社,2013.
    [9] 徐国智.MySQL数据库系统开发实例精粹[M].北京:电子工业出版社,2006
    [10] 朱华方.基于SSM框架轻量级的分布式高考成绩管理系统设计与实现[D].济南:山东师范大学,2016.
    [11] 胡启敏,薛锦云,钟林辉.基于Spring框架的轻量级J2EE架构与应用[J].计算机工程与应用,2008(05):115-118
    [12] 徐雯,高建华.基于Spring MVC及MyBatis的Web应用框架研究[J].微型电脑应用,2012,28(07):1-4
    6 评论 51 下载 2021-03-27 09:20:15
  • 基于C#和Sql Server的图书管理系统

    1 课程设计意义与目标1.1 课程设计的意义《可视化编程技术课程设计》是在学生学习完《可视化编程技术》以后进行的设计性集中实践课程,通过课程集中实践,目的是使学生能加深对理论教学内容的理解,学会可视化编程技术的综合应用,培养学生分析问题的解决问题的能力。
    1.2 课程设计的目标通过课程集中实践,要求学生加深对讲授内容的理解,累积经验、学会独立上机调试程序;并且逐步达到综合运用封装、继承和多态等C#难点知识,更深地理解面向对象程序设计的基本概念与方法,从而学会利用C#语言解决一般应用问题,能设利用可视化编程技术开发复杂和综合性的计算机管理信息系统,并为后续专业课程的学习奠定程序设计基础。
    2 课程设计的题目2.1 设计题目概述
    图书管理系统
    2.2 开发环境搭建
    开发语言:C#
    开发工具:Visual Studio 2010
    数据库管理工具:SQL Server 2008

    3 系统的设计与实现3.1 物理数据模型设计




    3.2 主要界面设计
    界面中用了textbox,label,combobox,textbox用于获取数据输入,combobox用于数据选取,button用于单击事件。在用户类别可以选择用户类型,管理员。

    界面中用了textbox,label,combobox,dataGridView,textbox用于获取数据输入,combobox用于数据选取,button用于单击事件,dataGridView用于数据显示。
    功能:可以增加,修改,删除图书。

    界面中用了textbox,label,combobox,dataGridView,textbox用于获取数据输入,combobox用于数据选取,button用于单击事件,dataGridView用于数据显示,用户借书,管理员可以查看用户的借书记录。

    密码修改:可以更改当前用户登录的密码,旧密码符合条件,新密码和旧密码不能相同,新密码和确认密码的相同的条件。

    界面中用了textbox,label,combobox,dataGridView,textbox用于获取数据输入,combobox用于数据选取,button用于单击事件,dataGridView用于数据显示,用户借书,管理员可以查看用户的借书记录。模糊查询在下面有具体介绍。

    管理员信息管理:可以对管理员进行增添改查。

    书库管理:对书库进行增删改查。

    书库查询:按地区分类和按书库编号分类,第二个combobox会自动加载所有记录的值供你选择。

    书库管理:用来增加书库,删除,修改。

    用户管理:对用户的增删改查。

    用户登录之后的界面。

    管理员登录之后的界面。
    4 调试过程中出现的问题及解决办法4.1 数组索引超出界限解决方法:利用断点调试,重新赋值。

    4.2 从试图获取数据时,应添加新的字段
    5 个人体会及建议在这次课设中,基本都是在学习新知识的过程,从powerdesigner到动软生成软件,让我知道了这个工具的强大之处,渐渐开始会用一点,在第一天晚上想重做一遍学生信息管理系统,不料,动软生成的路径没改,直接给覆盖了,所以只能重头再来,在这时就有想法想做个不一样的系统,上学期用C++做了个图书管理系统,有点印象,就选择做这个,一开始一直模范着你给的day1,day2,day3,看不懂BLL,DAL,MODEL之间的关系,经过思考,理解了他们之间的关系,BLL负责储存方法相当于API,DAL负责储存数据,MODEL负责各个对象的类,后面理解了就开始自己写,用户负责借书,用户的增删改,添加用户,管理员负责查询书库,书库的增删改查,查询图书,图书的增删改查,借书记录的增删改查,在这个过程中不仅了解了动软生成软件的机制,而且可熟练的利用这个工具,在这个工具的基础之上,我写出了更多好用的函数供自己使用。在windows应用开发上了解更多控件和控件属性的使用和结合,可以做出功能和界面相对完整的程序,总之,在这次课设中受益匪浅。
    19 评论 502 下载 2019-03-10 21:28:03
显示 0 到 15 ,共 15 条
eject