SpringBoot + Vue Hotel Booking Management System
In the digital transformation era, the hotel industry is actively adopting advanced information technology to optimize customer experience and operational efficiency. This study aims to develop a hotel booking management system based on Spring Boot backend framework and Vue.js frontend framework to meet modern hotels' needs for efficient, convenient, and secure booking management.
The system uses Spring Boot as the core of its backend technology stack, handling business logic, data storage, and security control. It employs Spring Security for permission menagement and user authentication. MySQL is used as the relational database to ensure data consistency and transactionality. Redis is utilized as a caching layer to enhance data read speed and reduce database pressure.
The frontend interface is built using Vue.js, providing an intuitive and responsive user interface with features such as room search, booking, cancellation, payment, and map services for location and nearby facilities information.
Security-wise, JWT (JSON Web Tokan) is used for identity verification to ensure secure communication.
The implementation of this system not only improved hotel booking management efficiency but also significantly enhanced customers' online booking experience. Performance tests and user feedback confirmed the system's superiority in response time, usability, and security, supporting the hotel industry's digital progress.
Code Snippets
Backend Controller
package com.example.hotel.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.hotel.common.CommonResult;
import com.example.hotel.common.StatusCode;
import com.example.hotel.domain.User;
import com.example.hotel.dto.LoginDTO;
import com.example.hotel.dto.PasswordDTO;
import com.example.hotel.dto.RegisterDTO;
import com.example.hotel.dto.ReturnUserDTO;
import com.example.hotel.service.UserService;
import com.example.hotel.util.WebUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private UserService userService;
@PostMapping(value = "/register")
public CommonResult<String> register(@RequestBody RegisterDTO registerDTO) {
long count = userService.count(new QueryWrapper<User>().eq("email", registerDTO.getEmail()));
if(count > 0) {
CommonResult<String> commonResult = new CommonResult<>();
commonResult.setData("Email already exists");
commonResult.setCode(StatusCode.COMMON_FAIL.getCode());
commonResult.setMessage(StatusCode.COMMON_FAIL.getMessage());
return commonResult;
}
CommonResult<String> commonResult = new CommonResult<>();
User user = new User();
BeanUtils.copyProperties(registerDTO, user);
user.setPassword(SecureUtil.md5(registerDTO.getPassword()));
userService.save(user);
commonResult.setData("Registration successful");
commonResult.setCode(StatusCode.COMMON_SUCCESS.getCode());
commonResult.setMessage(StatusCode.COMMON_SUCCESS.getMessage());
return commonResult;
}
@PostMapping(value = "/login")
public CommonResult<String> login(@RequestBody LoginDTO loginDTO) {
CommonResult<String> commonResult = new CommonResult<>();
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("email", loginDTO.getEmail());
String md5Password = SecureUtil.md5(loginDTO.getPassword());
queryWrapper.eq("password", md5Password);
User user = userService.getBaseMapper().selectOne(queryWrapper);
if (null != user) {
WebUtils.getSession().setAttribute("loginUser", user);
commonResult.setCode(StatusCode.COMMON_SUCCESS.getCode());
commonResult.setMessage(StatusCode.COMMON_SUCCESS.getMessage());
commonResult.setData("Login successful");
} else {
commonResult.setCode(StatusCode.COMMON_FAIL.getCode());
commonResult.setMessage(StatusCode.COMMON_FAIL.getMessage());
commonResult.setData("Invalid credentials");
}
return commonResult;
}
@GetMapping("/logout")
public CommonResult<String> logout(){
CommonResult<String> commonResult = new CommonResult<>();
WebUtils.getSession().removeAttribute("loginUser");
commonResult.setCode(StatusCode.COMMON_SUCCESS.getCode());
commonResult.setMessage(StatusCode.COMMON_SUCCESS.getMessage());
commonResult.setData("Logout successful!");
return commonResult;
}
@GetMapping("/userDetail")
public CommonResult<ReturnUserDTO> userDetail() {
CommonResult<ReturnUserDTO> commonResult = new CommonResult<>();
ReturnUserDTO returnUser = new ReturnUserDTO();
User user = (User) WebUtils.getSession().getAttribute("loginUser");
BeanUtils.copyProperties(user, returnUser);
commonResult.setCode(StatusCode.COMMON_SUCCESS.getCode());
commonResult.setMessage(StatusCode.COMMON_SUCCESS.getMessage());
commonResult.setData(returnUser);
return commonResult;
}
@PostMapping("/updatePassword")
public CommonResult<String> updatePassword(@RequestBody PasswordDTO passwordDTO) {
CommonResult<String> commonResult = new CommonResult<>();
QueryWrapper queryWrapper = new QueryWrapper();
User user = (User) WebUtils.getSession().getAttribute("loginUser");
String md5OldPassword = SecureUtil.md5(passwordDTO.getOldPassword());
if (!user.getPassword().equals(md5OldPassword)) {
commonResult.setCode(StatusCode.COMMON_FAIL.getCode());
commonResult.setMessage(StatusCode.COMMON_FAIL.getMessage());
commonResult.setData("Incorrect old password");
return commonResult;
}
String md5NewPassword = SecureUtil.md5(passwordDTO.getNewPassword());
user.setPassword(md5NewPassword);
userService.updateById(user);
commonResult.setCode(StatusCode.COMMON_SUCCESS.getCode());
commonResult.setMessage(StatusCode.COMMON_SUCCESS.getMessage());
commonResult.setData("Password updated successfully");
return commonResult;
}
}
Frontend Component
<template>
<div>
<el-container class="wrapper">
<el-main class="section text-center">
<div class="login-bg"></div>
<el-card class="box-card login-card">
<div class="text item">
<p class="login-title">
<i class="iconfont icon-r-yes" style="font-size: 32px"></i>
Hotel Booking System
</p>
<el-form :model="login" status-icon ref="login" label-width="80px">
<el-form-item label="Account Email" prop="email">
<el-input type="text" v-model="login.email" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="Password" prop="pass">
<el-input type="password" v-model="login.password" autocomplete="off"></el-input>
</el-form-item>
</el-form>
</div>
</el-card>
<el-button circle :type="btnType" @click="loginBtn" class="loginbtn" :disabled="disabled">
<i :class="iconstyle" style="font-size: 54px"></i>
</el-button>
<div class="register">
<p>
<router-link to="/register" style="color: black">Register Account</router-link>
</p>
</div>
</el-main>
</el-container>
<el-footer class="footer text-center">
<copyright></copyright>
</el-footer>
</div>
</template>
<script>
import copyright from '@/components/copyright.vue';
import store from '../store';
export default {
data() {
return {
login: {
email: '',
password: '',
},
iconstyle: 'iconfont icon-r-right',
disabled: false,
btnType: 'primary',
isRealLogin: true,
};
},
components: {
copyright,
},
methods: {
loginBtn() {
if (this.login.email.trim() === '' || this.login.password.trim() === '') {
this.$message({
message: 'Email or password cannot be empty',
type: 'error',
});
return;
}
this.iconstyle = 'el-icon-loading';
this.disabled = true;
this.axios.post('http://localhost:9151/user/login', {
email: this.login.email,
password: this.login.password,
}).then(res => {
if (res.data.code === 200) {
this.iconstyle = 'el-icon-check';
this.btnType = 'success';
this.$message({
message: 'Login successful, redirecting...',
type: 'success',
});
setTimeout(() => {
this.disabled = false;
this.$store.commit('setFind');
this.$router.push('/findroom');
}, 2000);
} else {
this.iconstyle = 'el-icon-close';
this.btnType = 'danger';
this.$message({
message: 'Login failed, invalid credentials',
type: 'error',
});
setTimeout(() => {
this.disabled = false;
this.iconstyle = 'iconfont icon-r-right';
this.btnType = 'primary';
}, 2000);
}
}).catch(e => {
this.iconstyle = 'el-icon-close';
this.btnType = 'danger';
setTimeout(() => {
this.disabled = false;
this.iconstyle = 'iconfont icon-r-right';
this.btnType = 'primary';
}, 2000);
if (e.response === undefined || e.response.data === undefined) {
this.$message({
showClose: true,
message: e,
type: 'error',
duration: 0,
});
} else {
this.$message({
showClose: true,
message: e.response.data,
type: 'error',
duration: 0,
});
}
});
},
nologinBtn() {
this.$store.commit('setFind');
this.$router.push('/findroom');
},
},
};
</script>
<style scoped>
.login-bg {
background: rgb(65, 105, 225);
height: 30vh;
background-size: 100%;
border: 0px solid transparent;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
.text {
font-size: 14px;
}
.item {
/* padding: 18px 0; */
}
.login-card {
margin: -7rem 1rem 1rem 1rem;
}
.login-title {
font-size: 2rem;
font-weight: lighter;
margin-top: 1rem;
}
.wrapper {
min-height: 90vh;
}
.el-main {
max-height: 90vh;
}
#app {
overflow: hidden;
}
.loginbtn {
width: 7rem;
height: 7rem;
font-size: 1.5rem;
margin-top: 2rem;
}
.register {
margin-top: 5vh;
}
.register a,
.register div {
color: #409eff;
}
.register p {
margin: 0.5rem;
}
</style>
Source Code Download
Download link: Baidu Cloud Extraction code: 1234