这回摊真的摊上大事啦!一个使用spring+mybatis+SpringMVC+maven+ajax+html5+css3+jvavScript整合的火车票售票管理系统被别人做出来了!
Posted 四原色
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了这回摊真的摊上大事啦!一个使用spring+mybatis+SpringMVC+maven+ajax+html5+css3+jvavScript整合的火车票售票管理系统被别人做出来了!相关的知识,希望对你有一定的参考价值。
这回摊真的摊上大事啦!一个使用spring+mybatis+SpringMVC+maven+ajax+html5+css3+jvavScript整合的火车票售票管理系统被别人做出来了!
目录
1. 前言
- 项目已经打包到了github了:
https://github.com/11000100111010101100111/raliwayManagerBaseSSM
2.还打包到了本站:
https://download.csdn.net/download/qq_44140450/20096676
3.也上传到了gitee中文网站:
https://gitee.com/code-on-top/SSMtrainStationManager
下面来带大家欣赏一些效果,具体源码可以直接github上查,或者点上面的链接去下载:
- github下载:开源免费;
- CSDN下载:不免费,需要花费积分。
2. 预览
- 客户首页:
-
//查票与购票两者实现的核心代码展示如下: //1.查票执行的异步请求: var data={start_point:startArea.value, end_point:endArea.value, time:startTime.value} $.ajax({ type: "post", url: "http://localhost:8080/raliway12307/getData/findTicket", dataType: "json", data:data, success: function (data) { if(data.falge == 200){ for(i=0;i<data.list.length;i++) add_table0(i,data.list[i]); } }); //2.查票的控制层执行方法: @ResponseBody @RequestMapping("/findTicket") public AjaxModel<ArrayList<String>> findTicket( @RequestParam("start_point") String start_point, @RequestParam("end_point") String end_point, @RequestParam("time") String time, HttpSession session) { AjaxModel<ArrayList<String>> arr=new AjaxModel<ArrayList<String>>(); ArrayList<ArrayList<String>> at=new ArrayList<ArrayList<String>>(); try { ArrayList<Ticket> trainLists= userService.alltrain(start_point,end_point,time); for (Ticket list:trainLists){ ArrayList li=new ArrayList(); for(Object ob :li) Li.add(ob.toString()); } arr.setList(at); arr.setFalge(200); }catch (Exception e){ arr.setFalge(0); } return arr; } 4.查票的service层业务处理: public String deleteStr(String item,String str){ if(item.substring(item.length()-1).equals(str)) item=item.substring(0,item.length()-1); return item; } public ArrayList<Ticket> alltrain( String startpoint, String endPoint, String time){ ArrayList<Integer > allTrain=new ArrayList<Integer>(); SimpleDateFormat sFormat =new SimpleDateFormat("yyyy-MM-dd"); Date start = null; try { start = sFormat.parse(time); } catch (ParseException e) {} time=sFormat.format(start); ArrayList<Integer> canChioseTrain=new ArrayList<Integer>(); ArrayList<Ticket> tickets=new ArrayList<Ticket>(); //模糊筛查合适的列车车次、、 allTrain=managerRaliway.findTicketNO( deleteStr(startpoint,"站"), deleteStr(endPoint,"站"), time); for (Integer trainId:allTrain){ //对查到的列车车次进行筛选 if(judgeTrain(trainId,startpoint,endPoint)){ if(isOverNow(managerRaliway.findTrain_time(trainId))) continue; //筛选结果保存在链表里 canChioseTrain.add(trainId); //根据总票情况进行计算余票余票 HashMap<String,Integer> reaoult=new HashMap<String,Integer>(); TrainList itemTicket=new TrainList(); reaoult = findOneTicketSeatTypes(trainId);; itemTicket=findTrainList(trainId); tickets.add(new Ticket( itemTicket.getTrain_name(), managerRaliway.findAStationName(itemTicket.getStart_point()), itemTicket.getStart_time(), managerRaliway.findAStationName(itemTicket.getTremial()), itemTicket.getVore_time(), reaoult.get("商务座")==null?0:reaoult.get("商务座"), reaoult.get("软卧")==null?0:reaoult.get("软卧"), reaoult.get("硬卧")==null?0:reaoult.get("硬卧"), reaoult.get("一等座")==null?0:reaoult.get("一等座"), reaoult.get("二等座")==null?0:reaoult.get("二等座"), reaoult.get("硬座")==null?0:reaoult.get("硬座"), reaoult.get("无座")==null?0:reaoult.get("无座") )); return tickets; } //根据列车id找出列车对应所有车厢具备的不同座位类型的数目, //以及卖出的所有不同类型座位的车票, //并返回不同类型座位的剩余车票情况. public HashMap<String,Integer> findOneTicketSeatTypes(Integer trainId){ ArrayList<TrainList> allTypeTickets= managerRaliway.getTrainSeatTypeAndNum(trainId); HashMap<String,Integer> allTickets_01=sortSeats(allTypeTickets); //计算这列合适列车的各类座位的售票数 ArrayList<String> allScalTickets= managerRaliway.getScalTicket(trainId); HashMap<String,Integer> allTickets_02 = sortSeatArray(allScalTickets); //根据总票情况进行计算余票余票 Set set=allTickets_01.keySet(); Object[] arr=set.toArray(); HashMap<String,Integer> reaoult=new HashMap<String,Integer>(); for(Object key:arr){ reaoult.put(key.toString(),allTickets_01.get(key)-allTickets_02.get(key)); } return reaoult; } //根据列车id查询对应车次和始发、终点站以及分别对应的到站时间 public TrainList findTrainList(Integer trainId){ TrainList itemTicket=new TrainList(); try{ itemTicket=managerRaliway.selectOneTrainById(trainId); } catch (Exception e){ } return itemTicket; } public HashMap<String,Integer> sortSeats(ArrayList<TrainList> arrayList){ HashMap<String ,Integer > seatType= new HashMap<String,Integer>(); ArrayList<SeatModel> seatTypes=managerRaliway.getSeatTypes(); for (TrainList list:arrayList){ if(seatType.containsKey(list.getTrain_name())){ seatType.replace(list.getTrain_name(), seatType.get(list.getTrain_name())+list.getIs_run()); } else seatType.put(list.getTrain_name(),list.getIs_run()); } for (SeatModel model:seatTypes){ if(!seatType.containsKey(model.getSeat_type())) seatType.put(model.getSeat_type(),0); } return sortMap(seatType); } public HashMap<String,Integer> sortSeatArray(ArrayList<String> arrayList){ HashMap<String ,Integer > seatType=new HashMap<String,Integer>(); ArrayList<SeatModel> seatTypes=managerRaliway.getSeatTypes(); for (String str:arrayList){ if(seatType.containsKey(str)) seatType.replace(str,seatType.get(str)+1); else seatType.put(str,1); } for (SeatModel model:seatTypes){ if(!seatType.containsKey(model.getSeat_type())) seatType.put(model.getSeat_type(),0); } return sortMap(seatType); } public HashMap<String,Integer> sortMap(HashMap<String,Integer> map){ Set set=map.keySet(); HashMap<String,Integer> item=new HashMap<String,Integer>(); Object[] arr=set.toArray(); Arrays.sort(arr); for(Object key:arr) item.put(key.toString(),map.get(key)); return map; } //判断列车是否处于所给区间 public boolean judgeTrain(Integer train_id , String strat_station, String end_Station){ ArrayList<HashMap> trains = managerRaliway.find_startEndStation(train_id); boolean a=false,b = false; ArrayList<String> s=new ArrayList<String>(); for(int i=0;i<trains.size();i++){ if(!a &&(managerRaliway.findAStationName(trains.get(i).get("start_station").toString() ).startsWith(strat_station) ) ) a=true; if(a && (managerRaliway.findAStationName(trains.get(i).get("end_station").toString() ).startsWith(end_Station))){ b=true; break; } } return a&&b; }
-
管理员首页:
3. 项目结构
4. 关于数据库
5. 项目描述
火车票管理系统包含有后台列车资源管理管理,以及前台用户购退票系统,前者主要实现管理员进行火车站、列车以及列车车次的管理,而后者为用户主要提供买票与退票管理功能,用户主页信息管理,修改登录密码,查看个人车票等,用户可以直接在主页输入查找内容跳转到购票页面,通过输入起点和终点以及出发日期可以找到相应的列车,同时系统为用户查找出这些列车对应的座位类型的车票剩余情况,然后可进行下单,选择有余票的座位类型进行购票,对于退票功能,客户可以进入一个退票页面,服务器为用户查找其购买的所有火车票,并返回车票的当前信息,提供可视化页面。
后台管理主要实现增加火车站信息、增加列车以及实时增加列车车次等功能。进入后台需要管理员员权限,实现的权限绑定的思想是对管理员控制层处理方法插入切面,管理员只有以管理员身份通过登录验证后才能操作后台功能。
- 其中,添加车站信息,主要是通过选择省份市区等地址信息定位车站位置以及输入车站名称和一个不可重复的编号,每次输入名称和编号,同样都会进行一次ajax异步请求,向服务器提交查询信息,如果输入的车站名称或编号已经存在,则情况并提示用户重新输入,防止数据冲突,添加一个车站的目的是为了定位车站位置,提供用户查票是模糊查询车次等。
- 添加列车信息不同于添加列车车次信息,添加一个列车信息主要包含列车的类型(如G高铁、D动车、T特快列车、Z直达列车、L临时列车等)、添加列车车厢数量(一列列车至少一节车厢,最多20节车厢)以及为每一节车厢分配座位类型(这里去理论状态一节车厢内只有一种座位类型),管理员每次输入完这些信息后同样都会执行一次ajax异步查询,防止数据重复,如:列车编号不可重复等,最终的提交亦是通过ajax进行异步提交的。
- 添加一趟列车车次的中心思想是围绕:一趟列车会经历不同的火车站,因此,我把添加列车车次分为两个部分,其一就是选择一个始发站以及一个辆列车和一个发车时间,其次是依次选择n趟区间(n>0),每次添加包含添加一个中转站、一个到站时间、一个到站距离,这里添加到站距离的目的是为了计算票价,如:某用户购买了一张从南昌西开往吉安西的火车票,其中共经历了新余站、萍乡站,则票价应等于这三个区间的距离之和与每公里票价之积再乘以不同用户类型对应的折扣,不同类型列车每公里票价也是不同的。添加这趟列车到数据库主要涉及到两个表,一个是列车车次表(是某趟列车的唯一信息表,一趟列车只能存在一次,因为这里一趟列车一天只能发车一次,所以根据时间和列车号就可以及精确找到任意列车),另一个是列车车次区间表(是某趟列车的所有区间集,通过这个区间集可以进行遍历搜索,在用户购票时,匹对用户出发地与目的地)。
客户端管理系统主要的实现功能有:用户查票、用户购票、用户退票以及用户修改个人信息等。
- 用户查票可通过主页提供的搜索面板输入出发地点、终点以及出发日期进行提交,查找信息将被转移到购票界面,并添加到输入框,用户点击确认按钮后,会显示出所有与用户需求匹配到的列车信息,其中查询的过程主要借助于ajax异步操作,通过将用户输入的起点、终点以及时间封装成JSON字符串发送到服务器,请求服务器查找相关列车信息,服务器接收到这个请求后会进行三步走战略:
- 进行第一次模糊筛查列车信息,将用户输入的时间和出发点以及到达点与列车车次区间表进行模糊匹配,只要找到对应时间出现相关车站时间这趟列车加入到一个链表,缩小筛查范围。
- 进行第二次筛查则是一次精确筛查过程,同过对链表中的列车车次进行分区间查找,遍历它的每一个到站节点,我首先设置两个boolean值用来标志是否查找到了始发站以及目的地站,如果能在一次遍历过程中匹配匹配到出发地点,则进行往下遍历是开始匹配目的地节点,如果能够匹配到目的地节点,则中断遍历,将这趟列车加入到可选列车链表,同时利用这趟列车唯一标识,查找其车厢数以及车厢对应类型,可以分别计算出这趟列车的个中类型座位的总数,并加入到一个HashMap中(表示座位类型:座位数量之间的关系),
- 之后开始查找一个列车售出车票表,根据此列车的唯一id找出所有已卖出的车票,并计算出个个座位类型已卖出票的数量,也存入一个HashMap中,最后将两张HashMap进行运算,总票数减去卖出的票得到剩余的票,并将趟列车及其各种座位类型对应的余票一并返回到客户端,客户可以查看到各种趟车票对应车票信息,并选择下单。
- 用户购票时,用户点击每张票后的去购买按钮后开始,用户可以看到完整的票信息,以及个人信息,然后选则一个座位类型,如果某个座位类型以及卖光了或者没有票,则用户无法选中,并且在用户每次选则一个座位类型后,系统都会进行一次ajax异步查询,查询当前车次、当前用户类型、当前乘车区间距离,当前列车每公里票价以及用户折扣量进行计算票价,实时反馈给用户选则,当用户选则购买后,通过ajax异步向服务器请求数据,打包的数据包含用户id,以及列车id、出发站、到达站、出发时间、票价和选则的座位类型发送大服务器,分别添加到列车卖出的票,和用户购买的票,其中在想列车卖出票的数据表中添加时,先检查者列列车对应的车票售出转态,一次查找有对应座位类型票可供的车厢,车厢内相应的座位卖出数量加一后用来标记这张票再此车厢内的编号,同时添加此车厢编号到表中,这样可以计算用户购买票的座位号以及车厢号。
- 用户退票的实现思想则是通过删除列车售出票表,修改用户买票表的票状态字段为退票,这样既不影响列车向其他用户提供余票,有不影响本人购票记录。
- 用户个人页管理主要实现了用户信息的查看、用户购票记录的查看和用户登录密码的修改。
6.总结
由于这次课程设计所有所花费的时间较往年稍微多一点,但是自己能够做到正确实现功能模块,能把想到的想法通过建模进行设计和编写代码,功能模块注重的是质量和可行性,自己能尽最大努力保障每一个模块的逻辑和数据正确性,坚持围绕“发现一个bug就解决一个bug”中心思想来进行。就比如在实现用户购票过程中查票环节是,当时进行模块测试时,页面中回显出来的数据产生了巨大的错误,正常情况下,一趟列车的票数大约出现在一个合理的区间上,但是回显出来得结果去破万了,这让我大吃一惊,喜欢较真的我从前端提交的ajax数据查到控制层,从控制层查到service层,最后发现是mysql映射语句写得不够严谨,在mysql里执行查询语句时发现了bug所在:
- 不合理的语句:
SELECT seattype.seat_type,seattype.seat_cap
FROM seattype,carrage WHERE
seattype.seat_id=carrage.carrage_no AND (
seattype.seat_id IN(
SELECT carrage_no FROM carrage WHERE train_id IN (
SELECT train_name FROM train_list
WHERE train_id = #{train_id} ))
- 通过修正后,正常执行的语句:
SELECT seattype.seat_type,seattype.seat_cap FROM seattype,carrage WHERE
(carrage.train_id IN (SELECT train_list.train_name FROM
train_list WHERE train_list.train_id = #{train_id} ) AND
carrage.carrage_no = seattype.seat_id)AND seattype.seat_id IN (
SELECT carrage.carrage_no FROM carrage WHERE
carrage.train_id IN (
SELECT DISTINCT (train_list.train_name) FROM train_list WHERE train_list.train_id = #{train_id} )
);
一个不严谨的select语句将本趟列车所有时间段出发的座位数取了出来,计算和的时候产生了数据错误,这是非常不应该的,以至于在之后的环节更加注重到了映射文件编写的重要性!
开发存在了诸多不足之处,在算法方面也还是比较欠缺的,至于前端这块,本人也只是在这个学期开始接触,学习一些web前端只是是比较简单的,我是利用网上的免费学习来展开,经常性的使用CSDN以及哔哩哔哩进行学习,就比如最近在看B站黑马程序员的springBoot教学入门,之前的web基础也是通过黑马程序员进行学习的,关于C3H5和js的学习我是两天完成的,之后开始做一些简单的页面巩固基础,也有将自己对编程中遇到的问题及其解决方案和一些学习记录,以及自己的作品上传到CSDN和GitHub等开源网站。
这次课程设计是关于火车票售票系统,相比于往年,难度的确有点大。在做项目的时候,开始是通过需求分析建立数据库,然后设计合适的页面,也就是原型图。之后开始设计逻辑结构,最后的阶段便是编码以及编码过程中进行的单元测试。
以上是关于这回摊真的摊上大事啦!一个使用spring+mybatis+SpringMVC+maven+ajax+html5+css3+jvavScript整合的火车票售票管理系统被别人做出来了!的主要内容,如果未能解决你的问题,请参考以下文章
Visual Studio安装程序中的背景图绿帽子摊上事了?