版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
汽车租赁管理系统的设计与实现摘要现代化的汽车租赁管理是集信息展示,金额交易与租车订单和车辆管理等多内容与管理一体化的经营业务REF_Ref8962\r\h[6]。面对日益热化的租赁市场,传统的人工租赁管理在处理各种业务信息时极为不方便,容易出现错误,服务质量低劣。为了提高租赁公司的运作效率,避免租车人员排队等候REF_Ref9034\r\h[7]。通过实现汽车租赁减缓私家车使用量,从而减少交通流量,缓解因汽车尾气污染大气带来的环境破坏REF_Ref9060\r\h[8]。本文主要论述了汽车租赁管理系统的设计与实施。该系统涉及三个主要角色:游客、会员和管理者,不同的角色可以执行不同的操作。管理员可拥有系统的特殊权限,其中包括发布租赁车辆信息、对租赁车辆进行管理(更新,删除)、对会员信息列表进行批量导入导出等操作,超级管理员还有对普通管理员进行菜单授权操作,不同的管理员登录后台显示的菜单栏有所差异。本系统采用J2EE作为系统开发技术平台REF_Ref3654\r\h[1],eclipse作为开发工具,TOMCAT作为容器,通过spring+springMVC+mybatis以及mySql数据库、B/S架构模式REF_Ref3706\r\h[2]来实现汽车租赁管理的各功能,并且在开发之前运用MVC设计模式搭建JAVA的运行环境和TOMCAT服务器。前端使用的技术是HTML+CSS+JavaScript+JSP,后端开发使用SSM框架REF_Ref10524\r\h[3]技术结合MySQL数据库。关键词:SSM框架;B/S;汽车租赁;管理系统目录1绪论 绪论1.1系统开发概述随着生活方式的改变和互联网的兴起,越来越多的人选择以“共享”的方式使用汽车。消费观念的改变使得人们对汽车有了新的认识,是作为一种满足日常生活需求的交通工具,为满足此需求,汽车租赁业务规模将越来越大。工业的快速发展和旅游业的升温更是在一定程度上刺激了租车服务行业的加快发展。企业传统的管理方式已无法适应当前的市场,新型的汽车租赁管理系统应将业务的各类数据联系起来,在各个职能部门中方便快速的传递处理,协调和控制整体业务,并且保证信息的准确性、安全性。1.2开发方案1.2.1SSM框架SSM是由Spring和MyBatis两个开源框架整合而成。Spring框架主要起到容器的功能,整合了SpringMVC和Mybatis,是实现层与层之间的解耦,同时使业务逻辑更加清晰REF_Ref12098\r\h[4]。Spring就像是整个项目中装配bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象。也可以称之为项目中的粘合剂。Spring的核心思想是IOC(控制反转),即不再需要程序员去显式地new一个对象,而是将创建对象的权利交给容器来管理,用的时候再从容器从获取。SpringMVC是一个基于MVC的框架,其主要负责表现层的功能,比如响应请求REF_Ref12098\r\h[4]。SpringMVC在项目中拦截用户请求,其核心Servlet即调DispatcherServlet承担调解或前台责任,通过处理器映射将用户请求匹配到控制器,控制器就是对请求的具体响应。Mybatis框架主要负责的是数据持久层,完成和数据库的相关操作REF_Ref12098\r\h[4]。mybatis是jdbc的封装,使数据库的基本操作透明化。Mybatis的操作都围绕着一个sqlSessionFactory实例。Mybatis通过配置文件与每个实体类的映射文件关联,该配置文件配置每个类所需的数据库sql语句映射。每次与数据库交互,通过sqlSessionFactory拿到一个sqlSession,再执行sql命令。页面将请求发送到控制器,控制器调用业务层处理逻辑,逻辑层将请求发送到持久层,持久层与数据库交互,然后将结果返回到业务层,业务层将处理逻辑发送到控制器,控制器然后调用视图显示数据,使程序具有良好的可维护性,并减少程序之间的耦合。1.2.2MVC模式MVC,分别代表模型、视图、控制器REF_Ref16288\r\h[5]。它是一种将业务逻辑、数据和界面显示分离的方法,将代码组织起来,将众多的业务逻辑集中到一个部分,在需要改进和个性化界面和用户互动的同时,不需要重写业务逻辑,减少编码时间,提高代码的再利用。其中用户在视图层的操作会传入控制层,由控制层调用模型层的方法实现数据的持久化存储。模型层:它封装数据和数据的操作,并且是实际处理数据的位置(模型层与数据库交互)。视图层:它负责将应用显示给用户和显示模型的状态。控制器:控制器负责视图和模型之间的交互,控制响应、响应和流向用户输入,主要负责两个操作,一是将用户请求分发给相应的模型,二是及时反映模型对视图的变化。1.2.3MySQLMySQL数据库是最流行的关系型数据库管理系统,它不是将所有数据放在一个大仓库内,而是将数据保存在不同的表中,增加了速度并提高了灵活性。它使用的核心是完全多线程,支持多处理器。它通过一个高度优化的类库实现SQL函数库并像他们能达到的一样快速,通常在查询初始化后没有任何内存分配。没有内存漏洞。MySQL也全面支持SQL的分组和排序自子句,支持聚合函数。可以在同一查询中混合来自不同数据库的表。1.3可行性技术1.3.1技术的可行性从硬件、软件的性能要求考虑,本人已安装好开发所需的软件Navicat、eclipse、MySQL并能够熟练使用这些软件。从技术能力上,本人对SSM框架、HTML、CSS、JSP、MYSQL等技术具有一定的专业知识,能顺利完成系统开发与设计。1.3.2经济可行性系统投入运行后可以提供许多以前无法及时提供的信息,例如:车辆的基本信息、租结算、租还时间等。在用户查询和使用信息上,不仅大大提高了使用的方便性,也提高了查询的速度,可以帮助管理人员系统地管理汽车租赁的相关信息。从时间和效率上看,系统的投入运行,可以为汽车租货公司安排信息管理节省大量的财力、物力,具有较大的经济效益。1.3.2运行可行性系统运行后,提高了管理员的工作能力和效率,也方便了用户对信息的理解和查询。同时系统的业务逻辑很清晰,功能实现的很明确,界面简单,操作方便,不会为管理员和用户在操作上造成困难。
2需求分析2.1系统功能模块图2.2系统功能描述本系统通过研究当前汽车租赁系统的管理现状、存在问题以及现实需求,主要实现对租赁车辆信息、客户信息以及租赁订单的管理,主要包括租赁订单、车辆的租赁状态、车辆的基本信息、客户信息管理等。由于在实际过程中的关系比较杂乱,使得管理工作变得庞大复杂,现在还有很多租赁公司还采用人工管理的方式,可能会导致了人为错误的产生,使得效率低下。汽车租赁管理系统的开发使得这一状况在一定程度上得到了很大的改善,使得汽车租赁服务快速、规范地完成,节省了人力物力资源,提高了服务质量和用户体验。2.2.1游客模块注册模块:游客填写注册会员信息,包括真实名字、用户名密码,注册成为会员。登录模块:查看全部租赁汽车信息,亦可分类查询汽车信息,商务租车、婚礼租车、旅游租车。2.2.2会员模块登录模块:会员填写登录信息,包括用户名、密码和验证码,登录汽车首页。查询模块:查看全部租赁汽车信息,亦可分类查询汽车信息,商务租车、婚礼租车、旅游租车,查看个人信息,查看个人租车订单情况。租赁模块:包括租车、还车。选择租赁车辆,填写预订日期以及还车日期,通过管理员审批预约单成功后方能租车。还车时,租金计算。留言模块:用匿名的身份进行留言、投诉。2.2.3管理员模块用户管理模块:对会员进行添加、删除、修改和批量导入导出等操作。点击“添加”按钮,将会弹出一个对话框,填写会员名字、性别、职业、身份证、住址、邮箱等相应信息并对数据进行校验,校验通过才能对用户进行添加操作。选择指定会员信息或者批量选择会员信息并单击"删除"按钮,会员信息将从数据库中删除。选择指定会员信息,然后单击"修改"按钮,跳转到界面修改指定会员信息。车辆管理模块:管理员添加、删除、修改车辆信息,点击"添加"按钮,将弹出一个界面添加车辆信息,添加车辆名称、车牌、品牌、颜色、租金等信息。选择指定车辆信息并单击"删除"按钮,车辆信息将从数据库中删除。选择指定车辆信息,然后单击"修改"按钮,跳转到界面修改指定车辆信息,并进行数据回显。订单管理模块:管理员添加新订单,修改或删除订单,对订单进行结算操作。角色管理模块:管理员添加和删除角色信息,并对角色进行菜单的授权操作。点击"添加"按钮,将弹出一个界面添加角色信息,添加角色名称信息。选择指定角色信息并单击"删除"按钮,角色信息将从数据库中删除。选择指定角色,对该角色进行菜单授权操作,修改数据库中相关联的表的信息。统计管理模块:按照月租量生成柱状图,其中报表内容包括车辆的名字和月租量。3数据库表的设计表3.1订单表表名:book列名数据类型说明空/非空约束条件idint非空主键bookNumVarchar(11)订单编号非空UniquecarIdInt(255)车牌号码空NormaluserIdint(11)用户编号空userNamevarchar(255)用户名空payTypevarchar(255)支付方式空payint(10)付款金额空statustinyint(255)状态空remarkvarchar(255)备注信息空createTimedatetime租车时间空endTimedatetime还车时间空表3.2品牌表表名:brand列名数据类型说明空/非空约束条件idint(11)品牌编号非空主键nameVarchar(11)品牌名称非空Normal表3.3汽车表表名:car列名数据类型说明空/非空约束条件idint(40)车辆编号非空主键namevarchar(255)车辆名称空Uniquecphvarchar(40)车牌号码空Normalysvarchar(40)颜色空lcvarchar(40)里程数空jgint(10)租借价格空yqjgint(10)逾期价格空zttinyint(40)状态空tpvarchar(255)车辆图片空brandIdint(11)品牌编号空表3.4顾客表表名:customer列名数据类型说明空/非空约束条件idint(11)顾客编号非空主键nameVarchar40)顾客名称非空loginNamevarchar(40)车牌号码非空passwordvarchar(40)颜色非空sexvarchar(40)里程数非空idCardvarchar(40)租借价格空addressvarchar(40)逾期价格空phonevarchar(40)状态空lastLoginTimeDate车辆图片空tpvarchar(255)品牌编号空表3.5评论表表名:message列名数据类型说明空/非空约束条件idint(11)评论编号非空主键useridint(11)顾客编号空contentvarchar(255)评论内容非空表3.6预约表表名:reservation列名数据类型说明空/非空约束条件idint(11)预约编号非空主键customerIdint(11)顾客编号非空外键brandIdint(10)品牌编号空startTimedate开始时间非空endTimeDate结束时间非空statusvarchar(50)状态非空表3.7管理员表表名:admin列名数据类型说明空/非空约束条件idint(11)管理员编号非空主键namevarchar(40)管理员名称非空外键loginNamevarchar(40)登录名非空passwordvarchar(40)密码非空lastLoginTimeDate最后登录时间空表3.8菜单栏表表名:Menu列名数据类型说明空/非空约束条件idint(11)菜单编号非空主键namevarchar(40)菜单名称非空Uniqueiconvarchar(40)图标空Normalurlvarchar(100)路径空leaftinyint子菜单非空accessTokenvarchar(100)空parentIdint(11)父节点空表3.9角色表表名:Role列名数据类型说明空/非空约束条件idint(11)角色ID非空主键namevarchar(40)角色名称非空Unique表3.10角色与管理员对应表表名:middle_role_admin列名数据类型说明空/非空约束条件roleIdint(11)角色ID非空主键adminIdint(11)管理员ID非空主键表3.10角色与菜单对应表表名:middle_role_menu列名数据类型说明空/非空约束条件roleIdint(11)角色ID非空主键MenuIdint(11)菜单ID非空主键4详细设计与实现4.1管理员登录数据校验数据校验界面如图4.1所示:图4.1管理员登录界面Fig.4.1Thepageofadminlogin实现原理:首先需要将文本框中的数据获取到,然后设置相应的用户名和密码的校验规则,这里使用的是正则表达式,判断文本框中的内容是否为空以及符合正确的规则,如果输入框内容为空或者不符合校验规则,会出现红色提示消息,否则出现√。登录验证码的实现首先自定义LoginInterceptor类实现HandlerInterceptor接口,实现preHandle()方法对所有访问地址进行过滤,如果管理员未登录直接访问除了登录界面之外的地址,将对该操作进行是否已登录判断,如果未登录,则跳转回登录界面,反之可以访问到相应的地址。登录操作是前端利用jquery时间监听函数,当html结构渲染完毕会触发该函数结合Ajax技术向后台服务器发送请求,后台由一个使用注解方式进行注册的CodeServlet类来处理该请求,生成四位数的验证码保存在session域中并通过画笔在画板上图画生成图片显示在登录界面上。当超级管理员在界面上输入正确的账号、密码和验证码,输入完成后点击“登录”按钮,前端利用Ajax和Json技术向后台服务器发送请求。后台根据URL找到控制层HomeController的login()函数,然后调用UserServiceImpl接口实现类的login()函数执行查询操作,并获取界面输入的验证码和session域中存的对验证码进行校验处理,如果验证码校验成功并在数据库中存在该用户则跳转到后台首页,反之页面不进行跳转,并提示“账号或密码错误”或“验证码错误”。核心代码如下所示:前端校验://用户名异步验证
$("input[name='loginName']").blur(function(){
//alert("失去焦点!");
//获取userName的值对用户名进行非空验证
varuserName=$(this).val().trim();
varnameRuler=/^[A-Z]+[a-zA-Z0-9\W]{4,15}$/;
if(userName==""||userName==null){
$("#loginInfo").html("请输入用户名");
$("#loginInfo").css({"color":"red","font-size":"15px","font-weight":"bolder"});
}elseif(!nameRuler.test(userName)){
$("#loginInfo").html("用户名首位大写,并且5-16位");
$("#loginInfo").css({"color":"red","font-size":"15px","font-weight":"bolder"});
}else{
$("#loginInfo").html("√");
$("#loginInfo").css({"color":"green","font-size":"15px","font-weight":"bolder"});
}
});
$("input[name='password']").blur(function(){
//alert("失去焦点!");
//获取userPassword的值对密码进行非空验证
varuserPassword=$(this).val().trim();
varpasswordRuler=/^[a-zA-Z0-9]{2,8}$/;
if(userPassword==""||userPassword==null){
$("#pwdInfo").html("请输入密码");
$("#pwdInfo").css({"color":"red","font-size":"15px","font-weight":"bolder"});
}elseif(!passwordRuler.test(userPassword)){
$("#pwdInfo").html("密码不能带符号并2-8位字母或数字");
$("#pwdInfo").css({"color":"red","font-size":"15px","font-weight":"bolder"});
}else{
$("#pwdInfo").html("√");
$("#pwdInfo").css({"color":"green","font-size":"15px","font-weight":"bolder"});
}
});后端生成验证码:@WebServlet("/code")
publicclassCodeServletextendsHttpServlet{
intlineCount=20;
@Override
publicvoidinit()throwsServletException{
StringlineCountStr=getServletContext().getInitParameter("lineCount");
if(!StringUtil.isEmpty(lineCountStr)){
lineCount=Integer.parseInt(lineCountStr);
}
}
@Override
protectedvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{
resp.setHeader("expires","-1");
resp.setHeader("Pragma","no-cache");
resp.setHeader("cache-control","no-cache");
StringBuildercode=newStringBuilder();
//4位数验证码
for(inti=0;i<4;i++){
code.append((int)(Math.random()*10));
}
req.getSession().setAttribute(ConstUtil.CODE,code.toString());
BufferedImagebufferedImage=newBufferedImage(50,30,BufferedImage.TYPE_INT_RGB);
//得到画板
Graphicsgraphics=bufferedImage.getGraphics();
//线
for(inti=0;i<lineCount;i++){
Colorcolor=newColor((int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*256));
graphics.setColor(color);
graphics.drawLine((int)(Math.random()*51),(int)(Math.random()*51),(int)(Math.random()*51),(int)(Math.random()*51));
}
Fontfont=newFont("宋体",Font.ITALIC,20);
graphics.setColor(Color.red);
graphics.setFont(font);
graphics.drawString(code.toString(),4,24);
OutputStreamoutputStream=resp.getOutputStream();
ImageIO.write(bufferedImage,"jpg",outputStream);
}
}4.2echarts插件首页显示订单量超级管理员登录成功后跳转到该页面,界面如图4.2所示:图4.2后台首页界面Fig.4.2Backgroundhomepageinterface实现原理:当超级管理员输入完整且正确信息后点击“登录”按钮,当html结构渲染完毕触发jquery的时间监听函数,结合ajax技术向后台服务器发送请求。后台根据url找到控制层CarController的analyzeData()函数,在该函数中做查询数据库操作,查询出所有车辆对应的月销量以及车辆名称,再响应数据给界面以柱形图形式显示。核心代码如下所示:<scripttype="text/javascript">
//jquery时间监听函数,当html结构渲染完毕会触发该函数
$(function(){
varmyChart=echarts.init(document.getElementById('bar'));
//显示标题,图例和空的坐标轴
myChart.setOption({
title:{
text:'订单统计表'
},
tooltip:{},
legend:{
data:['订单量']
},
xAxis:{
data:[]
},
yAxis:{},
series:[{
name:'订单量',
type:'bar',
data:[]
}]
});
myChart.showLoading();
$.ajax({
type:"get",//请求方式
url:"${pageContext.request.contextPath}/cars/stastic",
success:function(responseData){
myChart.hideLoading();
myChart.setOption({
xAxis:{
data:responseData.xData
},
series:[{
//根据名字对应到相应的系列
name:'订单量',
data:responseData.yData
}]
});
}
})
});
</script>4.3动态生成左侧菜单栏超级管理员登录成功后跳转到该页面,界面如图4.3所示:图4.3后台菜单栏Fig.4.3Backgroundmenubar实现原理:当项目启动成功之后菜单栏保持不变,不需要每类角色打开界面时都从数据库加载,换句话说就是每类角色打开界面都是读取同一份菜单,所以可以把菜单加载一份缓存到内存中,则需要监听servletContext的创建事件。创建一个监听类在web.xml中配置并实现ServletContextListener接口,实现ServletContextListener类中的contextInitialized()方法,在该方法中加载数据库中的菜单信息,由service层调用dao层。但是MyContextListener类不在容器中,不能使用自动注入获取menuService。写一个自定义工具类来获取menuService,首先初始化servletContext的值,再使用WebApplicationContextUtils的getWebApplicationContext()方法传递参数值servletContext获取上下文环境(容器)WebApplicationContext,该类又实现了ApplicationContext,所以可以调用ApplicationContext的getBean()方法给name获取menuService,由menuService调用dao层去执行查询操作,得到的结果存放到servletContext的属性中。前台通过对应的属性名去获取数据,又menu表中的数据有一对多的关系,所以遍历数据时使用jstl标签库的c:forEach标签嵌套遍历。核心代码如下所示:MyContextListener类:publicclassMyContextListenerimplementsServletContextListener{
@Override
publicvoidcontextInitialized(ServletContextEventsce){
SpringUtil.init(sce.getServletContext());
MenuServicemenuService=SpringUtil.getBean("menuServiceImpl");
List<Menu>leftMenus=menuService.findLeft();
sce.getServletContext().setAttribute("leftMenus",leftMenus);
//查找所有的叶子菜单
List<Menu>leafMenus=menuService.findLeafMenu();
sce.getServletContext().setAttribute("leafMenu",leafMenus);
}
}SpringUtil工具类:publicclassSpringUtil{
privatestaticServletContextservletContext;
publicstaticvoidinit(ServletContextservletContext){
SpringUtil.servletContext=servletContext;
}
publicstatic<T>TgetBean(Stringname){
return(T)WebApplicationContextUtils.getWebApplicationContext(servletContext).getBean(name);
}
}4.4系统管理顾客列表顾客列表界面如图4.4所示:图4.4顾客列表Fig.4.4Thelistofcustomers实现原理:当超级管理员点击左侧菜单栏的二级分类“顾客管理”,前端先向后台服务器发送请求,后台根据URL找到控制层CustomerController的list()函数,然后调用CustomerServiceImpl接口实现类的findByQuery()函数执行查询操作,得到结果数据后在前端进行分页,设置每页显示的记录数,在界面以表格形式显示。核心代码如下所示:publicJsonModellist(CustomerQuerycustomerQuery){
Page<Customer>pageC=customerService.findByQuery(customerQuery);
JsonModelJM=newJsonModel();
JM.setSuccess(true);
JM.setRows(page.getData());
//此处是当前条件下的总记录数
JM.setTotal(page.getTotal());
returnJM;
}前端:当页面的HTML结构渲染完显示table插件;设置插件显示的数据来源;设置每页显示的数量等;获取到服务器响应回来的数据;设置table显示的列名以及对应的值;编辑顾客管理员在顾客列表界面点击“编辑”按钮跳转到该界面。编辑顾客界面如图4.5所示:图4.5编辑顾客界面Fig.4.5Editthecustomerinterface实现原理:当超级管理员在顾客列表界面点击“编辑”发送请求。后台根据url找到控制层CustomerController的editUI()函数,执行查询进行数据的回显,再转发到编辑界面,管理员编辑完成后,点击“确定”重定向到顾客列表界面。核心代码如下所示:@RequestMapping(value="{id}/edit",method=GET请求)//转发到修改页面
@RequestMapping(value="{id}/edit",method=RequestMethod.GET)
publicStringeditUI(@PathVariable("id")IntegercustomerId,Modelmodel){
Customerc=customerService.findById(customerId);
model.addAttribute("customer",c);
return"customer/edit";//转发
}
//修改
@RequestMapping(value="{id}",method=RequestMethod.POST)
publicStringedit(Customercustomer){
customerService.update(customer);
重定向至顾客列表界面;
}添加顾客管理员在顾客列表界面点击“添加”按钮跳转到该界面。添加顾客界面如图4.6所示:图4.6添加顾客界面Fig.4.6Addacustomerinterface实现原理:当超级管理员在顾客列表界面点击“添加”通过超链接向后台服务器发送请求。后台根据url找到控制层CustomerController的addUI()函数进行页面跳转,在管理员输入相关信息后,点击“添加”按钮,通过url找到控制层CustomerController的add()函数执行添加操作,操作完成后重定向到顾客列表界面。核心代码如下所示:@RequestMapping(value="",method=POST请求)
publicStringadd(Customercustomer){
customer.setLastLoginTime(newDate());
customer.setPassword("123456");
customerService.add(customer);
重定向至顾客列表界面;
}查询顾客组合查询顾客界面如图4.7所示:图4.7查询顾客界面Fig.4.7Querythecustomerinterface实现原理:当超级管理员在顾客列表界面输入顾客名字或者账号,点击“查询”后台根据url找到控制层CustomerController的list()函数进行查询,分页可以分为前端分页和后端分页,该功能使用前端分页,查询结果在前端进行分页,以表格形式显示。核心代码如下所示:publicJsonModellist(CustomerQuerycustomerQuery){
Page<Customer>pageC=customerService.findByQuery(customerQuery);
JsonModelJM=newJsonModel();
JM.setSuccess(true);
JM.setMsg("查找用户成功");
JM.setRows(pageC.getData());
JM.setTotal(pageC.getTotal());
returnjsonModel;
}4.5车辆管理车辆列表车辆列表界面如图4.8所示:图4.8车辆列表界面Fig.4.8Vehiclelistinterface实现原理:当超级管理员点击左侧菜单栏的二级分类“车辆管理”,前端先向后台服务器发送get请求。后台根据url找到控制层CarController的list()函数,然后调用CarServiceImpl接口实现类的findByQuery()函数执行查询操作,得到结果数据后在前端进行分页,设置每页显示的记录数,在界面以表格形式显示。核心代码如下所示:publicPage<Car>findByQuery(CarQuerycarQuery){
Page<Car>pageCar=newPage<Car>();
pageCar.setData(carDao.findByQuery(carQuery));
inttotal=carDao.findTotal(carQuery);
pageCar.setTotal(total);
returnpageCar;
}编辑顾客管理员在车辆列表界面点击“详情与编辑”按钮跳转到该界面。编辑车辆信息界面如图4.9所示:图4.9编辑车辆信息界面Fig.4.9Editthevehicleinformationinterface实现原理:当超级管理员在车辆列表界面点击“详情与编辑”向后台服务器发送请求。后台根据url找到控制层CarController的editUI()函数,执行查询进行数据的回显,再转发到编辑界面,编辑界面做相应的数据回显,利用开源的纯Javascript图表库ECharts进行简单配置。核心代码如下所示:@RequestMapping(value="{id}/edit",method=GET请求)
publicStringeditUI(@PathVariable("id")IntegercarId,Modelmodel){
Carc=carService.findById(carId);
BrandQuerybrandQuery=newBrandQuery();
List<Brand>brandLists=brandService.findByQuery(brandQuery).getData();
model.addAttribute("brands",brandLists);
model.addAttribute("car",c);
return"car/edit";
}
@RequestMapping(value="{id}",method=POST请求)
publicStringedit(Carcar){
carService.update(car);
return"redirect:/cars/list";
}添加车辆信息管理员在车辆列表界面点击“添加新的车辆信息”按钮跳转到该界面。添加车辆信息界面如图4.10所示:图4.10添加车辆信息界面Fig.4.10Addavehicleinformationinterface实现原理:当超级管理员在车辆列表界面点击“添加新的车辆信息”前端通过超链接向后台服务器发送请求。后台根据url找到控制层CarController的addUI()函数进行页面跳转,管理员输入相关车俩信息后,当“车牌号”的输入框失去焦点时,前台会对该值使用正在表达式进行校验,常规车牌号:仅允许以汉字开头,后面可录入六个字符,由大写英文字母和阿拉伯数字组成。如:粤B12345。首先截取车牌号的首字符,循环判断输入的车牌号首字符是否在指定的省份内,符合后再对整个值进行是否符合常规车牌号校验,如果校验不通过,焦点会被锁定在该输入框中,直至输入的车牌号正确。信息填写完成后点击“添加”按钮,通过url找到控制层CarController的add()函数执行添加操作,操作完成后重定向到车辆信息列表界面。核心代码如下所示:校验代码:<scripttype="text/javascript">
functioncheckNumberPlate(){
varcph=document.getElementById("cph");
varshortProvince=newArray("京","沪","津","渝","冀","晋","蒙",
"辽","吉","黑","苏","浙","皖","闽","赣","鲁","豫","鄂","湘","粤","桂",
"琼","川","贵","云","藏","陕","甘","青","宁","新");
if(cph.value==""||cph.value==null){//验证是否为空
$("#cphInfo").html("您输入的车牌号码有误!");
$("#cphInfo").css({
"color":"red",
"font-size":"15px",
"font-weight":"bolder",
"margin-left":"130px"
});
cph.focus();
return;
}
varstr=cph.value.substring(0,1);//截取车牌号的首字符
varres=false;
for(vari=0;i<shortProvince.length;i++){//循环判断输入的车牌号首字符是否在指定的省份内
if(str==shortProvince[i].toString()){
res=true;//在指定简写省份名称范围内
}
}
varregExpression1=/^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/;
if(!regExpression1.test(cph.value)){
$("#cphInfo").html("您输入的车牌号码有误!");
$("#cphInfo").css({
"color":"red",
"font-size":"15px",
"font-weight":"bolder",
"margin-left":"130px"
});
cph.focus();
return;
}else{//如果符合规则,判断首字符是否为各省级名称的简写
if(!res){
$("#cphInfo").html("车牌号码首字符无效!Error!");
$("#cphInfo").css({
"color":"red",
"font-size":"15px",
"font-weight":"bolder",
"margin-left":"130px"
});
cph.focus();
return;
}
$("#cphInfo").html("车牌号码有效");
$("#cphInfo").css({
"color":"green",
"font-size":"15px",
"font-weight":"bolder",
"margin-left":"130px"
});
}
}
</script>查询车辆管理员在车辆信息列表界面输入查询条件,可根据查询条件进行组合查询。查询车辆信息界面如图4.11所示:图4.11查询车辆信息界面Fig.4.11Checkthevehicleinformationinterface实现原理:当超级管理员在车辆信息列表界面输入车辆的颜色或者品牌,点击“查询”向后台服务器发送post请求。后台根据url找到控制层CarController的list()函数进行组合查询,查询结果在前端进行分页,以表格形式显示。核心代码如下所示:publicJsonModellist(CarQuerycarQuery){
Page<Car>pageCar=carService.findByQuery(carQuery);
JsonModelJM=newJsonModel();
JM.setSuccess(true);
JM.setMsg("查找成功");
JM.setRows(pageCar.getData());
JM.setTotal(pageCar.getTotal());
returnJM;
}4.6订单管理a)订单列表订单列表界面如图4.12所示:图4.12订单列表界面Fig.4.12Orderlistinterface实现原理:当超级管理员点击左侧菜单栏的二级分类“订单管理”,前端先向后台服务器发送请求,再转发到订单列表界面,当HTML结构渲染完毕会触发监听函数结合ajax技术向后台服务器发送请求。后台根据url找到控制层BookController的list()函数,然后调用RentCarServiceImpl接口实现类的findByQuery()函数执行查询操作,得到结果数据后在前端进行分页,设置每页显示的记录数,在界面以表格形式显示。核心代码如下所示:publicPage<Book>findByQuery(BookQueryrentCarQuery){
Page<Book>pageBook=newPage<Book>();
pageBook.setData(rentCarDao.findByQuery(rentCarQuery));
inttotal=rentCarDao.findTotal(rentCarQuery);
pageBook.setTotal(total);
returnpageBook;
}b)编辑订单管理员在订单列表界面点击“编辑”按钮跳转到该界面。编辑订单信息界面如图4.13所示:图4.13编辑订单信息界面Fig.4.13Edittheorderinformationinterface实现原理:当超级管理员订单列表界面点击“编辑”后台服务器发送get请求,后台根据url找到控制层BookController的editUI()函数,执行查询进行数据的回显,再转发到编辑界面,管理员编辑完成后,点击“编辑”重定向到订单列表界面。核心代码如下所示:@RequestMapping(value="{id}/edit",method=GET请求)
publicStringeditUI(@PathVariable("id")IntegerbookId,Modelmodel){
Bookb=bookService.findById(bookId);
model.addAttribute("book",b);
return"book/bookedit";
}
@RequestMapping(value="{id}",method=POST请求)
publicStringedit(Bookbook){
bookService.update(book);
return"redirect:/books/list";
}c)添加订单信息管理员在订单列表界面点击“添加”按钮跳转到该界面。添加订单信息界面如图4.14所示:图4.14添加订单信息界面Fig.4.14Addanorderinformationinterface实现原理:当超级管理员在订单列表界面点击“添加”通过超链接向后台服务器发送get请求。后台根据URL找到控制层BookController的addUI()函数进行页面跳转,在管理员输入相关信息后,点击“添加”按钮,通过URL找到控制层BookController的add()函数执行添加操作,操作完成后重定向到订单信息列表界面。核心代码如下所示:publicStringadd(Bookbook){
book.setCreateTime(newDate());
bookService.add(book);
return"redirect:/books/list";
}d)查询订单信息根据管理员在订单信息列表界面输入查询条件进行组合操作。查询订单信息界面如图4.15所示:图4.15查询订单信息界面Fig.4.15Querytheorderinformationinterface实现原理:当超级管理员在订单信息列表界面输入订单号或者付款人,点击“查询”利用ajax和Json技术向后台服务器发送请求。后台根据url找到控制层BookController的list()函数进行查询,查询结果在前端进行分页,以表格形式显示。核心代码如下所示:publicJsonModellist(BookQuerybookQuery){
Page<Book>pageBook=bookService.findByQuery(bookQuery);
JsonModelJM=newJsonModel();
JM.setSuccess(true);
JM.setMsg("查找成功");
JM.setRows(pageBook.getData());
JM.setTotal(pageBook.getTotal());
returnJM;
}4.7预约单管理a)预约单列表预约单列表界面如图4.16所示:图4.16预约单列表界面Fig.4.16Appointmentlistinterface实现原理:当超级管理员点击左侧菜单栏的二级分类“预约单管理”向后台服务器发送get请求,再转发到订单列表界面。后台根据URL找到控制层ReservationController的list()函数,然后调用ReservationServiceImpl接口实现类的findByQuery()函数执行查询操作。由于在数据库reservation(预约)表中的branId字段存储的是车辆品牌的ID,但是在界面中要显示车辆ID对应的品牌名,所以这里涉及到两个表关联查询。说明:一条预约单信息只会包含一个车辆品牌信息,所以从查询预约单信息出发关联查询品牌信息为一对一查询。MyBatis中使用association标签来解决一对一的关联查询,配置映射关联的品牌信息,association用于映射关联查询单个对象的信息,property是指要将关联查询的品牌信息映射到reservation中所对应的属性,javaType是指映射到bank的哪个属性。得到结果数据后在前端进行分页,设置每页显示的记录数,在界面以表格形式显示。核心代码如下所示:ReservationMapper.xml:<resultMaptype="reservation"id="baseResultMap">
<idcolumn="id"property="id"></id>
<resultcolumn="customerId"property="customerId"/>
<resultcolumn="name"property="name"/>
<resultcolumn="startTime"property="startTime"/>
<resultcolumn="endTime"property="endTime"/>
<resultcolumn="status"property="status"/>
<associationproperty="brand"javaType="com.neu.domain.Brand"columnPrefix="b_">
<idcolumn="id"property="id"/>
<resultcolumn="name"property="name"/>
</association>
</resultMap><selectid="findByQuery"parameterType="reservationQuery"resultMap="baseResultMap">
selectr.*,b_name,b.idb_idfromreservationr,brandbwherer.brandId=b.idlimit#{offset},#{pageSize}
</select>ReservationController:publicJsonModellist(ReservationQueryreservationQuery,HttpSessionsession){
Page<Reservation>pageReservation=reservationService.findByQuery(reservationQuery);
JsonModelJM=newJsonModel();
JM.setSuccess(true);
JM.setMsg("查找结算成功");
JM.setRows(pageReservation.getData());
JM.setTotal(pageReservation.getTotal());
returnJM;
}ReservationServiceImpl:publicintadd(Reservationreservation){
returnreservationDao.add(reservation);
}
publicPage<Reservation>findByQuery(ReservationQueryreservationQuery){
Page<Reservation>page=newPage<Reservation>();
page.setData(reservationDao.findByQuery(reservationQuery));
inttotal=reservationDao.findTotal(reservationQuery);
page.setTotal(total);
returnpage;
}b)结算订单管理员在预约单列表界面点击“结算”按钮跳转到该界面。结算订单界面如图4.17所示:图4.17结算订单信息界面Fig.4.17Settlementorderinformationinterface实现原理:当超级管理员订单列表界面点击“结算”向后台服务器发送GET请求。后台根据URL找到控制层ReservationController的Sum()函数,执行查询操作并进行页面的跳转,管理员在前台完成信息的输入后,点击“生成订单”按钮向后台发送POST请求,后台根据URL找到控制层ReservationController的Sum()函数,向数据库的订单表(Book)插入一条记录,操作成功后重定向到预约列表界面。核心代码如下所示:@RequestMapping(value="{id}/sum",method=GET请求)
publicStringSum(@PathVariable("id")IntegerreservationId,Modelmodel){
Reservationr=reservationService.findById(reservationId);
BrandQuerybrandQuery=newBrandQuery();
List<Brand>brandLists=brandService.findByQuery(brandQuery).getData();
model.addAttribute("brands",brandLists);
model.addAttribute("reservation",r);
return"book/booksum";
}c)查询预约单信息管理员在预约单信息列表界面输入预约开始时间进行查询操作。查询预约单信息界面如图4.18所示:图4.18查询预约单信息界面Fig.4.18Checktheappointmentorderinformationinterface实现原理:当超级管理员在预约单信息列表界面输入预约开始时间,点击“查询”向请求分发器发送请求。后台根据URL找到控制层ReservationController的list()函数进行查询,查询结果在前端进行分页,以表格形式显示。核心代码如下所示:publicJsonModellist(ReservationQueryreservationQuery,HttpSessionsession){
Page<Reservation>pageReservation=reservationService.findByQuery(reservationQuery);
JsonModelJM=newJsonModel();
JM.setSuccess(true);
JM.setRows(pageReservation.getData());
JM.setTotal(pageReservation.getTotal());
returnJM;
}4.8角色管理a)显示角色列表角色列表界面如图4.19所示:图4.19角色列表Fig.4.19Thelistofroles实现原理:当超级管理员点击左侧菜单栏的二级分类“角色管理”,前端先向后台服务器发送请求,后台根据url找到控制层RoleController的list()函数,然后调用roleServiceImpl接口实现类的findByQuery()函数执行查询操作,得到结果数据回显到个人信息界面。核心代码如下所示:publicPage<Role>findByQuery(RoleQueryroleQuery){
Page<Role>pageRole=newPage<Role>();
pageRole.setData(roleDao.findByQuery(roleQuery));
inttotal=roleDao.findTotal(roleQuery);
pageRole.setTotal(total);
returnpageRole;
}b)添加角色管理员在角色列表界面点击“添加”按钮跳转到该界面。添加角色界面如图4.20所示:图4.20添加角色界面Fig.4.20Addaroleinterface实现原理:当超级管理员在角色列表界面点击“添加”通过超链接的形式向后台服务器发送GET请求。后台根据url找到控制层RoleController的add()函数进行页面跳转,在管理员输入新添的角色名称后,点击“添加”按钮,再向后台发送POST请求,后台通过URL找到控制层RoleController的add()函数执行添加操作,操作完成后重定向到角色列表界面。核心代码如下所示:publicStringadd(Rolerole){
roleService.add(role);
return"redirect:/roles";
}c)批量删除角色批量删除角色界面如图4.21所示:图4.21批量删除角色界面Fig.4.21Bulkdeletetheroleinterface实现原理:当超级管理员在角色列表界面选择要删除的角色选项或多个选项,点击角色列表上的“删除”按钮,前端通过jquery监听delete按钮的点击事件,通过ajax向后台服务器发送POST请求。后台根据URL找到控制层RoleController的delete()方法,在该方法中,首先使用字符串的分割函数,对前台发送的带有管理员要删除的所有角色的id的字符串,分割后再用一个一维数组来存储,再把该数组作为参数传递给RoleServiceImpl层,RoleServiceImpl层再调用RoleDao层,最后执行删除操作,这里使用到mybatis的foreach标签,foreach标签主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合,其中,item属性表示集合中每一个元素进行迭代时的别名,open属性表示该语句以什么开始,separator属性表示在每次进行迭代之间以什么符号作为分隔符,close属性表示以什么结束,foreach标签的collection属性是必须指定的,但是在不同情况下,该属性的值是不一样的,主要有以下3种情况:如果传入的是单参数且参数类型是一个List的时候,collection属性值为list如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array如果传入的参数是多个的时候,需要把它们封装成一个Map,当然单参数也可以封装成Map因为这里从控制层传递的参数是数组,属于array参数类型,所以collection="array"。操作完成后刷新角色列表界面。核心代码如下所示:前台jquery代码:varidArrays=$roleTable.bootstrapTable('getAllSelections');
if(idArrays.length==0){
alert("请选择一条记录");
return;
}
idArrays=idArrays.map(function(item,index){
returnitem.id;
});
$.ajax({
type:"post",
url:"${pageContext.request.contextPath}/roles/"+idArrays.join(),
data:"_method=post",
success:function(respData){
if(respData.success){
$roleTable.bootstrapTable('refresh');
}else{
alert(respData.msg);
}
}
});RoleController:@RequestMapping(value="/{ids}",method=POST请求)
@ResponseBody
publicJsonModeldelete(@PathVariable("ids")Stringids){
Stringid[]=ids.split(",");
JsonModelJM=newJsonModel();
JM.setSuccess(true);
JM.setMsg("删除成功");
intlen=id.length;
Integer[]idArrays=newIn
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 商洛地区柞水县2025-2026学年第二学期四年级语文期末考试卷(部编版含答案)
- 宝鸡市金台区2025-2026学年第二学期四年级语文第八单元测试卷(部编版含答案)
- 水下钻井设备操作工岗前技能掌握考核试卷含答案
- 诊断试剂生产工安全管理模拟考核试卷含答案
- 斫琴师安全实践测试考核试卷含答案
- 2026年能效提升项目验收标准:节能量核定方法
- 六安市舒城县2025-2026学年第二学期四年级语文第七单元测试卷(部编版含答案)
- 宜宾市兴文县2025-2026学年第二学期五年级语文第八单元测试卷(部编版含答案)
- 巴彦淖尔盟杭锦后旗2025-2026学年第二学期三年级语文期末考试卷(部编版含答案)
- 许昌市鄢陵县2025-2026学年第二学期五年级语文期末考试卷(部编版含答案)
- 2026清远鸡行业分析报告
- 四川乐山峨边彝族自治县县属国企招聘笔试题库2026
- 湖南省医疗保险“双通道”单行支付管理药品使用申请表2026
- 矿山井下安全培训考试题及答案
- 非高危行业生产经营单位主要负责人安全培训(初训)理论考试题库500题(含答案)
- 2025年高考天津卷物理真题(解析版)
- 2025年山东档案职称考试《档案基础理论》考试题库(浓缩500题)
- 投标文件澄清函标准格式
- 2025PACK结构工程师校招笔试题及答案
- 2026届高考数学复习策略课件
- 零工经济中的女性劳动者权益保障研究
评论
0/150
提交评论