版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
.图4-1系统功能模块图系统功能模块图所示,整个系统主要包含商品购买、登录注册、个人中心、后台管理四个部分。对于商品的购买而言,所有的人都能够浏览系统中的所有的商品并选择自己想要购买的商品,对于商品的购买有两种方式,可以在选择商品的时候就进行购买,也可以将商品加入到自己的购物车中然后在购物车中付费购买商品,当然后面对于将商品加入购物车以及购买商品都是需要会员登录的。对于注册和登录而言,根据不同的系统角色,则有不同的注册和登录的方式。本系统中分为三类角色:系统管理员、品牌管理员、会员,其中系统管理员是系统置的用户,不能通过注册产生,品牌管理员通过注册产品,在品牌管理员注册的时候需要将自己的品牌信息一起注册,注册成功过后等待系统管理员的审核。品牌管理员登录系统成功过后则管理自己的基本信息和商品信息,包括:品牌信息、商品类型、商品信息、订单信息等。对于系统会员也是通过注册产生,注册时需要简单的用户名和密码以及地址,注册成功过后不需要等待管理员的审核便可以登录,登录成功过后能够对自己的个人中心进行管理,包括对自己的基本信息的管理、登录密码、支付密码的管理以及购物车和订单的管理。对于后台管理则需要要根据管理员的权限来确定,系统管理员主要是管理品牌管理员,品牌管理员主要是管理品牌下的商品类型、商品信息、订单等等。整个系统的架构采用4.2系统功能流程图图4-2系统功能流程图如图4-2系统功能结构图所示,本系统所有人都可进行浏览和查看商品信息,当需要将商品加入到购物车或者需要购买商品的时候则需要会员登录系统才行,在登录的时候会对用户的用户名和密码进行判断,登录成功过后才能将商品加入到购物车中和商品的购买,同时也可以进入到个人中心管理个人的各项信息。如果还没有会员账号则可以注册一个,通过成功过后即可登录系统。在商品的购买过程中会检测用户是否登录,用户没有登录则提示用户进行登录,如果用户已经登录则处理商品的数据,然后进行购买,在购买支付的过程中会检测用户的账户余额,如果余额不足就作出提示,反之则直接购买商品成功。管理员分为两类系统管理员和品牌管理员,系统管理员主要管理品牌管理员,审核管理员、删除等,系统管理员由系统置。品牌管理员有注册生成,注册成功则等待系统管理员的审核,注册失败则返回注册页面进行重新注册。品牌管理员通过审核过后就可以登录到系统后台。5系统详细设计与实现5.1公共模块设计与实现本节从以下几个方面进行介绍,详细的说明整个程序的架构和一些公共模块:5.1.1程序目录结构图5-1项目目录结构图如图5-1项目目录结构图所示,图中展示了该系统的代码以及各项资源。从src目录目录下能够很好的理解整个系统的核心架构,在系统架构中采用Dao、Service、Controller的处理方式,结合页面的View,便是典型的MVC模式。Dao和Service主要通过Hibernate处理数据持久层,Controller作为核心控制器,处理系统的业务逻辑。右边部分是项目Webroot目录结构,在该目录结构下存放的是页面以及页面的资源。5.1.2系统整体架构该系统采用的MVC的编程模式,MVC模式〔Model-View-Controller是软件工程中的一种软件架构模式[9],把软件系统分为三个基本部分:模型〔Model、视图〔View和控制器〔Controller。在本系统的架构中是以Html作为视图层,通过FreeMarker作为页面标签来处理和展示数据,同时在一定程度上使用Jquery的Ajax处理数据的交互并结合Jquery的DOM操作来实现页面效果。控制器则是采用的SpringMvc,通过SpringMvc作为核心控制器处理系统的所有的业务逻辑。模型层则是JavaBean,结合Dao与Service中的Hibernate来处理数据[8]。5.1.3baseDao介绍BaseDao是整个系统与数据库交互,处理数据的核心接口,在该接口中声明了许多的方法,通过BaseDaoImp来实现,以此作为整个系统的核心,在实现类中是通过Spring的HibernateTemplate来调用各种方法来处理数据的。HibernateTemplate是Spring对Hibernate的Session的进一步封装,使用HibernateTemplate非常简单。创建HibernateTemplate实例后,注入一个SessionFactory的引用,就可执行持久化操作。SessionFactory对象可通过构造参数传入,或通过设值方式传入。下面对该结构中的部分方法做一定的介绍。根据条件获取一条数据的方法,在basedao中声明了两个方法来实现该功能:publicTgetEntity<Stringproperty,Objectvalue>;publicTgetEntity<String[]properties,Object[]values>;在这两个方法中第一个是传入一个属性值和属性名称,根据这一个条件去查询相应的数据,只返回一条数据。第二个方法则是多条件查询,该方法两个参数都是数组,第一个数组是String类型,存放的是字段名数组。该方法的第二个参数是Object类型的数组,存放的是对应字段的值。在具体的方法实现过对数组的循环生成查询的hql语句。根据条件获取数据集合的方法,在BaseDao中同样声明了两个方法,两个方法如下:publicList<T>getList<Stringproperty,Objectvalue>;publicList<T>getList<String[]properties,Object[]values>;第一个方法需要两个参数,一个是字段名称另一个是字段名称对应的值,通过该值去查询相应的最近最后返回一个list集合。第二个方法同样是须需要两个参数,第一个参数是String类型的数组,存放的是字段名数组。该方法的第二个参数是Object类型的数组,存放的是对应字段的值。在具体的方法实现过对数组的循环生成查询的hql语句,最后方法返回一个list集合。分页查询方法publicPagerfindByPager<Pagerpager,Stringhql>;该方法实现了分页查询的,主要应用于前段页面需要显示列表的时候数据过大进行分页操作的,每次只查询当前页的数据。该方法需要两个参数,第一个是分页基类Pager,另外一个则是查询的hql语句。为了做到灵活多变以及实现各种条件的查询,这儿的查询语句用调用的方法提供,根据不同的业务逻辑程序设计者自己实现。为针对发展的查询条件同样的basedao中声明了两个方法来实现这样的功能,两个方法都只需要传入一个hql语句,通过具体的实现,两个方法分别返回一条数据和一个list数据集合。方法声明如下:publicList<T>getListBySql<Stringhql>;publicTgetEntityBySql<Stringhql>;验证是否存在方法publicBooleanisExists<Stringproperty,Objectvalue>;该方法声明要实现的功能是判断某个值是否存在。该方法需要两个参数,一个是字段名称,另一个则是字段对应的值,最后方法返回Boolean的true和false。5.1.4分页bean介绍绝大多数系统对于数据过大都会采用分页,在该系统中也采用了常规的分页,分页的各种数据是通过pager这个javabean来保存的。在Pager中有一下几个参数:privateIntegerpageNumber=1;//当前页码 privateIntegerpageSize=15;//每页记录数 privateIntegertotalPage=0;//总记录数 privateIntegerpageCount=0;//总页数 privateStringkeyWord;//查询关键字r privateList<?>list;//数据List如上代码所示,pageNumber记录的是当前页,pageSize记录的每一页显示的数据条数,totalPage记录的是总的数据条数,pageCount记录的是总的页数。这些数据都是分页所需要的基本数据。keyWord存放的是搜索关键字用于查询使用,对于这个关键字的设计是这样考虑和实现的,单条件查询keyWord中就存放单个值,多条件查询则将查询条件封装成json格式,由后台解析在组成hql语句,以此来实现多条件查询搜索。List属性是用来存放查询返回的数据的。5.2系统模块实现在本节中将对系统的具体的功能的设计和实现做详细的介绍,并对系统完成过后所取得的一些效果进行展示。5.2.1商品展示和购买模块本系统是以品牌为中心进行展示和管理的,系统置7大类型,在7大类型下面有着各种各样的品牌,在品牌才是各种商品的类型。这种逻辑关系很好的体现了系统作为一个平台的特点。图5-2首页图如图5-2首页图所示,整个导航条按照日用百货、服饰、电器/家电、数码、家具建材、汽车/配件、饰品这七大类来进行展示,在页面的右边则是这七大类下的品牌的导航,通过这儿能够跳转到某一个品牌的展示页去浏览和选购商品。在品牌的展示页首先是通过Ajax展示所有的商品,在品牌的展示页能够通过该品牌下的类型来筛选商品信息。对于首页显示的数据大部分来自于Jquery的Ajax请求,然后通过Jquery操作Dom生成而来,核心代码如下://查询日用百货的所有品牌trademarks=trademarkService.getList<"flag",flag>;if<trademarks!=null&&trademarks.size<>>0>{ //将信息存放到object中object.put<"title",title>;object.put<"trademarks",JSONArray.fromObject<trademarks>>;//将object放入到array中array.add<object>;}以上代码是查询某一主类型下的品牌信息,最后将主类型以及主类型下的品牌信息封装到一个JsonObject中,然后存放到JsonArray数组中。最后将7个主类型的品牌获取完,JsonArray中的数据就是前段显示所需的数据。//循环遍历data数据,生成品牌信息for<vari=0;i<data.length;i++>{//显示7个主类型html='<divclass="type"id="type_'+i+'"><divclass="mTitle">'+data[i].title+'</div></div>'; $<"#title">.append<html>; trademarks=data[i].trademarks; //显示主类型下的品牌信息列表 for<varj=0;j<trademarks.length;j++>{ trademark=trademarks[j]; html='<divclass="lTitle"name="lTitle"><ahref="showTrademark?id='+trademark.id+'&flag='+trademark.flag+'">'++'</a></div>'; $<"#type_"+i>.append<html>; }}以上代码是通过Ajax请求前面所介绍的方法,从那个方法中获取到数据,然后循环遍历出7个主要的类型,判断类型下面是否存在品牌,如果不存在品牌则不显示该类型,存在品牌则显示,并在该类型下面循环遍历出所有的品牌。选择自己要选购的商品点击商品进入单件商品的展示和购买页,页面如下:图5-3商品购买页如图5-3商品购买页所示,在这一页中用户可以清楚的查看到商品的信息,鼠标移动到左边的商品图片上面能够清晰的查看商品的每一个细节。对于大图的查看在此处使用的是easyzoom的插件,对于图片的生成意见插件的初始化是通过如下代码来完成的,代码如下://获取图片的路径 varimages=$<"input[name='images']">.val<>; if<images!=null>{ //解析图片的路径 images=eval<images>; images=eval<"<"+images+">">; //设置图片路径 $<"#a_zoom">.attr<"href",images.sourceImagePath.substr<3>>; $<"#a_img">.attr<"src",images.smallImagePath>; //初始化插件 $<'a.zoom'>.easyZoom<>;}在本页的中间部分则是商品的一些信息和销售价格等,同时提供了购买数量的操作和立即购买、加入购物车的操作,最右边则是推荐的同类商品。在这儿,用户可以直接购买商品也可以将商品加入到购物车。在这个两个操作之前都会检查用户是否已经登录,如果用户没有登录,页面将跳转到登录界面,登录成功过后将返回该页面,用户可继续操作。以上操作多数通过Javascript来实现的,核心代码如下://生成提示信息varhtml="您正在将"+number+"件,单价为"+price+"的"+name+"商品加入到购物车,是否确认加入?";//进行提示if<confirm<html>>{//确认加入购物才varurl="addCar";vardate="number="+number+"&goodsId="+goodsId;ajax<url,date,function<data>{//加入成功if<data.status==1>{alert<"加入购物车成功,你可以在个人中心查看并付费">;}else{alert<"加入购物车失败">;}}>;}当用户点击立即购买时,系统会根据商品信息以及用户设计的购买数量生成提示信息,提示用户是否购买。当用户确认购买过后需要用户输入部分信息,如下图所示:图5-4支付页如图5-4支付页所示,在进行最后支付下订单的时候需要用户补全信息和输入支付密码,其中的信息来自于会员的基本信息,此处可做修改,在订单中以字符串存放,与会员表没有实质性关系。在填写完信息过后系统通过Jquery的Ajax将数据提交给服务器。在服务器端首先通过如下代码:DigestUtils.md5Hex<payPassWord>.equals<member.getPayPassWord<>>floatprice=goodsInfo.getMemberPrice<>;price=price*number;if<price<=member.getCash<>>{}首先检测支付密码是否正确,在支付密码的检测过程中使用了DigestUtils的md5Hex方法对密码进行加密。当支付密码正确过后再检测余额是否足够完成此次交易,不足则返回页面并作出提示,足够的进行购买。这里采用的是一个模拟的支付方式,并不涉及真实的金钱交易。对于选择加入购物车操作的话,系统会将该商品按照用户选择的数量加入到自己的购物车中。5.2.2个人中心模块用户登录成功过后可以进入到个人中心,在个人中心用户可以对自己的一些基本信息、密码、购物车、订单等进行管理,如下图所示:图5-5个人中心图如图5-5个人中心图所示,在个人中心用户可以对个人信息、购物车信息、订单信息进行管理。在个人信息管理中可以修改个人信息、修改登录密码、修改支付密码;在购物车信息中用户能够查看自己的购物车中的商品,并且能够进行支付购买。订单信息管理中用户能够查看自己的购买记录,能够了解到购买的商品的发货状态,当收货过后需要在这里确认收货。5.2.3注册登录模块对于本系统而言,会员与品牌管理员都是通过注册产生的,会员、品牌管理员、系统管理员都拥有登录功能,登录成功过后根据不同的角色有不同的管理项。在会员注册的时候需要填入的有信息分别为用户名、密码、地址,密码是经过MD5加密保存到数据中的,并且用户名和地址都不能为空。品牌管理员的注册相对而言容会多一些,在账户的注册的过程中需要新添加品牌,管理员账号和品牌信息一起添加来完成的,如下图:图5-6品牌管理员注册图如图5-6品牌管理员注册图所示,在注册的时候需要填入基本的用户信息用户名和密码,同时还需要添加品牌的信息,包括品牌的名称、品牌类型、品牌图标等等。用户名、密码、品牌名称不能为空,这些约束条件是通过Javascript和Jquery验证的。对于品牌图标的上传,使用的是上传插件,上传插件中的部分事件配置如下://检测FLASH失败调用'onFallback':function<>{alert<"您未安装FLASH控件,无法上传图片!请安装FLASH控件后再试。">;},//上传到服务器,服务器返回相应信息到data里'onUploadSuccess':function<file,data,response>{$<"img">.attr<"src",data.substr<3>>;$<"input[name='icon']">.val<data>;},//把文件名传给后台'onUploadStart':function<file>{ $<"#uploadify">.uploadify<"settings",'formData',{'fileInputFileName':,}>;},对于系统的登录会员和管理员的操作基本相同,只有在登录成功过后对应的处理项不同。在这三种系统角色登录的时候都需要填写用户名、密码、验证码,并且在前端会对这些容采用Javascript和Jquery做简单的验证,保证填写的信息不为空。表单提交到后台,首先判断验证码是否正确,不正确则直接返回,验证码正确过后再查询数据库看数据是否存在,需要说明的是由于密码采用过MD5加密,所以在进行密码比对前也需要对输入的密码进行MD5加密。登录核心代码如下:if<check.equals<s_code>>{//验证码相等if<StringUtils.isNotEmpty<password>>{password=DigestUtils.md5Hex<password>;}//根据用户名和密码查询用户Adminadmin=adminService.getEntity<newString[]{"name","passWord","isEnabled"},newObject[]{name,password,1}>;if<admin!=null>{//用户存在session.setAttribute<"admin",admin>;return"admin/index";}else{//用户不存在model.addAttribute<"message","用户名或密码错误或者用户不可用">;return"admin/login";}}else{//验证码不等model.addAttribute<"message","验证码错误">;return"admin/login";}5.2.4系统管理员后台管理模块对于后台管理模块根据管理员不同的系统角色有着不同的功能模块系统管理员管理这一部分容,品牌管理员管理着一部分容,下面是系统管理员的管理容,如图所示:图5-7系统管理员管理容图如图5-7系统管理员管理容图所示,系统管理员总共拥有四个大的功能模块,分别是个人信息管理,管理员管理、品牌信息管理、商品信息管理。其中的个人信息管理包括头像的修改和密码维护,因为系统管理员账号是系统置的账号,所以系统管理员的账号是不提供修改的。对于头像的修改是采用Ajax的方式上传文件,最后改变现有头像Img标签中的Src路径来显示图片的显示。对于header部分的头像的修改是采用Javascript的如下代码来实现的,基本思想是通过Window对象获取父级的frame,window.parent.frames['topFrame'].document.getElementById<'header'>.src,通过上面的代码就能修改header里的头像了。对于密码的维护,需要输入原始密码和新密码,新密码需要输入两次,当原始密码输入正确的时候,才将新密码加密并更新到数据库。图5-8品牌管理员管理图如图5-8品牌管理员管理图所示为品牌管理员管理的功能模块,列表信息中清晰的展示了管理员的一些基本信息和管理员账号是否可用。在该模块中拥有两个功能,其一是管理员信息的修改,这儿并不能对平品牌管理员的信息进行修改,而是对品牌管理员的状态进行调整,基本上都是审核通过和回复账户的可用行。其二是删除品牌管理员,在本系统本分数据是采用假删除的思想来处理的,在这儿也是这样处理的。当执行删除操作的时候,实际上是对isEnable进行修改,然后更新数据,使用户不可用。核心代码如下://通过<#list>标签循环遍历显示数据<#listpager.listasadmin><tr><td>${<admin.id>!}</td><td>${<>!}</td><td><imgsrc="${<admin.header>!}"width="55px"height="25px"/></td><td>//判断是否审核<#if<admin.isEnabled==0>>未审核<#else>可用</#if></td>//显示操作的图标<td><ahref="adminGet?id=${<admin.id>!}"><imgsrc="../resources/images/pencil.png"alt="Edit"></a><ahref="adminDelete?id=${<admin.id>!}"onclick="returnconfirm<'确认要删除?'>"><imgsrc="../resources/images/cross.png"alt="Delete"></a></td></tr></#list>图5-9品牌信息管理图如图5-9品牌信息管理图所示,对于品牌的管理同样只有修改和删除功能,系统管理员对于品牌的管理其实也不是必须,由于品牌是作为整个系统的管理管理,所以在系统的管理项中也添加了对品牌的管理,但是并不提供对品牌的添加功能。图5-10商品信息管理图如图5-10商品信息管理图所示,商品信息管理分为商品信息管理和下架商品信息管理,在此处同样只提供了修改和删除两个功能,删除同样是通过isEnable来实现的假删除。下架商品的管理则是isEnable为0的商品,这项功能只是一个展示功能,让管理员了解到哪些商品已经下架。5.2.5品牌管理员管理容模块对于品牌管理员而言则是管理自己品牌下的所有的商品以及一些其它的信息,在这一节中将详细的介绍这些容,对于系统管理员模块中已经有介绍的模块则做简单介绍。图5-11品牌管理员管理图如图5-11品牌管理员管理图所示,品牌管理员拥有着四个管理模块,分别是个人信息管理、类型信息管理、商品信息管理、订单信息管理。对于个人信息管理模块中是个人头像的修改和密码的维护,这两个功能模块与系统管理员的相同,在系统管理员管理中已经详细的做过介绍。图5-12商品类型管理图如图5-12商品类型管理图所示,商品类型管理采用的是树形结构来展示的,这也很好的体现了商品类型无限分类的表结构。该树形结构的根节点是品牌名称,所有的商品类型都是该品牌的子类型。在树形结构上点击右键能够显示出右键菜单,该菜单中包含添加节点、修改节点、删除节点三个功能选项,点击添加节点就会弹出右边点的添加界面来实现节点的添加。树的初始化代码如下:loadTree:function<>{//加载树<> //通过Ajax获取数据 $.ajax<{ url:"goodsType", type:"POST", dataType:"json", cache:false, success:function<data>{//数据获取成功、初始化树形结构 tree.zTree=$<"#tree">.zTree<tree.setting,data>; } }>;},对于商品的管理,品牌管理员拥有添加商品信息、修改商品信息、删除商品信息、管理下架商品信息等功能,在系统管理员管理容中已经做过介绍,在此处就不在详细介绍。图5-13订单信息管理图如图5-13订单信息管理图所示,订单信息管理中能够很清楚的了解到每一次订单的商品名称、购买单价、购买数量、消费总金额和状态。当还未发货时能够通过列表中的操作来模拟发货的功能。6重难点分析及解决方案6.1HibernateTemplate的应用HibernateTemplate是包下的一个类,是Spring对JDBC更加深层次的封装,极大的方便了通过Hibernate对数据库的操作[10]。本系统中对HibernateTemplate的使用都是封装在BaseDaoImp中的,该类继承自HibernateDaoSupport[11],HibernateDaoSupport需要注入一个SessionFactory,在BaseDaoImp中我通过setSuperSessionFactory<SessionFactorysessionFactory>方法将SessionFactory注入到该类中。HibernateDaoSupport类中有一个getHibernateTemplate的方法,通过该方法能够获取到HibernateTemplate,获取到HibernateTemplate过后,则通过它来操作数据库,下面对BaseDaoImp中用到的几个方法做简单的介绍。HibernateTemplate对于简单的Save、Update、Delete这些方法,同样是传入一个实体对象,就能够完成相应的操作,另外一个方法是Find方法,这个方法需要一个HQL格式的查询语句,并且这个方法直接返回一个List数据集合,这样就可以通过HibernateTemplate完成简单的增删查改功能了。在BaseDaoImp这个类中使用最多的方法是FindByNamedParam方法,并且这个方法有多种的重载形式,在本系统中主要是了了两种,在本系统使用的这两种都需要三个参数并且都是返回一个List集合,第一种是org.springframework.orm.hibernate3.HibernateTemplate.findByNamedParam<StringqueryString,String[]paramNames,Object[]values>throwsDataAccessException有如上代码可以看出该方法需要的第一个参数是一个查询语句,该查询语句类似于Hibernate的HQL语句[12],只是在查询语句中使用的是paramName=:paramName这种格式,第二个参数是一个String类型的数组,该数字存放的是字段名称的集合,第三个参数为一个Object的数组,存放的是每一个字段所对应的Value值,按照相应的规定传入三个参数,HibernateTemplate部会自动的封装好相应的查询语句,最后通过查询得到一个List的数据集合,并且返回给该方法的调用者。需要说明的是这个方法会抛出一个DataAccessException异常,DataAccessException是RuntimeException,是一个无须检测的异常,不要求代码去处理这类异常,遵循了Spring的一般理念:异常检测会使代码到处是不相关的catch或throws语句,使代码杂乱无章;并且NestedRuntimeException的子类,是可以通过NestedRuntimeException的getCause〔方法获得导致该异常的另一个异常。在BaseDaoImp中还是用了FindByNamedParam方法的另一个重载方法,这个方法同样需要三个参数并且返回一个List数据集合,同样会抛出DataAccessException异常,org.springframework.orm.hibernate3.HibernateTemplate.findByNamedParam<StringqueryString,StringparamName,Objectvalue>throwsDataAccessException在这个方法的三个参数与前面的那个方法的参数有一定的相似,第一个参数同样是一个查询语句,语句中需要查询的字段同样按照paramName=:paramName的方式进行设置,第二个参数则是字段的名称,第三个参数则是一个Object类型的Value值。最后按照正确的查询语句和对应的值,就可以获取到相应的数据集合。在BaseDaoImp中有一个是分页查询的方法,在该方法中使用了HibernateTemplate的executeFind方法,该方法需要HibernateCallback<?>action作为参数,最后返回一个List数据集合,HibernateCallback是一个回调函数,在这个回调函数中对于分页查询的具体实现如下:newHibernateCallback<>{publicObjectdoInHibernate<Sessionsession>throwsHibernateException,SQLException{Queryquery=session.createQuery<hql>;query.setFirstResult<first>;query.setMaxResults<max>;List<T>list=query.list<>;returnlist;}}如上代码所示,在executeFind中创建了一个HibernateCallback的实例对象,在该对象中中有一个doInHibernate的方法,该方法会把Hibernate的Session传入其中,通过session.createQuery<hql>获取到Hibernate的Query对象,通过设置query.setFirstResult<first>;query.setMaxResults<max>;来实现分页查询,最后通过List<T>list=query.list<>;获取到List数据集合并将数据集合返回,至此通过HibernateTemplate很好的实现了分页查询。6.2Freemarker的应用FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出。在本系统中还是较多的使用了FreeMarker的各种标签[13],下面对在项目中使用FreeMarker以及系统中所涉及到的标签做简单的介绍:要使用FreeMarker需要将其整合到系统的架构中,本系统的核心架构为SpringMvc,在SpringMvc的配置过如下配置来将FreeMarker整合到系统中的,代码如下:<beanid="freemarkerConfiguration"class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <propertyname="location"value="classpath:perties"/></bean>该段配置代码是在SpringMvc的dispatcher-servlet.xml配置文件中配置的,这段配置主要是去加载FreeMarker的配置文件perties,在这文件中对Freemarker的字符集等进行了设置。<beanid="freemarkerConfig"class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <propertyname="freemarkerSettings"ref="freemarkerConfiguration"/> <propertyname="templateLoaderPath"value="/html/"/></bean>这段配置是对FreeMarker的模板的路径进行配的,通过这儿的配置可以看出所有的模板都是存放在html目录下的,简而言之就是SpringMvc在返回视图的时候,会在html目录下寻找相应的模板也就是页面。<beanid="viewResolver"class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> <propertyname="cache"value="true"/> <propertyname="suffix"value=".html"/> <propertyname="viewClass"value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/> <propertyname="exposeSpringMacroHelpers"value="true"/> <propertyname="exposeRequestAttributes"value="true"/> <propertyname="exposeSessionAttributes"value="true"/> <propertyname="requestContextAttribute"value="rc"/> <propertyname="contentType"value="text/html;charset=UTF-8"/> </bean>以上代码是对FreeMarker解析器的配置,由以上配置代码可知解析器设定为后缀名为.html的文件即Html文件,同时还设置了编码集等。通过这三个配置就成功的将FreeMarker整合到系统中了。在整个系统中使用了几种简单的标签来获取和处理并显示数据,最常用的则是${},通过${}可以直接获取到SpringMvc中的model中的数据,为避免因为数据为空而导致错误,可以使用${<value>!},此种格式的作用是当value不为空的时候显示value值,当value为空时显示"!"后面的容这样就不会因为数据为空而产生错误。在系统中使用较多的标签还有<#if></#if>标签,该标签是用来作为判断使用的,可以在该标签中使用各种判断条件,比如:<#if<totalPage>0>>这句代码的意思是判断totalPage是否大于0,<#iftotalPage??>这句代码的意思是判断totalPage是否存在。另外使用较为常见的还有<#list></#list>标签,该标签使用来处理List数据集合的,比如:<#listlistasgoodsInfo>这段代码的作用是循环遍历list集合,每次循环对应的数据取别名为goodsInfo,然后通过goodsInfo就可以获取到相应的数据。6.3树形结构插件JqueryZtree对于商品类型这种无限分类的表结构的处理,在本系统中采用的是树形结构来展示,对于树形结构系统采用了Ztree。Ztree是Jquery的一个插件[14],这个插件目前发展很好得到了很好的发展,实现起来整体效果也非常的不错。对于Ztree的使用首先需要陪着好树形结构的参数也就是对象中的setting,然后通过Jquery的Ajax从后台获取数据,最后通过$<"#tree">.zTree<tree.setting,data>;初始化树形结构,这样基本的结构就建立起来了。在Ztree中有几个必计较重要的配置参数,下面做简单的介绍。Ztree中的setting配置是整个的核心配置,对于树形结构是否展开、以何种形式展示都可以在这个setting中配置。根据系统的功能需求,这儿需要特别介绍一点,在setting中有一个callback,callback是一个回调函数,在该回调函数当中有一个rightClick,这是一个右键单击事件,在该事件中显示了右键菜单。在右键菜单中有三个功能按钮,分别为:新增类型、修改类型、删除类型,在显示右键菜单前会根据的值来做判断,当该值如果等于0则表示是根节点,该节点表示的是品牌信息,不能进行删除和修改该,所以通过如下代码tree.showItem<["#r_addNode"]>;来完成树形结构的创建的。在Ztree中的配置中较为重要的还有init,这是Ztree的初始化事件,在该事件中对Ztree的右键菜单的三个功能做了事件绑定。对于右键菜单的显示和隐藏是通过Ztree的showRightMenu事件来处理的。在该事件中会做条件判断,当的值大于0事则表示商品类型信息,商品信息类型便能够有添加、修改和删除的功能,在程序过以下代码来显示三个功能按钮代码如下:tree.showItem<["#r_addNode","#r_updateNode","#r_deleteNode"]>。对于右键菜单的隐藏是通过hideItem来配置的,在该配置中设置了右键菜单的隐藏。下面对节点的添加、修改、删除的实现做简单介绍:addNode中实现的是节点的添加,首先是调用showNode<>方法,在该方法中创建一个弹出层用于设置类型的名称,然后通过Ajax将父节点的ID和类型名称提交给后台,后台将类型保存。当Ajax请求成功过后将弹出层的数据清空并隐藏弹出层,然后就在树形结构中添加一个节点,节点的添加是通过如下代码来实现的tree.zTree.addNodes<tree.pNode,[{//添加节点id:goodsType.id,pId:tree.pNode.id,name:nodeName,isParent:false}]>;。Ztree有一个addNodes的方法,在此处向该方法中传入了两个参数一个是父级节点,在此处通过tree.pNode来获取的,另外一个参数是options配置信息,在这儿主要设置了ID、PID、NodeName、IsParent这几个参数,这样就完成了新的商品信息类型和节点的添加。showNode中实现的是节点的更新,在该方法中同样首先调用的是showNode<>方法,并且向该方法中传入了节点的名称,在弹出层中用于显示和修改,节点的名称是通过Ztree的获取得到的。在弹出成中修改好以后点击确定,将新的类型名称和类型的ID通过Jquery的Ajax传入到后台进行数据更新,数据更新成功过后清除弹出层中的数据并将弹出层隐藏,最后更新树形结构。对于树形结构的修改,首先对name的修改是通过tree.pN=newName实现的,要更新页面还需要调用Ztree的updateNode方法,如下代码:tree.zTree.updateNode<tree.pNode,true>,在该方法中需要两个参数,一个是当前的节点,第二个是一个Boolean类型的值,这儿传入true,表示立即更新,这样就实现了一个商品类型的更新从页面的更新到数据库的更新。deleteNode中实现的是节点的删除,在该方法中首先通过判断该节点是否为父节点,然后通过window.confirm作出不同的提示信息,提示管理员是否进行删除。当为True时删除该节点包括以下的节点,反正则删除该节点,对于数据库中的数据是通过Jquery的Ajax来实现删除的。最后调用tree.zTree.removeNode<tree.pNode>中的removeNode方法并将当前节点传入其中进行节点的删除,最后调用tree.zTree.refresh<>,来刷新Ztree的树形结构,自此节点删除完成。6.4文件上传插件UploadflyUploadify是JQuery的一个上传插件,实现的效果非常不错,带进度显示,并且支持大文件的上传,在本系统中该插件主要用于商品图片、各种图标的上传。下面从该插件的使用、配置等几方面做详细的介绍:首先要使用该插件的话需要引入相关的Javascript和Css文件,需要引入的Javascript文件有swfobject.js、、jQuery.js,Css文件有uploadify.css,然后是对该插件进行配置,配置文件需要在$<"#uploadify">.uploadify<{}>中进行设置,下面对较为重要的几个配置项进行介绍。配置项Auto是配置文件选择后是否自动上传,如果设置为True,则表示立即上传,设置为False,表示不自动上传。Multi使用与配置该插件是否支持多文件上传,设置为True表示支持多文件上传,设置为False表示单文件上传。Swf为插件加载的Flash插件,在文件上传的过程中需要使用到。queueID为该插件上传文件时请求的路径。fileTypeExts设置的是允许上传的文件的类型,在此处为上传的文件为图片,所以设置的文件类型为:'*.jpg;*.gif;*.jpeg;*.png;*.bmp;'。在该插件的配置项中配置着许多的触发事件。onUploadStart事件表示的是在文件开始上传的时候触发,在该事件过如下的代码:$<"#uploadify">.uploadify<"settings",'formData',{'fileInputFileName':,}>将文件的名称提交给后台,其中文件名称是通过来获取的。onUploadSuccess事件是在文件上传成功的时候触发,在该事件中可以进行一些操作,在本系统中主要是对图片的处理,通过如下代码修改Img的Src$<"img">.attr<"src",data>。至此已经对该插件做了大体的介绍,对于简单的事件和配置项便不再做介绍。6.5Ajax分页在本系统中有两种分页的方式一种是后台管理中的信息列表中的分页,这也是常规的分页,是通过查询结合Pager这个JavaBean来实现的,在此处不做详细介绍。另外一种分页方式则是通过Jquery的Ajax实现的分页,这是在商品展示中采用的分页,这种方式的好处是能够异步加载数据,页面实现局部刷新。下面对Jquery的Ajax的分页做详细的介绍:要使用Jquery的Ajax分页需要引入一个Javascript插件,并且设置相应的CSS样式还需要在页面中设置<divid="pageNav"></div>这样的DIV,这也是分页界面的显示DIV。对于该插件的初始化是调用pageNav.go<>方法,该方法需要两个参数,第一个参数需要的是当前页码,第二个参数是总的页数。在点击下一页、上一页的时候会去调用pageNav.go<>方法,并且将点击的页面传入到这个方法中,对于分页过后还有相应操作的则需要去重写pageNav.go<>方法,在本系统中对于该方法的重写主要体现在Jquery对DOM的操作上。在该方法的重写中代码较多,不便于粘贴出来,该方法中的答题流程是首先通过Ajax请求数据,然后将数据解析通过Jquery操作将数据展示到页面上。在分页查询的服务器端的处理也是非常的简单的,想通过查询条件生成相应的查询语句,让后通过如下代码实现分页查询,代码如下:Queryquery=session.createQuery<hql>;query.setFirstResult<<pageNumber-1>*20>;query.setMaxResults<20>;如上代码,通过HibernateSession的createQuery[15]方法获取到Hibernate的Query对象,该对象有两个方法是用于处理分页的,一个是setFirstResult,需要传入一个Int类型的参数,表示查询的起始页,另外一个方法是setMaxResults,也需要一个Int类型的参数,该方法表示的是最大的返回结构数,也就是每页的查询数量。最后通过Query对象获取到数据集合返回给页面,这样就实现了分页的查询。7系统测试7.1功能测试对于功能测试本系统主要体现在测试用例的编写上,采用的是JUnit4进行测试的。在本系统中首先建立了一个BaseTestCase的基类,基类代码如下:RunWith<SpringJUnit4ClassRunner.class>ContextConfiguration<locations={"classpath:beans.xml"}>publicclassBaseTestCase{}如上代码所示,首先通过RunWith设置测试由SpringJUnit4ClassRunner进行操作管理,SpringJUnit4ClassRunner是对JUnit4的进一步封装。然后通过ContextConfiguration注解设置locations为classpath:beans.xml,这句注解的意思是加载Spring的配置文件,这样测试的基类就建立好了。 对于其它的测试用例都是继承成BaseTestCase这一个基类,在测试用例上同样需要添加RunWith<SpringJUnit4ClassRunner.class>注解。下面用一个测试方法来讲解测试的过程,该方法如下:Test publicvoidgetAll<>{ List<Member>members=memberService.getAll<>; for<Membermember:members>{ member.setPassword<DigestUtils.md5Hex<"123456">>; memberService.update<member>;}如上代码所示,需要在方法上添加Test注解就行了,然后在整个方法体中做测试的操作,对于该测试方法可以通过RunTest进行测试,Junit进行会根据测试的情况给出测试结果。7.2性能测试通过简单的测试可知系统的性能良好,各个页面间的跳转反应迅速,对于数据的存取和解析效率也非常的搞,同时Jquery的Ajax获取数据效果也不错,整体页面流程,数据交换号。8系统部署本系统的开发是采用的MyEclipse发开工具,服务器采用的是Tomcat,这两种工具在Windows下面都十分的容易操作。在程序的开发的过程中需要在本地建立Tomcat服务器,然后通过Myeclipse建立起与Tomcat之间的联系,在Myeclipse中可以通过RunOnService将项目发布到Tomcat中并启动Tom
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025河南郑州陇海马路社区卫生服务中心招聘考试笔试模拟试题及答案解析
- 2025年德州临邑县人民医院公开招聘备案制工作人员(15名)笔试考试备考题库及答案解析
- 制冷空调设备装配工岗前改进考核试卷含答案
- 2025四川成都市青羊区新华少城社区卫生服务中心招聘3人笔试考试参考题库及答案解析
- 飞机无线电雷达系统装调工岗前技术落地考核试卷含答案
- 弹簧工岗前设备性能考核试卷含答案
- 2025鞋类研发设计师行业市场现状供需分析及投资评估规划分析研究报告
- 炼焦工安全理论能力考核试卷含答案
- 2025鞋服行业智能制造工厂改造实施步骤及品牌竞争力提升研究报告
- 2025鞋业品牌国际化发展路径研究及文化融合营销与线下门店数字化转型研究报告
- 上海财经大学2026年辅导员及其他非教学科研岗位人员招聘备考题库带答案详解
- 2026湖北恩施州建始县教育局所属事业单位专项招聘高中教师28人备考笔试试题及答案解析
- 心肺康复课件
- 骶部炎性窦道的护理
- 2025人民法院出版社社会招聘8人(公共基础知识)测试题附答案解析
- 多元催化体系下羊毛脂转酯化制备胆固醇的工艺解析与效能探究
- 上海市奉贤区2026届高三一模英语试题
- 设施设备综合安全管理制度以及安全设施、设备维护、保养和检修、维修制
- 2025届高考全国二卷第5题说题课件
- 2026福建春季高考语文总复习:名篇名句默写(知识梳理+考点)原卷版
- QSY08002.3-2021健康安全与环境管理体系第3部分审核指南
评论
0/150
提交评论