一、背景介绍
在之前的工作中,我只知道每个平台使用各自的代码。但在加入现公司后,我发现多个平台共享一套代码,包括数据库和服务器等资源。起初,我感到非常奇怪,因为不同平台的所有数据都集中在一起。交接工作的同事解释说,他们通过在表中使用一个字段来区分不同平台的数据。尽管每个平台的功能和用户都是不同的,我当时并没有完全理解。
在接手工作后,我主要处理的是某个平台独有的功能,因此没有深入了解平台之间的交互。最近,我接手了一个跨境项目,由于国际化的需求,同一平台需要支持多种语言,并且使用了所谓的SaaS架构。这让我意识到这一架构的重要性,因为这是我第一次接触这种形式,所以决定记录一下。
二、整合原理
整合的原理是通过不同平台的域名来区分。虽然使用的是同一套代码,但不同平台的域名是不同的。根据不同平台的域名,设置相应的SaaS,并将其保存到数据库中。在需要区分平台信息的表中,通过设置saasId
来进行区分。例如:会员表、商品表、公告内容表、订单表等。
三、代码实现
以下是代码实现。基本原理是通过请求的域名来区分平台。如果是第一次访问,会查询数据库并将结果缓存到Redis中,从而有效减少数据库压力:
/**
* <p>
* SAAS 服务实现类
* </p>
*
* @author developer
* @since 2021-12-27
*/
@Slf4j
@Service
public class SaasServiceImpl extends ServiceImpl<SaasMapper, Saas> implements ISaasService {
@Resource
private RedisCache redisCache;
private static final Long CUSTOM_SAAS_ID = null;
@Override
public Long getSaas(HttpServletRequest request) {
try {
StringBuilder url = new StringBuilder(request.getHeader("Referer"));
if (StringUtils.isEmpty(url)) {
return CUSTOM_SAAS_ID;
}
String domain;
if (url.toString().startsWith("https")) {
domain = url.delete(0, 8).delete(url.indexOf("/"), url.length()).toString();
} else {
domain = url.delete(0, 7).delete(url.indexOf("/"), url.length()).toString();
}
log.info("SAAS域名:=====================================================================:{}", domain);
if (StringUtils.isNotEmpty(domain)) {
Long saasId = redisCache.getCacheObject(domain);
if (saasId != null && saasId != 0L) {
return saasId;
} else {
Saas saas = lambdaQuery().eq(Saas::getDomain, domain).eq(Saas::getDeleteFlag, Constants.NO).one();
if (ObjectUtil.isNotNull(saas)) {
redisCache.setCacheObject(domain, saas.getId());
return saas.getId();
}
}
}
return CUSTOM_SAAS_ID;
} catch (Exception e) {
log.error("获取SAAS域名错误:=====================================================================:{}", e.getMessage());
return CUSTOM_SAAS_ID;
}
}
}
该方法返回一个Long
类型的saasId
,在需要区分平台的功能中可以直接获取。
虽然这是一个伪SaaS架构,但它依然有效地连接了多个平台,已经非常不错了。