智慧养老功能描述
一、业务实现
1. 管理员端
功能:管理员登录,管理员密码修改,删除用户,修改用户密码,登录会先查询所有用户,根据手机号准确查找用户。
2.用户端
1)用户基本操作
功能:用户注册;用户登录;用户退出;查询医疗机构;绑定用户;修改用户姓名;查询用户信息;配置监控;修改密码
2) 定位操作
功能:获取定位信息,存入鹰眼;设置围栏lng,lat经纬度,radius范围;查询用户的位置信息;查询用户的围栏信息;
第三方接口:鹰眼地图轨迹
3)商城操作
功能:查看购物车;购买商品(向订单中添加商品);减少订单中商品数量;删除订单中的商品;提交订单;支付页面请求;
支付(模拟);支付成功请求;查看订单;个人信息;商品主界面请求;推荐列表产生;商品列表;商品详情;搜索商品
4)人脸识别操作
功能:用户绑定人脸;绑定时查询该人脸是否绑定用户;登录时查找人脸;获得token
第三方接口:百度人脸识别,参考链接人脸识别
二、数据库表
1. admin 表
用于后台管理员登录。
2. user表
用户表:老人type=1,子女type=0。
3.goods表
商品表:商城中的各种商品信息。
4.items表
5.orders表
6.tops表
7.shouhuo表
8. jiankong表
9.types表
10.weilan表
11.yiyaowang表
三、具体功能实现
提示:以下各功能所写返回均为接收前端请求后,向前端所返回的数据
1.管理员端(AdminController第一请求/admin)
1)管理员登录
方法:login
接口:/login
参数:admin(用户名)、password(密码)
调用:adminService .checkUser( admin, password );
返回:“success” or “error"
dao层处理:根据用户名和密码在admins表中查找返回Admins实体类,实体类 != null时说明查找成功
2)删除用户
方法:deleteUser
接口:/deleteUser
参数:phone(手机)
调用:adminService .deleteUser( phone );
返回:“success” or “error"
dao层处理:根据手机号从user表中删除该用户,返回int类型值,值大于0说明删除成功
3)查询所有用户
方法:selectUsers
接口:/selectUsers
参数:无
调用:adminService .selectUsers();
返回:JSONArray格式的userArrayList
service层:
1. 通过adminDao.selectUsers()获取所有用户,返回ArrayList
2. 将user集合通过adminService中的removeNull方法分别对用户名,手机号,家庭住址为null的进行处理
3. 对处理完的user集合使用JSONArray.fromObject格式转换
4)修改用户密码
方法:changePwd
接口:/changePwd
参数:phone(手机号),password(密码)
调用:adminService .changePwd( phone, password );
返回:“success” or “error"
dao层 adminDao.changePwd( phone, password ):
sql语句:update user set password = ?where phone=?
返回:int类型,值大于0说明修改成功
5) 修改管理员密码
方法:changeAdminPwd
接口:/changeAdminPwd
参数:newpwd,username,oldpwd
调用:adminService .changeAdminPwd( username, newpwd, oldpwd );
返回:“success” or “error"
service 层:
1. 先调用checkUser( username, oldpwd );查询用户信息,若查到返回“success”;查不到返回“error"
2. 判断上步返回得字符串msg,若msg .equals( “success” )执行dao层数据修改,返回“success”;否则返回“error"
6) 按手机号查找用户
方法:selectUser
接口:/selectUser
参数:phone
调用:adminService. selectUser( phone );
返回:json 格式user集合
service 层:
1. 首先调用 adminDao .selectUser( phone ) 查找该手机号对应的用户,返回User实体类
2. 调用userService.deleteNull(User)对返回得user实体类中的地址,姓名,绑定用户进行处理,处理完返回user实体类
3. 通过JSONObject.fromObject( user );对上步得到的user实体类进行格式转化
2.用户端
提示:@ResponseBody注解作用,controller中有使用,不明白点击链接查看
2.1 用户基本操作(UserController第一请求/user)
1)用户注册
方法:register
接口:/register1
参数:phone(手机号)、password(密码)、type(老人 or 子女)
调用:userService .register(phone, password, type);
返回:“success” or “error"
service层:
1.执行userDao.selectUBP( phone );查询该表中该手机号是否注册过,返回User实体类,若User!=null,说明该手机号已经注册过,返回“error”。若等于null,执行第二步判断。
2. 将该手机号添加到鹰眼实体类中,调用locationService.add_Yingyan_Entity( phone ),成功添加返回“success”,对返回结果进行判断,返回字符串.equals( “success” )时继续执行第三步,否则返回“error"。
3.为注册用户生成用户名,格式:“用户”+随机数,然后添加用户userDao.addUser( phone, password, type, username );执行完后返回”success“。
2)用户登录
方法:login
接口:/login
参数:phone(手机号)、password(密码)、type(老人 or 子女),session
调用:userService .login(phone, password, type);
返回:JSONObject格式的user实体类,并将user加入session中
service层:
1. 调用userDao.selectUser( phone, password, type )查询该用户是否存在,返回User实体类,若 user == null,则查无此人,返回null,登录失败,不为空时执行第二步。
2.调用deleteNull(User user)对返回得user实体类中的地址,姓名,绑定用户进行处理,处理完返回user实体类,执行第三步。
3. return JSONObject.fromObject( user );格式转换并返回
3)用户退出
方法:quit
接口:/quit
参数:session
调用:session .removeAttribute(“user”);删除session中的user
返回:“success”
4)查询医疗机构
方法:selectHos
接口:/selectHos
参数:location
调用:userService .selectHos(location);
返回:JSONArray格式的hospitalArrayList
service层:
1.先使用location .contains( “市” )判断location是否包含字符”市“,若没有字符串进行拼接location += “市”。
2.然后在进行拼接location = “%” + location + “%”;方便模糊查询使用
3.执行userDao .selectHos( location );通过模糊查询拿到10条数据返回ArrayList
4.将拿到的集合通过setLocation(ArrayList)设置location的值,返回ArrayList
5)绑定用户
方法:bind_phone
接口:/bind_phone
参数:phone,bind_phone(绑定的手机号),password
调用:userService .bind_phone(phone, bind_phone, password);
返回:“success” or “error"
service层:
1.绑定用户操作为子女绑定老人手机号,所以定义type=1进行查询,调用userDao .selectUser( bindPhone, password, type );查询是否存在该老人用户。返回user实体类,若user == null,直接返回”error",不为空时执行第二步。
2.执行userDao.userBind( phone, bindPhone);进行绑定,然后返回“success”
sql :update user set bindPhone =? where phone = ?
6)修改用户姓名
方法:changeName
接口:/changeName
参数:phone,name
调用:userService .changeName(phone, name);
返回:“success”
service层:通过userDao .setName( phone, name );修改姓名
7)查询用户信息
方法:selectUser
接口:/selectUser
参数:phone
调用:userService .selectPhone(phone);
返回:“success” or “error"
service层:adminsDao .selectUser( phone );按照手机号查询用户信息,返回user实体类,若user == null,返回“error",否则返回”success"。
8)配置监控
方法:selectJianKong
接口:/selectJianKong
参数:phone
调用:userService .selectJianKong(phone);
返回:JSONArray格式的 jianKongEntities
service层:执行userDao .selectJianKong( phone );按照手机号从jiankong表中查询信息,返回ArrayList
9)修改密码
方法:changeUserPwd
接口:/changeUserPwd
参数:phone,password
调用:userService .changeUserPwd(phone, password);
返回:“success”
service层:直接执行userDao .changeUserPwd( phone, password );以手机号为条件进行修改密码
2.2 定位操作(LocationController第一请求/location)
1)获取定位信息,存入鹰眼
方法:getLocation
接口:/getLocation
参数:lng(经度),lat(纬度),phone
调用:locationService.putYingYan(lng, lat, phone); 加入try–catch中,产生异常时返回error
返回:“success” or “error"
service层:无返回值,仅进行存入定位信息,下图为service业务处理
public void putYingYan(String lng, String lat, String phone) throws IOException {
HttpClient client = HttpClients.createDefault();// 创建默认http连接
HttpPost post = new HttpPost("https://yingyan.baidu.com/api/v3/track/addpoint");// 创建一个post请求
ArrayList<NameValuePair> paramList = new ArrayList<>();
paramList.add(new BasicNameValuePair("ak", ak));//传递的参数
paramList.add(new BasicNameValuePair("service_id", service_id));//传递的参数
paramList.add(new BasicNameValuePair("entity_name", phone));//传递的参数
double g = Double.valueOf(lng);
double t = Double.valueOf(lat);
paramList.add(new BasicNameValuePair("latitude", t + ""));//传递的参数
paramList.add(new BasicNameValuePair("longitude", g + ""));//传递的参数
long time = System.currentTimeMillis();
String nowTimeStamp = String.valueOf(time / 1000);
paramList.add(new BasicNameValuePair("loc_time", nowTimeStamp + ""));//传递的参数
paramList.add(new BasicNameValuePair("coord_type_input", "bd09ll"));//传递的参数
// 把参转码后放入请求实体中
HttpEntity httpEntity = new UrlEncodedFormEntity(paramList, "utf-8");
post.setEntity(httpEntity);// 把请求实体放post请求中
client.execute(post);// 用http连接去执行get请求并且获得http响应
}
2)设置围栏lng,lat经纬度,radius(半径)范围
方法:createWeilan
接口:/createWeilan
参数:lng(经度),lat(纬度),phone ,radius
调用:locationService.creatYingyanWeilan(lng, lat, phone, radius); 加入try–catch中,产生异常时返回error
返回:“success” or “error"
service层:
1. locationDao.select_fence_id(phone); 按手机号为条件查询是否存在fence_id1返回字符串fence_id1
sql :select fence_id from weilan where phone = #{phone}
2.判断 fence_id1 是否为空,若不为空表明设置过执行updateWeilan(fence_id1, lng, lat, radius);修改围栏范围返回字符串,若msg.equals(“成功”)则返回“success”,业务结束。修改围栏细节如下:
public String updateWeilan(String fence_id, String lng, String lat, String radius) throws IOException {
HttpClient client = HttpClients.createDefault();// 创建默认http连接
HttpPost post = new HttpPost("https://yingyan.baidu.com/api/v3/fence/updatecirclefence");// 创建一个post请求
ArrayList<NameValuePair> paramList = new ArrayList<>();
paramList.add(new BasicNameValuePair("ak", ak));//传递的参数
paramList.add(new BasicNameValuePair("service_id", service_id));//传递的参数
paramList.add(new BasicNameValuePair("fence_id", fence_id));
paramList.add(new BasicNameValuePair("longitude", lng));//传递的参数
paramList.add(new BasicNameValuePair("latitude", lat));//传递的参数
paramList.add(new BasicNameValuePair("radius", radius));
paramList.add(new BasicNameValuePair("coord_type", "bd09ll"));
// 把参转码后放入请求实体中
HttpEntity entitya = new UrlEncodedFormEntity(paramList, "utf-8");
post.setEntity(entitya);// 把请求实体放post请求中
HttpResponse response1 = client.execute(post);// 用http连接去执行get请求并且获得http响应
HttpEntity entity = response1.getEntity();// 从response中取到响实体
String html = EntityUtils.toString(entity);// 把响应实体转成文本
JSONObject json = JSONObject.fromObject(html);
return json.getString("message");
}
3.若第二步开始判断fence_id1 为空,则表明未设置过围栏,执行insertWeilan(lng, lat, radius, phone);为用户添加围栏,返回字符串fence_id,执行insert_fence_id(phone, fence_id);将fence_id添加到weilan表中,无返回值。执行结束后返回“success",业务结束。添加围栏细节如下:
public String insertWeilan(String lng, String lat, String radius, String phone) throws IOException {
String url = "https://yingyan.baidu.com/api/v3/fence/createcirclefence";
HttpClient client = HttpClients.createDefault();// 创建默认http连接
HttpPost post = new HttpPost(url);// 创建一个post请求
ArrayList<NameValuePair> paramList = new ArrayList<>();
paramList.add(new BasicNameValuePair("ak", ak));//传递的参数
paramList.add(new BasicNameValuePair("service_id", service_id));//传递的参数
paramList.add(new BasicNameValuePair("monitored_person", phone));//传递的参数
paramList.add(new BasicNameValuePair("longitude", lng));//传递的参数
paramList.add(new BasicNameValuePair("latitude", lat));//传递的参数
paramList.add(new BasicNameValuePair("radius", radius));
paramList.add(new BasicNameValuePair("coord_type", "bd09ll"));
// 把参转码后放入请求实体中
HttpEntity entitya = new UrlEncodedFormEntity(paramList, "utf-8");
post.setEntity(entitya);// 把请求实体放post请求中
HttpResponse response1 = client.execute(post);// 用http连接去执行get请求并且获得http响应
HttpEntity entity = response1.getEntity();// 从response中取到响实体
String html = EntityUtils.toString(entity);// 把响应实体转成文本
JSONObject json = JSONObject.fromObject(html);
return json.getString("fence_id");
}
3)查询用户的位置信息
方法:selectAddress
接口:/selectAddress
参数:phone
调用:locationService .selectOlderLocation(phone); 加入try–catch中,产生异常时返回null
返回:JSONArray格式的用户位置信息 或者是 null
4)查询用户的围栏信息
方法:selectWeiLan
接口:/selectWeiLan
参数:phone
调用:locationService .select_fence_id(phone); 加入try–catch中,产生异常时返回null
返回:JSONArray格式的用户围栏信息 或者是 null
service层:执行locationDao.select_fence_id(phone);按手机号查询facen_id是否存在。
若facen_id为空:则将(“msg”, “error”)转化为JSONArray格式返回
若facen_id不为空:则返回(“msg”, “success”)和 selectWeilan(fence_id);查询到的结果
2.3 商城操作(IndexController第一请求/index)
1)查看购物车
方法:cart
接口:/cart
参数:model —(Model是一个接口,包含addAttribute方法,用于向前端页面传递参数)
调用:
model.addAttribute( "typeList", typeService.getList() );
返回:/index/shop/view/cart.jsp
service层:获取列表,返回ArrayList
dao层sql :select * from types order by id desc ; 查询所有数据,并按 id 降序排列
2)购买操作
方法:buy
接口:/buy
参数:goodid(goods表中id),session
调用:goodService.get( goodid );
返回:“empty” or “ok”
controller层详解:通过goodid拿到商品所有信息,第一步判断库存量,如果为0,则返回”empty“,不为空时向下执行;第二步从session中取出order,判断order是否为null,若为null,则创建订单,并将该订单添加到session中,key值仍为order;若order不为null,则向订单中添加商品,然后将该订单添加到session中,key值仍为order。最终返回“ok"。
service层:
1. 创建订单:orderService.add( goods )
第一步:将goods添加到item集合(List)中,给变量itemList
第二步:实例化order,通过set方法将itemList,price,amount加入其中,返回order
2.向订单添加项目:orderService.addOrderItem( order, goods )
第一步:获得itemList,然后判断是否为空,若为空,实例化ArrayList()并赋值给itemList;不为空时,itemList内容不变。
第二步:foreach循环判断购物车中是否已有此商品,如果有了此时item中商品数+1,价格改变;如果是新添加的商品,便将该商品添加到itemList中。
第三步:最终通过set方法修改order中总价和数量。
3)减少订单商品数量
方法:lessen
接口:/lessen
参数:goodid,session
调用:order = session .getAttribute( ”order“);
返回:“ok”
controller层:if( order != null ),首先通过goodService.get( goodid )获取goods信息,然后执行减少商品操作orderService.lessenIndentItem( order, goods),并将减少后的order加入session,key值仍为order。最终返回”ok"。
service层:从订单中减少项目:orderService.lessenIndentItem( order, goods)
第一步:获得itemList,然后判断是否为空,若为空,实例化ArrayList()并赋值给itemList;不为空时,itemList内容不变。
第二步:foreach循环判断购物车中是否已有此商品,如果有,先执行if判断,如果商品数量减一后为0,则直接从订单中删除该商品,然后返回order;如果商品数量大于0此时item中商品数-1,价格改变;如果订单中根本没有此商品,直接返回订单。
第三步:最终通过set方法修改order中总价和数量。
4)删除订单中的商品
方法:delete
接口:/delete
参数:goodid,session
调用:order = session .getAttribute( ”order“);
返回:“ok”
controller层:if( order != null ),首先通过goodService.get( goodid )获取goods信息,然后执行减少商品操作orderService.deleteIndentItem( order, goods),并将减少后的order加入session,key值仍为order。最终返回”ok"。
service层:从订单中删除项目 orderService.deleteIndentItem( order, goods)
第一步:获得itemList,然后判断是否为空,若为空,实例化ArrayList()并赋值给itemList;不为空时,itemList内容不变。
第二步:foreach遍历itemList,如果购物车中有该商品(goods),数量置为0,继续continue,直到遍历结束。然后将处理后的item添加到resultList中。
第三步:对resultList判空,如果为空则返回null。不为空时,将resultList设为order的itemList属性。
第四步:如果购物车没有该商品,直接返回订单(order)。
第五步:最终通过set方法修改order中总价和数量。
5)提交订单
方法:save
接口:/save
参数:request,session,model
返回:"/index/user/view/login.html" or “/index/shop/view/cart.jsp” or “redirect:topay?orderid=” + orderid; or “/index/shop/view/cart.jsp”
controller层:
1. 将types表中数据存入model中,key值为typeList,然后从session中拿到用户名和密码
model.addAttribute( "typeList", typeService.getList() ); // 获取user信息,得到用户的用户名和密码 JSONObject user = (JSONObject) session.getAttribute( "user" );
2.判断user是否为null,若为空表示未登录,向前端返回信息"请登录后提交订单!",跳转至”/index/user/view/login.html"。
3.用户已登录时,从session中获取order,赋值给sessionOrder,如果sessionOrder不等于null时执行第4步。如果为null,向前端返回信息"处理失败!",跳转至”/index/shop/view/cart.jsp“。
4. 为防止库存不足,遍历sessionOrder中的ItemList,先根据商品id,获得库存商品(product),如果购买的商品数量大于product的数量,向前端返回信息"商品xx库存不足,当前库存数量xx!",跳转至"/index/shop/view/cart.jsp"。遍历结束后,通过set方法为sessionOrder添加下单用户的user_id,和用户信息user。然后执行orderService.save( sessionOrder );保存订单,返回int型orderid。之后从session中移除order,即订单提交后清理购物车,返回字符串信息 “redirect:topay?orderid=” + orderid;
service层:保存订单orderService .save(order)
1.用set方法为order设置订单状态(未付款,1)和订单创建时间。
2.将order中的信息插入到order表中,获得order的id(orderid),遍历order中的ItemList,将orderid加入item中,然后将item中的信息添加到数据库item表中。
6)支付页面请求
方法:topay
接口:/topay
参数:orderid,request,model
调用:
model.addAttribute( "typeList", typeService.getList() );
request.setAttribute( "order", orderService.get( orderid ) );
返回:"/index/shop/view/pay.jsp"
service层:orderService.get( orderid )通过id获取订单信息
7)支付模拟
方法:pay
接口:/pay
参数:orderid,model
调用:orderService. pay( order );
返回:
"redirect:payok?orderid=" + order.getId();
service层:pay(order)订单支付
1. 根据orderid拿到订单信息返回old;然后在获取订单支付方式返回int型paytype
2.判断支付方式paytype是否为1或2,若是则设置订单状态为已付款;若不是则为货到付款,设置订单状态运输中。
3.设置old中的支付方式,收货人,收货电话,收货地址;并将old传入dao层修改数据库
8)支付成功
方法:payok
接口:/payok
参数:orderid,request,model
返回:"/index/shop/view/payok.jsp"
controller层:
1.根据orderid拿到订单信息返回order,获取支付方式paytype
2.判断支付方式paytype是否为1或2,若是则设置提示信息为 “订单[” + orderid + “]支付成功” ;若不是则为货到付款,设置提示信息为"订单[" + orderid + “]货到付款” 。
9)查看订单
方法:order
接口:/order
参数:model,session
返回:"/index/user/view/login.html" or “/index/shop/view/order.jsp”
controller层:
1. model中添加两个键值对;从session中拿到user信息,强转为json格式。
2. 进行if判断,如果用户id为“-1”,说明未登录,返回前端提示信息并跳转前端登录界面。
3.通过用户id拿到order列表orderList,如果orderList不为空,遍历orderList,根据orderid查询到订单项目列表,设置到order里。最后将orderList添加到model中。
10)个人信息
方法:my
接口:/my
参数:session
调用:session中拿到user信息进行 if 判断
返回:"/index/user/view/login.html" or “”/index/shop/view/my.jsp"
11)商城主界面请求
方法:index
接口:/index
参数:request
调用:
request.setAttribute( "flag", 1 );
request.setAttribute( "typeList", typeService.getList() );
request.setAttribute( "top1List", topService.getList( Tops.TYPE_SCROLL, 1, 1 ) );
request.setAttribute( "top2List", topService.getList( Tops.TYPE_LARGE, 1, 6 ) );
request.setAttribute( "top3List", topService.getList( Tops.TYPE_SMALL, 1, 8 ) );
返回:"/index/shop/view/index.jsp"
controller层前端商品推荐topService.getList(type, page, size):
1. type分为三类:条幅代号“1”,大图代号“2”,小图代号“3”。
2. 创建tops类型的集合topList,接收topDao.getList(type, (page-1)*size, size);的值,其中type为查询东西的类型,(page-1)*size为每页第一个商品,size为每页需要查询的商品数量。
3.遍历topList,从top中取到goodid,按goodid拿到商品goods,通过set方法为top设置goods。最终返回topList。
12)推荐列表
方法:tops
接口:/top
参数:typeid,page,request
调用:
request.setAttribute( "flag", typeid == 2 ? 7 : 8 );
request.setAttribute( "typeList", typeService.getList() );
request.setAttribute( "goodList", goodService.getList( typeid, page, rows ) );
request.setAttribute( "pageTool", PageUtil.getPageTool( request, goodService.getTotal( typeid ), page, rows ) );
返回:"/index/shop/view/goods.jsp"
controller层分页操作封装在PageUtil的getPafeTool方法中,直接传入参数调用。
PageUtil:
1. 四个参数:request,total(总记录数),page(当前页面),size(每页数量)
2.根据total对size求余计算需要展示多少页,如果结果为0,正好整除,页数pages=total/size,要是不为0,说明不能整除,剩下的还需要拿出一页用来展示,此时页数pages=total/size+1。如果pages=0,表示要显示的总数量还达不到一页的数量,此时pages=1。
3.从request中获取到url请求地址,通过StringBuilder拼接字符串完成分页。
13)商品列表
方法:tops
接口:/top
参数:typeid,page,request
调用:
request.setAttribute( "flag", 2 );
if (typeid > 0) {
request.setAttribute( "type", typeService.get( typeid ) );
}
request.setAttribute( "typeList", typeService.getList() );
request.setAttribute( "goodList", goodService.getListByType( typeid, page, rows ) );
request.setAttribute( "pageTool", PageUtil.getPageTool( request, goodService.getTotalByType( typeid ), page, rows ) );
返回:"/index/shop/view/goods.jsp"
14)商品详情
方法:detail
接口:/detail
参数:goodid,request
调用:
request.setAttribute( "good", goodService.get( goodid ) );
request.setAttribute( "typeList", typeService.getList() );
返回:"/index/shop/view/detail.jsp"
15)搜索
方法:search
接口:/search
参数:name,page,request
返回:"/index/shop/view/goods.jsp"
controller层:如果name不为空,然后根据name来获取商品列表,page和size决定当前页展示的商品数量。还根据name查询该商品的总数量,有助于分页展示。
2.4 人脸识别操作(FaceController第一请求/face)
1)绑定人脸
方法:bind_face
接口:/bind_face
参数:phone,img
调用:faceService.bind_face(phone, img);
返回:res.toString(2); res为JSONObject格式,参数2为json格式缩进,缩进两格
2)绑定时查询该人脸是否绑定用户
方法:select_faceBP
接口:/select_faceBP
参数:phone
调用:faceService.select_faceBP(phone);
返回:res.toString(2);
3)登录时查找人脸
方法:select_faceBF
接口:/select_faceBF
参数:img
调用:faceService.select_face(img);
返回:res.toString(2);
4)获得token
方法:getToken
接口:/getToken
参数:无
调用:faceService.getToken();
返回:字符串token