这个项目是本人在工作之余利用闲暇时间进行开发的,主要是为了弥补大学毕业设计的遗憾(本人并不是没有过_,只是没有做自己喜欢的毕业设计)。酒店信息管理系统是一个前后端分离项目,前端使用vue,后端使用java开发,开发完后部署在云服务器上。
废话少说直接上项目地址,http://121.43.170.105:8004
账号:black 密码:root (也可以自行注册)
如果有不明白可以看我的主页关于酒店信息管理项目系列的文章
- 酒店信息管理项目——之短信验证码登录
- 前言
- 一、项目结构和技术栈的使用
- 二、功能介绍
- 1.短信验证码登录
前言
有需要代码的小伙伴私信我WX: 1208191350
一、项目结构和技术栈的使用
项目的整体结构采用的是前后端分离的形式:
后端框架的使用:spring-boot maven mybatis-plus mybatisX
后端技术栈的使用:
1.JWT令牌权限校验与授权登录
2.短信验证码登录,使用阿里云短信服务
3.swagger api接口文档生成器
4.mybatis-plus-generator 代码生成
5.七牛云图片上传服务,将图片保存到三方服务器
6.结合数据库使用spring-boot的定时调度任务
7.redis进行短信验证码的验证,和JWT令牌(Token)的激活(保活)
后台项目结构:
前端框架的使用:vue-cli3 element-ui vue-router
前端技术栈的使用:html css scss js vue axsio
前端项目结构:
1.1使用redis的工具类:
package com.hotel.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
// 去除警告
@SuppressWarnings("all")
public class RedisUtil {
@Autowired
private RedisTemplate redisTemplate;
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
//============================String=============================
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
//================================Map=================================
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
public Map
1.1使用导入阿里云短信服务的依赖包:
com.aliyun
aliyun-java-sdk-core
4.4.6
com.aliyun
aliyun-java-sdk-ecs
4.17.6
org.apache.tomcat.embed
tomcat-embed-core
org.apache.tomcat.embed
tomcat-embed-core
1.3使用阿里云短息服务的工具类:
package com.hotel.sms;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Random;
public class SmsUtil {
static final String accessKeyId ;
static final String accessKeySecret ;
static {
InputStream inputStream = SmsUtil.class.getClassLoader().getResourceAsStream("sms.properties");
Properties properties = new Properties();
try {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
accessKeyId = properties.getProperty("accessKeyId");
accessKeySecret = properties.getProperty("accessKeySecret");
}
public static String sendSms(String phoneNum) throws Exception {
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
IAcsClient client = new DefaultAcsClient(profile);
CommonRequest request = new CommonRequest();
request.setSysMethod(MethodType.POST);
request.setSysDomain("dysmsapi.aliyuncs.com");
request.setSysVersion("2017-05-25");
request.setSysAction("SendSms");
request.putQueryParameter("RegionId", "cn-hangzhou");
request.putQueryParameter("PhoneNumbers", phoneNum);//设置手机号
request.putQueryParameter("SignName", "oldqiu");//设置短信签名
request.putQueryParameter("TemplateCode", "SMS_186953933");//设置短信模板
StringBuffer randomNumStr = new StringBuffer();
for (int i = 0; i < 6; i++) {//产生随机验证码
randomNumStr.append(new Random().nextInt(10));
}
System.out.println(randomNumStr.toString());
request.putQueryParameter("TemplateParam", "{"code":""+randomNumStr.toString()+""}");//设置验证码
try {
CommonResponse response = client.getCommonResponse(request);
System.out.println(response.getData());
} catch (Exception e) {
e.printStackTrace();
}
return randomNumStr.toString();
}
}
1.5随机码的生成类:
package com.hotel.sms;
import java.util.Random;
public class VerifyCodeUtil {
public static final String VERIFY_CODES = "2345678";
public static String generateVerifyCode(int verifySize, String sources) {
if (sources == null || sources.length() == 0) {
sources = VERIFY_CODES;
}
int codesLen = sources.length();
Random rand = new Random(System.currentTimeMillis());
StringBuilder verifyCode = new StringBuilder(verifySize);
for (int i = 0; i < verifySize; i++) {
verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));
}
return verifyCode.toString();
}
}
1.6业务代码实现(发送验证码和校验验证码,JWT的部分请看其他的文章):
public ResultVo sendCode(String phoneNum) throws Exception {
// 检验手机号码的正确性
if (!RegexUtils.isChinaPhoneLegal(phoneNum)) return new ResultVo(2000,"输入的手机号码不正确");
// 查询数据库——校验电话号码是否存在,不存在直接返回,请其先注册
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("phone", phoneNum);
User user = userMapper.selectOne(queryWrapper);
if (user == null) return new ResultVo(2000,"手机号码不存在,请注册");
String code = SmsUtil.sendSms(phoneNum);
// 发送成功,存到redis里面,有效1分钟
redisUtil.set("phone",phoneNum,60);
redisUtil.set("code",code,60);
return new ResultVo(1000,"发送验证码成功",code);
}
@Override
public ResultVo verifyCode(Map map) throws Exception {
String phone = (String) map.get("phone");
String code = (String) map.get("code");
// 判断手机号码是否正常
if (!RegexUtils.isChinaPhoneLegal(phone)) return new ResultVo(2000,"请输入正常格式的号码");
if (StringUtils.isEmpty(code) || StringUtils.isEmpty(phone)) return new ResultVo(2000,"电话或验证码不能为空");
// 从redis里面取值
String codeRedis = (String) redisUtil.get("code");
String phoneNum = (String) redisUtil.get("phone");
// 判断手机号码是否和发送验证码的手机号码一致
if (!phone.equals(phoneNum)) return new ResultVo(2000,"手机号码错误");
// 判断验证码是否过期
if (StringUtils.isEmpty(code)) return new ResultVo(2001,"验证码已过期");
// 判断验证码是否错误
if (!code.equals(codeRedis)) return new ResultVo(2001,"验证码错误");
// 登录成功返回token令牌给前端
// 查询数据库——校验电话号码是否存在,不能存在直接返回
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("phone", phone);
User user = userMapper.selectOne(queryWrapper);
if (user == null) return new ResultVo(2000,"手机号码不存在,请注册");
// 颁发JWT令牌
PrivateKey privateKey = null;
try {
ClassPathResource resource = new ClassPathResource("rsa.pri");
InputStream inputStream = resource.getInputStream();
privateKey = RsaUtils.getPrivateKey(JwtUtils.readBytes3(inputStream));
} catch (Exception e) {
e.printStackTrace();
}
// 把user信息存储到token,设置token过期时间为30分钟
String jwtToken = JwtUtils.generateTokenExpireInMinutes(user, privateKey, 30);
return new ResultVo(1000,"登录成功",jwtToken);
}



