栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

美年

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

美年

文章目录
    • 短信发送【山东鼎信】【扩展】
    • 2.8.1 阿里云,云市场,购买短信API
    • 通过Java代码测试
    • 1 SmsTest
    • 2 HttpUtils.java 工具类
    • 3 common项目中配置pom.xml
    • 2.8.2.4 封装成工具类,存放到meinian_common项目中
    • 第三章. 旅游预约
    • 【路径】
    • 3.1. 前端代码
    • 3.1.1. 展示预约的套餐信息
    • 3.1.2. 手机号校验
    • 3.1.3. 30秒倒计时效果
    • 3.1.4. 发送ajax请求
    • 3.1.5. 日历展示
    • 3.1.6. 提交预约请求(身份证校验)
    • 3.2. 后台代码
    • 3.2.1. Controller
    • 3.2.2. 服务接口
    • 3.2.3. 服务实现类
    • 3.2.4. Dao接口
    • 3.2.4.1. OrderSettingDao.java
    • 3.2.4.2. MemberDao.java
    • 3.2.4.3. OrderDao.java
    • 3.2.5. Mapper映射文件
    • 3.2.5.1. OrderSettingDao.xml
    • 3.2.5.2. MemberDao.xml
    • 3.2.5.3. OrderDao.xml
    • 第四章. 预约成功页面展示
    • 【目标】
    • 【路径】
    • 【讲解】
    • 4.1. 页面调整
    • 4.2. 后台代码
    • 4.2.1. Controller
    • 4.2.2. 服务接口
    • 4.2.3. 服务实现类
    • 4.2.4. Dao接口
    • 4.2.5. Mapper映射文件
    • 【小结】

短信发送【山东鼎信】【扩展】 2.8.1 阿里云,云市场,购买短信API

通过阿里云购买第三方短信发送,免费的即可(5次)

通过Java代码测试 1 SmsTest
参考:https://market.aliyun.com/products/56928004/cmapi023305.html?spm=5176.2020520132.101.3.4b697218KUgzH1#sku=yuncode1730500007 
package com.atguigu;
 
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpResponse;
public class SmsTest {
   public static void main(String[] args) {
      String host = "http://dingxin.market.alicloudapi.com";
      String path = "/dx/sendSms";
      String method = "POST";
      String appcode = "62c2ebd07c7c4a95b270feff6c896c6c";
      Map headers = new HashMap();
      // 最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
      headers.put("Authorization", "APPCODE " + appcode);
      Map querys = new HashMap();
      querys.put("mobile", "18610025821");
      querys.put("param", "code:9966");
      querys.put("tpl_id", "TP1711063");
      Map bodys = new HashMap();
      try {
            
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            System.out.println(response.toString());
            // 获取response的body
            // System.out.println(EntityUtils.toString(response.getEntity()));
            //{"return_code":"00000","order_id":"ALY1549881237643456814"}
      } catch (Exception e) {
            e.printStackTrace();
      }
   }
}
将测试类,封装成工具类SMSUtils.java,放在 meinian_common中。 

2 HttpUtils.java 工具类

参考:https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java

3 common项目中配置pom.xml

参考:https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
在 meinian_common 中导入坐标


com.alibaba
fastjson
1.2.15


org.apache.httpcomponents
httpclient
4.2.1


org.apache.httpcomponents
httpcore
4.2.1


commons-lang
commons-lang
2.6


org.eclipse.jetty
jetty-util
9.3.7.v20160115


2.8.2.4 封装成工具类,存放到meinian_common项目中

大致流程

第三章. 旅游预约

实现旅游预约
需求:

  1. 在套餐详情页面(setmeal_detail.html)点击立即预约,页面跳转到预约页面(orderInfo.html)
  2. 在预约页面(orderInfo.html)录入旅游人信息,包括手机号,点击发送验证码
  3. 在预约页面录入收到的手机短信验证码,点击提交预约,完成预约
【路径】

前台代码编写
在/pages/orderInfo.html

完成需求:
1.展示预约套餐信息
2.手机号校验
3.30秒倒计时效果
4.发送ajax请求,完成【发送验证码】功能
5.日期中使用日历插件
6.【提交预约】请求
后台代码编写
1.类OrderController.java
2.类OrderService.java
3.类OrderServiceImpl.java
4.类OrderDao.java
 OrderSettingDao.java
 MemberDao.java
5.配置文件OrderDao.xml
 OrderSettingDao.xml
 MemberDao.xml

完成需求:

后台代码1:短信验证码
1. 填写 手机号码, 点击发送验证码 请求服务器(携带手机号码)
2. 在后台
  - 获得手机号码
  - 生成验证码
  - 使用阿里云服务发送验证码
  - 把生成验证码存到redis里面(存5分钟)



提交预约
后台代码2
1:Controller

点击提交预约, 把用户信息 提交到服务器
在Controller里面
      - 获得用户信息
      - 校验验证码(redis里面存的和用户输入的比较)
      - 调用业务, 进行预约, 响应

2:Service
    
1. 判断当前的日期是否可以预约(根据orderDate查询t_ordersetting, 能查询出来可以预约;查询不出来,不能预约)
2. 判断当前日期是否预约已满(判断reservations(已经预约人数)是否等于number(最多预约人数))
3. 判断是否是会员(根据手机号码查询t_member)
    - 如果是会员(能够查询出来), 防止重复预约(根据member_id,orderDate,setmeal_id查询t_order)
    - 如果不是会员(不能够查询出来) ,自动注册为会员(直接向t_member插入一条记录)
4.进行预约
      - 向t_order表插入一条记录
      - t_ordersetting表里面预约的人数reservations+1

导入数据库

DROp TABLE IF EXISTS `t_member`;
CREATE TABLE `t_member` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `fileNumber` varchar(32) DEFAULT NULL,
 `name` varchar(32) DEFAULT NULL,
 `sex` varchar(8) DEFAULT NULL,
 `idCard` varchar(18) DEFAULT NULL,
 `phoneNumber` varchar(11) DEFAULT NULL,
 `regTime` date DEFAULT NULL,
 `password` varchar(32) DEFAULT NULL,
 `email` varchar(32) DEFAULT NULL,
 `birthday` date DEFAULT NULL,
 `remark` varchar(128) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=93 DEFAULT CHARSET=utf8;


-- ----------------------------
-- Records of t_member
-- ----------------------------
INSERT INTO `t_member` VALUES ('82', null, '小明', '1', '123456789000999999', '18544279942', '2020-02-08', null, null, null, null);
INSERT INTO `t_member` VALUES ('83', null, '美丽', '1', '132333333333333', '13412345678', '2020-02-11', null, null, null, null);
INSERT INTO `t_member` VALUES ('84', null, '小星星', null, null, '18343569942', '2020-02-13', null, null, null, null);
INSERT INTO `t_member` VALUES ('85', null, '小强', null, null, 18344249942, '2020-02-06', null, null, null, null);
INSERT INTO `t_member` VALUES ('86', null, '红康', null, null, 18544579942, '2020-02-04', null, null, null, null);
INSERT INTO `t_member` VALUES ('87', null, '大海', null, null, 18544274442, '2020-02-06', null, null, null, null);
INSERT INTO `t_member` VALUES ('88', null, '小婷', null, null, 18544269942, '2020-02-10', null, null, null, null);
INSERT INTO `t_member` VALUES ('89', null, '晓晓', null, null, 18544339942, '2020-02-01', null, null, null, null);
INSERT INTO `t_member` VALUES ('90', null, '纯生', null, null, 18544669942, '2020-02-02', null, null, null, null);
INSERT INTO `t_member` VALUES ('91', null, '闰土', null, null, 18544779942, '2020-02-01', null, null, null, null);
INSERT INTO `t_member` VALUES ('92', null, '波波', '2', '234234145432121345', '18019286521', '2020-02-19', null, null, null, null);


DROP TABLE IF EXISTS `t_order`;
CREATE TABLE `t_order` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `member_id` int(11) DEFAULT NULL COMMENT '员会id',
 `orderDate` date DEFAULT NULL COMMENT '约预日期',
 `orderType` varchar(8) DEFAULT NULL COMMENT '约预类型 电话预约/微信预约',
 `orderStatus` varchar(8) DEFAULT NULL COMMENT '预约状态(是否旅游)',
 `setmeal_id` int(11) DEFAULT NULL COMMENT '餐套id',
 PRIMARY KEY (`id`),
 KEY `key_member_id` (`member_id`),
 KEY `key_setmeal_id` (`setmeal_id`),
 ConSTRAINT `key_member_id` FOREIGN KEY (`member_id`) REFERENCES `t_member` (`id`),
 ConSTRAINT `key_setmeal_id` FOREIGN KEY (`setmeal_id`) REFERENCES `t_setmeal` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;


-- ----------------------------
-- Records of t_order
-- ----------------------------
INSERT INTO `t_order` VALUES (1, 84, '2020-02-01', '微信预约', '已出游', 3);
INSERT INTO `t_order` VALUES (2, 84, '2020-02-17', '微信预约', '未出游', 3);
INSERT INTO `t_order` VALUES (3, 84, '2020-02-01', '微信预约', '未出游', 3);
INSERT INTO `t_order` VALUES (4, 84, '2020-02-17', '微信预约', '已出游', 4);
INSERT INTO `t_order` VALUES (5, 84, '2020-02-09', '微信预约', '未出游', 4);
INSERT INTO `t_order` VALUES (6, 84, '2020-02-09', '微信预约', '已出游', 4);
INSERT INTO `t_order` VALUES (7, 84, '2020-02-18', '微信预约', '未出游', 5);
INSERT INTO `t_order` VALUES (8, 84, '2020-02-10', '微信预约', '未出游', 6);
INSERT INTO `t_order` VALUES (9, 84, '2020-02-10', '微信预约', '未出游', 6);
INSERT INTO `t_order` VALUES (10, 84, '2020-02-13', '微信预约', '未出游', 7);
INSERT INTO `t_order` VALUES (17, 84, '2020-02-06', '微信预约', '已出游', 12);

3.1. 前端代码


1:在详情页面(/pages/setmeal_detail.html)点击预约



2:toOrderInfo()方法:

toOrderInfo(){
    window.location.href = "orderInfo.html?id=" + id;
}

3:在预约页面(/pages/orderInfo.html)进行调整

3.1.1. 展示预约的套餐信息

第一步:从请求路径中获取当前套餐的id



第二步:定义模型数据setmeal,用于套餐数据展示



第三步:显示套餐信息

{{setmeal.name}}

{{setmeal.remark}}

{{setmeal.sex == '0' ? '性别不限' : setmeal.sex == '1' ? '男':'女'}} {{setmeal.age}}

第四步:在VUE的钩子函数中发送ajax请求,根据id查询套餐信息,修改七牛云图片地址

mounted(){
   axios.post("/setmeal/findById.do?id=" + id).then((response) => {
       this.setmeal = response.data.data;
       this.imgUrl = 'http://pspmuf4c3.bkt.clouddn.com/' + this.setmeal.img;
  });
}

第五步:修改七牛云图片地址

3.1.2. 手机号校验

回顾:正则表达式简单语法及常用正则表达式
https://www.w3cschool.cn/jsref/jsref-obj-regexp.html

基本符号:
^  表示匹配字符串的开始位置  (例外  用在中括号中[ ] 时,可以理解为取反,表示不匹配括号中字符串)
$  表示匹配字符串的结束位置
*  表示匹配 零次到多次
+  表示匹配 一次到多次 (至少有一次)
?  表示匹配零次或一次
.  表示匹配单个字符 
|  表示为或者,两项中取一项
(  ) 小括号表示匹配括号中全部字符
[  ] 中括号表示匹配括号中一个字符 范围描述 如[0-9 a-z A-Z]
{  } 大括号用于限定匹配次数  如 {n}表示匹配n个字符  {n,}表示至少匹配n个字符  {n,m}表示至少n,最多m
  转义字符 如上基本符号匹配都需要转义字符   如 *  表示匹配*号
w 表示英文字母和数字  W  非字母和数字
d  表示数字   D  非数字

例子:



	
		
		
	
			
	
	


第一步:在 orderInfo.html页面导入的healthmobile.js文件中已经定义了校验手机号的方法


healthmobile.js:

function checkTelephone(telephone) {
    var reg=/^[1][3,4,5,7,8][0-9]{9}$/;
    if (!reg.test(telephone)) {
        return false;
    } else {
        return true;
    }
}

第二步:为发送验证码按钮绑定事件 sendValidateCode()

sendValidateCode() 方法:
对手机号进行校验

//发送验证码
sendValidateCode(){
    //获取用户输入的手机号
    var telephone = this.orderInfo.telephone;
    //校验手机号输入是否正确
    if (!checkTelephone(telephone)) {
        this.$message.error('请输入正确的手机号');
        return false;
    }
},

3.1.3. 30秒倒计时效果

第一步:前面在 sendValidateCode方法中进行了手机号校验,如果校验通过,需要显示30秒倒计时效果

//发送验证码
sendValidateCode(){
   //获取用户输入的手机号
   var telephone = this.orderInfo.telephone;
   //校验手机号输入是否正确
   if (!checkTelephone(telephone)) {
       this.$message.error('请输入正确的手机号');
       return false;
  }
   validateCodeButton = $("#validateCodeButton")[0];//这一步是将jQuery对象装换为 dom对象 
   clock = window.setInterval(doLoop, 1000); //一秒执行一次
},

第二步:其中,validateCodeButton 和 clock 是在healthmobile.js文件中定义的属性。
doLoop是在 healthmobile.js文件中定义的方法

var clock = '';//定时器对象,用于页面30秒倒计时效果
var nums = 30;
var validateCodeButton;
//基于定时器实现30秒倒计时效果
function doLoop() {
   validateCodeButton.disabled = true;//将按钮置为不可点击
   nums--;
   if (nums > 0) {
       validateCodeButton.value = nums + '秒后重新获取';
  } else {
       clearInterval(clock); //清除js定时器
       validateCodeButton.disabled = false;
       validateCodeButton.value = '重新获取验证码';
       nums = 30; //重置时间
  }
}

3.1.4. 发送ajax请求

接口文档:
请求方式:get 请求
请求路径 :

"/validateCode/send4Order.do?telephone=" + telephone

第一步:发送ajax请求

//发送验证码
sendValidateCode(){
   //获取用户输入的手机号
   var telephone = this.orderInfo.telephone;
   //校验手机号输入是否正确
   if (!checkTelephone(telephone)) {
       this.$message.error('请输入正确的手机号');
       return false;
  }
   validateCodeButton = $("#validateCodeButton")[0];
   clock = window.setInterval(doLoop, 1000); //一秒执行一次
   //
   axios.post("/validateCode/send4Order.do?telephone=" + telephone).then((response) => {
       if(!response.data.flag){
           //验证码发送失败
           this.$message.error('验证码发送失败,请检查手机号输入是否正确');
      }
  });
},

第二步:创建 ValidateCodeController,提供方法发送短信验证码,并将验证码保存到redis

package com.atguigu.controller;

import com.atguigu.constant.MessageConstant;
import com.atguigu.constant.RedisConstant;
import com.atguigu.constant.RedisMessageConstant;
import com.atguigu.entity.Result;
import com.atguigu.utils.SMSUtils;
import com.atguigu.utils.ValidateCodeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.JedisPool;

@RestController
@RequestMapping("/validateCode")
public class ValidateCodeController {
 
   @Autowired
   private JedisPool jedisPool;

   //预约时发送手机验证码
   @RequestMapping("/send4Order")
   public Result send4Order(String telephone){
       Integer code = ValidateCodeUtils.generatevalidateCode(4);//生成4位数字验证码
       try {
           //发送短信
           SMSUtils.sendShortMessage(telephone,code.toString());
      } catch (ClientException e) {
           e.printStackTrace();
           //验证码发送失败
           return new Result(false, MessageConstant.SEND_VALIDATECODE_FAIL);
      }
       System.out.println("发送的手机验证码为:" + code);
       //将生成的验证码缓存到redis
       jedisPool.getResource().setex(telephone + RedisMessageConstant.SENDTYPE_ORDER, 5 * 60, code.toString());
       //验证码发送成功
       return new Result(true, MessageConstant.SEND_VALIDATECODE_SUCCESS);
  }
}

3.1.5. 日历展示

页面中使用DatePicker控件来展示日历。根据需求,最多可以提前一个月进行预约,所以日历控件只展示未来一个月的日期
第一步:引入dataPicker.js


第二步:定义日期
通过样式:.picktime,对应input组件中的class=“picktime”

第三步:定义日期控件
.picktime表示通过样式查找输入框。



其中getSpecifiedDate方法定义在healthmobile.js文件中

//获得指定日期后指定天数的日期
function getSpecifiedDate(date, days) {
    date.setDate(date.getDate() + days);//获取指定天之后的日期
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    var day = date.getDate();
    return (year + "-" + month + "-" + day);
}

3.1.6. 提交预约请求(身份证校验)

为提交预约按钮绑定事件
第一步:定义“旅游预约”

第二步:submitOrder()方法

//提交预约
submitOrder(){
    //校验身份证号格式
    if(!checkIdCard(this.orderInfo.idCard)){
        this.$message.error('身份证号码输入错误,请重新输入');
        return ;
    }
    axios.post("/order/submit.do",this.orderInfo).then((response) => {
        if(response.data.flag){
            //预约成功,跳转到预约成功页面
            window.location.href="orderSuccess.html?orderId=" + response.data.data.id;
        }else{
            //预约失败,提示预约失败信息
            this.$message.error(response.data.message);
        }
    });
}

第三步:其中checkIdCard方法是在healthmobile.js文件中定义的,用来验证身份证的js

function checkIdCard(idCard){
    var reg = /(^d{15}$)|(^d{18}$)|(^d{17}(d|X|x)$)/;
    if(reg.test(idCard)){
        return true;
    }else{
        return false;
    }
}

3.2. 后台代码 3.2.1. Controller

在 meinian_mobile_web 工程中创建 OrderMobileController 并提供 submitOrder 方法

package com.atguigu.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.atguigu.constant.MessageConstant;
import com.atguigu.constant.RedisMessageConstant;
import com.atguigu.entity.Result;
import com.atguigu.pojo.Order;
import com.atguigu.service.OrderService;
import com.atguigu.utils.SMSUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.JedisPool;
import java.util.Map;

@RestController
@RequestMapping("/order")
public class OrderMobileController {
   @Reference
   private OrderService orderService;
   @Autowired
   private JedisPool jedisPool;

   
   @RequestMapping("/submit")
   public Result submitOrder(@RequestBody Map map){//提交表单用map 由于表单数据来源多张表的操作 pojo接受不完整
       // ① 在页面获取手机号
       String telephone = (String) map.get("telephone");
        //② 在页面获取验证码
       String validateCode = (String) map.get("validateCode");
       //从Redis中获取缓存的验证码,key为手机号+RedisConstant.SENDTYPE_ORDER
       String codeInRedis = jedisPool.getResource().get(telephone + RedisMessageConstant.SENDTYPE_ORDER);
      
       //校验手机验证码
       if(codeInRedis == null || !codeInRedis.equals(validateCode)){
           return new Result(false, MessageConstant.VALIDATECODE_ERROR);
      }
       Result result =null;
       //调用旅游预约服务
       try{
           map.put("orderType", Order.ORDERTYPE_WEIXIN);
           // 断点调试,查看map里面封装了哪些数据
           result = orderService.order(map);
      }catch (Exception e){
           e.printStackTrace();
           //预约失败
           return result;
      }
       if(result.isFlag()){
           //预约成功,发送短信通知,短信通知内容可以是“预约时间”,“预约人”,“预约地点”,“预约事项”等信息。
           String orderDate = (String) map.get("orderDate");
           try {
               SMSUtils.sendShortMessage(telephone,orderDate);
          } catch (ClientException e) {
               e.printStackTrace();
          }
      }
       return result;
  }
}

3.2.2. 服务接口

在 meinian_interface 工程中创建旅游预约服务接口 OrderService 并提供预约方法

package com.atguigu.service;

import com.atguigu.entity.Result;
import java.util.Map;

public interface OrderService {
   Result order(Map map) throws Exception;
}

3.2.3. 服务实现类

在 meinian_service 工程中创建旅游预约服务实现类 OrderServiceImpl 并实现旅游预约方法。
旅游预约方法处理逻辑比较复杂,需要进行如下业务处理:
【路径】
1、检查用户所选择的预约日期是否已经提前进行了预约设置,如果没有设置则无法进行预约
2、检查用户所选择的预约日期是否已经约满,如果已经约满则无法预约
3、检查用户是否重复预约(同一个用户在同一天预约了同一个套餐),如果是重复预约则无法完成再次预约
4、检查当前用户是否为会员,如果是会员则直接完成预约,如果不是会员则自动完成注册并进行预约
5、预约成功,更新当日的已预约人数
实现代码如下:

package com.atguigu.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.atguigu.constant.MessageConstant;
import com.atguigu.dao.MemberDao;
import com.atguigu.dao.OrderDao;
import com.atguigu.dao.OrdersettingDao;
import com.atguigu.entity.Result;
import com.atguigu.pojo.Member;
import com.atguigu.pojo.Order;
import com.atguigu.pojo.OrderSetting;
import com.atguigu.service.CheckItemService;
import com.atguigu.service.OrderService;
import com.atguigu.utils.DateUtils;
import org.apache.poi.ss.usermodel.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service(interfaceClass = OrderService.class)
@Transactional
public class OrderServiceImpl implements OrderService {

   @Autowired
   private OrderSettingDao orderSettingDao;
   @Autowired
   private MemberDao memberDao;
   @Autowired
   private OrderDao orderDao;

   //旅游预约
   public Result order(Map map) throws Exception {
       //检查当前日期是否进行了预约设置
       String orderDate = (String) map.get("orderDate");
       // 因为数据库预约设置表里面的时间是date类型,http协议传递的是字符串类型,所以需要转换
       Date date = DateUtils.parseString2Date(orderDate);
       // 使用预约时间查询预约设置表,看看是否可以 进行预约
        //(1)使用预约时间,查询预约设置表,判断是否有该记录
       OrderSetting orderSetting = orderSettingDao.findByOrderDate(date);
       // 如果预约设置表等于null,说明不能进行预约,压根就没有开团
       if (orderSetting == null) {
           // 如果没有说明预约设置表没有进行设置,此时不能预约
           return new Result(false,MessageConstant.SELECTED_DATE_CANNOT_ORDER);
      }else{
              //如果有,说明预约可以进行预约,//可预约人数
               int number = orderSetting.getNumber();
              //已预约人数
               int reservations = orderSetting.getReservations();
           //如果预约人数大于等于最大预约数,此时不能预约,提示“预约已满”
               if(reservations>=number){
                   return new Result(false, MessageConstant.ORDER_FULL);
              }
        }

       //获取手机号
       String telephone = (String) map.get("telephone");
      //(2)使用手机号,查询会员表,判断当前预约人是否是会员
       // 根据手机号,查询会员表,判断当前预约人是否是会员
       Member member = memberDao.findByTelephone(telephone);
       //如果是会员,防止重复预约(一个会员、一个时间、一个套餐不能重复,否则是重复预约)
       if (member != null) {
           Integer memberId = member.getId();
           // 获取套餐id
           int setmealId = Integer.parseInt((String) map.get("setmealId"));
           Order order = new Order(memberId, date, null, null, setmealId);
           // 根据预约信息查询是否已经预约
           List list = orderDao.findByCondition(order);
           // 判断是否已经预约list不等于null,说明已经预约,不能重复预约
           if (list != null && list.size() > 0) {
               //已经完成了预约,不能重复预约
               return new Result(false, MessageConstant.HAS_ORDERED);
          }
      }else{
               // 如果不是会员:注册会员,向会员表中添加数据
               member = new Member();
               member.setName((String)map.get("name"));
               member.setSex((String)map.get("sex"));
               member.setPhoneNumber((String)map.get("telephone"));
               member.setIdCard((String)map.get("idCard"));
               member.setRegTime(new Date()); // 会员注册时间,当前时间
               memberDao.add(member);
          }
        //(3)可以进行预约,更新预约设置表中预约人数的值,使其的值+1
       //可以预约,设置预约人数加一
       orderSetting.setReservations(orderSetting.getReservations() + 1);
       orderSettingDao.editReservationsByOrderDate(orderSetting);

      
       //(4)可以进行预约,向预约表中添加1条数据
       //保存预约信息到预约表
       Order order = new Order();
       order.setMemberId(member.getId()); //会员id
       order.setOrderDate(date); // 预约时间
       order.setOrderStatus(Order.ORDERSTATUS_NO); // 预约状态(已出游/未出游)
       order.setOrderType((String)map.get("orderType"));
       order.setSetmealId(Integer.parseInt((String)map.get("setmealId")));
       orderDao.add(order);

       return new Result(true, MessageConstant.ORDER_SUCCESS, order);
  }
}

导入DateUtils放置到meinian_common中

3.2.4. Dao接口 3.2.4.1. OrderSettingDao.java
package com.atguigu.dao;

import com.atguigu.pojo.OrderSetting;
import java.util.Date;
import java.util.List;
import java.util.Map;

public interface OrderSettingDao {
   //根据预约日期查询预约设置信息
   OrderSetting findByOrderDate(Date date);
   //更新已预约人数
   void editReservationsByOrderDate(OrderSetting orderSetting);
}

3.2.4.2. MemberDao.java
package com.atguigu.dao;

import com.atguigu.pojo.Member;

public interface MemberDao {
   // 添加会员
   public void add(Member member);
   // 根据手机号查询会员信息(唯一)
   public Member findByTelephone(String telephone);
}

3.2.4.3. OrderDao.java
package com.atguigu.dao;

import com.atguigu.pojo.Order;
import java.util.List;

public interface OrderDao {
   List findByCondition(Order order);
   void add(Order order);
}

3.2.5. Mapper映射文件 3.2.5.1. OrderSettingDao.xml

      select * from t_member where phoneNumber = #{phoneNumber}
   


3.2.5.3. OrderDao.xml




    
   
       SELECT * FROM t_order
      
          
               and id = #{id}
          
        


有where标签,and会自动识别,where类似于where 1=1,这样后面就可以添加and了,SQL语句就变成如下:
select * from t_order where 1=1 and member_id =#{memberId}

【小结】
验证码
1.调用阿里服务, 发送成功后, 验证码存到Redis(存5分钟)
2.用户点击了预约, 需要把用户输入的验证码和redis里面存的验证码进行校验
预约业务
1.判断当前的日期是否可以预约
2.判断当前的日期预约是否已满
3.判断是否 是会员
 如果是会员, 避免重复预约
 不是会员, 自动注册成会员,t_member 表插入一条记录
4.进行预约
 向t_order 表插入一条记录
 向t_ordersetting更新reservations+1

第四章. 预约成功页面展示 【目标】

前面已经完成了旅游预约,预约成功后页面会跳转到成功提示页面(orderSuccess.html)并展示预约的相关信息(会员姓名、旅游套餐、旅游时间等)。
使用订单id,查询订单详细信息 在OrderDao.xml中会使用联合查询的sql,关联订单表,会员表,套餐表,以map数据结构返回。
orderSuccess.html


跳转到 orderSuccess.html,传递预约成功的订单id。

axios.post("/order/submit.do",this.orderInfo).then((response) => {
   if(response.data.flag){
       //预约成功,跳转到预约成功页面
       window.location.href="orderSuccess.html?orderId=" + response.data.data.id;
  }else{
       //预约失败,提示预约失败信息
       this.$message.error(response.data.message);
  }
});

【路径】

前台代码编写
在/pages/orderSuccess.html
会员姓名:{{orderInfo.member}}
旅游套餐:{{orderInfo.setmeal}}
旅游日期:{{orderInfo.orderDate}}
预约类型:{{orderInfo.orderType}}

完成需求:
1.页面输出订单相关人的信息
2.使用订单id,查询订单详细信息。存放到orderInfo的模型中。

后台代码编写:

1.类OrderController.java
2.类OrderService.java
3.类OrderServiceImpl.java
4.类OrderDao.java
5.配置文件OrderDao.xml

使用订单id,查询订单详细信息
在OrderDao.xml中会使用联合查询的sql,关联订单表,会员表,套餐表,以map数据结构返回。

【讲解】 4.1. 页面调整

提供orderSuccess.html页面,展示预约成功后相关信息
第一步:页面输出订单相关人的信息

旅游预约成功
旅游信息

会员姓名:{{orderInfo.member}}

旅游套餐:{{orderInfo.setmeal}}

旅游日期:{{orderInfo.orderDate}}

预约类型:{{orderInfo.orderType}}

第二步:使用订单id,查询订单详细信息。存放到orderInfo的变量中。



4.2. 后台代码 4.2.1. Controller

在OrderController中提供findById方法,根据预约id查询预约相关信息

package com.atguigu.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.atguigu.constant.MessageConstant;
import com.atguigu.constant.RedisMessageConstant;
import com.atguigu.entity.Result;
import com.atguigu.pojo.Order;
import com.atguigu.service.OrderService;
import com.atguigu.utils.SMSUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.JedisPool;
import java.util.Map;


@RestController
@RequestMapping("/order")
public class OrderController {

   @Autowired
   private JedisPool jedisPool;

   @Reference
   private OrderService orderService;

   @RequestMapping("/findById")
   public Result findById(Integer id){
       Map map =null;
       try{
           map = orderService.findById4Detail(id);
           //查询预约信息成功
           return new Result(true,MessageConstant.QUERY_ORDER_SUCCESS,map);
      }catch (Exception e){
           e.printStackTrace();
           //查询预约信息失败
           return new Result(false,MessageConstant.QUERY_ORDER_FAIL);
      }
  }

4.2.2. 服务接口

在OrderService服务接口中扩展findById4Detail方法

//根据id查询预约信息,包括人信息、套餐信息
Map findById4Detail(Integer id);

4.2.3. 服务实现类

在 OrderServiceImpl 服务实现类中实现 findById4Detail 方法

package com.atguigu.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.atguigu.constant.MessageConstant;
import com.atguigu.dao.MemberDao;
import com.atguigu.dao.OrderDao;
import com.atguigu.dao.OrdersettingDao;
import com.atguigu.entity.Result;
import com.atguigu.pojo.Member;
import com.atguigu.pojo.Order;
import com.atguigu.pojo.OrderSetting;
import com.atguigu.service.CheckItemService;
import com.atguigu.service.OrderService;
import com.atguigu.utils.DateUtils;
import org.apache.poi.ss.usermodel.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Map;


@Service(interfaceClass = OrderService.class)
@Transactional
public class OrderServiceImpl implements OrderService {

   @Autowired
   private OrdersettingDao ordersettingDao;

   @Autowired
   private MemberDao memberDao;

   @Autowired
   private OrderDao orderDao;

   //根据id查询预约信息,包括旅游人信息、套餐信息
   public Map findById4Detail(Integer id) throws Exception {
       Map map = orderDao.findById4Detail(id);
       if(map != null){
           //处理日期格式
           Date orderDate = (Date) map.get("orderDate");
           map.put("orderDate",DateUtils.parseDate2String(orderDate));
           return map
      }
       return map;
  }

4.2.4. Dao接口

在 OrderDao 接口中扩展 findById4Detail 方法

Map findById4Detail(Integer id);
4.2.5. Mapper映射文件

在 OrderDao.xml 映射文件中提供SQL语句


  select m.name member ,s.name setmeal,o.orderDate orderDate,o.orderType orderType
  from  t_order o, t_member m,  t_setmeal s
  where o.member_id=m.id and o.setmeal_id=s.id and o.id=#{id}


m.name member ,s.name setmeal,o.orderDate orderDate,o.orderType orderType
对应:页面内容

会员姓名:{{orderInfo.member}}

旅游套餐:{{orderInfo.setmeal}}

旅游日期:{{orderInfo.orderDate}}

预约类型:{{orderInfo.orderType}}

【小结】

使用订单id,查询订单详细信息 在OrderDao.xml中会使用联合查询的sql,关联订单表,会员表,套餐表,以map数据结构返回。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/632288.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号