集信达短信JAVA项目,保证短信高效、准确送达、简单易操作的对接方式。通过对服务的解耦、通讯方式的升级来提升系统的吞吐量 同时在多通道的加持下,通过智能动态的通道 评级、选举、降级、热插拔、增强了系统的健壮性,摆脱对单一通道的依赖。 并且提供了多个平台的对接方式,满足项目需求
系统构架图
项目整体工程和模块功能如下
1 pd-sms-entity # 短信平台实体 2 pd-sms-manage # 系统管理服务 3 pd-sms-api # 短信接收服务,应用系统调用接口、发送短信 4 pd-sms-server # 短信发送服务,调用短信通道、发送短信 5 pd-sms-sdk # 短信SDK,应用系统引入、发送短信
集信达短信服务一共有三个:后台管理服务,短信接收服务,短信发送服务;
| 应用 | 端口 | 说明 | 启动命令 |
|---|---|---|---|
| pd-sms-manage | 8770 | 后台管理服务 | java -jar pd-sms-manage.jar & |
| pd-sms-api | 8771 | 短信接收服务 | java -jar pd-sms-api.jar & |
| pd-sms-server | 8772 | 短信发送服务 | java -jar pd-sms-server.jar & |
业务架构如下:
难点 1:
Aop通过切面方式,自定义注解,实现实体基础数据的注入
难点 2:懒汉式+DCL+voliate
public class SingleCaseType {
private String name;
private Integer age;
//只要类加载就会创建对象并消耗内存
private volatile static SingleCaseType single;
private SingleCaseType(String name, Integer age) {
this.name = name;
this.age = age;
}
private SingleCaseType() {
}
//对外提供获取实例的方法--这里采用DCL确认
public static SingleCaseType getInstance() {
if(single==null) {
synchronized (SingleCaseType.class) {
if(single==null) {
single = new SingleCaseType();
return single;
}else {
return single;
}
}
}else {
return single;
}
}
}
难点 3:反射获取对象
首先讲下反射机制:
反射就是在程序运行状态中,对于任何一个类,都能通过特定的方式方法获取到这个类的属性和方法,并且可以对这些属性、方法进行调用。
说白了,反射就是在程序运行时获取和执行某个类属性或方法的功能。
其次讲一些常用的反射相关的API:
比如获取一个Class对象。Class.forName(完整类名)。通过Class对象获取类的构造方法
使用class对象创建一个对象,class.newInstance等。
最后可以说一下反射的优点和缺点:
优点就是增加灵活性,可以在运行时动态获取对象实例。缺点是反射的效率很低,而且会破坏封装,通过反射可以访问类的私有方法,不安全。
难点 4:编写的sdk如何集成到别人的项目里
由于springboot在启动的时候只会扫描启动类下对应的包,而我们的sdk的包路径不能和集成sdk的服务适配,需要利用springboot的自动装配
在resource目录下建立MATE-INF目录并编写spring.factory目录
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.itheima.sdk.service.impl.SmsSendServiceImpl----此处为sdk需要注入到ioc容器中去的类的全路径
难点 1:短信发送的升降级规则
1)校验了ak是否存在
2)判断接入平台是否需要权限校验,如果开起了权限校验则通过ak,sk,时间戳加密对比传入的校验值,如果校验值和加密的密文相同证明身份通过,否则失败
3)判断手机号是否为空,是否合法,是否是很名单手机号
4)判断模板是否为空,判断签名是否为空,判断签名模板是否有对应的通道
5)判断模板参数和模板内容是否匹配
难点 2:定时发送短信的业务逻辑
启动一个定时任务:
1)使用redis的分布式锁,为了防止短信重复发送
2)根据时间等值从time-push这张表中查询未处理(status=0)的数据
3)根据查询的结果,依次调用发短信的接口并更新短信发送状态为已处理((status=1)
难点3 :manager工程为什么最后要往redis里发送消息
由于server服务为了提升性能,在服务启动的时候会主动去将mysql中的数据缓存下来,而manager服务修改了数据库里的内容后,server服务缓存中的数据并没有改变
需要通过redis发送一个同步数据的消息到server服务,server服务重新读取数据库里的内容到缓存中,否则会出现缓存中的内容和数据库中的内容不一致的情况
DTO是数据传输对象: 主要用于封装前台页面传过来的数据,在各个层之间进行数据的传递,主要用于接受前台数据进行封装并向各个层之间传递数据(个人理解是向下层传递数据)
ENTITY是实体对象: 主要用于封装从数据库里取的数据,字段跟数据库中的表可一致,定义规范跟Bean一致,主要用于封装从数据库里获取的数据并向各个层之间传递(个人理解是向上层传递数据)
4 SDK概述什么是sdk
SDK 是 Software Development Kit 的缩写,即软件开发工具包。SDK被开发出来是为了减少程序员工作量的,比如公司开发出某种软件的某一功能,把它封装成SDK,提供给其他公司和个人使用。
本小节需要开发短信接收服务SDK,通过SDK可以使应用系统更加方便的调用短信接收服务。
通过SDK方式调用短信接收服务,本质上还是调用的短信接收服务提供的HTTP接口(Controller),只不过是调用的过程在SDK中进行了封装。
软件开发工具包广义上指辅助开发某一类软件的相关文档、范例和工具的集合。
sdk作用
SDK开发完成后,为了方便其他应用使用,通常会将SDK打成jar包上传到远程maven仓库,那么别人的系统需要在自己的Pom文件里导入
sdk软件开发包可以直接导入到自己的项目里面,里面的功能都是开发好的,配合自动装配,直接调用接口就行,可以简化
5 自动装配就是可以自动设置依赖关系,在导入别人的sdk工具包后不需要手动调整依赖关系,简化代码的复杂度,利于开发
6 HttpClient概述HttpClinent是什么
HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。
HTTPClient特性
- 基于标准、纯净的java语言。实现了Http1.0和Http1.1
- 以可扩展的面向对象的结构实现了Http全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。
- 支持HTTPS协议。
- 通过Http代理建立透明的连接。
在集信达平台中我们拆分出api服务server服务manager服务三个服务,因为需要采用分布式设计需要拆分成3个服务,采用单体架构需要拓展的服务会包含manager后台管理功能,而manager没有并发和大数据量不需要横向拓展需要单独抽离
api服务和server服务的业务复杂度不同,api服务仅仅对请求的数据做校验,server服务是真正发送http请求到短信服务商的,承载的数据压力不同,需要单独抽离成两个服务
1)在项目启动的时候,我们通过实现CommandLineRunner接口初始化每个通道对应的策略类,并且每个策略类都实现共同的抽象类
2)在执行具体发短信的时候,我们通过多态的思想,使用共同的抽象类接收,然后调用对应的方法。
理由:
1)策略模式符合开闭原则,对修改关闭,对扩展开放。
2)避免使用多重条件转移语句,如if…else…语句、switch 语句



