《订单管理系统(ssh版)》_第1页
《订单管理系统(ssh版)》_第2页
《订单管理系统(ssh版)》_第3页
《订单管理系统(ssh版)》_第4页
《订单管理系统(ssh版)》_第5页
已阅读5页,还剩49页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、浪潮优派 订单管理系统(ssh版)技术总结报告订单管理系统(ssh版)技术总结报告年级班级姓名教师成绩山东浪潮优派教育科技有限公司1、软件开发流程。按照标准的的项目开发流程,整个项目的过程需要经历以下几个步骤,分别是可行性分析和项目开发计划、需求分析、概要设计、详细设计、编码、测试、维护。首先,可行性分析和项目开发计划主要是在经济可行性、社会可行性和技术可行性三个主要方面进行研究,比如技术可行性这个方面,如果我们没有学过jsp和j2ee技术的话那么这个项目是不能做出来的。这个阶段出的文档主要有可行性研究报告项目开发计划。需求分析阶段主要分析功能的需求、性能的需求、环境的需求以及用户界面的需求。

2、出的主要文档是需求规格说明书。概要设计主要是在宏观的角度对整个项目的结构和组织进行分析,设计软件系统结构和进行数据结构及数据库设计,主要文档是概要设计说明书、数据库设计说明书。详细设计阶段主要是对每个模块进行主要算法的设计以及其它部分的具体设计,必须要写的文档是详细设计说明书。然后是编码,这个过程才是我们主要去要完成的。前几个过程都在项目的原始文件夹中已经都被设计好了,我们需要工作的就是编写具体的代码。编码之后最重要的工作就是进行测试,测试是保证软件质量的重要环节。最后,是进行软件维护,软件维护在整个的软件生命周期中占有的比重是很大的,所以不能忽视它的作用。分为预防性维护、改正性维护、完善性维

3、护和适应性维护。其中,预防性维护比例最小。如果我们对我们的项目在开发后一个较短的时间内需要进行维护的话,看主要是进行改正性维护和完善性维护。当然,这个项目中主要需要我们完成的是编码阶段的工作。注:以上文字来源于jsp课程设计-设计报告的“软件开发流程”部分。2、项目整体功能概要。了解项目的功能,首先要了解整个公司的大概的业务领域和工作模式。从需求规格说明书中可以很明确的了解到,该公司的主要经营业务领域是电力电缆、连接配件等电力设备,工作模式是“业务员+代理商”。其实这里还隐藏了一个工厂,没有工厂哪来的业务员。那么,这三者之间是有关系的,工厂负责生产,代理商负责销售,业务员负责连通工厂和代理商,

4、作为生产和销售之间的重要桥梁。当然,业务员进行工作,需要进行记录,比如和代理商签订合同、开具发票、回收货款,这一些都需要进行认真地记录。那么在以往的方式中,刀耕火种的纸笔记录和口头传话模式首先工作量比较大,再者也比较容易出错,甚至是造成一错再错的情况。不利于公司的稳定运行和长期发展。那么,就需要一种现代化的方式来进行干预。故该项目就应运而生,需求中对该项目的要求是发现回款是否延迟、统计业务员的业绩和代理商的出货情况,从而以为公司领导提供数据参考。3、 团队组成说明。序号组员分工是否是组长0102030405064、个人承担的开发任务说明。通过“订单管理系统概要设计说明书”文件夹中的“画面迁移及

5、概要说明”得知整个项目由29个画面或者说29个功能模块组成。我在该项目中完成了前11个模块。下面简单叙述所完成的这11个功能模块,以及截图和功能说明。4.1已完成的模块及完成时间。序号画面名称页面名称完成时间01登录画面login2014.11.1102菜单画面mainmenu2014.11.1103密码修改画面resetpassword2014.11.1204用户管理usermaster2014.11.1205用户增加/编辑画面useredit2014.11.1206客户管理customermaster2014.11.1307客户增加/编辑画面customeredit2014.11.1308

6、货币管理currencymaster2014.11.1309货币增加/编辑画面currencyedit2014.11.1310代理商管理agencymaster2014.11.1411代理商增加/编辑画面agencyedit20每个子模块的截图和功能说明。(1)登陆画面功能说明:这是用户访问该系统的唯一入口。任何未登录的用户想要访问该系统中的任一功能界面,都会被定义的拦截器拦截,并转向登陆界面提示登录后再访问。输入正确的用户名和密码才能够正常登陆,转向“菜单界面”。如果用户名或密码输入错误,会提示错误。功能说明:经过后台处理发现用户名或密码输入错误,那么把该信息返回给前台

7、,提示用户重新登录。功能说明:此外,如果用户名或密码任何一个没有输入完全那么会弹出对话框提示。当然这是有前台直接控制的,避免了把空值发给服务器才进行校验的小题大做。(2)菜单画面功能说明:正确登录以后会转向“菜单界面”,菜单界面展现了该系统的全部功能。但是并不是所有的用户可以使用全部的功能,从概要说明书的画面迁移图中可以知道,该系统系统成员身份有三种,分别是管理人员、财务人员和业务人员。每个人员有不同的功能模块。其中,管理人员享有的功能模块是全部模块,即下图中的9个按钮。因为在该项目中完成的11个画面的大多数是在后四个大模块中,即用户管理、客户管理、代理商管理和货币管理,在管理人员的权限下都可

8、以进行查看和测试。故不再展现财务人员和业务人员的眼前画面。(3)密码修改画面功能说明:系统的右上角单击自己的用户名,会出现下拉菜单,下拉菜单中有修改密码模块可以单击进去进行密码的修改。功能说明:输入密码提交后就会有校验。如下图所述,是旧密码没有输入正确,然后把该消息告诉前台,那么用户需要重新检查后再次提交修改申请。功能说明:如果两次新密码输入不一致,也会提醒。当都输入正确后,提交后会返回登陆界面,这时候可以输入新密码重新登录系统。功能说明:此外,与修改密码在一起的还有一个退出系统的功能。当选择退出系统后,系统也会跳转到登陆界面,这时候用户可以继续登录或者关闭页面。(4)用户管理功能说明:下图展

9、现了用户管理界面。在该界面内,可以查看到所有用户的个人信息,默认每页显示10条记录,下面的页码可以进行自由的切换和进行显示条数的选择。需要说明的是,测试中为了插入数据方便以能够插入大量的数据来测试分页效果,故用户名那一列没有进行唯一性约束。真实环境中还是应该进行唯一性约束的,毕竟登陆的时候需要使用唯一的用户名和与之匹配的正确的密码才能登陆系统。功能说明:下图展现了页码切换区的灵活展现与切换功能。所谓灵活展现和切换。首先是要正确,正确显示该显示的页码标签数,比如经过与后台的交流发现一共有45条记录,发现在用户指定每页显示10条记录的情况下,应该显示5个页码标签,而且第5页应该显示最后的5条记录。

10、像这种的情况,首先是要灵活的展现该显示的争取的页码标签。再者,做到灵活,第一,比如单击任何一页页码号,都可以查询到那一个页面上对应的数据。第二,比如页数为20页,那么不会显示20个页码标签,而显示的是用户所选择的当前页的前后10页的页码标签。如果这时候用户想回到第一页,首选需要单击下图的5。更过分的如果有50页总不能显示50个页码的标签,所以还是需要一定的灵活的措施和判断逻辑来决定当前页面上应该显示的页码标签的起止区间。功能说明:如果单击了50,表示用户要求一页中显示50条记录。可以看到,左侧的序号已经递增到了50,且原先的10多页已经缩减为了4页。这是用户可以自由选择一页内显示多少条记录的选

11、项。功能说明:下图是当前页面内现实的记录的记录状态的说明。该区域表示当前页面中显示的是第几条到第几条记录,斜杠右边表示按照您的查询条件数据库中一共有多少条符合要求的记录。功能说明:下图使用了条件查询和模糊查询功能。用于想要查找名字中含有li的用户,并且联系电话含有130字样,并且是管理人员或者业务人员,状态可以有效或者无效都可以。那么查找出来了一部分符合要求的记录,上图仅仅截图了前四条。功能说明:再比如查询所有的状态为无效的用户。(5) 用户增加/编辑画面功能说明:下图展现了“新增用户”的界面,空空的输入框等待用户输入信息。其中用户编号是后台自动生成的,用户不需要也不能进行输入。功能说明:输入

12、好用户的信息,单击“保存”后,用户的信息会被保存到数据库,保存成功后,弹出对话框告诉用户保存成功。功能说明:“用户编辑”模块使用的是与“新增用户”模块同一样的对话框模板。但是当用户双击一行或者单击一行后面的“编辑”链接的时候弹出的对话框里面的值是会与那一行的数据同步的,这是与空空如也的新增用户模块的区别。功能说明:同样,当用户单击“保存”后,更新请求会提交到服务器,更新成功后,前台会有成功的提示。功能说明:无论是编辑还是保存,如果用户名没有填写或者写了又删了,那么会有提示,不会提交到服务器。(6)客户管理功能说明:前面对用户管理界面的各种细致的功能点已经介绍的很详细了,其实客户管理、货币管理和

13、代理商管理与前面介绍的用户管理模块的80%都是相同的。所以,这里进行更简略的说明。下图展现了客户管理的最基本的查询功能,当单击主菜单的客户管理按钮进来的时候,已经默认查找出所有的客户的个人信息供用户进行查看。功能说明:当然,如果用户在默认查询出的全部信息中通过翻页也找不到目标行,那么可以使用支持模糊查询的条件查询功能。比如下图,进行了名字中含有“sa”并且客户类型是“国网”或者“南网”的所有客户的查询。结果显示两条。最下方的页码和信息状态也是正常的。关于页码,用户管理中展示的很详细,这里不再絮叨。(7)客户增加/编辑画面功能说明:与用户增加类似,单击新增客户按钮也会弹出一个对话框,对话框中的文

14、本框是空白的等待输入。其中“客户名称”是必须输入的,否则会有提示必须输入的提示框。最后,输入完成,单击保存,当服务器完成保存后前台会有提示。功能说明:下图是“客户编辑”模块。首先会把用户要修改的那一个客户的所在行的值同步到这个编辑对话框中。然后等待用户进一步的修改动作。如下图,对sally修改为了sally3。当单击保存,服务器会进行保存操作,保存成功后前台会有成功的提示。(8)货币管理功能说明:下图是“货币管理”的界面。当用户单击主菜单的货币管理的时候第一眼看到的即如下所展示的画面,已经默认查询出了数据库中的所有货币的信息。当然,测试的时候没有对货币名称列进行唯一性约束,否则也不会有这么多“

15、卢布”充斥眼球。仅为了测试方便使用,真实环境中这种情况不允许。功能说明:使用了条件查询功能,查询数据库中所有含有“元”字样的货币信息,并且要求货币的“状态”是“有效”的。(9)货币增加/编辑页面功能说明:新增货币界面尤为简单,只需要用户填写“货币名称”,默认已经勾选状态为“有效”。然后单击保存即可。与用户和客户的添加类似,“货币名称”必须填写,否则会弹出对话框阻止用户提交。功能说明:“货币编辑”界面,也是会把用户想要编辑的那行的值同步到对话框中然后等待用户编辑。单击“保存”后提交到服务器。(10)代理商管理功能说明:上图展现了代理商界面的查询功能,也是默认查询出系统中所有的代理商的信息。如果找

16、出一个与前面三个实体管理不同的一点,那就是该代理商查询界面中有一个字段是关联到另一个实体的,即“业务员”字段。这个关系是说的,每一个代理商会有一个业务员来负责,唯一对应到一个业务员,该业务员指的是“用户类型”为s的用户。功能说明:下图使用了条件查询,查询出了所有业务员为“strong”这个人的所有的代理商信息。如上图所示,查询出来了三个,状态有“无效”的也有“有效”的。功能说明:如果再只勾选一个无效条件约束进行查询,结果集中就只有两条记录了。那一条状态为有效的已经不符合条件,所以没有查询出带到前台来。(11)代理商增加/编辑画面功能说明:上图展现了单击“新增代理商”按钮后弹出来的对话框,文本框

17、中等待用户输入。其中代理商编号为后台自动生成,用户不需要也不能进行输入。只需要填写好“代理商名称”和勾选“状态”以及“业务员”的选择。这三项中,代理商名称是必须填写的,不填写不能提交。“状态”默认“有效”。关于业“务员”的选择,相对复杂一些,下页来介绍。功能说明:关于“业务员”的选择,需要单击父对话框的放大镜弹出小对话框如上图所述,可以进行“业务员”的选择。这个画面的布局和结构的一部分是自己编写的。按照项目模板中的代码,如果单击“选择业务员”后弹出的页面中的页码切换或者目标查询,如果提交一个表单请求进行查询,那么肯定会引起页面的刷新,再次来到该页面的时候还要通过javascript代码来还原提

18、交前的页面状态,如还原用户打开对话框的层次,还原用户曾经选择了哪一个业务员等等。或者页码切换和查询请求不使用表单提交和链接跳转,而是用ajax请求,然后把返回的数据通过javascript再组装,数据量较大重新组装比较麻烦。这里,改变了原项目模板中的前台代码,使用iframe嵌套一个子页面,该子页面即下图所示的选择业务员这一个页面。下图中的业务员选择模块的组件都是放在一个单独的jsp文件中,然后被iframe标签来引用到父页面中。这样做的好处是,依旧可以使用原来的页码切换和查询逻辑,依旧可以使用表单提交和链接跳转来实现数据的更新和页码的切换,但是不需要javascript来还原现场也不需要aj

19、ax后的javascript来重新组织数据,因为iframe的刷新只会影响iframe本身,而不会影响父页面的刷新。上面简单说了一下修改后的实现思路。然后说一下该页面如何操作来实现选择业务员的功能,最上面一行蓝色字提示的很清楚,双击一行即代表选择一个业务员,然后业务员的信息会显示在最下面的那个单行的表格中,代表用户的选择。当然,用户这时候如果再双击另一行,那么这一个单行表格也会跟着更新。而且,提交请求进行页码切换或者目标查询的时候,用户曾经选择的这个业务员信息也不会丢,不仅本页面不会丢,父页面也会依旧记得。因为第一,父页面还是那个父亲,不会刷新的,第二,每双击一行,不仅更新了单行表格中的值呈现

20、给用户,也通知了父页面的javascript中的变量来记忆。单击“完成选择”即可选择一个业务员。父对话框中就会显示用户选择的这一个业务员的名字。功能选择:如下图,新增的代理商是tomcat名称,然后业务员最终在百般纠结之后选择了“superwoman”,即测试用户增加模块的时候增加的那一个用户。这个业务员的文本框是不能编辑的,不能手工输入,所以“superwoman”这几个字符的显示是建立在单击放大镜按钮之后的系统进行业务员查询后的罗列和用户坐在电脑前双击一行进行选择的基础上生成的。单击保存后,保存该代理商到系统,保存成功后,前台会有提示。4.3该系统如何工作。以上结合系统中已做模块的截图对系

21、统的功能层面进行了简要又罗嗦但是必要的说明,看到了系统的外观和它能完成怎样的工作。下面我想对系统内部是如何工作的进行叙述。也是因为在本设计报告模板的第五部分,对于“技术总结”每个部分的标题都很有较强针对性,不太方便单独拿出一块去做这样的叙述,故在这里拿出一块来进行系统内部工作的叙述。这里直接结合一个具体的例子来叙述一下这个请求响应在客户端和服务器走过了怎样的路线。那就以上边刚写完的“代理商查询”为例,趁热打铁,叙述一下这个流程。下面开始步入正题。首先,客户端在主菜单界面单击大大的“代理商管理”按钮即可进入这一个功能,回忆前面的功能叙述,用户应该看到的应该是系统默认查询出的第一页的全部代理商的信

22、息。别着急,这个结果的出现还是需要经过一些周折的。下面从用户单击动作开始。下图展现了前台的按钮界面,以及界面背后的代码的真实面目。从代码可以看出,用户单击按钮后,页面会跳转,跳转的目的地在location后面有描述。即跳转到agencyaction.action这一个action,并且传递了参数。猜测一下参数的含义,getall代表是查询,first代表是第一次查询,第一次的意思是指是主菜单上单击“代理商管理”按钮而引起的默认查询,而不是单击分页的查询或条件查询,所以应该清空action中原有的查询参数采用默认查询。上面对参数的含义进行了猜测。实际实现中,就是如此。现在还是在前台,当单击事件发

23、生,代码执行,发送请求到了后台。那么这些参数是怎么传递的。答案肯定是参数按照名字进行匹配注入到action中对应的同名属性字段上来的。当然,这些属性字段它们都必须有合法的get和set方法。现在登场的这两个简单的参数对应的action中的属性字段的如下图。action收到请求,通过purpose参数来分流请求,看看是增删改查中的哪一类请求。当然关于分流请求还有其它多种方式,比如使用dmi动态方法调用提交到不同的方法,这里请求种类并不是很多,就采用这种参数分流的方式吧。那么当action知道当前的请求类型是getall查询请求的时候,就会走查询逻辑,这时候又发现purposeflag是first

24、,于是知道了这是从主菜单过来的默认查询请求,所以查询参数置空,这个判断和置空的过程,如下图。之所以查询参数要置空,是因为要抹除那些非默认查询的参数的干扰,可能在拿个环节会有残余。比如上一次查询可能用户刚经过一次由页码切换或者条件查询引起的查询,action中或者url中还保存着陈旧的参数。而当用户从主菜单单击进入代理商查询的时候,这时候执行的查询应该是默认的查询,如果使用这些旧参数进行查询,那查出来的结果会使用户感到茫然,“咦,怎么默认查出来是这个样子,我没做这样的筛选条件啊”。当然,这样未尝不可,在技术层面上讲无可厚非,但是更好的还是刚进入这一个查询模块的时候采用默认查询方式。上图可见,参数

25、都已经初始化为默认值。一串变量初始化为空串,当前页面为1,页长为10,且purposeflag重置为null,那么下一次请求只要不是主菜单过来的便不会走这个重置参数为默认值的逻辑了,因为purposeflag不会再为first了。废话少说,其实也没少说多少,来步入关键的查询逻辑。查询逻辑这里不是简单地一个getall()方法的调用就拍屁股走人,因为这样的getall()获得全部的逻辑太简单了,这一层调下一层,最后的hql才仅仅是个“from agency”。虽然这里是默认查询全部,但是在前面的功能讲解中也有看到查询界面中,还有分页查询、排序查询、条件查询等一系列复杂查询,这些查询是会有更多的参

26、数进行控制和约束的。那么为了代码的高复用性和低耦合性,所以使用了相同的查询逻辑。这也是为什么上一段说的查询参数重置为默认值的原因,置空即处理,处理了当然就要用,怎么用,就是把这些参数往公共查询逻辑里面塞,为了代码的复用,只能牺牲上述的参数重置默认值的逻辑来契合公共逻辑的胃口了。那么下图就展现了这些参数的使用和业务逻辑层查询逻辑的代码的调用。为了不引起介绍逻辑上的混乱,还是以默认值的方式进行默认查询为例,后面再叙述分页查询、排序查询和条件查询的实现,那时候这些参数可能就是千奇百怪,这个后面再说,反正都是调用的相同的逻辑。看到上图中的三大部分,被绿色注释分隔开。第一部分,按照默认条件去查询了代理商

27、的结果集,虽然是所有的,但是也必须遵守默认条件,默认条件即默认参数,虽然是默认参数但是分页参数却是有值的,分页参数就决定了查询的结果是从第1条开始,长度为10,所以这一句话返回的应该是前10个代理商的结果集给list类型的agencies。既然说到了这个功能,就把它的实现展开说完,下面将叙述代码走到这里是如何一层层调用下去的。它的实现需要调用service业务逻辑处理层的方法,该方法的方法体如下图。业务逻辑层的逻辑主要分为两部分。第一部分,对参数的初步处理,第二部分,调用dao层访问数据库。首先第一部分,对参数进行初步处理,这里调用了一个方法,由于方法体较长,就不截图了,但是逻辑很简单,一说就

28、明白。这个函数的主要功能就是根据传过来的参数来组装一个hql的雏形,比如采用默认参数的,组装回来的hql就是“from agency a and 1=1 and 1=1 and 1=1”,意思不就是没有筛选条件的情况下查询所有的记录嘛。因为传给了这个函数有三个参数即分别是name、username和isvalid,且每一个都在action中被置为空串,那么经过判断,默认查询全部,为了代码的可复用性,所以这里都被翻译为了“1=1”永真,即传过来的这些条件不起到筛选作用。不过这样说可能有些故意和矫情,感觉“1=1”加不加都行。那么再举一个有参数的例子,别混乱,这里我们还是说的无参数的情况,只不过借

29、用一个有参数的例子来说明这个hql构造函数的逻辑的可靠性和复用性。如果传入name为“bob”,传入username为“tom”,传入isvalid为“t”,那么返回的hql的样子是怎样的呢?这里的三个参数肯定是起到筛选作用了,肯定不能再是坑爹的“1=1”了。而且这三个参数的筛选条件还应该同时满足,即“and”来连接。那么答案就是“from agancy a and like %bob% and a.user.username like %tom% and a.isvalid=t”,显而易见,原本的“1=1”被三个筛选条件替换了。与事先的分析一样,筛选参数起作用了,并且用“and

30、”来连接。这也是为什么会有“1=1”,既然这个恒等式可有可无为什么还要出现三次,这是因为“and”的原因。无论传过来的参数是不是默认,该函数接受了三个参数name、username和isvalid,那么无论怎样,首先两个“and”摆上,如果参数不是默认那么让你起到筛选作用填到“and”的空里,如果是默认值筛选参数不起作用,那么就是向“and”的空里填入“1=1”。么?不填行不行?那两个“and”在一起肯定出错了。当然,也可以用别的逻辑判断和处理来避免这种情况,比如一看是默认值“and”也不加这是完全可以的,这完全取决于if是怎样来摆放以及每句筛选子句是自带“and”还是经过其它判断的。不多说了

31、,总结一句。逻辑上实现很简单,只需要根据传递的每个参数是不是默认值,来组装为不同的hql的where字句中的筛选子句,通过if-else和字符串处理函数很容易来实现。继续接着前一段说。那么第一句话调用函数返回了一个hql子句的雏形,之所以是雏形,是还不能直接用,还需要经过再处理和再加工。因为刚才调用的函数在之前也说好了是可以复用的,那么也就是说用于返回结果集也行、进行统计数目也行。所以,正式因为这样,该函数中才只去影响了where子句,只组装了查询和统计两个部分所能共用hql子句,试想能公用的不就是where嘛。查询结果集还需要order by和设置分页,而统计总数不需要这两块,然后统计总数还

32、需要select count(x.id),查询结果集通过hql的“from agancy.”就已经可以方便的得到list这样的结果集了,select加上多此一举除非单独选字段或其它类型的查询,这里也没这个必要。所以,这些求同存异出来的“异”就在调用该函数后的自己的模块中进行了再处理和再加工。所谓的再处理和再加工,在目前叙述的这个例子中,如上图所述,所做的工作是去检查是否有排序的要求,如果有那么组装排序order by语句缀在hql雏形后面,如果没有,就不加order by子句采用数据库默认的顺序。到这里hql就组装完了,再调用dao层的逻辑来访问数据库,把组装好的hql和分页参数传给dao即可

33、。从这一对叙述中,似乎感到了service层重要的责任和较复杂的逻辑,起到一个承上启下和中流砥柱的作用。如果没有它,action会显得臃肿或者dao会显得太操心。各司其职,service把处理好的hql和分页参数给dao之后,dao就只负责进行数据库的查询了。通过上一句的叙述,我们可以想到有hql和分页参数,那么不就是用hql实例化一个query实例,然后为它setfirstresult()和setmaxresults()嘛,似乎无论是代理商还是用户还是客户或者货币的查询来了,dao层的代码都是这样的嘛。这正是由于service的存在和辛勤工作导致了dao层逻辑瞬间清晰了很多。所以这里调用的d

34、ao的查询函数虽然是写的agencydao的,但是其实是agencydao和所有实体类dao的父类basedao中的函数,核心代码如下。通过泛型,让其可以支持更多不同的实体类的查询。反正都是给hql和分页参数的查询,仅仅只是实体类不一样罢了,一个泛型就可以解决的问题嘛。从上图可以看出,真实的代码与上一段分析的一致,实例化query然后设置分页参数,调用list()方法进行查询,返回一个list。到这里,dao层的任务就已经结束了。本来嘛,dao层就是做数据访问用的,数据访问就是那么单纯,说到底就是连接好数据库然后通过hql进行交流,然而使用了hibernatetemplate或者是使用原生的h

35、ibernate接口,似乎连接的过程也不用程序员去操心了。然后dao层把这个查询出来的结果集返回给service,再返回给action。这样关于默认的查询的元素部分的查询就结束了,action的agencies属性字段中就保存了从第1条记录开始10条记录的这些agency代理商实体,这就是默认查询查询出来的结果集的结果。说完了,松了一口气,但是这仅仅只是结果集的查询。回想action中的代码截图,似乎还有两块逻辑没有说。action中的下一个逻辑如下图。那么下面,还要进行的第二部分的工作,那就是总数的查询。既然都查出前10个元素来了,给用户看不就完了,为么还要查总数。这是因为前台分页和显示当前

36、已查到的记录状态的需要。如果不知道总记录数,只知道页长10,当前页是1,又怎么能知道一共应该显示多少个页码标签给用户,用户又怎能单击写有页号的页码标签来实现分页查询。所以,查询总数还是必须的。action中进行这一个操作的代码就是上面那幅图片中所述的代码了。依旧调用了service层的逻辑,但是查询总数传入的参数似乎比查询结果集的参数简单多了。来,再看一下查询结果集时使用的参数。对比很明显,查询总数只需要代理商名字、业务员名字和状态,这些似乎都只是where子句中的,我们意想,应该就是符合where子句中的这些筛选条件的代理商会被一个个统计计数。然而在查询结果集的时候,还传入了分页和排序相关的

37、,这影响到了用户将会看到哪一个记录区间的记录和以怎样的顺序去看。而统计总数不需要排序不需要分页,排序了也不影响结果,分页了那还哪是总数。讲明白这一点,就知道为什么传这些参数。那么下面调用service层逻辑,与查询结果集的时候类似,只不过参数少了,如下图。同样,调用刚才查询结果集的时候调用过的组装参数为hql雏形的方法。上面也有提到该方法之所以只组装where子句,是为了复用,如果该方法中又涉及了排序子句的组装,那么对于统计总数的hql是无法进行复用的。上图中,理所当然的,把属于where子句参数的三个参数传到方法中,返回一个hql雏形。至于雏形啥样,针对是否是默认参数有不同的样子,叙述结果集

38、查询的时候已经进行了很详尽的解析了。好了,hql雏形有了。对比查询结果集时候的再加工,那时是对order by的加工,那么在统计总数这里不需要order by,排序了也没用,但是需要的聚集函数来统计总数,所以这一模块的再加工就是在hql雏形前面加上”select count(a.id)”,即以id的数目来统计总数,否则不用count聚集函数怎能返回总数。然后调用dao层查询逻辑进行查询,同样,这一个方法也是agencydao从basedao继承而来的,basedao中规定了进行数据库访问中一些共用的模块和方法。调用到的这个函数,可以想到的是实例化一个query,然后调用uniqueresult

39、()返回一个long类型的总数就可以了。当然也可以直接使用hibernatetemplate的find来返回一个list,不过再转比较麻烦。于是实际代码中使用了前者,如下图。然后得到的long类型的总数count返回给service返回给action。于是action就知道了当前应该传送给客户哪一些数据,也知道了一共有多少条数据从而前台可以参考它来做分页。action中最后做的,就是根据记录总条数和当前页长,来计算出了页码号的总数,前台直接拿到这个数据进行页码的显示就好了。哎,action还真是操心。如图。计算分页总数,即记录总条数除以每页中的记录数得出double类型值再向上取整。比如rec

40、ordcount为11代表一共有11条记录,pagesize为5代表每页显示5条记录,除法运算之后得2.2,如果分页为2页的话,那么第1-10条肯定没问题,但是第11条肯定显示不出来,所以应该ceil()向上取整得3才是最后的答案。到了这里,服务器端的处理就结束了,知道了结果集,知道了分页参数。然后转向agencymaster字符串指向的逻辑视图即agencymaster.jsp。jsp页面中的展现牵扯到了一些前台的部分,毕竟本次项目的主要精力放在后台,给的原始项目模板中前台也编写的差不多了。这样,下面对前台使用struts2标签进行数据展现的部分和分页部分的前台实现进行一些必要的说明。首先说

41、,对于结果集的展现。服务器勤苦的按照默认参数查询出了第一条记录开始,前十条记录的结果集,或者说干脆说第一页的结果集,前台这时候需要展现服务器的辛勤工作的成果了。如何展现,强有力的方式就是通过struts2的标签,然后使用ognl访问action的值栈。action中的agencies结果集和计算出来的分页数据都在值栈中。如下图,使用s:iterator标签进行遍历。然后把每一次遍历得到的当前的那个agency实例放到var指向的agency变量中,再一个个抽取它的属性值进行展现。展现输出即使用了s:property标签,然后用s:if标签进行了一些判断以进行参数的必要转换,毕竟有的参数是面向数

42、据库的为了好存储,但是前台不一定好看,即用户不一定很快的看懂,比如数据库寸的isvalid为“t”,意思是“有效”,那么前台应该显示哪个?当然现实“有效”了,显示“t”还以为是“transformer”变形金刚来。所以,有些转换还是很有必要的。如下图,同时展现了这两种标签的作用。当然那一块s:if的也可以使用s:property并在其中使用三元运算符一个问号一个叹号来决定是显示“有效”还是“无效”,但是该字段中还有一个icon图标,那样做不太方便,所以使用了s:if标签来进行判断以显示不同的状态。以上说明了结果集的遍历和展现,action中还有分页属性。对于分页的相关属性,前台的处理方式如下。

43、这一个引入的jsp文件的说明就到此为止。从而知道了from区间左端点和to区间右端点,那么下面只需要把from-to这个左闭右闭区间内的这pagesize个数字给遍历出来,然后以有好的形式展现给用户。这一个展现的过程就是上面使用counter类的s:bean的标签和标签体内的过程。s:iterator标签不具有jstl中的c:foreach标签那样指定好var、begin、end、step就能实现for循环的功能。所以这样的遍历需要借助struts的counter类,这一点也是刚学到的。关于学习过程和遇到的问题会在后面的异常及问题描述中很详细的提到,关于counter类的学习和探索过程是学习的

44、同时进行记录的,不是在报告书写的时候才补充的。使用了counter,知道了起止点,那么通过s:iterator来每次拿去一个实体数来进行前台展现的组织就可以了。当当前数与当前页号吻合的时候,给与一个特别的标记。简单的遍历的过程如下图所示。到这里,关于用户单击主菜单上的代理商管理,然后服务器进行默认参数查询,然后把查询结果放到action值栈,直到最后jsp中通过struts标签的遍历就絮叨完了。下面再补充一点,就是用户如何操作,从而产生了分页查询、排序查询和条件查询。再一次絮叨之前,声明两点。第一,后台代码是完全一模一样的复用,故后台不做介绍;第二,前台注册事件和事件处理涉及太多前台,不做介绍

45、。那么要介绍的就是javascript得到参数后如何向服务器发送请求的这个过程。发送请求的方式有很多,熟悉的表单可以一个form写上然后指定好action,或者单击一个链接就看到了一条新闻的这样的习以为常却又视而不见的链接跳转,或者富互联网应该用兴起所应运而生的ajax或者等等。在项目的原始模板中,使用的form不多,使用ctrl+f查询agencymaster.jsp中的form一个也没查到。关于分页查询、排序查询和条件查询使用ajax的话太费劲,回来的数据需要用javascript做调整,做微调还可以,但是一旦变换条件回来的数据可能是天翻地覆的区别,这种调整太费劲,虽然使用ajax可以很好

46、地保存页面上用户曾经的输入值,因为页面都不会刷新。那么这里,如果使用链接跳转的方式,第一,不用写form,第二,可以在每次重新加载页面的时候使用struts的s:iterator和s:property方便的展现数据从而也不用ajax后使用javascript来小题大做的费劲调整。所以,项目中这一块的请求还是统一使用的链接跳转。如何获得各各参数的过程不看,只看把怎样的值以怎样的形式传给了谁。如图。请求还是发给了agencyaction.action,目的purpose参数还是getall查询。然后是一对关于分页查询、排序查询和条件查询的7个参数。之所以一下子传过去所有的参数,而不是说用户只进行了

47、排序那么传排序参数,只进行了分页那么传分页参数。之所以这么做,是因为第一,再一次的查询需要遵循用户上一次的喜好,比如用户查询了业务员是bob或者含有bob的记录,然后这时候又想按照代理商名字排序,然后又想勾选出所有状态为有效的信息,这样的操作不是一次查询请求完成的,而是用户根据这一次的返回结果来进行喜好的补充。所以,这一些历史的查询条件应该被记住,被记住的过程很简单,这里絮叨一下。第一次喜好传过去,存在了action的属性中,直到查询出数据回来还在这个界面,action就不会消亡,值栈中还是有那些喜好的,然后通过s:property标签遍历出这些喜好,赋值给javascript的变量,比如上图

48、中的name、username以及isvalid等。然后再次发送请求的时候,无论这些变量的值改变否,都能有效的把旧的但是不过时的喜好和用户新添加的喜好传给action进行下一次的查询请求。好了,该说第二点了。什么?你找不到“第一”那两个字了,嗯,就在上面,说了太多,仔细找找。那么第二点就是因为代码的复用性,之前的段落中通过好长一段的叙述,可以看到后台代码的简洁性和高度复用性,即使是默认查询也要把参数赋值为默认还要费劲的穿进去还要组装成1=1的hql的where子句,原因就在这里,为了高复用性和低耦合性。高复用性和理解,意思是谁都可以用,说的是共性,低耦合性是因为查询逻辑不与某一类特定的查询有关

49、,比如不与单独的分页查询有关不与默认的从主菜单迁移过去的默认查询有关,屏蔽了个性,求同存异。继续说上面的javascript代码,也就最后一句话没说了。调用windows.location.href=location让页面重新跳转到location指定的界面,这一句执行以后即向服务器发送了一个请求。优点已经从上面的叙述中说到了,弊端是所有的参数都在url后面,如果是密码什么的很不合适,再一个就是乱码问题,url中的中文乱码不能通过request的setcharacterencoding()来作用。这个在后面的异常叙述中也会进行很详细的描述。到这里,请求发送给了服务器,然后服务器重复与前面叙述了

50、的一样的逻辑进行查询,返回值,前台再以同样的方式进行遍历,就是这么简单,就是这么无聊。关于具体例子的叙述就到这里,结合了代理商管理进行了详细的叙述。当然,每个环节的实现都有更优秀的太多方法和方式。这里叙述的大概只是一天内能够想到的最笨的一种方法。5、技术总结。5.1、说明对系统逻辑结构设计的理解。关于逻辑结构的设计无非就是上述三层和已经叙述太多遍的mvc。但是还是要认真地再简单的说一遍这个逻辑结构这块的东西。结合第四部分最后叙述的例子和上图,表示层就是agencymaster.jsp和agencyaction这两个成员,业务层就是agencyservice,持久层就是agencydao和bas

51、edao。前台jsp发送请求给action,action作为控制器,调用service业务逻辑处理层进行业务处理和逻辑处理,然后service层再调用dao数据访问层进行数据库访问取得数据。返回给service,返回给action,然后action根据返回的结果转向不同的逻辑视图,从而转向不同的物理视图。物理视图比如一个jsp页面中可以通过ognl来访问action值栈的数据,来取出值来进行展示。5.2、个人所开发的模块涉及到的数据库表及对表中数据所进行的处理说明。上图展现了该项目中完成的11个子模块中所涉及到的四个表。其中m_agency的一个外键fk引用到m_user的主键pk,表示一个代

52、理商由一名特定的业务员来负责。虽然看上去只有这么一个关联,用户表和货币表似乎很独立。其实这四个表的联系最终是在订单表中可以观察到的,因为项目中没有做订单模块,没有建立表,不方便展现。引用项目模板中的文档中的er图可以更直观的表述。左侧是用户表、客户表、代理商表和货币表,中间一个订单表,四个外键引出分别指向了这四个表,使他们产生了联系。表示一个订单,对应一个客户对应一个业务员对应一个代理商对应一种货币。换句更通俗的话就是,代理商把货物卖给哪一个客户,使用哪一种货币进行结算,这个过程中有一个唯一的业务员负责。其它右边的三个表,分别是订单明细表、回款表和发票表,已经完成的项目模块中没有涉及到。5.3

53、、个人所开发的模块中主要有哪些处理过程会发生异常。(1)关于java编译环境版本的不统一问题:解决:properties-java build pathproperties-java compilerproperties-myeclipse-project facets(2)javascript中字符串类型的var,求它的字符串长度的方法是:即使用length属性,而绝对不能使用length()方法。这一点不同于java。否则会报错:(3)使用struts2的标签判断字符串的时候,如下使用导致页面中什么都没有输出,即本应该输出管理、财政、业务中的一个词,却什么也没有:原因:这样的字符串比较的写

54、法不被页面所正确解析。解决:交换其中双引号和单引号的位置,即双引号永远用来表示字符串常量,特殊需要的时候test可以使用单引号来引出。于是结果表现为:此外,s:property等标签中可以使用字符串处理函数,如图方式使用即可:以及(4)异常:表象:根源:原因:插入的数据的长度超过字段定义的最大长度值。比如,原本对m_currency表的name列定义是varchar(15),但是前台传过来的值是:8个汉字,至少varchar(16)才能存下,所以,报处理截断异常。解决:方案一:前台使用js来控制输入长度,把异常的苗头扼杀在前台的摇篮;优点:更加友好,减轻服务器负担;缺点:与数据库定义耦合太大,

55、表定义修改会引起前台js的修改。方案二:后台捕捉该异常,捕捉到后提示前台长度非法重新输入。优点:与数据库定义耦合减小,表定义随便改,只要长度非法,抛出异常捕获提示就是了;缺点:用户认为可以自由输入,却返回异常信息,友好度下降,增加服务器负担。折中方案:前台向后台先ajax询问长度,再使用js控制。5.4、svn工具的安装和使用。(1)必备的安装软件svn服务器:svn- 1.4.6-setup.exesvnservice.exe /配置svn服务自动运行svn客户端:tortoisesvn-2137-win32-svn-1.4.6.msilanguagepack-2137-win32-zh_cn.exe /svn客户端中文包(2)安装服务器运行svn-1.4.6-setup.exe,指定软件的安装路径,不断点击next就成功了。(3)安装客户端运行tortoisesvn-2137-win32-svn-1.4.6.msi,直接运行tortoisesvn安装文件,无须特殊设置,安装完毕后会提示你重启。客户端机器只需要安装tortoisesvn。服务器上安装客户端是为

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论