摘要
本文首先研究并介绍国内外目前的背景和现状,在此基础上给出论文的主要研究内容,其次,对汽车售票系统的需求进行了分析。再次,对汽车售票系统进行了总体设计,根据其总体设计、软件架构和总体功能模块进行了详细设计,作出了业务流程图以及数据流程图。总体上把汽车售票系统分为用户和管理员两种角色,用户角色主要负责了用户注册、用户登录、时刻表查询、购票、改签、退票、修改个人信息、修改密码等;管理员角色主要负责了用户的审核和管理、时刻表管理、售票管理、修改个人信息、修改密码等。并最后根据详细设计的结果,运用JavaEE技术平台,使用更灵活的B/S开发模式和经典的SSM组合框架实现系统的MVC分层架构,并结合MySQL数据库实现了汽车售票系统的信息化管理,并列出核心代码和部分主要页面。还对系统的核心功能就行了压力测试。
关键词:汽车售票;SSM;MySQL
3.2.1功能需求
基于web的汽车售票系统分为了用户和管理员两种角色。
用户模块
(1)用户注册:不是本系统的用户可以在线注册自己的账户;
(2)用户登录:可以登录使用本系统;
(3)时刻表查询:可以根据始发地、目的地、发车日期等条件来查询想要的汽车车票信息;
(4)购票:可以在线购买汽车车票;
(5)改签:在汽车没发车之前可以将自己购买的车票进行改签;
(6)退票:在汽车没发车之前可以将自己购买的车票进行退票;
(7)修改个人信息:可以对自己注册时的个人信息继续修改完善;
(8)修改密码:可以修改自己的个人密码;
管理员模块:
(1)用户管理:可以对注册的用户信息进行审核和管理;
(2)时刻表管理:可以对各汽车车票的时刻表信息进行维护和管理;
(3)车票管理:可以对所有用户的购票记录进行维护和管理;
(4)修改个人信息:可以对自己的个人信息继续修改完善;
(5)修改密码:可以修改自己的个人密码;
4.1系统总体模块设计
根据前面的分析研究,基于web的汽车售票系统的功能性需求可大致分为前台和后台两大部分。
4.2.2物理设计
根据汽车售票系统主要功能模块需求,汽车售票系统将由多个MySQL数据表组成,下面主要介绍数据库中核心的几个数据表内容。
(1)用户表:用于存储系统用户的所有信息,具体内容如下表4-1所示。
表4-1用户user表
字段名称 | 字段意义 | 字段类型 | 是否主键 | 是否外键 | 能否为空 |
id | 主键编号 | int(10) | 是 | 否 | 否 |
username | 用户名 | varchar(200) | 否 | 否 | 否 |
password | 密码 | varchar(200) | 否 | 否 | 否 |
name | 姓名 | varchar(200) | 否 | 否 | 否 |
tel | 电话 | varchar(200) | 否 | 否 | 否 |
| 邮箱 | varchar(200) | 否 | 否 | 否 |
idcard | 身份证 | varchar(200) | 否 | 否 | 否 |
address | 地址 | varchar(200) | 否 | 否 | 否 |
status | 审核状态 | varchar(200) | 否 | 否 | 否 |
time | 注册时间 | varchar(200) | 否 | 否 | 否 |
isadmin | 角色(0管理员,1用户) | varchar(200) | 否 | 否 | 否 |
(2)时刻表:用于存储系统时刻表信息。
表4-2时刻表信息timetable表
字段名称 | 字段意义 | 字段类型 | 是否主键 | 是否外键 | 能否为空 |
id | 主键编号 | int(11) | 是 | 否 | 否 |
beginaddress | 始发站 | varchar(255) | 否 | 否 | 否 |
endaddress | 目的站 | varchar(255) | 否 | 否 | 否 |
date | 发车日期 | varchar(255) | 否 | 否 | 否 |
begintime | 发车时间 | varchar(255) | 否 | 否 | 否 |
endtime | 到达时间 | varchar(255) | 否 | 否 | 否 |
sumcount | 可乘坐人数 | varchar(255) | 否 | 否 | 否 |
incount | 已购票人数 | varchar(255) | 否 | 否 | 否 |
price | 票价 | varchar(255) | 否 | 否 | 否 |
(3)售票记录表:用于存储系统上用户购买票的记录信息。
表4-3售票记录信息ticket表
字段名称 | 字段意义 | 字段类型 | 是否主键 | 是否外键 | 能否为空 |
id | 主键编号 | int(11) | 是 | 否 | 否 |
userid | 用户ID | int(11) | 否 | 是 | 否 |
timetableid | 时刻表ID | int(11) | 否 | 是 | 否 |
changes | 是否改签 | varchar(255) | 否 | 否 | 否 |
status | 状态 | varchar(255) | 否 | 否 | 否 |
type | 取票方式 | varchar(255) | 否 | 否 | 否 |
5 详细设计与实现
5.1 用户注册
非本汽车售票系统的用户,可以在线注册成为汽车售票系统的会员。填写好注册信息,点击注册按钮后,会先验证非空数据,再验证用户名是否重复,都验证没问题后,将会注册成功;否则将会提示相应错误信息。
图5-1 用户注册
主要实现代码如下:
public ModelAndView regedit(HttpServletRequest request){
Map<String,Object> map = new HashMap<String,Object>();
String username = request.getParameter("username");
String password = request.getParameter("password");
String name = request.getParameter("name");
String tel = request.getParameter("tel");
String email = request.getParameter("email");
String idcard = request.getParameter("idcard");
String address = request.getParameter("address");
IdcardValidator iv = new IdcardValidator();
map.put("username", username);
List<User> userlist = userService.getList(map);
//身份证校验
if(!iv.isValidatedAllIdcard(idcard)){
map.put("msg", "身份证不合法,请重新注册");
}else if(userlist.size() >0){
map.put("msg", "该用户已存在,请直接登录");
}else{
User user = new User();
user.setUsername(username);
user.setPassword(password);
user.setName(name);
user.setTel(tel);
user.setEmail(email);
user.setIdcard(idcard);
user.setAddress(address);
user.setIsadmin(1);
user.setStatus("未审核");
userService.insert(user);
map.put("msg", "注册成功,请等待管理员审核");
}
return jsp("regedit", map, request);
}
5.2 用户登录
在用户填写好登录信息后,会先验证非空数据,再验证填写的用户信息和数据库中保存的是否一致,一致后将会登录成功,登录成功后将会在左上角上显示用户信息;否则将会提示相应错误信息。
图5-2 用户登录
主要实现代码如下:
public ModelAndView main(HttpServletRequest request){
Map<String,Object> map = new HashMap<String,Object>();
String username = request.getParameter("username");
String password = request.getParameter("password");
if("".equals(username) || username == null || "".equals(password) || password == null){
map.put("msg", "用户名或密码不能为空!");
return jsp("login", map, request);
}
map.put("username", username);
map.put("password", password);
List<User> list = userService.getList(map);
if(list.size() == 0){
map.put("msg", "用户名或密码错误!");
return jsp("login", map, request);
}
User user = list.get(0);
request.getSession().setAttribute(SessionKeys.LOGIN_USER, user);
map.put("user", user);
return jsp("main", map, request);
}
5.3 用户模块
5.3.1 用户主界面
登录的是用户角色时,将会进入到它的操作界面。
图5-3 用户主界面
5.3.2 时刻表查询
可以始发地、目的地、发车日期来组合查询条件查询自己想要的汽车车票信息。
图5-4 时刻表查询
主要实现代码如下:
public ModelAndView checklist(HttpServletRequest request){
Map<String,Object> map = new HashMap<String,Object>();
String pagerNum = request.getParameter("pagerNum");
if(pagerNum==null){
pagerNum = "1";
}
map.put("beginaddress", request.getParameter("beginaddress"));
map.put("endaddress", request.getParameter("endaddress"));
map.put("date", request.getParameter("date"));
map.put("usefuldate", DateUtil.formatHMS(new Date()));
List<Timetable> list = timetableService.getList(map);
map.put("count", list.size());
list = (List<Timetable>) PagerUtil.getPager(list, Integer.parseInt(pagerNum));
map.put("maxPager", list.size()/PagerUtil.getPagerSize()+1);
map.put("pagerNum", pagerNum);
map.put("list", list);
return jsp("timetable/checklist", map, request);
}
当点击“购票”后会可以添加购买数量和取票方式。填写完购票信息点击“保存按钮后,会先验证是否有非空数据,其次再验证购买数量是否时数字,最后验证当购买票数量大于剩余票数量时会提示“售票不足”的提示信息,都验证没问题后将会执行购票操作,并会温馨提示“购票成功”,数据库表中该班次的车票会自动扣除1。
图5-5 购票
主要实现代码如下:
String id = request.getParameter("id");
Parkingspace parkingspace = parkingspaceService.getById(id);
String msg = "";
String stoptime = null;
int paytime = 0,payhours=0;
Dict dict = DictService.getById("1");
if("use".equals(request.getParameter("type"))){
Pay pay = new Pay();
pay.setParkingspaceid(Integer.parseInt(id));
pay.setUserid(getSessionUser(request).getId());
parkingspace.setStatus("使用中");
pay.setStarttime(DateUtil.formatHMS(new Date()));
payService.insert(pay);
msg = "使用成功";
parkingspaceService.update(parkingspace);
}
5.3.3 我的车票
用户可以查看到自己以往的购买的车票记录信息。
图5-6 我的停车记录
主要实现代码如下:
public ModelAndView list(HttpServletRequest request){
Map<String,Object> map = new HashMap<String,Object>();
String pagerNum = request.getParameter("pagerNum");
if(pagerNum==null){
pagerNum = "1";
}
map.put("userid", getSessionUser(request).getId());
List<Ticket> list = ticketService.getList(map);
map.put("count", list.size());
list = (List<Ticket>) PagerUtil.getPager(list, Integer.parseInt(pagerNum));
map.put("maxPager", list.size()/PagerUtil.getPagerSize()+1);
map.put("pagerNum", pagerNum);
map.put("list", list);
return jsp("ticket/list", map, request);
}
当汽车没发车之前,用户需要改签时可以点击列表后的“改签”按钮将会自动进入到改签的界面,再改签界面中选择要改签到的车次后,点击对应列表后的“改签”按钮即可。
图5-7 改签
主要实现代码如下:
public ModelAndView adminupdate(HttpServletRequest request){
Map<String,Object> map = new HashMap<String,Object>();
String id = request.getParameter("id");
String timetableid = request.getParameter("timetableid");
//当前车票
Ticket ticket = ticketService.getById(id);
//改签车票
Timetable timetable = timetableService.getById(timetableid);
int remaindcount = Integer.parseInt(timetable.getSumcount()) - Integer.parseInt(timetable.getIncount());
if(remaindcount>=1){
//元车票更新状态
ticket.setStatus("已改签");
ticket.setChanges("已改签至"+timetable.getDate()+" "+timetable.getBegintime());
ticketService.update(ticket);
//插入改签车票
Ticket ticketchange = new Ticket();
ticketchange.setTimetableid(Integer.parseInt(timetableid));
ticketchange.setStatus("已购买");
ticketchange.setUserid(ticket.getUserid());
ticketchange.setType(ticket.getType());
ticketService.insert(ticketchange);
//原时刻表票数增加
Timetable timetableold = timetableService.getById(ticket.getTimetableid()+"");
int oldticketcount = Integer.parseInt(timetableold.getIncount())-1;
System.err.println(oldticketcount);
timetableold.setIncount(oldticketcount+"");
timetableService.update(timetableold);
//票数减少
timetable.setIncount((Integer.parseInt(timetable.getIncount())+1)+"");
timetableService.update(timetable);
map.put("msg", "改签成功");
}else{
map.put("msg", "票数不足,改签失败");
}
String pagerNum = request.getParameter("pagerNum");
if(pagerNum==null){
pagerNum = "1";
}
List<Ticket> list = ticketService.getList(map);
map.put("count", list.size());
list = (List<Ticket>) PagerUtil.getPager(list, Integer.parseInt(pagerNum));
map.put("maxPager", list.size()/PagerUtil.getPagerSize()+1);
map.put("pagerNum", pagerNum);
map.put("list", list);
return jsp("ticket/adminlist", map, request);
}
同时“我的车票”列表中该笔售票记录的状态更新为“已改签”,改签期次也显示出。
图5-8 改签结果
当汽车没发车之前,用户需要退票时可以点击列表后的“退票”按钮将会自动退票,并且状态更新为“已退票”,并且该班次车票会加1。
图5-9 退票
主要实现代码如下:
public ModelAndView admindel(HttpServletRequest request){
Map<String,Object> map = new HashMap<String,Object>();
Ticket ticket = ticketService.getById(request.getParameter("id"));
ticket.setStatus("已退票");
ticketService.update(ticket);
//原时刻表票数增加
Timetable timetableold = timetableService.getById(ticket.getTimetableid()+"");
int oldticketcount = Integer.parseInt(timetableold.getIncount())-1;
System.err.println(oldticketcount);
timetableold.setIncount(oldticketcount+"");
timetableService.update(timetableold);
map.put("msg", "退票成功");
String pagerNum = request.getParameter("pagerNum");
if(pagerNum==null){
pagerNum = "1";
}
List<Ticket> list = ticketService.getList(map);
map.put("count", list.size());
list = (List<Ticket>) PagerUtil.getPager(list, Integer.parseInt(pagerNum));
map.put("maxPager", list.size()/PagerUtil.getPagerSize()+1);
map.put("pagerNum", pagerNum);
map.put("list", list);
return jsp("ticket/adminlist", map, request);
}
5.3.4 修改个人信息
用户可以查看到自己注册时填写的个人信息并且可以修改。修改完个人信息点击“保存”按钮后会先验证手机号格式是否正确,身份证号是否有效,都验证没问题后将会执行修改个人信息操作。
图5-10 修改个人信息
主要实现代码如下:
public ModelAndView changemsg(HttpServletRequest request){
Map<String,Object> map = new HashMap<String,Object>();
String tel = request.getParameter("tel");
String email = request.getParameter("email");
String idcard = request.getParameter("idcard");
String address = request.getParameter("address");
IdcardValidator iv = new IdcardValidator();
User user = userService.getUserById(request.getParameter("id"));
//身份证校验
if(!iv.isValidatedAllIdcard(idcard)){
map.put("msg", "身份证不合法,请重新输入");
}else{
user.setTel(tel);
user.setEmail(email);
user.setIdcard(idcard);
user.setAddress(address);
userService.update(user);
map.put("msg", "修改成功");
}
map.put("user", user);
return jsp("changemsg", map, request);
}
5.4管理员模块
5.4.1 管理员主界面
登录的是管理员角色时,将会进入到它的操作界面。
图5-11 管理员主界面
5.4.2 用户管理
管理员可以对注册的用户信息进行维护和管理。
图5-12用户管理
主要实现代码如下:
public ModelAndView list(HttpServletRequest request){
Map<String,Object> map = new HashMap<String,Object>();
String pagerNum = request.getParameter("pagerNum");
if(pagerNum==null){
pagerNum = "1";
}
map.put("isadmin", "1");
map.put("status", request.getParameter("status"));
map.put("name", request.getParameter("name"));
map.put("lou", request.getParameter("lou"));
List<User> list = userService.getList(map);
map.put("count", list.size());
list = (List<User>) PagerUtil.getPager(list, Integer.parseInt(pagerNum));
map.put("maxPager", list.size()/PagerUtil.getPagerSize()+1);
map.put("pagerNum", pagerNum);
map.put("list", list);
return jsp("user/list", map, request);
}
新注册的用户需要管理员审核通过后,才能使用本系统。管理员可以从用户列表中选择“审核”按钮来为新注册用户进行审核。
主要实现代码如下:
public ModelAndView shenhe(HttpServletRequest request){
Map<String,Object> map = new HashMap<String,Object>();
User user = userService.getUserById(request.getParameter("id"));
user.setStatus("已审核");
boolean issuc = userService.update(user);
if(issuc){
map.put("msg", "审核成功");
}else{
map.put("msg", "修改失败,请重新操作");
}
String pagerNum = request.getParameter("pagerNum");
if(pagerNum==null){
pagerNum = "1";
}
map.put("isadmin", "1");
List<User> list = userService.getList(map);
map.put("count", list.size());
list = (List<User>) PagerUtil.getPager(list, Integer.parseInt(pagerNum));
map.put("maxPager", list.size()/PagerUtil.getPagerSize()+1);
map.put("pagerNum", pagerNum);
map.put("list", list);
return jsp("user/list", map, request);
}
点击有上上角的“新增”按钮后,管理员可以为不熟悉电脑使用的用户给开设账户。填写完用户信息点击“保存”按钮后会先验证是否有非空数据,其次再验证身份证号是否有效以及手机号格式是否正确,最后验证账号是否重复,都验证没问题后将会执行新增操作。
图5-13添加用户
5.4.3 时刻表管理
管理员可以对汽车站中的各车次的时刻表信息进行维护和管理。
图5-14时刻表管理
主要实现代码如下:
public ModelAndView list(HttpServletRequest request){
Map<String,Object> map = new HashMap<String,Object>();
String pagerNum = request.getParameter("pagerNum");
if(pagerNum==null){
pagerNum = "1";
}
map.put("beginaddress", request.getParameter("beginaddress"));
map.put("endaddress", request.getParameter("endaddress"));
map.put("date", request.getParameter("date"));
List<Timetable> list = timetableService.getList(map);
map.put("count", list.size());
list = (List<Timetable>) PagerUtil.getPager(list, Integer.parseInt(pagerNum));
map.put("maxPager", list.size()/PagerUtil.getPagerSize()+1);
map.put("pagerNum", pagerNum);
map.put("list", list);
return jsp("timetable/list", map, request);
}
可以点击右边的“新增”来添加新的时刻表信息。当输入时刻表信息点击“保存”按钮后会先验证是否有非空数据,没问题后才执行新增操作。
图5-15添加时刻表
主要实现代码如下:
public ModelAndView add(HttpServletRequest request){
Map<String,Object> map = new HashMap<String,Object>();
String beginaddress = request.getParameter("beginaddress");
String endaddress = request.getParameter("endaddress");
String date = request.getParameter("date");
String begintime = request.getParameter("begintime");
String endtime = request.getParameter("endtime");
String sumcount = request.getParameter("sumcount");
String price = request.getParameter("price");
Timetable timetable = new Timetable();
timetable.setBeginaddress(beginaddress);
timetable.setBegintime(begintime);
timetable.setDate(date);
timetable.setEndaddress(endaddress);
timetable.setEndtime(endtime);
timetable.setIncount("0");
timetable.setSumcount(sumcount);
timetable.setPrice(Integer.parseInt(price));
boolean issuc = timetableService.insert(timetable);
if(issuc){
map.put("msg", "新增成功");
}else{
map.put("msg", "新增失败,请重新操作");
}
String pagerNum = request.getParameter("pagerNum");
if(pagerNum==null){
pagerNum = "1";
}
List<Timetable> list = timetableService.getList(map);
map.put("count", list.size());
list = (List<Timetable>) PagerUtil.getPager(list, Integer.parseInt(pagerNum));
map.put("maxPager", list.size()/PagerUtil.getPagerSize()+1);
map.put("pagerNum", pagerNum);
map.put("list", list);
return jsp("timetable/list", map, request);
}
5.4.4 售票记录
管理员可以查看各全部的售票记录,以及为不方便电脑操作的用户进行改签和退票操作。
图5-16售票记录
主要实现代码如下:
public ModelAndView adminlist(HttpServletRequest request){
Map<String,Object> map = new HashMap<String,Object>();
String pagerNum = request.getParameter("pagerNum");
if(pagerNum==null){
pagerNum = "1";
}
List<Ticket> list = ticketService.getList(map);
map.put("count", list.size());
list = (List<Ticket>) PagerUtil.getPager(list, Integer.parseInt(pagerNum));
map.put("maxPager", list.size()/PagerUtil.getPagerSize()+1);
map.put("pagerNum", pagerNum);
map.put("list", list);
return jsp("ticket/adminlist", map, request);
}
5.5修改密码
所有用户都可以修改自己的个人密码。当点击“保存”按钮后会先验证是否有非空数据,再验证原密码是否正确,再验证密码和重复密码是否一致,都验证没问题后将会执行修改操作,否则将会弹出对应提示信息。
图5-17修改密码
主要实现代码如下:
public ModelAndView changepsd(HttpServletRequest request){
Map<String,Object> map = new HashMap<String,Object>();
String password = request.getParameter("password");
User user = getSessionUser(request);
user.setPassword(password);
boolean issuc = userService.update(user);
if(issuc){
map.put("msg", "修改密码成功");
}else{
map.put("msg", "修改密码失败,请重新操作");
}
return jsp("changepsd", map, request);
}