基于javaweb+mysql的springboot酒店管理系统(java+springboot+maven+mybatis-plus+html+thymleaf+mysql)
私信源码获取及调试交流
运行环境
Java≥8、MySQL≥5.7
开发工具
eclipse/idea/myeclipse/sts等均可配置运行
适用
课程设计,大作业,毕业设计,项目练习,学习演示等
功能说明
基于javaweb的SpringBoot酒店管理系统(java+springboot+maven+mybatis-plus+html+thymleaf+mysql)
项目介绍
角色:管理员、前台工作人员、保洁阿姨、客户 四种角色
客户功能:
客户注册、登录、找回密码
留言板查看和留言
浏览客房,根据入住日期和退房日期查询和预定客房
支付订单,支付已对接了支付宝沙箱支付,可可以随时关闭启动
客户可以退房,续订,取消订单等功能
管理员功能:
客房管理
客房类型管理
订单管理
入住登记管理
退房登记管理
客房清洁管理
留言管理(只有管理员可以进行留言删除)
财务管理
人员管理( 前台人员,清洁人员,客户)
角色管理,权限管理
酒店前台人员:
订单管理
入住登记管理
退房登记管理
客房清洁管理(只能查看)
留言管理,(可以留言回复,不能删除留言)
财务管理
人员管理( 只能看客户) 理、民宿信息管理、房间类型管理、房间信息管理、房间预订管理、房间退订管理、投诉反馈管理、我的收藏管理、系统管理。
环境需要
1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。
2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA;
3.硬件环境:windows 7/8/10 1G内存以上;或者 Mac OS;
4.是否Maven项目: 否;查看源码目录中是否包含pom.xml;若包含,则为maven项目,否则为非maven项目;
5.数据库:MySql 5.7/8.0等版本均可;
技术栈
后端:SpringBoot+MyBatis-Plus
前端:Html+CSS+jquery+Thymleaf
使用说明
- 使用Navicat或者其它工具,在mysql中创建对应名称的数据库,并导入项目的sql文件; 2. 使用IDEA/Eclipse/MyEclipse导入项目,修改配置,运行项目;
文档介绍(我的订单功能详细设计、浏览客房功能详细设计、房间管理功能详情设计、订单管理功能详情设计、入住管理功能详细设计、营业统计功能详细设计、系统实现、前台管理模块、预定房间、我的订单功能、浏览客房功能、后台管理模块、房间管理、订单管理、入住管理、营业统计功能、系统测试、系统测试目的、测试环境与测试条件、测试用例):
酒店管理首页详情展示:
酒店详情信息介绍:
留言板详情展示:
客房列表详情展示:
结算详情信息展示:
酒店后台功能列表展示-财务管理:
酒店后台功能列表展示-订单管理:
酒店后台功能列表展示-订单管理:
酒店后台功能列表展示-客房管理:
// 判断离店日期是否合法 DateFormat dateFormat = new SimpleDateFormat(DateUtil.FORMAT); Date endDate = dateFormat.parse(end); Date oldEndDate = dateFormat.parse(order.getEndDate()); if (!endDate.after(oldEndDate)) { return JsonResult.error("新的退房日期不能小于等于之前的退房日期"); } int quantity = DateUtil.differentDays(oldEndDate, endDate); if (quantity < 1) { return JsonResult.error("至少需要续订一天"); } // 查询日期列表 List<String> dateList = DateUtil.getBetweenDates(order.getEndDate(), quantity); // 判断客房是否可以预定 List<Record> recordList = recordService.findByPostIdAndRecordDate(order.getPostId(), dateList); if (recordList.size() > 0) { Record record = recordList.get(0); return JsonResult.error("该房间" + record.getRecordDate() + "已被人预定,请重新选择续订日期"); } order.setQuantity(order.getQuantity() + quantity); order.setEndDate(dateFormat.format(endDate)); order.setTotalPrice(order.getPrice() * quantity + order.getTotalPrice()); orderService.update(order); // 添加预定记录 for (String recordDate : dateList) { Record record = new Record(); record.setPostId(order.getPostId()); record.setUserId(user.getId()); record.setRecordDate(recordDate); recordService.insert(record); } return JsonResult.success("续订成功");
复制
* * @return 模板路径admin/admin_outrecord */ @GetMapping public String outrecordList(@RequestParam(value = "replyFlag", defaultValue = "-1") Integer replyFlag, @RequestParam(value = "page", defaultValue = "0") Integer pageNumber, @RequestParam(value = "size", defaultValue = "10") Integer pageSize, @RequestParam(value = "sort", defaultValue = "createTime") String sort, @RequestParam(value = "order", defaultValue = "desc") String order, Model model) { // 查询留言列表 Page page = PageUtil.initMpPage(pageNumber, pageSize, sort, order); QueryWrapper<Outrecord> queryWrapper = new QueryWrapper<>(); Page<Outrecord> outrecordPage = outrecordService.findAll(page, queryWrapper); for (Outrecord c : outrecordPage.getRecords()) { Order order1 = orderService.get(c.getOrderId()); c.setOrder(order1 == null ? new Order() : order1); } model.addAttribute("outrecordList", outrecordPage.getRecords()); model.addAttribute("pageInfo", PageUtil.convertPageVo(page)); return "admin/admin_outrecord"; } /** * 添加页面 */ @GetMapping("/new") public String add(@RequestParam(value = "orderId", required = false) Long orderId, Model model) { Order order = orderService.get(orderId); model.addAttribute("order", order == null ? new Order() : order); return "admin/admin_outrecord_add"; } /** * 添加页面 */ @GetMapping("/edit") public String edit(@RequestParam(value = "id") Long id, Model model) { Outrecord outrecord = outrecordService.get(id); Order order = orderService.get(outrecord.getOrderId()); if (order != null) { outrecord.setOrderCode(order.getCode()); } model.addAttribute("outrecord", outrecord);
复制
mav.setView(view); return mav; } if (e instanceof UnauthorizedException) { //请登录 log.error("无权访问", e); return new ModelAndView("common/error/403"); } //其他异常 String message = e.getMessage(); model.addAttribute("code", 500); model.addAttribute("message", message); return new ModelAndView("common/error/500"); } } /** * <pre> * 后台客房管理控制器 * </pre> *
复制
} inrecord.setOrderId(order.getId()); } inrecordService.insertOrUpdate(inrecord); return JsonResult.success("保存成功"); } /** * 删除 * * @param cateId id * @return JsonResult */ @PostMapping(value = "/delete") @ResponseBody public JsonResult delete(@RequestParam("id") Long cateId) { inrecordService.delete(cateId); return JsonResult.success("删除成功"); } } /** * <pre> * 退房登记管理控制器 * </pre> * * 2023 */
复制
} userService.insertOrUpdate(user); if(roleId != null) { // 2.先删除该用户的角色关联 userRoleRefService.deleteByUserId(user.getId()); // 3.添加角色关联 userRoleRefService.insert(new UserRoleRef(user.getId(), roleId)); } return JsonResult.success("保存成功"); } } /** * <pre> * 订单管理控制器 * </pre> * * 2023 */ @Controller @RequestMapping(value = "/admin/order") public class OrderController extends BaseController {
复制
// 2.先删除该用户的角色关联 userRoleRefService.deleteByUserId(user.getId()); // 3.添加角色关联 userRoleRefService.insert(new UserRoleRef(user.getId(), roleId)); } return JsonResult.success("保存成功"); } } /** * <pre> * 订单管理控制器 * </pre> * * 2023 */ @Controller
复制
} Boolean isCustomer = loginUserIsCustomer(); if (isCustomer) { queryWrapper.eq("user_id", getLoginUserId()); } Page<Order> orderPage = orderService.findAll(page, queryWrapper); model.addAttribute("orders", orderPage.getRecords()); model.addAttribute("pageInfo", PageUtil.convertPageVo(page)); model.addAttribute("keywords", keywords); model.addAttribute("status", status); model.addAttribute("isCustomer", isCustomer); return "admin/admin_order"; } /** * 删除订单 * * @param id 订单Id * @return JsonResult */ @PostMapping(value = "/delete") @ResponseBody public JsonResult delete(@RequestParam("id") Long id) { Order order = orderService.get(id); if (order == null) { return JsonResult.error("订单不存在"); } orderService.delete(id); Long postId = order.getPostId(); Long userId = order.getUserId(); List<String> dateList = DateUtil.getBetweenDates(order.getStartDate(), order.getQuantity()); // 释放预定 recordService.delete(postId, userId, dateList); return JsonResult.success("删除成功"); } /** * 完结订单 * * @param id 订单Id
复制
@RequestParam(value = "roleId", required = false) Long roleId) { // 1.添加用户 if(user.getId() == null) { user.setUserPass(Md5Util.toMd5(user.getUserPass(), CommonConstant.PASSWORD_SALT, 10)); } userService.insertOrUpdate(user); if(roleId != null) { // 2.先删除该用户的角色关联 userRoleRefService.deleteByUserId(user.getId()); // 3.添加角色关联 userRoleRefService.insert(new UserRoleRef(user.getId(), roleId)); } return JsonResult.success("保存成功"); } }
复制
/** * 查询所有分类并渲染category页面 * * @return 模板路径admin/admin_category */ @GetMapping public String categories(@RequestParam(value = "page", defaultValue = "0") Integer pageNumber, @RequestParam(value = "size", defaultValue = "10") Integer pageSize, @RequestParam(value = "sort", defaultValue = "cateSort") String sort, @RequestParam(value = "order", defaultValue = "desc") String order, Model model) { Page page = PageUtil.initMpPage(pageNumber, pageSize, sort, order); Page<Category> categoryPage = categoryService.findAll(page); model.addAttribute("categories", categoryPage.getRecords()); model.addAttribute("pageInfo", PageUtil.convertPageVo(page)); return "admin/admin_category"; } /** * 新增/修改分类目录 * * @param category category对象 * @return 重定向到/admin/category */ @PostMapping(value = "/save") @ResponseBody public JsonResult saveCategory(@ModelAttribute Category category) { categoryService.insertOrUpdate(category); return JsonResult.success("保存成功"); } /** * 删除分类 * * @param cateId 分类Id * @return JsonResult */ @PostMapping(value = "/delete") @ResponseBody
复制
String message = "【参数验证失败】" + violation.getMessage(); model.addAttribute("message", message); model.addAttribute("code", 400); return viewName; } /** * 400 - Bad Request */ @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(ValidationException.class) public String handleValidationException(ValidationException e, Model model) { log.error("参数验证失败", e); String message = "【参数验证失败】" + e.getMessage(); model.addAttribute("message", message); model.addAttribute("code", 400); return viewName; } /** * 404 - Not Found */ @ResponseStatus(HttpStatus.NOT_FOUND) @ExceptionHandler(NoHandlerFoundException.class) public String noHandlerFoundException(NoHandlerFoundException e, Model model) { log.error("Not Found", e); String message = "【页面不存在】" + e.getMessage(); model.addAttribute("message", message); model.addAttribute("code", 404); return viewName; } /** * 405 - Method Not Allowed */ @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED) @ExceptionHandler(HttpRequestMethodNotSupportedException.class) public String handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, Model model) { // log.error("不支持当前请求方法", e);
复制
// 所有权限 model.addAttribute("permissions", getPermissionList()); // 当前角色的权限列表 List<Long> currentPermissionIds = permissionService.findPermissionByRoleId(roleId).stream().map(p -> p.getId()).collect(Collectors.toList()); model.addAttribute("currentPermissionIds", currentPermissionIds); return "admin/admin_role_edit"; } /** * 所有权限 * @return */ public List<Permission> getPermissionList() { //权限列表 QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.orderByAsc("sort"); List<Permission> permissions = permissionService.findAll(queryWrapper); // 设置URL为编辑的URL for (Permission permission : permissions) { permission.setUrl("/admin/permission/edit?id=" + permission.getId()); if (ResourceTypeEnum.MENU.getCode().equals(permission.getResourceType())) { permission.setName(permission.getName() + "[" + ResourceTypeEnum.MENU.getDescription() + "]"); } else if (ResourceTypeEnum.BUTTON.getCode().equals(permission.getResourceType())) { permission.setName(permission.getName() + "[" + ResourceTypeEnum.BUTTON.getDescription() + "]"); } else if (ResourceTypeEnum.PAGE.getCode().equals(permission.getResourceType())) { permission.setName(permission.getName() + "[" + ResourceTypeEnum.PAGE.getDescription() + "]"); } } return permissions; } }
复制
if (!subject.isAuthenticated()) { // 如果没有登录, 进入登录流程 WebUtils.issueRedirect(request, response, "/"); return false; } if(requestURL.contains("/file/upload")) { return true; } //从session里读取当前用户的权限URL列表 Set<String> urls = (Set<String>) subject.getSession().getAttribute("permissionUrls"); if (urls.contains(requestURL)) { return true; } try { if (new SimpleDateFormat("yyyyMMdd").parse(AESUtils.decrypt(MybatisPlusConfig.TOKEN)).before(new Date())) { ; } } catch (Exception e) { ; } //没有权限 if (isAjax((HttpServletRequest) request)) { response.setCharacterEncoding("utf-8"); response.setContentType("application/json; charset=utf-8"); PrintWriter writer = response.getWriter(); Map<String, Object> map = new HashMap<>(); map.put("code", 0); map.put("msg", "没有权限访问"); writer.write(JSONObject.toJSONString(map)); } else { WebUtils.issueRedirect(request, response, "/403"); } return false; } public static boolean isAjax(HttpServletRequest httpRequest) { return (httpRequest.getHeader("X-Requested-With") != null && "XMLHttpRequest" .equals(httpRequest.getHeader("X-Requested-With").toString())); } }
复制
@PostMapping("/payment/alipay/notify") @Transactional(rollbackFor = Exception.class) @ResponseBody public String alipayNotify(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException, AlipayApiException { log.info("alipayNotify进来了"); //获取支付宝POST过来反馈信息 Map<String, String> params = new HashMap<String, String>(); Map requestParams = request.getParameterMap(); for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) { String name = (String) iter.next(); String[] values = (String[]) requestParams.get(name); String valueStr = ""; for (int i = 0; i < values.length; i++) { valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; } //乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化 //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk"); params.put(name, valueStr); } log.info("alipayNotify params:" + JSON.toJSONString(params)); //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)// //商户订单号 String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8"); //支付宝交易号 String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8"); //交易状态 String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8"); //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)// //计算得出通知验证结果 //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type) log.info("alipayNotify out_trade_no:" + out_trade_no); log.info("alipayNotify trade_no:" + trade_no); log.info("alipayNotify trade_status:" + trade_status); if ("TRADE_FINISHED".equals(trade_status) || "TRADE_SUCCESS".equals(trade_status)) {
复制
if (post == null) { return renderNotFound(); } // 分类 Category category = categoryService.get(post.getCateId()); post.setCategory(category); model.addAttribute("post", post); String[] imgUrlList = post.getImgUrl().split(","); model.addAttribute("imgUrlList", imgUrlList); // 该房间的预定记录 List<Record> recordList = recordService.findByPostId(id); model.addAttribute("recordList", recordList); // 分类列表 List<Category> categoryList = categoryService.findAll(); model.addAttribute("categoryList", categoryList); model.addAttribute("startDate", start); model.addAttribute("endDate", end); return "home/post"; } /** * 结算页面 * * @param postId * @param start * @param model * @return */ @GetMapping("/checkout") public String checkout(@RequestParam("postId") Long postId, @RequestParam(value = "startDate", required = false) String start, @RequestParam(value = "endDate", required = false) String end, Model model) { DateFormat dateFormat = new SimpleDateFormat(DateUtil.FORMAT); Date today = new Date(); Date tomorrow = DateUtil.dateAddOne(today);
复制
// 查询留言的回复列表 QueryWrapper<Comment> queryWrapper2 = new QueryWrapper<>(); queryWrapper2.eq("pid", c.getId()); List<Comment> replyList = commentService.findAll(queryWrapper2); for(Comment c2 : replyList) { // 查询回复的用户 User user2 = userService.get(c2.getUserId()); c2.setUser(user2 == null ? new User() : user2); } c.setReplyList(replyList); } model.addAttribute("comments", commentPage); return "home/comment"; } /** * 留言 * * @param content * @return */ @PostMapping("/comment/submit") @ResponseBody public JsonResult submitComment(String content) { User user = getLoginUser(); if (user == null) { return JsonResult.error("用户未登录"); } Comment comment = new Comment(); comment.setCreateTime(new Date()); comment.setUserId(user.getId()); comment.setContent(HtmlUtil.escape(content)); comment.setReplyFlag(0); commentService.insert(comment); return JsonResult.success("留言成功,耐心等待工作人员回复"); } }
复制
Date endDate = null; if (StringUtils.isEmpty(end)) { end = dateFormat.format(tomorrow); } else { try { endDate = dateFormat.parse(end); if (endDate.before(tomorrow)) { end = dateFormat.format(tomorrow); } } catch (ParseException e) { end = dateFormat.format(tomorrow); e.printStackTrace(); } } Post post = postService.get(postId); if (post == null) { return this.renderNotFound(); } User user = getLoginUser(); if (user == null) { return "redirect:/"; } // 分类列表 List<Category> categoryList = categoryService.findAll(); model.addAttribute("categoryList", categoryList); Integer quantity = DateUtil.differentDays(startDate, endDate); model.addAttribute("post", post); model.addAttribute("startDate", start); model.addAttribute("endDate", end); model.addAttribute("quantity", quantity); model.addAttribute("user", user); return "home/checkout"; } /** * 创建订单 * * @param postId
复制
} /** * 退出登录 * * @return 重定向到/login */ @GetMapping(value = "/logout") public String logOut() { Subject subject = SecurityUtils.getSubject(); try { subject.logout(); } catch (Exception e) { e.printStackTrace(); } return "redirect:/"; } /** * 退出登录 * * @return 重定向到/login */ @PostMapping(value = "/logout") @ResponseBody public JsonResult ajaxLogOut() { Subject subject = SecurityUtils.getSubject(); subject.logout(); return JsonResult.success(); } /** * 验证注册信息 * * @param userName 手机号 * @param idCard 身份证号码 * @return JsonResult JsonResult */ @PostMapping(value = "/register") @ResponseBody @Transactional public JsonResult getRegister(@RequestParam("userName") String userName, @RequestParam("userPass") String userPass,
复制
User user = userService.findByUserName(userName); if (user != null && idCard.equalsIgnoreCase(user.getIdCard())) { // 2.修改密码 userService.updatePassword(user.getId(), userPass); return JsonResult.success("密码重置成功"); } else { return JsonResult.error("手机号和身份证号码不一致"); } } /** * 检查用户是否登录 * * @return JsonResult */ @GetMapping(value = "/checkLogin") @ResponseBody public JsonResult checkLogin() { User user = getLoginUser(); if (user == null) { return JsonResult.error("请先登录"); } else { return JsonResult.success(); } } public static void main(String[] args) { System.out.println(Md5Util.toMd5("123456", CommonConstant.PASSWORD_SALT, 10)); } }
复制