第三方接口或者服务大部分都是以rest风格的,需要http请求去调用,通过网络发送请求去调用,然后等待第三方服务的响应,并发量多的话,会严重拖慢业务逻辑的处理速度。为了提高系统的性能,调用第三方服务,最好做成异步的,如果条件允许,最好用单独的服务器,或者几台服务器来做调用第三方接口,来提高业务逻辑的处理速度。当然,测试环境也可以用一台机器来做伪分布式。
实现方式:将业务逻辑与调用第三方服务的代码分离,来达到解耦,以及异步调用,具体实现(以调用阿里云短信服务为例):
1、编写配置类
public class ApiConfig implements Serializable {
private static final long serialVersionUID = -3043278191484112872L;
/**
* 产品名称
*/
protected String product;
/**
* 接口域名或者IP地址
*/
protected String domain;
/**
* appCode;
*/
protected String accessKeyId; /**
* appSecret
*/
protected String accessKeySecret; /**
* 链接超时时间
*/
private String defaultConnectTimeout;
/**
* 读取返回参数的超时时间
*/
private String defaultReadTimeout;
/**
* 短信模板代码
*/
private String templateCode;
/**
* 签名
*/
private String signName;
/**
* 请求参数
*/
private String templateParam;省略get,set方法
}
2、将调用阿里云服务的demo封装成接口:
public interface ShortMessageSendService<T extends ApiConfig> {
/**
* 发送短信
* @param config 配置类(appkey等配置信息)
* @param phoneNumbers 要发送的手机号
* @param templateParam 短信的模板以及短信的内容
* @throws ClientException
*/
public void sendMsessages (T config, String phoneNumber, String templateParam,Emp user) throws ClientException;
/**
* 获取信息发送结果
* @param config 配置类(appkey等配置信息)
* @param ShortMessage 发送的短信的内容,以及是否发送成功
* @throws ClientException
* @throws ParseException
*/
public void getMessageInfo (T config, ShortMessage message) throws ClientException, ParseException;
}
2、根据业务逻辑,把不同类型的短信进行分类,并编写配置文件,方便spring自动注入。
mes.product = Dysmsapi
mes.domain = dysmsapi.aliyuncs.com
mes.accessKeyId =
mes.accessKeySecret =
mes.queueName =
mes.defaultConnectTimeout = 10000
mes.defaultReadTimeout = 10000
spring 配置父类:
<bean id="messageConfig" class="com.zedev.config.ApiConfig">
<property name="product" value="${mes.product}"></property>
<property name="domain" value="${mes.domain}"></property>
<property name="accessKeyId" value="${mes.accessKeyId}"></property>
<property name="accessKeySecret"
value="${mes.accessKeySecret}"></property>
<property name="defaultConnectTimeout"
value="${mes.defaultConnectTimeout}"></property>
<property name="defaultReadTimeout"
value="${mes.defaultReadTimeout}"></property>
<property name="queueName" value="${mes.queueName}"></property>
</bean>
spring 配置子类1:短信模板和签名不一样
<bean id="XXConfig"
class="com.zedev.config.XXConfig" parent="messageConfig">
<property name="templateCode" value="${vio.mes.templateCode}"></property>
<property name="signName" value="${vio.mes.signName}"></property> </bean>
spring 配置子类2:短信模板和签名不一样
<bean id="XXXConfig"
class="com.zedev.config.XXXConfig" parent="messageConfig">
<property name="templateCode"
value="${code.mes.templateCode}"></property>
<property name="signName" value="${code.mes.signName}"></property>
</bean>
3、结合消息队列,将调用短信接口和业务逻辑进行解耦。
将短信息发送给消息队列:(消息队列的配置jmsQueueTemplate已省略)
@Component
public class MessageSender {
@Autowired
@Qualifier("jmsQueueTemplate")
private JmsTemplate jmsTemplate;
/**
* @Description: 将消息发送给消息队列
* @param destination 消息队列名称
* @param message 消息体
*/
public void send(String destination, final String message) {
jmsTemplate.send(destination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
return jmsTemplate.getMessageConverter().toMessage(message, session);
}
});
}
}
消息队列监听器:
@Component
@EnableJms
public class MesSenderQueueListener {
protected Logger log = LoggerFactory.getLogger(ViolationQueryQueueListener.class);
// 当收到消息后,自动调用该方法,spring配置默认监听器,负责接收消息 concurrency = "3-8"最少三个线程,最多8个线程监听,启用多线程,提高系统效率
@JmsListener(containerFactory = "jmsListenerContainerFactory", destination = "消息队列名", concurrency = "3-8")
public void onMessage(Message message) throws JMSException {
ActiveMQTextMessage msg = (ActiveMQTextMessage) message;
final String ms = msg.getText();
try { if (StringUtils.isBlank(ms)) {
return;
}
Emp user = null;
user = userService.getSystemUser();
/**
* 业务逻辑处理,调用2发送请求,并获取信息发送的结果,并存入数据库
*/
XXConfig= null;
param = JSONObject.parseObject(ms, XXConfig.class);// 转换成相应的对象
if (null == param) {
return;
} //这里调用调用短信发送的接口,生成记录短信的对象ShortMessage ,并存入数据库中。
} catch (Exception e) {
log.info(ms);
e.printStackTrace();
}
}
}
阿里云短信回执消息队列监听器
@Component
public class ShortMessageQueueListener {
@Autowired
private VioMessageConfig cioConfig;
@Autowired
private ShortMessageService mesService;
private Logger log = LoggerFactory.getLogger(ShortMessageQueueListener.class); @PostConstruct
public void listenMessage() throws ClientException, ParseException {
DefaultAlicomMessagePuller puller = new DefaultAlicomMessagePuller();
puller.startReceiveMsg(cioConfig.getAccessKeyId(), cioConfig.getAccessKeySecret(), "SmsReport",
cioConfig.getQueueName(), new MyMessageListener());
}
class MyMessageListener implements MessageListener {
@Override
public boolean dealMessage(Message message) {
JSONObject result = null;
result = JSONObject.parseObject(message.getMessageBodyAsString());
if (null == result) {
return true;
}
//业务逻辑,更新MesSenderQueueListener生成的发送结果,并处理相关的业务逻辑
}
}}
以上可以整合到一个系统,也可以整合成分布式架构,不需要spring cloud或者dubbo等分布式的开源框架。