目录:

(1)预约挂号-预约下单功能接口开发1

(2)预约挂号-预约下单功能接口开发2

(3)预约挂号-预约下单-整合RabbitMQ1

(4)预约挂号-预约下单-整合RabbitMQ2


(1)预约挂号-预约下单功能接口开发

当点击确认挂号,会生成一个挂号的订单,当订单生成过成功它会向订单表中,添加一条数据

下单参数:就诊人id与排班id

  1. 下单我们要获取就诊人信息
  2. 获取排班下单信息与规则信息
  3. 获取医院签名信息,然后通过接口去医院预约下单
  4. 下单成功更新排班信息与发送短信

创建新的模块:

 

pom.xml:先加一个远程调用的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>service</artifactId><groupId>com.atguigu</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>service_order</artifactId><dependencies><!--做远程调用--><dependency><groupId>com.atguigu</groupId><artifactId>service_cmn_client</artifactId><version>0.0.1-SNAPSHOT</version></dependency></dependencies></project>

创建配置文件:

# 服务端口
server.port=8206
# 服务名
spring.application.name=service-order
# 环境设置:dev、test、prod
spring.profiles.active=dev# mysql数据库连接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/yygh_hosp?characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root123#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8spring.data.mongodb.uri=mongodb://192.168.23.128:27017/yygh_hosp# nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848#rabbitmq地址
spring.rabbitmq.host=192.168.23.128
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

创建启动类:

ServiceOrderApplication

package com.atguigu.yygh.order;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;@SpringBootApplication
@ComponentScan(basePackages = {"com.atguigu"})
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"com.atguigu"})
public class ServiceOrderApplication {public static void main(String[] args) {SpringApplication.run(ServiceOrderApplication.class, args);}
}

在网关模块做一下配置:service-order

实体类已经引入过了:

创建配置类:OrderConfig

package com.atguigu.yygh.order.config;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;@Configuration
@MapperScan("com.atguigu.yygh.order.mapper")
public class OrderConfig {
}

创建mapper:

package com.atguigu.yygh.order.mapper;import com.atguigu.yygh.model.order.OrderInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;public interface OrderMapper extends BaseMapper<OrderInfo> {
}

创建controller:添加访问接口

package com.atguigu.yygh.order.api;import com.atguigu.yygh.common.result.Result;
import com.atguigu.yygh.order.service.OrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@Api(tags = "订单接口")
@RestController
@RequestMapping("/api/order/orderInfo")
public class OrderApiController {@Autowiredprivate OrderService orderService;//生成挂号订单@ApiOperation(value = "创建订单")@PostMapping("auth/submitOrder/{scheduleId}/{patientId}")public Result submitOrder(@ApiParam(name = "scheduleId", value = "排班id", required = true)@PathVariable String scheduleId,@ApiParam(name = "patientId", value = "就诊人id", required = true)@PathVariable Long patientId) {Long aLong = orderService.saveOrder(scheduleId, patientId);return Result.ok(aLong);}}

OrderService 接口:

package com.atguigu.yygh.order.service;import com.atguigu.yygh.model.order.OrderInfo;
import com.baomidou.mybatisplus.extension.service.IService;public interface OrderService extends IService<OrderInfo> {//保存订单Long saveOrder(String scheduleId, Long patientId);
}

实现类:没有实现,需要先在相应的模块,获取就诊人信息接口,排班信息接口,最后在这里远程调用

package com.atguigu.yygh.order.service.impl;import com.atguigu.yygh.model.order.OrderInfo;
import com.atguigu.yygh.order.mapper.OrderMapper;
import com.atguigu.yygh.order.service.OrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;@Service
public class OrderServiceImpl extendsServiceImpl<OrderMapper, OrderInfo> implements OrderService {//保存订单@Overridepublic Long saveOrder(String scheduleId, Long patientId) {return null;}
}

在service-user模块编写根基就诊人id获取就诊人信息的接口:

在PatientApiController:中继续添加访问接口:

 //根据就诊人id获取就诊人信息@GetMapping("inner/get/{id}")public Patient getPatientOrder(@PathVariable Long id) {Patient patient = patientService.getPatientId(id);return patient;}

访问service的方法原来写过,可以简单看一下:

package com.atguigu.yygh.user.service;import com.atguigu.yygh.model.user.Patient;
import com.baomidou.mybatisplus.extension.service.IService;import java.util.List;public interface PatientService extends IService<Patient> {//获取就诊人列表List<Patient> findAllUserId(Long userId);//根据id获取就诊人信息Patient getPatientId(Long id);
}

实现类:

//根据id获取就诊人信息@Overridepublic Patient getPatientId(Long id) {/*Patient patient=baseMapper.selectById(id);this.packPatient(patient);*///一行写完,调用下面的方法return this.packPatient(baseMapper.selectById(id));}//Patient对象里面其他参数封装private Patient packPatient(Patient patient) {//根据证件类型编码,获取证件类型具体指String certificatesTypeString =dictFeignClient.getName(DictEnum.CERTIFICATES_TYPE.getDictCode(), patient.getCertificatesType());//联系人证件//联系人证件类型String contactsCertificatesTypeString =dictFeignClient.getName(DictEnum.CERTIFICATES_TYPE.getDictCode(),patient.getContactsCertificatesType());//省String provinceString = dictFeignClient.getName(patient.getProvinceCode());//市String cityString = dictFeignClient.getName(patient.getCityCode());//区String districtString = dictFeignClient.getName(patient.getDistrictCode());patient.getParam().put("certificatesTypeString", certificatesTypeString);patient.getParam().put("contactsCertificatesTypeString", contactsCertificatesTypeString);patient.getParam().put("provinceString", provinceString);patient.getParam().put("cityString", cityString);patient.getParam().put("districtString", districtString);patient.getParam().put("fullAddress", provinceString + cityString + districtString + patient.getAddress());return patient;}

创建远程调用的模块:

创建远程访问接口:

package com.atguigu.yygh.user.client;import com.atguigu.yygh.model.user.Patient;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@FeignClient(value = "service-user")
@Repository
public interface PatientFeignClient {//获取就诊人@GetMapping("/api/user/patient/inner/get/{id}")Patient getPatientOrder(@PathVariable("id") Long id);
}

在service-hosp模块: 在HospApiController:继续添加访问接口

ScheduleService接口:

//根据排班id获取预约下单数据ScheduleOrderVo getScheduleOrderVo(String scheduleId);

实现类:

 //获取排班id获取排班数据@Overridepublic Schedule getScheduleId(String scheduleId) {Schedule schedule = scheduleRepository.findById(scheduleId).get();return this.packageSchedule(schedule);} //根据排班id获取预约下单数据@Overridepublic ScheduleOrderVo getScheduleOrderVo(String scheduleId) {ScheduleOrderVo scheduleOrderVo = new ScheduleOrderVo();//获取排班信息Schedule schedule = this.getScheduleId(scheduleId);//Schedule schedule = baseMapper.selectById(scheduleId);if(schedule == null) {throw new HospitalException(ResultCodeEnum.PARAM_ERROR);}//获取预约规则信息Hospital hospital = hospitalService.getByHoscode(schedule.getHoscode());if(hospital == null) {throw new HospitalException(ResultCodeEnum.PARAM_ERROR);}BookingRule bookingRule = hospital.getBookingRule();if(bookingRule == null) {throw new HospitalException(ResultCodeEnum.PARAM_ERROR);}//把获取数据设置到scheduleOrderVoscheduleOrderVo.setHoscode(schedule.getHoscode());scheduleOrderVo.setHosname(hospitalService.getHospName(schedule.getHoscode()));scheduleOrderVo.setDepcode(schedule.getDepcode());scheduleOrderVo.setDepname(departmentService.getDepName(schedule.getHoscode(), schedule.getDepcode()));scheduleOrderVo.setHosScheduleId(schedule.getHosScheduleId());scheduleOrderVo.setAvailableNumber(schedule.getAvailableNumber());scheduleOrderVo.setTitle(schedule.getTitle());scheduleOrderVo.setReserveDate(schedule.getWorkDate());scheduleOrderVo.setReserveTime(schedule.getWorkTime());scheduleOrderVo.setAmount(schedule.getAmount());//退号截止天数(如:就诊前一天为-1,当天为0)int quitDay = bookingRule.getQuitDay();DateTime quitTime = this.getDateTime(new DateTime(schedule.getWorkDate()).plusDays(quitDay).toDate(), bookingRule.getQuitTime());scheduleOrderVo.setQuitTime(quitTime.toDate());//预约开始时间DateTime startTime = this.getDateTime(new Date(), bookingRule.getReleaseTime());scheduleOrderVo.setStartTime(startTime.toDate());//预约截止时间DateTime endTime = this.getDateTime(new DateTime().plusDays(bookingRule.getCycle()).toDate(), bookingRule.getStopTime());scheduleOrderVo.setEndTime(endTime.toDate());//当天停止挂号时间DateTime stopTime = this.getDateTime(new Date(), bookingRule.getStopTime());scheduleOrderVo.setStartTime(startTime.toDate());return scheduleOrderVo;}

在HospitalApiController:中添加:

 //获取医院签名信息@ApiOperation(value = "获取医院签名信息")@GetMapping("inner/getSignInfoVo/{hoscode}")public SignInfoVo getSignInfoVo(@ApiParam(name = "hoscode", value = "医院code", required = true)@PathVariable("hoscode") String hoscode) {return hospitalSetService.getSignInfoVo(hoscode);}

HospitalSetService 接口:

package com.atguigu.yygh.hosp.service;import com.atguigu.yygh.model.hosp.HospitalSet;
import com.atguigu.yygh.vo.order.SignInfoVo;
import com.baomidou.mybatisplus.extension.service.IService;public interface HospitalSetService extends IService<HospitalSet> {//根据医院编码获取签名String getSignKey(String hoscode);//获取医院签名信息SignInfoVo getSignInfoVo(String hoscode);
}

实现类:

//获取医院签名信息@Overridepublic SignInfoVo getSignInfoVo(String hoscode) {QueryWrapper<HospitalSet> wrapper = new QueryWrapper<>();wrapper.eq("hoscode",hoscode);HospitalSet hospitalSet = baseMapper.selectOne(wrapper);if(null == hospitalSet) {throw new HospitalException(ResultCodeEnum.HOSPITAL_OPEN);}SignInfoVo signInfoVo = new SignInfoVo();signInfoVo.setApiUrl(hospitalSet.getApiUrl());signInfoVo.setSignKey(hospitalSet.getSignKey());return signInfoVo;}

创建远程访问接口:

HospitalFeignClient :

package com.atguigu.yygh.hosp.client;import com.atguigu.yygh.vo.hosp.ScheduleOrderVo;
import com.atguigu.yygh.vo.order.SignInfoVo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@FeignClient(value = "service-hosp")
@Repository
public interface HospitalFeignClient {/*** 根据排班id获取预约下单数据*/@GetMapping("/api/hosp/hospital/inner/getScheduleOrderVo/{scheduleId}")ScheduleOrderVo getScheduleOrderVo(@PathVariable("scheduleId") String scheduleId);/*** 获取医院签名信息*/@GetMapping("/api/hosp/hospital/inner/getSignInfoVo/{hoscode}")SignInfoVo getSignInfoVo(@PathVariable("hoscode") String hoscode);
}

(2)预约挂号-预约下单功能接口开发2

在servvice-order的pom.xml中引入远程调用的接口依赖:

医院接口模块调用的工具类:

医院系统的模块:

实体类

package com.atguigu.yygh.vo.order;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import java.io.Serializable;/*** <p>* HospitalSet* </p>** @author qy*/
@Data
@ApiModel(description = "签名信息")
public class SignInfoVo  implements Serializable {private static final long serialVersionUID = 1L;@ApiModelProperty(value = "api基础路径")private String apiUrl;@ApiModelProperty(value = "签名秘钥")private String signKey;}

继续在OrderServiceImpl中添加未写的实现功能:

package com.atguigu.yygh.order.service.impl;import com.alibaba.fastjson.JSONObject;
import com.atguigu.yygh.common.exception.HospitalException;
import com.atguigu.yygh.common.helper.HttpRequestHelper;
import com.atguigu.yygh.common.result.ResultCodeEnum;
import com.atguigu.yygh.enums.OrderStatusEnum;
import com.atguigu.yygh.hosp.client.HospitalFeignClient;
import com.atguigu.yygh.model.order.OrderInfo;
import com.atguigu.yygh.model.user.Patient;
import com.atguigu.yygh.order.mapper.OrderMapper;
import com.atguigu.yygh.order.service.OrderService;
import com.atguigu.yygh.user.client.PatientFeignClient;
import com.atguigu.yygh.vo.hosp.ScheduleOrderVo;
import com.atguigu.yygh.vo.msm.MsmVo;
import com.atguigu.yygh.vo.order.OrderMqVo;
import com.atguigu.yygh.vo.order.SignInfoVo;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.HashMap;
import java.util.Map;
import java.util.Random;@Service
public class OrderServiceImpl extendsServiceImpl<OrderMapper, OrderInfo> implements OrderService {//注入远程调用@Autowiredprivate PatientFeignClient patientFeignClient;@Autowiredprivate HospitalFeignClient hospitalFeignClient;//保存订单@Overridepublic Long saveOrder(String scheduleId, Long patientId) {//获取就诊人信息Patient patient = patientFeignClient.getPatientOrder(patientId);//获取排班相关信息ScheduleOrderVo scheduleOrderVo = hospitalFeignClient.getScheduleOrderVo(scheduleId);//判断当前时间是否还可以预约if(new DateTime(scheduleOrderVo.getStartTime()).isAfterNow()|| new DateTime(scheduleOrderVo.getEndTime()).isBeforeNow()) {throw new HospitalException(ResultCodeEnum.TIME_NO);}//获取签名信息SignInfoVo signInfoVo = hospitalFeignClient.getSignInfoVo(scheduleOrderVo.getHoscode());//添加到订单表OrderInfo orderInfo = new OrderInfo();//scheduleOrderVo 数据复制到 orderInfoBeanUtils.copyProperties(scheduleOrderVo,orderInfo);//向orderInfo设置其他数据String outTradeNo = System.currentTimeMillis() + ""+ new Random().nextInt(100);orderInfo.setOutTradeNo(outTradeNo);orderInfo.setScheduleId(scheduleId);orderInfo.setUserId(patient.getUserId());orderInfo.setPatientId(patientId);orderInfo.setPatientName(patient.getName());orderInfo.setPatientPhone(patient.getPhone());orderInfo.setOrderStatus(OrderStatusEnum.UNPAID.getStatus());baseMapper.insert(orderInfo);//调用医院接口,实现预约挂号操作//设置调用医院接口需要参数,参数放到map集合Map<String, Object> paramMap = new HashMap<>();paramMap.put("hoscode",orderInfo.getHoscode());paramMap.put("depcode",orderInfo.getDepcode());paramMap.put("hosScheduleId",orderInfo.getScheduleId());paramMap.put("reserveDate",new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd"));paramMap.put("reserveTime", orderInfo.getReserveTime());paramMap.put("amount",orderInfo.getAmount());paramMap.put("name", patient.getName());paramMap.put("certificatesType",patient.getCertificatesType());paramMap.put("certificatesNo", patient.getCertificatesNo());paramMap.put("sex",patient.getSex());paramMap.put("birthdate", patient.getBirthdate());paramMap.put("phone",patient.getPhone());paramMap.put("isMarry", patient.getIsMarry());paramMap.put("provinceCode",patient.getProvinceCode());paramMap.put("cityCode", patient.getCityCode());paramMap.put("districtCode",patient.getDistrictCode());paramMap.put("address",patient.getAddress());//联系人paramMap.put("contactsName",patient.getContactsName());paramMap.put("contactsCertificatesType", patient.getContactsCertificatesType());paramMap.put("contactsCertificatesNo",patient.getContactsCertificatesNo());paramMap.put("contactsPhone",patient.getContactsPhone());paramMap.put("timestamp", HttpRequestHelper.getTimestamp());String sign = HttpRequestHelper.getSign(paramMap, signInfoVo.getSignKey());paramMap.put("sign", sign);//请求医院系统接口JSONObject result = HttpRequestHelper.sendRequest(paramMap, signInfoVo.getApiUrl() + "/order/submitOrder");if(result.getInteger("code")==200) {JSONObject jsonObject = result.getJSONObject("data");//预约记录唯一标识(医院预约记录主键)String hosRecordId = jsonObject.getString("hosRecordId");//预约序号Integer number = jsonObject.getInteger("number");;//取号时间String fetchTime = jsonObject.getString("fetchTime");;//取号地址String fetchAddress = jsonObject.getString("fetchAddress");;//更新订单orderInfo.setHosRecordId(hosRecordId);orderInfo.setNumber(number);orderInfo.setFetchTime(fetchTime);orderInfo.setFetchAddress(fetchAddress);baseMapper.updateById(orderInfo);//排班可预约数Integer reservedNumber = jsonObject.getInteger("reservedNumber");//排班剩余预约数Integer availableNumber = jsonObject.getInteger("availableNumber");//发送mq消息,号源更新和短信通知//发送mq信息更新号源//待写} else {throw new HospitalException(result.getString("message"), ResultCodeEnum.FAIL.getCode());}return orderInfo.getId();}
}

(3)预约挂号-预约下单-整合RabbitMQ

  1. 预约成功后处理逻辑

预约成功后我们要更新预约数和短信提醒预约成功,为了提高下单的并发性,这部分逻辑我们就交给mq为我们完成,预约成功发送消息即可

(1)RabbitMQ简介

以商品订单场景为例,

如果商品服务和订单服务是两个不同的微服务,在下单的过程中订单服务需要调用商品服务进行扣库存操作。按照传统的方式,下单过程要等到调用完毕之后才能返回下单成功,如果网络产生波动等原因使得商品服务扣库存延迟或者失败,会带来较差的用户体验,如果在高并发的场景下,这样的处理显然是不合适的,那怎么进行优化呢?这就需要消息队列登场了。

消息队列提供一个异步通信机制,消息的发送者不必一直等待到消息被成功处理才返回,而是立即返回。消息中间件负责处理网络通信,如果网络连接不可用,消息被暂存于队列当中,当网络畅通的时候在将消息转发给相应的应用程序或者服务,当然前提是这些服务订阅了该队列。如果在商品服务和订单服务之间使用消息中间件,既可以提高并发量,又降低服务之间的耦合度。

RabbitMQ就是这样一款消息队列。RabbitMQ是一个开源的消息代理的队列服务器,用来通过普通协议在完全不同的应用之间共享数据。

(2)典型应用场景:

异步处理。把消息放入消息中间件中,等到需要的时候再去处理。

流量削峰。例如秒杀活动,在短时间内访问量急剧增加,使用消息队列,当消息队列满了就拒绝响应,跳转到错误页面,这样就可以使得系统不会因为超负载而崩溃。

日志处理

应用解耦

2)安装RabbitMQ

docker pull rabbitmq:management

docker run -d -p 5672:5672 -p 15672:15672 --name rabbitmq rabbitmq:management

rabbitmq里面的访问端口是5672 ,而后台管理端口是15672

原来自己安装过了,进行启动:

查看启动状态:

访问:

默认登录都是guest

登录成功:

rabbit-util模块封装

由于后续可能多个模块都会使用mq,所以我们把它封装成一个模块,需要的地方直接引用即可

创建新的模块:

 

pom.xml中引入依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>common</artifactId><groupId>com.atguigu</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>rabbit_util</artifactId><dependencies><!--rabbitmq消息队列--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bus-amqp</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId></dependency></dependencies></project>

RabbitService :发送消息

package com.atguigu.common.rabbit.service;import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class RabbitService {@Autowiredprivate RabbitTemplate rabbitTemplate;/***  发送消息* @param exchange 交换机* @param routingKey 路由键* @param message 消息*/public boolean sendMessage(String exchange, String routingKey, Object message) {rabbitTemplate.convertAndSend(exchange, routingKey, message);return true;}
}

消息转换器:创建一个配置类,完成json的序列化,默认使用的是jdk的序列化

package com.atguigu.common.rabbit.config;import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MQConfig {@Beanpublic MessageConverter messageConverter(){return new Jackson2JsonMessageConverter();}
}

(4)预约挂号-预约下单-整合RabbitMQ2

在发送短信模块中加入rabbit模块的依赖:

在配置文件中 加上mq的配置:

在rabbit_util模块创建一个常量类,常量类配置一些,相关的内容比如交换机,队列,路由等等

package com.atguigu.common.rabbit.constant;public class MqConst {/*** 预约下单*/public static final String EXCHANGE_DIRECT_ORDER= "exchange.direct.order";public static final String ROUTING_ORDER = "order";//队列public static final String QUEUE_ORDER  = "queue.order";/*** 短信*/public static final String EXCHANGE_DIRECT_MSM = "exchange.direct.msm";public static final String ROUTING_MSM_ITEM = "msm.item";//队列public static final String QUEUE_MSM_ITEM  = "queue.msm.item";
}

发送短信的实体:

@Data
@ApiModel(description = "短信实体")
public class MsmVo {@ApiModelProperty(value = "phone")private String phone;@ApiModelProperty(value = "短信模板code")private String templateCode;@ApiModelProperty(value = "短信模板参数")private Map<String,Object> param;
}

在service_msm模块的MsmService接口继续中添加发送短信的接口

发送短信的接口

package com.atguigu.yygh.msm.service;import com.atguigu.yygh.vo.msm.MsmVo;public interface MsmService {//整合短信服务进行发送,发送手机验证码boolean send(String phone, String code);//mq使用发送短信boolean send(MsmVo msmVo);
}

实现类:发送短信方法

 //mq发送短信封装@Overridepublic boolean send(MsmVo msmVo) {if(!StringUtils.isEmpty(msmVo.getPhone())) {boolean isSend = this.send(msmVo.getPhone(), msmVo.getParam());return isSend;}return false;}private boolean send(String phone, Map<String,Object> param) {//判断手机号是否为空if(StringUtils.isEmpty(phone)) {return false;}//整合阿里云短信服务//设置相关参数DefaultProfile profile = DefaultProfile.getProfile(ConstantPropertiesUtils.REGION_Id,ConstantPropertiesUtils.ACCESS_KEY_ID,ConstantPropertiesUtils.SECRECT);IAcsClient client = new DefaultAcsClient(profile);CommonRequest request = new CommonRequest();//request.setProtocol(ProtocolType.HTTPS);request.setMethod(MethodType.POST);request.setDomain("dysmsapi.aliyuncs.com");request.setVersion("2017-05-25");request.setAction("SendSms");//手机号request.putQueryParameter("PhoneNumbers", phone);//签名名称request.putQueryParameter("SignName", "阿里云短信测试");//模板coderequest.putQueryParameter("TemplateCode", "SMS_154950909");request.putQueryParameter("TemplateParam", JSONObject.toJSONString(param));//调用方法进行短信发送try {CommonResponse response = client.getCommonResponse(request);System.out.println(response.getData());return response.getHttpResponse().isSuccess();} catch (ServerException e) {e.printStackTrace();} catch (ClientException e) {e.printStackTrace();}return false;}

定义监听器类:

package com.atguigu.yygh.msm.receiver;import com.atguigu.common.rabbit.constant.MqConst;
import com.atguigu.yygh.msm.service.MsmService;
import com.atguigu.yygh.vo.msm.MsmVo;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class SmsReceiver {@Autowiredprivate MsmService msmService;@RabbitListener(bindings = @QueueBinding(value = @Queue(value = MqConst.QUEUE_MSM_ITEM, durable = "true"),exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_MSM),key = {MqConst.ROUTING_MSM_ITEM}))public void send(MsmVo msmVo, Message message, Channel channel) {msmService.send(msmVo);}
}

更新排班数量:

这个模块的配置 文件中加入rabbitmq的配置地址:

#rabbitmq地址
spring.rabbitmq.host=192.168.23.128
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

Model中更新排班的实体:

@Data
@ApiModel(description = "OrderMqVo")
public class OrderMqVo {@ApiModelProperty(value = "可预约数")private Integer reservedNumber;@ApiModelProperty(value = "剩余预约数")private Integer availableNumber;@ApiModelProperty(value = "排班id")private String scheduleId;@ApiModelProperty(value = "短信实体")private MsmVo msmVo;
}

在ScheduleService:添加接口

/*** 修改排班
*/
void update(Schedule schedule);

实现类:

//更新排班信息 用于mq@Overridepublic void update(Schedule schedule) {schedule.setUpdateTime(new Date());//主键一致就是更新scheduleRepository.save(schedule);}

创建监听器:

package com.atguigu.yygh.hosp.receiver;import com.atguigu.common.rabbit.constant.MqConst;
import com.atguigu.common.rabbit.service.RabbitService;
import com.atguigu.yygh.hosp.service.ScheduleService;
import com.atguigu.yygh.model.hosp.Schedule;
import com.atguigu.yygh.vo.msm.MsmVo;
import com.atguigu.yygh.vo.order.OrderMqVo;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.io.IOException;@Component
public class HospitalReceiver {@Autowiredprivate ScheduleService scheduleService;@Autowiredprivate RabbitService rabbitService;@RabbitListener(bindings = @QueueBinding(value = @Queue(value = MqConst.QUEUE_ORDER, durable = "true"),exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_ORDER),key = {MqConst.ROUTING_ORDER}))public void receiver(OrderMqVo orderMqVo, Message message, Channel channel) throws IOException {//下单成功更新预约数Schedule schedule = scheduleService.getScheduleId(orderMqVo.getScheduleId());schedule.setReservedNumber(orderMqVo.getReservedNumber());schedule.setAvailableNumber(orderMqVo.getAvailableNumber());scheduleService.update(schedule);//发送短信MsmVo msmVo = orderMqVo.getMsmVo();if(null != msmVo) {rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_MSM, MqConst.ROUTING_MSM_ITEM, msmVo);}}
}

在service_order模块中引入:依赖:

在配置文件中加入rabbitmq的依赖:

#rabbitmq地址
spring.rabbitmq.host=192.168.23.128
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

OrderServiceImpl实现类:添加未写的发送短信方法:

package com.atguigu.yygh.order.service.impl;import com.alibaba.fastjson.JSONObject;
import com.atguigu.common.rabbit.constant.MqConst;
import com.atguigu.common.rabbit.service.RabbitService;
import com.atguigu.yygh.common.exception.HospitalException;
import com.atguigu.yygh.common.helper.HttpRequestHelper;
import com.atguigu.yygh.common.result.ResultCodeEnum;
import com.atguigu.yygh.enums.OrderStatusEnum;
import com.atguigu.yygh.hosp.client.HospitalFeignClient;
import com.atguigu.yygh.model.order.OrderInfo;
import com.atguigu.yygh.model.user.Patient;
import com.atguigu.yygh.order.mapper.OrderMapper;
import com.atguigu.yygh.order.service.OrderService;
import com.atguigu.yygh.user.client.PatientFeignClient;
import com.atguigu.yygh.vo.hosp.ScheduleOrderVo;
import com.atguigu.yygh.vo.msm.MsmVo;
import com.atguigu.yygh.vo.order.OrderMqVo;
import com.atguigu.yygh.vo.order.SignInfoVo;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.HashMap;
import java.util.Map;
import java.util.Random;@Service
public class OrderServiceImpl extendsServiceImpl<OrderMapper, OrderInfo> implements OrderService {//注入远程调用@Autowiredprivate PatientFeignClient patientFeignClient;@Autowiredprivate HospitalFeignClient hospitalFeignClient;@Autowiredprivate RabbitService rabbitService;//保存订单@Overridepublic Long saveOrder(String scheduleId, Long patientId) {//获取就诊人信息Patient patient = patientFeignClient.getPatientOrder(patientId);//获取排班相关信息ScheduleOrderVo scheduleOrderVo = hospitalFeignClient.getScheduleOrderVo(scheduleId);//判断当前时间是否还可以预约if(new DateTime(scheduleOrderVo.getStartTime()).isAfterNow()|| new DateTime(scheduleOrderVo.getEndTime()).isBeforeNow()) {throw new HospitalException(ResultCodeEnum.TIME_NO);}//获取签名信息SignInfoVo signInfoVo = hospitalFeignClient.getSignInfoVo(scheduleOrderVo.getHoscode());//添加到订单表OrderInfo orderInfo = new OrderInfo();//scheduleOrderVo 数据复制到 orderInfoBeanUtils.copyProperties(scheduleOrderVo,orderInfo);//向orderInfo设置其他数据String outTradeNo = System.currentTimeMillis() + ""+ new Random().nextInt(100);orderInfo.setOutTradeNo(outTradeNo);orderInfo.setScheduleId(scheduleId);orderInfo.setUserId(patient.getUserId());orderInfo.setPatientId(patientId);orderInfo.setPatientName(patient.getName());orderInfo.setPatientPhone(patient.getPhone());orderInfo.setOrderStatus(OrderStatusEnum.UNPAID.getStatus());baseMapper.insert(orderInfo);//调用医院接口,实现预约挂号操作//设置调用医院接口需要参数,参数放到map集合Map<String, Object> paramMap = new HashMap<>();paramMap.put("hoscode",orderInfo.getHoscode());paramMap.put("depcode",orderInfo.getDepcode());paramMap.put("hosScheduleId",orderInfo.getScheduleId());paramMap.put("reserveDate",new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd"));paramMap.put("reserveTime", orderInfo.getReserveTime());paramMap.put("amount",orderInfo.getAmount());paramMap.put("name", patient.getName());paramMap.put("certificatesType",patient.getCertificatesType());paramMap.put("certificatesNo", patient.getCertificatesNo());paramMap.put("sex",patient.getSex());paramMap.put("birthdate", patient.getBirthdate());paramMap.put("phone",patient.getPhone());paramMap.put("isMarry", patient.getIsMarry());paramMap.put("provinceCode",patient.getProvinceCode());paramMap.put("cityCode", patient.getCityCode());paramMap.put("districtCode",patient.getDistrictCode());paramMap.put("address",patient.getAddress());//联系人paramMap.put("contactsName",patient.getContactsName());paramMap.put("contactsCertificatesType", patient.getContactsCertificatesType());paramMap.put("contactsCertificatesNo",patient.getContactsCertificatesNo());paramMap.put("contactsPhone",patient.getContactsPhone());paramMap.put("timestamp", HttpRequestHelper.getTimestamp());String sign = HttpRequestHelper.getSign(paramMap, signInfoVo.getSignKey());paramMap.put("sign", sign);//请求医院系统接口JSONObject result = HttpRequestHelper.sendRequest(paramMap, signInfoVo.getApiUrl() + "/order/submitOrder");if(result.getInteger("code")==200) {JSONObject jsonObject = result.getJSONObject("data");//预约记录唯一标识(医院预约记录主键)String hosRecordId = jsonObject.getString("hosRecordId");//预约序号Integer number = jsonObject.getInteger("number");;//取号时间String fetchTime = jsonObject.getString("fetchTime");;//取号地址String fetchAddress = jsonObject.getString("fetchAddress");;//更新订单orderInfo.setHosRecordId(hosRecordId);orderInfo.setNumber(number);orderInfo.setFetchTime(fetchTime);orderInfo.setFetchAddress(fetchAddress);baseMapper.updateById(orderInfo);//排班可预约数Integer reservedNumber = jsonObject.getInteger("reservedNumber");//排班剩余预约数Integer availableNumber = jsonObject.getInteger("availableNumber");//发送mq消息,号源更新和短信通知//发送mq信息更新号源OrderMqVo orderMqVo = new OrderMqVo();orderMqVo.setScheduleId(scheduleId);orderMqVo.setReservedNumber(reservedNumber);//预约数量orderMqVo.setAvailableNumber(availableNumber);//可预约数量//短信提示MsmVo msmVo = new MsmVo();msmVo.setPhone(orderInfo.getPatientPhone());String reserveDate = new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd") + (orderInfo.getReserveTime()==0 ? "上午" : "下午");Map<String,Object> param = new HashMap<String,Object>(){{put("title", orderInfo.getHosname()+"|"+orderInfo.getDepname()+"|"+orderInfo.getTitle());put("amount", orderInfo.getAmount());put("reserveDate", reserveDate);put("name", orderInfo.getPatientName());put("quitTime", new DateTime(orderInfo.getQuitTime()).toString("yyyy-MM-dd HH:mm"));}};msmVo.setParam(param);orderMqVo.setMsmVo(msmVo);//发送rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_ORDER, MqConst.ROUTING_ORDER, orderMqVo);} else {throw new HospitalException(result.getString("message"), ResultCodeEnum.FAIL.getCode());}return orderInfo.getId();}
}

总结以上的调用过程:首先是在service_orser模块发送消息到交换机,在service_hosp模块监听到消息进行进行更新预约数,再发送消息,在service_msm模块接收到消息,然后调用发送短息的方法进行发送短信

尚医通-预约下单接口开发-整合RabbitMQ(三十六)相关推荐

  1. 尚医通-阿里云短信服务(二十九)

    目录: (1)前台用户系统-手机登录-阿里云短信服务介绍 (2)手机登录-整合短信服务 (3)整合短信发送服务测试 (1)前台用户系统-手机登录-阿里云短信服务介绍 现在使用阿里云完成短信服务:注册登 ...

  2. 尚医通-预约下单中rabbitmq的使用

    需求描述 在挂号界面选择完需要挂号的医生和排版后,添加就诊人,确认挂号 附上业务流程图 技术分析 我们今天主要来看看这块 mq 的运用,也是一个思考,我还是挑着重要的来讲,这里讲讲我们这里怎么使用 m ...

  3. 尚医通-医院列表接口-等级接口-功能测试(二十二)

    目录: (1)医院列表接口-医院等级接口  (2)医院列表接口-远程调用  (3)医院列表接口-功能测试 (1)医院列表接口-医院等级接口 由于我们的医院等级.省市区地址都是取的数据字典value值, ...

  4. 某一个接口403 其他接口可以调通_Neo的务实外设指南 篇三十六:一个就够,65W快充+C口混插+最多6个设备 - 飞利浦65W摩天轮插座_插座...

    2020-10-26 15:29:0623点赞23收藏2评论 嗨,大家好!我是沈少! 之前晒雷电3扩展坞的时候,已经有小伙伴注意到我用来提供PD充电的是一个很小巧的魔方插座.也有朋友私下提醒我,这类产 ...

  5. 地主家也没有余粮了---走出软件作坊:三五个人十来条枪 如何成为开发正规军(三十六)

    有个网友给我的留言让我陷于深思. 他是一个十来条枪公司的小老板.他的困境也是许多同样规模小软件公司的困境.我也有不少朋友创业,他们所处的困境都是相似的. 大家都是差不多认识几个客户,然后觉得时机成熟了 ...

  6. Android开发笔记(三十六)展示类控件

    View/ViewGroup View是单个视图,所有的控件类都是从它派生出来:而ViewGroup是个视图组织,所有的布局视图类都是从它派生出来.由于View和ViewGroup是基类,因此很少会直 ...

  7. OpenCV开发笔记(三十六):红胖子8分钟带你深入了解缩放与图像金字塔(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载 原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客导航:https://blog.csdn.net/qq21497936/ ...

  8. 尚医通-OAuth2-微信登录接口开发(三十一)

    目录: (1)微信登录-OAuth2介绍 (2)前台用户系统-微信登录-准备工作 (3)微信登录-生成微信二维码-接口开发 (4)微信登录-生成验证码-前端整合 (5)微信登录-获取扫码人信息-实现分 ...

  9. 尚医通 (三十一) --------- 手机登录

    目录 一.登录需求 1. 登录效果 2. 登录需求 二.登录 1. 搭建 service-user 模块 2. 添加用户基础类 3. 登录 API 接口 4. 生成 token 5. 阿里云短信 6. ...

最新文章

  1. 研究生实名举报深圳大学导师强迫学生延迟毕业,违规报销,各方回应
  2. java 偶数求和 数组_JAVA实现幻方
  3. Qt Creator共享项目设置
  4. 基于大数据搭建社交好友推荐系统
  5. 将 AR 新创公司收入囊中后,Lyft 的自动驾驶脚步要加快了
  6. 大数据_MapperReduce_协处理器_类似Mysql的触发器---Hbase工作笔记0024
  7. 五个 PostgreSQL 典型故障案例及处理
  8. 谷歌搜索363搜索引擎入口_SEO谷歌搜索引擎优化到底有啥好?
  9. Magnet for mac(专业窗口辅助工具)支持m1
  10. MaxtoCode 2.0 7月1日发布 测试版
  11. 身高回归现象是否真的存在?
  12. 计算机一级考word几,计算机一级word考试主要内容
  13. 虚拟机安装LEDE之后如何配置连接互联网
  14. 金蝶云星空表单插件开发常用事件、方法、函数
  15. 【文化课每周学习记录】2019.3.17——2019.3.23
  16. 【ASO项目使用的技术】(例如:1、hook CFUserNotificationCreat 截取Header 部分信息、Message内容 进行任务处理2、设备信息的修改、清理数据3、js逆向)
  17. arduino麦轮转弯程序_麦克纳姆轮全向轮战车程序精髓分享
  18. 特斯拉自动驾驶功能更新:将上线红绿灯识别自动停车
  19. Twinmotion 2020 视频教程-学习笔记
  20. UNIZEN每周洞察第四期:Unizen生态迎来丰富进展

热门文章

  1. 用php打出2020年是庚子鼠年,2020庚子鼠年九宫飞星图,2020年的鼠是什么命
  2. 基于Cesium的实景三维模型动态更新-以3Dtiles为例(一)
  3. power iso linux启动盘,如何使用PowerISO制作Centos7启动U盘?
  4. 供应链管理SCM(一)
  5. 《烈火如歌》书写悱恻爱情 原著小说上线书旗小说
  6. 转: Javascript收藏
  7. IBM DB2 V9 存储过程异常捕获
  8. Unity NavMesh蓝色表面不出现
  9. wampserver3.1.7_x64启动后橙色不变绿解决办法
  10. 整型和bcd的对应关系_BCD码与整数之间的转换