酒店后台管理系统
这是一个基于ssm+jsp的maven后台管理系统项目,使用idea,Mysql来搭建项目,在完成项目后,我想通过一篇博客来记录我的学习过程已经对项目进行讲解,具体的代码会放在Github上
功能介绍:
1,能够实现对系统管理员进行授权,不同级别的管理员可以授予不同的管理员权限。
2,能够实现入住信息的查询,添加,删除。
3,能够实现对客房信息的查询,已经管理不同类型的客房
4,管理VIP客户
功能展示
添加系统用户
注册会员
入住信息
在介绍项目之前,我想先记录一个分页功能和按条件查询功能(手机号,姓名,房间号),分页在展示数据的时候是必不可少的,按条件查询也同样重要
1在pom中加分页插件
<!-- 分页插件 --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>4.1.6</version></dependency>
2, 配置mybatis的分页插件PageHelper
<!-- 配置mybatis的分页插件PageHelper --><plugins><!-- com.github.pagehelper为PageHelper类所在包名 --><plugin interceptor="com.github.pagehelper.PageHelper"><!-- 设置数据库类型Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库 --><property name="dialect" value="mysql"/></plugin></plugins>
在service层调用
3,service层
@AutowiredUserDao userDao;@Overridepublic List<Map<String, Object>> findUsersInfo(Map<String, Object> paramMap, Integer pageNum, Integer pageSize) {PageHelper.startPage(pageNum, pageSize);return userDao.selectUser(paramMap);}
在controller层调用
4,controller层@RequestMapping("/getUserInfo.do")public String getInRoomInfo(Model model,@RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,@RequestParam(value = "pageSize", required = false, defaultValue = "2") Integer pageSize,@RequestParam(value = "name", required = false) String name,@RequestParam(value = "email", required = false) String email,@RequestParam(value = "tel", required = false) String tel){Map<String, Object> paramMap = new HashMap<String, Object>();if(name!=null){name=name.trim();}if(email!=null){email=email.trim();}if(tel!=null){tel=tel.trim();}paramMap.put("name", name);paramMap.put("email", email);paramMap.put("tel",tel);List<Map<String, Object>> usersInfo = userService.findUsersInfo(paramMap, pageNum, pageSize);PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(usersInfo);model.addAttribute("pageInfo",pageInfo);return "testuserinfo.jsp";}
在jsp页面
<script src="${pageContext.request.contextPath }/static/js/bootstrap/jquery.min.js"></script><!-- 引入bootstrap分页 --><link rel="stylesheet" href="${pageContext.request.contextPath }/static/js/bootstrap/bootstrap.css" /><%-- <script src="<%=basePath%>/static/js/bootstrap/jquery.min.js"></script> --%><script src="${pageContext.request.contextPath }/static/js/bootstrap.min.js"></script><script src="${pageContext.request.contextPath }/static/js/bootstrap-paginator.js"></script><div class="row"><div class="col-md-6">第${pageInfo.pageNum}页,共${pageInfo.pages}页,共${pageInfo.total}条记录</div><div class="col-md-6 offset-md-4"><nav aria-label="Page navigation example"><ul class="pagination pagination-sm"><li class="page-item"><a class="page-link" href="${pageContext.request.contextPath}/getUserInfo.do?pageNum=1">首页</a></li><c:if test="${pageInfo.hasPreviousPage}"><li class="page-item"><a class="page-link"href="${pageContext.request.contextPath}/getUserInfo.do?pageNum=${pageInfo.pageNum-1}">上一页</a></li></c:if><c:forEach items="${pageInfo.navigatepageNums}" var="page"><c:if test="${page==pageInfo.pageNum}"><li class="page-item active"><a class="page-link" href="#">${page}</a></li></c:if><c:if test="${page!=pageInfo.pageNum}"><li class="page-item"><a class="page-link"href="${pageContext.request.contextPath}/getUserInfo.do?pageNum=${page}">${page}</a></li></c:if></c:forEach><c:if test="${pageInfo.hasNextPage}"><li class="page-item"><a class="page-link"href="${pageContext.request.contextPath}/getUserInfo.do?pageNum=${pageInfo.pageNum+1}">下一页</a></li></c:if><li class="page-item"><a class="page-link" href="${pageContext.request.contextPath}/getUserInfo.do?pageNum=${pageInfo.pages}">末页</a></li></ul></nav></div></div>
按条件查询
实现步骤:
1,在jsp页面的form标签中以post的方式发请求到获取全部用户信息的请求方法getInRoomInfo.do。
<table><form action="<%=basePath %>/getInRoomInfo.do" method="post" name="serch"><tr><td class="zi"><span>选择分类:</span></td><td><select id="conditionType"><option value="roomNum">房间号</option><option value="customerName">客人姓名</option><option value="phone">手机号码</option></select></td><td class="zi"><span>关键字:</span></td><td><input id="keyword" name="roomNum" type="text" value="" placeholder="与分类关联"/></td><td><input type="submit" value="查询" class="button"/></td></tr></form></table><script type="text/javascript">jQuery(function(){jQuery("#conditionType").change(function(){var v = jQuery(this).find("option:selected").val();console.log(v);jQuery("#keyword").attr("name",v);});});</script>
在controller中,将customerName,roomNum,phone放入map集合中再去调用service方法,由于只能按照一个条件去查询,所以这三个参数只有一个是有值的,另外两个是null的。
@RequestMapping("/getInRoomInfo.do")public String getInRoomInfo(Model model,@RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,@RequestParam(value = "pageSize", required = false, defaultValue = "3") Integer pageSize,@RequestParam(value = "customerName", required = false) String customerName,@RequestParam(value = "roomNum", required = false) String roomNum,@RequestParam(value = "phone", required = false) String phone) {Map<String, Object> paramMap = new HashMap<String, Object>();paramMap.put("customerName", customerName);paramMap.put("roomNum", roomNum);paramMap.put("phone", phone);List<Map<String, Object>> inRoomList = inRoomService.findInRoomInfo(paramMap, pageNum, pageSize);PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(inRoomList);model.addAttribute("pageInfo", pageInfo);return "bill/inroominfo.jsp";}
service层中调用dao方法接口
在Mapper中SQL是这样写的,使用if标签,使得传进来的非空的值能够成为条件拼接到SQL语句中。
<!-- 查询入住信息 --><select id="selectInRoomInfo" resultType="Map" parameterType="Map">SELECT iri.out_room_status,rm.room_num,rt.room_type_name,iri.customer_name,iri.gender,iri.phone,iri.money,iri.idcard,iri.create_date,iri.is_vip,vp.vip_rateFROM hotel.in_room_info iri INNER JOIN hotel.rooms rm ON iri.room_id=rm.idINNER JOIN hotel.room_type rt ON rt.id=rm.room_type_id LEFT JOIN hotel.vip vp ONiri.idcard=vp.idcard WHERE iri.status='1'<if test="customerName!=null and customerName!=''">AND iri.customer_name=#{customerName}</if><if test="roomNum!=null and roomNum!=''">and rm.room_num=#{roomNum}</if><if test="phone!=null and phone!=''">AND iri.phone=#{phone}</if></select>
项目搭建:只需要配置Spring,Springmvc,Mybatis的配置文件,CSDN上很多这种文件,只需要修改一下数据库文件即可使用,需要注意的是不同版本的数据库文件数据库驱动不同,这里代码就不贴上来了。
自此,项目的底层就搭建好了!
.接下来我分三层,来讲解我的项目:dao层(持久层),service(服务层),controller(层)
持久层主要用于操作数据库,实现对数据库的增删改查
- 代码不在一一赘述,我想记录一些SQl语句,便于后来学习。
首先是验证登录的SQL,用户名,密码正确,使用状态为1
<select id="login" resultType="Integer">SELECT COUNT(*) FROM system_user where username=#{username} AND pwd=#{password} AND use_status=1</select>
2,授权信息列表 ,因为不同权限的管理登录,他拥有的权限也是不同的,所以在完成登录之后需要去获取权限
<select id="getSQAuthority" resultMap="BaseOneMenu">SELECT * FROM(SELECT id AS oneId,authority_name AS oneName FROM system_authority WHERE parent=0) t1INNER JOIN(SELECT id AS twoId,authority_name AS twoName,authority_url AS url,parentFROM system_authority WHERE parent!=0) t2ON t2.parent=t1.oneId WHERE t1.oneId!=5</select>
<!-- 根据用户id获取具体的权限 --><select id="getAuthorityByUsername" resultMap="BaseOneMenu">select * from(select sa.id as oneId,sa.authority_name as oneName from hotel.system_authority sainner join hotel.user_authority ua on sa.id=ua.authority_idinner join hotel.system_user su on su.id=ua.user_id where su.username=#{0} and sa.parent=0) t1inner join(select sa.id as twoId,sa.authority_name as twoName,sa.authority_url as url,sa.parent from hotel.system_authority sainner join hotel.user_authority ua on sa.id=ua.authority_idinner join hotel.system_user su on su.id=ua.user_id where su.username=#{0} and sa.parent!=0) t2on t1.oneId=t2.parent;</select>
在service层中完成调用Mapper的方法,实现基本的业务逻辑
注入Mapper对象
@Autowiredprivate LoginMapper loginMapper;
验证登录
@Transactional(readOnly = false)public boolean login(String username, String pwd, HttpSession session) throws Exception {// 对明文密码进行加密后在调用mapper层pwd = MD5Tool.md5(pwd);int flag = loginMapper.login(username, pwd);if (flag >= 1) {List<OneMenu> oneMenuList = loginMapper.getAuthorityByUsername(username);session.setAttribute("oneMenuList", oneMenuList);session.setAttribute("username", username);return true;}return false;
controller层:调用service层的业务逻辑,并且返回给前端
注入service对象用于调用,登录成功即可跳到首页,登录失败则跳到登录页重新登录
@Controller
public class LoginController {@Resourceprivate LoginService loginService;@RequestMapping("/login.do")public String login(String username, String pwd, HttpSession session) throws Exception {boolean flag = loginService.login(username, pwd, session);return flag ? "index.jsp" : "login.jsp";}}
以上便是登录功能,接下来介绍增加系统管理员功能
向系统添加管理员涉及到两条SQL
<!-- 添加系统用户parameterType参数类型 keyProperty:key的值 keyColumn:取到的对应数据库的列--><insert id="insertSystemUser" parameterType="Map" useGeneratedKeys="true" keyProperty="userId" keyColumn="id">INSERT INTO SYSTEM_USER VALUES(NULL,#{username},#{pwd},NOW(),'1','0')</insert><!-- 添加二级权限信息 --><insert id="insertAuthority" parameterType="Long" >INSERT INTO user_authority VALUES(#{userId},#{authority})</insert>
因为这个功能的实现,需要涉及到多张表,因此在这里着重记录一下数据库的相关知识
只读事务(@Transactional(readOnly = true))的一些概念
注意是一次执行多次查询来统计某些信息,这时为了保证数据整体的一致性,要用只读事务,在将事务设置成只读后,相当于将数据库设置成只读数据库,此时若要进行写的操作,会出现错误
service层中,使用map,将用户名和密码放入map集合中,然后调用登录的接口,验证登录。再将userId与权限id都添加到user_authority表中
@Transactional(readOnly = false)@Overridepublic boolean saveSystemUser(String username, String pwd, String oneIds, String twoIds) throws Exception {// 1、往system_user表中添加数据,获取生成的主键值Map<String, Object> paramMap = new HashMap<>();paramMap.put("username", username);paramMap.put("pwd", MD5Tool.md5(pwd));int flag1 = systemUserMapper.insertSystemUser(paramMap);// 2、将userId与权限id都添加到user_authority表中中if (flag1 <= 0)return false;Long userId = Long.parseLong(paramMap.get("userId") + "");String idStr = oneIds + twoIds;// "1,1,1,4,4,10,12,14"String[] idAttr = idStr.replaceAll("(.,)\\1+", "$1").split("\\,");for (String authorityId : idAttr) {int flag2 = systemUserMapper.insertAuthority(userId, Long.parseLong(authorityId));if (flag2 <= 0){return false;}}return true;}
controller中去调用即可
/* 添加系统用户(同时授权)*/@RequestMapping("/addSystemUser.do")public @ResponseBodyboolean addSystemUser(String username, String pwd, String oneIds, String twoIds)throws Exception {return systemUserService.saveSystemUser(username, pwd, oneIds, twoIds);}@RequestMapping("/getSystemUserByLimit.do")public String getSystemUserByLimit(Model model,@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {List<Map<String, Object>> systemUserList = systemUserService.findSystemUserByLimit(pageNum, pageSize);model.addAttribute("systemUserList", systemUserList);return "user/showSystemUser.jsp";}
以上记录的是两个比较常见的功能,其他功能类似,就不在一一介绍了。