胖葵酒店管理系统app
完整项目已上传github,链接在文章下面
先看效果图:
登录:
主页面(点击右上角图标进入个人中心页面):
经理模块(客房管理模块和员工管理模块与经理管理模块类似,员工管理模块还包括增加和删除员工功能):
修改经理信息:
添加员工:
删除员工:
财务查询模块:
个人中心页面:
修改密码:
忘记密码:
开发工具
客户端:Android Studio 4.1.0
服务端:IDEA 2020.1
网络通信框架:Android Volley
短信验证平台:MobTech SMSSDK
tomcat 9.0
jdk 13.0
数据库:腾讯云数据库Mysql 5.7
服务器:腾讯云服务器Windows Server 2012 R2
客户端app
项目框架
说明:
activity(从上到下)
1、基础activity。定义顶部导航栏,供其他页面继承使用
2、修改员工。包括增删改查功能
3、修改经理。包括修改和查看经理信息功能
4、修改密码。
5、修改客房。包括修改和查看客房信息功能
6、忘记密码。包括对用户输入手机号是否与数据库预留的匹配验证,以及短信验证功能
7、登录。
8、查看员工信息数据表
9、查看经理信息数据表
10、查看财务信息数据表
11、查看客房信息数据表
12、主页面
13、个人中心页面。包括修改密码和退出登录功能
14、欢迎页面
constants
1、保存用户登录信息,用于自动登录功能
help
1、用户自动登录功能
utils
1、SharedPreferences工具
views
1、输入样式,供其他页面调用
主要功能页
与服务端建立通信的页面包括登录页面、经理信息管理模块、客房信息管理模块、员工信息管理模块、修改密码模块。下面以登录页面为例进行说明,其他页面可以下载代码自己看。
登录模块代码如下:
package com.example.hotelmanager.activities;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.blankj.utilcode.util.RegexUtils;
import com.example.hotelmanager.R;
import com.example.hotelmanager.help.UserHelp;
import com.example.hotelmanager.utils.SPUtils;
import com.example.hotelmanager.views.InputView;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
public class Login extends BaseActivity {
private InputView mInputId, mInputPassword;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
initView();
}
//初始化View
private void initView() {
initNavBar(false, "登录", false);
mInputId = findViewById(R.id.input_phone);
mInputPassword = findViewById(R.id.input_password);
}
//登录点击事件
public void onCommitClick(View v) {
String id = mInputId.getInputStr();
String password = mInputPassword.getInputStr();
//验证输入是否合法
if (!validateLogin(this, id, password)) {
return;
}
SignInRequest(id, password);
}
//验证用户输入合法性
public static boolean validateLogin(Context context, String phone, String password) {
if (!RegexUtils.isMobileExact(phone)) {
Toast.makeText(context, "用户id无效", Toast.LENGTH_SHORT).show();
}
if (TextUtils.isEmpty(password)) {
Toast.makeText(context, "请输入密码", Toast.LENGTH_SHORT).show();
return false;
}
//保存用户登录标记
boolean isSaved = SPUtils.saveUser(context, phone);
if (!isSaved) {
Toast.makeText(context, "系统错误,请稍后重试", Toast.LENGTH_SHORT).show();
return false;
}
UserHelp.getInstance().setPhone(phone);
return true;
}
public void onForgetClick(View view) {
String id = mInputId.getInputStr();
//验证输入是否合法
if (!validateForget(this, id)) {
return;
}
UserHelp.getInstance().setPhone(id);
//startActivity(new Intent(this,ChangePassword.class));
ForgetRequest(id,"****");
}
private boolean validateForget(Login login, String phone) {
if (!RegexUtils.isMobileExact(phone)) {
Toast.makeText(this, "手机号无效", Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
public void SignInRequest(final String username, final String password) {
//请求地址
String url = "http://132.232.81.77:8080/HotelServer/loginServlet";
String tag = "Login";
//取得请求队列
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
//防止重复请求,所以先取消tag标识的请求队列
requestQueue.cancelAll(tag);
//创建StringRequest,定义字符串请求的请求方式为POST(省略第一个参数会默认为GET方式)
final StringRequest request = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
JSONObject jsonObject = (JSONObject) new JSONObject(response).get("params");
String result = jsonObject.getString("Result");
if (result.equals("TheUserDoesNotExist")) {
Toast.makeText(Login.this, "用户不存在", Toast.LENGTH_SHORT).show();
} else if (result.equals("PasswordError")) {
Toast.makeText(Login.this, "密码错误", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(Login.this, "登录成功", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Login.this, MainActivity.class);
intent.putExtra("username", username);
startActivity(intent);
finish();
}
} catch (JSONException e) {
//做自己的请求异常操作,如Toast提示(“无网络连接”等)
Log.e("TAG", e.getMessage(), e);
}
}
}, new Response.ErrorListener() {
@Override
public void one rrorResponse(VolleyError error) {
//做自己的响应错误操作,如Toast提示(“请稍后重试”等)
Log.e("TAG", error.getMessage(), error);
}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("username", username);
params.put("password", password);
return params;
}
};
//设置Tag标签
request.setTag(tag);
//将请求添加到队列中
requestQueue.add(request);
}
public void ForgetRequest(final String username, final String password){
//请求地址
String url = "http://132.232.81.77:8080/HotelServer/loginServlet";
String tag = "Login";
//取得请求队列
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
//防止重复请求,所以先取消tag标识的请求队列
requestQueue.cancelAll(tag);
//创建StringRequest,定义字符串请求的请求方式为POST(省略第一个参数会默认为GET方式)
final StringRequest request = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
JSONObject jsonObject = (JSONObject) new JSONObject(response).get("params");
String result = jsonObject.getString("Result");
if (result.equals("TheUserDoesNotExist")) {
Toast.makeText(Login.this, "用户不存在", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(Login.this, "用户验证通过", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Login.this, ForgetPassword.class);
intent.putExtra("username",username);
startActivity(intent);
}
} catch (JSONException e) {
//做自己的请求异常操作,如Toast提示(“无网络连接”等)
Log.e("TAG", e.getMessage(), e);
}
}
}, new Response.ErrorListener() {
@Override
public void one rrorResponse(VolleyError error) {
//做自己的响应错误操作,如Toast提示(“请稍后重试”等)
Log.e("TAG", error.getMessage(), error);
}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("username", username);
params.put("password", password);
return params;
}
};
//设置Tag标签
request.setTag(tag);
//将请求添加到队列中
requestQueue.add(request);
}
}
登陆部分
传入两个参数,分别是用户输入的id和密码,请求与服务端建立连接,以Json格式传给服务端处理,服务端验证id与密码是否匹配,将处理结果返回给客户端,根据接收到的结果将相应的信息反馈到屏幕提示用户
忘记密码部分
其实这里只需要传入一个参数,就是用户id,但为了偷懒我直接复制了登陆部分的代码,不必在意这些细节。
同样请求与服务端建立连接,服务端验证用户输入的id是否存在于数据库中,将结果返回给客户端。
关键技术点
Android Volley 通信框架
Volley可以说把异步网络通信和网络图片的加载都封装于一身,他让开发者们更轻松地进行HTTP通信和加载网络上的图片。Volley除了简单易用之外,在性能上也进行了大幅度的调整,它的设计目标就是非常适合进行数据量不大且通信频繁的网络操作,所以并不适合对大数据量的网络操作,比如下载文件。
如何使用:
1、创建一个android项目
2、导入volley包
3、声明网络权限
4、发送请求
参考博客:
https://blog.csdn.net/Mr_Megamind/article/details/74048891
https://blog.csdn.net/perArther/article/details/50856394?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-1.control
webview网页显示
WebView的最简单的使用方式即是直接显示网页内容,有以下两个步骤:
- 在布局文件中添加WebView控件;
- 在代码中让WebView控件加载显示网页。
参考博客:https://blog.csdn.net/weixin_40438421/article/details/85700109
短信验证服务
这里短信验证码服务采用MobTech平台的SMSSDK短信验证服务,附上平台链接:https://new.dashboard.mob.com/#/SMSSDK,按照教程在平台创建应用,会得到一个app key和app secret,如下:
在android studio完成相应的配置即可使用,附上配置教程:https://www.mob.com/wiki/detailed?wiki=SMSSDK_for_Android_kuaisujicheng&id=23
我的配置如下:
在project的build.gradle里:
在module的build.gradle里加上:
服务端
项目框架
说明:
bean(封装数据,是数据库中表的映射)
1、员工表
2、经理信息表
3、客房表
4、经理id、密码表
dao(实现数据的持久化操作,如增删改查)
1、员工信息操作
2、经理信息操作
3、客房信息操作
4、经理密码操作
service(业务逻辑的实现)
上面四个Impl分别实现下面四个interface封装的功能集合
util(工具)
1、连接数据库
2、读取配置文件
web.servlet(服务连接器,前后端通信)
1、添加员工
2、修改员工信息
3、修改经理信息
4、修改密码
5、修改客房信息
6、删除员工
7、登录(包括忘记密码)
config
数据库配置文件
四个.jsp文件
1、查看员工数据表信息
2、查看经理数据表信息
3、查看财务数据表信息
4、查看客房数据表信息
Style.css
jsp样式效果
下面主要说一下连接腾讯云数据库和servlet部分
配置文件如下:
url=jdbc:mysql://cdb-fmhwq8ww.cd.tencentcdb.com:10074/hotel?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8
driverClass=com.mysql.jdbc.Driver
user=root
password=b980227l
cdb-fmhwq8ww.cd.tencentcdb.com:10074/hotel 这是云数据库的外网地址和接口,hotel是项目数据库
以登录为例说明
.servlet
package PKhotel.web.servlet;
import PKhotel.bean.User;
import PKhotel.service.Impl.UsersServiceImpl;
import PKhotel.util.DButil;
import net.sf.json.JSONObject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
@WebServlet(name="loginServlet")
public class LoginServlet extends HttpServlet {
DButil dButil = new DButil();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置相应内容类型
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
try(PrintWriter out = response.getWriter()){
String username = request.getParameter("username").trim();
String password = request.getParameter("password").trim();
UsersServiceImpl service = new UsersServiceImpl();
int verigyResult = service.verifyLogin(new User(username,password),dButil);
Map<String,String> params = new HashMap<>();
JSONObject jsonObject = new JSONObject();
if(verigyResult == -1){
params.put("Result","TheUserDoesNotExist");
}else if(verigyResult == 0){
params.put("Result","PasswordError");
}else if(verigyResult == 1){
params.put("Result","CorrectPassword");
}
jsonObject.put("params",params);
out.write(jsonObject.toString());
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
接收客户端传来的id和密码,调用service中的verifyLogin函数处理,将结果返回给客户端
verifyLogin函数如下:
@Override
public int verifyLogin(User u, DButil dButil) {
List<User> userList = null;
String username = u.getUsername();
String password = u.getPassword();
try{
userList = userDao.queAll(dButil);
}catch (Exception e){
e.printStackTrace();
}
boolean hasUser = false;
boolean rightPass = false;
for(User user:userList){
if(user.getUsername().equals(username)){
hasUser = true;
if(user.getPassword().equals(password)){
rightPass = true;
}
break;
}
}
if(!hasUser) return -1;//无该用户
else if(!rightPass) return 0;//有该用户,但是密码输入错误
return 1;//有该用户,且密码输入正确
}
遍历数据库表,验证是否有该用户以及密码与用户是否匹配
坑点
web项目无法加载css文件解决方法:https://blog.csdn.net/YOUYOU0710/article/details/106267793/?utm_medium=distribute.pc_relevant.none-task-blog-title-3&spm=1001.2101.3001.4242
项目部署
IDEA将项目打包成war包:https://blog.csdn.net/weixin_43716048/article/details/108639475?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-5.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-5.control
将war包部署在云服务器:https://blog.csdn.net/zhangjin2024/article/details/101173520?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param
查看数据表信息
http://132.232.81.77:8080/HotelServer/lookmanager.jsp
http://132.232.81.77:8080/HotelServer/lookorder.jsp
http://132.232.81.77:8080/HotelServer/lookemployees.jsp
http://132.232.81.77:8080/HotelServer/lookroom.jsp
完整项目链接
github:https://github.com/guyuanjunxi/PKHotelManager
csdn:https://download.csdn.net/download/qq_41117896/13208830