1.阿里云实名认证
- 阿里云对象存储oss,标准高频率访问, 低频访问存储,归档存储(根本不经常访问)
冗余存储(备份) 读写权限(所有人还是自己访问)
@Component public class ConstantOssPropertiesUtils implements InitializingBean {不用注入,由spring创建bean
- 使用流 MultipartFile得到流,返回url,防止文件覆盖(使用uuid)
//生成UUID,但是遇到-全部替换为空格
UUID.randomUUID().toString().replaceAll("-","");
- 根据日期分类(好用配合joda-time日期工具)
new DateTime().toString("yyyy/MM/dd");
fileName=timeUrl+"/"+fileName;
- 用户认证信息在请求头得到,然后通过id更新用户认证信息
2.nuxt 跳/user固定路由 需要创建 page/user/index.vue
3.如果没有用户认证不能预约
4.写用户进行预约之前的增删改查,和管理员进行审核(改状态为2)
//分页对象遍历
pages.getRecords().stream().forEach(item->{});
//重要的是处理 标志位的值为 其他数据,pack方法聚合数据
如:
@Override
public OrderInfo getOrder(String orderId) {//根据字典整合数据
OrderInfo orderInfo = baseMapper.selectById(orderId);
OrderInfo orderInfo1 = this.packOrderInfo(orderInfo);
return orderInfo1;
}
private OrderInfo packOrderInfo(OrderInfo orderInfo) {
orderInfo.getParam().put("orderStatusString", OrderStatusEnum.getStatusNameByStatus(orderInfo.getOrderStatus()));
return orderInfo;
}
5.预约挂号,获取可预约的日期(天数)
//放号时间(用户打开10点 过去了,需要可预约的时间+1)+周期
releaseTime.isBeforeNow()//判断当前时间 过期
new DateTime().plusDays(i).toString("yyyy-MM-dd"); //for,得到可预约的所有日期
//对list分页,数据全部放进去会自动分页
IPage<Date> ip=new Page(page,7,dateList.size());
ip.setRecords(pageList);
6.预约挂号的统计日期,和处理统计mongodb的数据使用Aggregation
//聚合就是把一个对象,转换为另外一个对象(临时改一个对象的数据)
图预约日期聚合
7.list转map 使用流
8.如果业务太复杂就拆分成多个方法实现 如果是最后一页就设置为等待放号,某天如果超过预约时间就停止挂号
9.生成下单
修改预约数-1和可用预约数-1 使用mq,更新和短信通知
10.整合mq,提高下单的并发性,异步削峰(以免服务奔溃)
0.管理交换机和routing和队列的实体类
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";
public static final String EXCHANGE_DIRECT_TASK = "exchange.direct.task";
public static final String ROUTING_TASK_8 = "task.8";
//队列
public static final String QUEUE_TASK_8 = "queue.task.8";
}
1.写MQ配置类,使用Jackson转换Json为字符串
@Configuration
public class MQConfig {
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}
2.通用MQ发送消息的类
@Service
public class RabbitService {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送消息
* @param exchange 交换机
* @param routingKey 路由键
* @param message 消息
*/
public boolean sendMessage(String exchange, String routingKey, Object message) {
rabbitTemplate.convertAndSend(exchange, routingKey, message);
return true;
}
}
- 服务模块写监听类
@Component
public class HospitalReceiver {
@Autowired
private ScheduleService scheduleService;
@Autowired
private 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,
//xxx写业务方法
}
}
11.枚举类 values()得到所有枚举类
12.微信支付.查询微信支付状态, 其实就是要调用其他的服务接口
//注意支付的数量.要求参数是xml,用wx工具类可以设置(map转换) //二维码2个小时过期,使用redis
qriously前端显示二维码,因为微信返回地址是 weixin://协议
//在前端clearInterval定时不停查询后端支付状态(后端调用要修改数据库的相关接口)
//微信返回xml,又得变为map
/**
* 根据订单号下单,生成支付链接
*/
@Override
public Map createNative(Long orderId) {
try {
Map payMap = (Map) redisTemplate.opsForValue().get(orderId.toString());
if(null != payMap) return payMap;
//根据id获取订单信息
OrderInfo order = orderService.getById(orderId);
// 保存交易记录
paymentService.savePaymentInfo(order, PaymentTypeEnum.WEIXIN.getStatus());
//1、设置参数
Map paramMap = new HashMap();
paramMap.put("appid", ConstantPropertiesUtils.APPID);
paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER);
paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
String body = order.getReserveDate() + "就诊"+ order.getDepname();
paramMap.put("body", body);
paramMap.put("out_trade_no", order.getOutTradeNo());
//paramMap.put("total_fee", order.getAmount().multiply(new BigDecimal("100")).longValue()+"");
//以分为单位
paramMap.put("total_fee", "1");
paramMap.put("spbill_create_ip", "127.0.0.1");
paramMap.put("notify_url", "http://guli.shop/api/order/weixinPay/weixinNotify");
paramMap.put("trade_type", "NATIVE");
//2、HTTPClient来根据URL访问第三方接口并且传递参数
HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
//client设置参数
client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY));
client.setHttps(true);
client.post();
//3、返回第三方的数据
String xml = client.getContent();
Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);
//4、封装返回结果集
Map map = new HashMap<>();
map.put("orderId", orderId);
map.put("totalFee", order.getAmount());
map.put("resultCode", resultMap.get("result_code"));
map.put("codeUrl", resultMap.get("code_url"));
if(null != resultMap.get("result_code")) {
//微信支付二维码2小时过期,可采取2小时未支付取消订单
redisTemplate.opsForValue().set(orderId.toString(), map, 1000, TimeUnit.MINUTES);
}
return map;
} catch (Exception e) {
e.printStackTrace();
return new HashMap<>();
}
}
13.取消预约
1.未支付取消订单(直接修改数据库)
2.已经支付取消订单(需要退款) 先退款后更新(需要微信证书)写到配置文件(斜杠转义)
先查后改(http工具类设置证书)
//过了取消日期不能退款 最后mq更新预约数量
14.就医提醒(提前提醒不要超时)
//定时任务8点执行
//类加注解
@Component
@EnableSchedule
//方法加
@Scheduled(cron="")
//生成工具 https://cron.qqe2.com复制七位(它生成了8位)
//使用mq发送消息,其他服务监听到mq消息,进行发送短信
全部代码:
@Component
@EnableScheduling
public class ScheduledTask {
@Autowired
private RabbitService rabbitService;
/**
* 每天8点执行 提醒就诊
*/
//@Scheduled(cron = "0 0 1 * * ?")
@Scheduled(cron = "0/30 * * * * ?")
public void task1() {
System.out.println("aaa");
rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_TASK, MqConst.ROUTING_TASK_8, "");
}
}
15.预约统计(Echarts是百度捐给apache)柱状图饼图折线图
//x,y轴, 还有显示的统计数据数组
//mybatis的mapper文件的动态sql, 接口写@Param(“vo”)起别名,类写resultType=“全限定路径.xx”
<select >
<where>
<if test="vo.hosname!=null and vo.hosname!='' ">
and hosname like CONCAT('%',#{vo.hosname},'%')
</if>
<if test="vo.reserve_date!=null and vo.reserve_date!='' ">
and reserve_date >= #{vo.begin}
</if>
//坑爹,需要转义
<if test="vo.reserve_dateEnd!=null and vo.reserve_dateEnd!='' ">
and reserve_date <= #{vo.reserve_dateEnd}
</if>
and is_deleted=0
</where>
</select>
//还需要注意maven加打包插件
//map放两个list方便数据返回
16.stream流将list中的成员遍历变 1个list(如多个对象,只需要取到其中的name变为list)(方便前端图标显示)
list.stream().map(Vo::name).collect(Collectors.toList());
17.NoSql总结
1.redis做缓存和验证码有效时间
2.mongodb存储数据提升查询效率 复杂查询