方案说明:
项目启动时,将不同的数据源配置和产品相关基本配置注入,不同渠道的请求都携带产品识别字段
(包名,统一的路径格式,或者其他识别方案),每次请求将产品绑定放到线程上下文中实现数据隔离,数据隔离这里主要指持久化数据(mysql)和缓存(redis,内存缓存)的隔离
1.数据库隔离根据上下文链接不同的数据库,
2.redis根据上下文读取对应格式的key
3.主要拦截器部分代码(将隔离识别码放到线程上下文中)
内部请求或者可以自己可开发的请求,可将识别码放到 header中
public class ... implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest req, HttpServletResponse rep, Object arg2) throws Exception {
...
String pkg = req.getHeader("...");
...
return true;
}
}
只能提供url的开发接口,可以根据url参数判断
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse rep, Object arg2) throws Exception {
Map pathVariables = (Map) req.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
if (pathVariables != null && pathVariables.get("...") != null) {
setConfigAndDb.openReqAppSet(req.getRequestURI(), (String) pathVariables.get("..."));
return true;
}
return true;
}
4.redis的隔离
普通 redisTemplate
@Bean(name = "redisTemplate")
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
return new RedisCacheManager(
new ZsRedisWriter(redisConnectionFactory),
this.getRedisCacheConfigurationWithTtl(Duration.ofDays(1)), // 默认策略,未配置的 key 会使用这个
this.getRedisCacheConfigurationMap() // 指定 key 策略
);
}
ZsRedisWriter 为自定义 继承DefaultRedisCacheWriter ,
DefaultRedisCacheWriter 方法不是public 的 这里我们复制出来 开放接口就可以了,DefaultRedisCacheWriter implements RedisCacheWriter
package com.ydtc.redis;
import com.ydtc.context.bean.BaseConfig;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.lang.Nullable;
import java.time.Duration;
public class ZsRedisWriter extends DefaultRedisCacheWriter {
public ZsRedisWriter(RedisConnectionFactory connectionFactory) {
super(connectionFactory);
}
public ZsRedisWriter(RedisConnectionFactory connectionFactory, Duration sleepTime) {
super(connectionFactory, sleepTime);
}
private String dealPkg(String name) {
return BaseConfig.getDbKey() + ":"+name;
}
private byte[] dealKey(byte[] key) {
String keyStr = new String(key);
return (BaseConfig.getDbKey()+ ":"+keyStr).getBytes();
}
@Override
public void put(String name, byte[] key, byte[] value, @Nullable Duration ttl) {
name = dealPkg(name);
key = dealKey(key);
super.put(name, key, value, ttl);
}
@Override
public byte[] get(String name, byte[] key) {
name = dealPkg(name);
key = dealKey(key);
return super.get(name, key);
}
@Override
public byte[] putIfAbsent(String name, byte[] key, byte[] value, @Nullable Duration ttl) {
name = dealPkg(name);
key = dealKey(key);
return super.putIfAbsent(name, key, value, ttl);
}
@Override
public void remove(String name, byte[] key) {
name = dealPkg(name);
key = dealKey(key);
super.remove(name, key);
}
@Override
public void clean(String name, byte[] pattern) {
name = dealPkg(name);
pattern = dealKey(pattern);
super.clean(name, pattern);
}
}