|
@@ -1,22 +1,11 @@
|
|
|
package com.rongwei.bscommon.system.config;
|
|
|
|
|
|
import com.alibaba.druid.pool.DruidDataSource;
|
|
|
-import com.rongwei.commonservice.service.RedisService;
|
|
|
-import com.rongwei.rwadmincommon.system.vo.SysUserVo;
|
|
|
import com.rongwei.rwcommon.utils.SqlAdaptationUtil;
|
|
|
-import com.rongwei.rwcommon.utils.StringUtils;
|
|
|
-import org.apache.ibatis.binding.MapperMethod;
|
|
|
import org.apache.ibatis.executor.statement.StatementHandler;
|
|
|
import org.apache.ibatis.mapping.BoundSql;
|
|
|
import org.apache.ibatis.plugin.*;
|
|
|
-import org.slf4j.Logger;
|
|
|
-import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.beans.factory.annotation.Value;
|
|
|
-import org.springframework.web.context.request.RequestContextHolder;
|
|
|
-import org.springframework.web.context.request.ServletRequestAttributes;
|
|
|
-
|
|
|
-import javax.servlet.http.HttpServletRequest;
|
|
|
import java.lang.reflect.Field;
|
|
|
import java.sql.Connection;
|
|
|
import java.util.Properties;
|
|
@@ -27,89 +16,26 @@ import java.util.Properties;
|
|
|
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
|
|
|
public class QuerySqlAdaptationInterceptor implements Interceptor {
|
|
|
|
|
|
- private static final Logger logger = LoggerFactory.getLogger(QuerySqlAdaptationInterceptor.class);
|
|
|
-
|
|
|
- @Value("${saas.tenantmode:NONE}")
|
|
|
- private String saasmode;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private RedisService redisService;
|
|
|
-
|
|
|
@Autowired
|
|
|
private DruidDataSource datasource;
|
|
|
|
|
|
@Override
|
|
|
public Object intercept(Invocation invocation) throws Throwable {
|
|
|
-// DruidDataSource datasource = (DruidDataSource)DynamicDataSource.dataSourcesMap.get(DynamicDataSource.getDataSource());
|
|
|
// 获取数据库类型
|
|
|
String dbType = datasource.getDbType();
|
|
|
// 方法一
|
|
|
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
|
|
|
- //映射工具
|
|
|
-// MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
|
|
|
-// MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
|
|
|
- //先拦截到RoutingStatementHandler,里面有个StatementHandler类型的delegate变量,其实现类是BaseStatementHandler,然后就到BaseStatementHandler的成员变量mappedStatement
|
|
|
-// MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
|
|
|
- //id为执行的mapper方法的全路径名,如com.uv.dao.UserMapper.insertUser
|
|
|
BoundSql boundSql = statementHandler.getBoundSql();
|
|
|
-
|
|
|
//获取到原始sql语句
|
|
|
String sql = boundSql.getSql();
|
|
|
// dao参数
|
|
|
Object parObj = statementHandler.getParameterHandler().getParameterObject();
|
|
|
SqlAdaptationUtil sqlAdaptation = new SqlAdaptationUtil();
|
|
|
- String mSql = sqlAdaptation.modifySql(sqlAdaptation.commonRuleAnalysis(sql),dbType,parObj);
|
|
|
+ String mSql = sqlAdaptation.modifySql(sqlAdaptation.commonRuleAnalysis(sql), dbType, parObj);
|
|
|
//通过反射修改sql语句
|
|
|
Field field = boundSql.getClass().getDeclaredField("sql");
|
|
|
field.setAccessible(true);
|
|
|
-
|
|
|
- // SaaS环境下schema切换
|
|
|
- if("DATASOURCE".equals(saasmode)){
|
|
|
- System.out.println("saas切换");
|
|
|
- logger.info("saas切换");
|
|
|
- String schema = null;
|
|
|
- try{
|
|
|
- schema = this.getSchema();
|
|
|
- }catch (Exception e){
|
|
|
- e.printStackTrace();
|
|
|
- }
|
|
|
- // 判断是否有参数(appointSchema)指定schema
|
|
|
- if(parObj instanceof MapperMethod.ParamMap){
|
|
|
- MapperMethod.ParamMap paramMap = (MapperMethod.ParamMap)parObj;
|
|
|
- if(paramMap.containsKey("appointSchema") && paramMap.get("appointSchema") != null){
|
|
|
- String appointSchema = paramMap.get("appointSchema").toString();
|
|
|
- schema = appointSchema;
|
|
|
- }
|
|
|
- }
|
|
|
- System.out.println("schema:"+schema);
|
|
|
- logger.info("schema:"+schema);
|
|
|
- if(StringUtils.isNotBlank(schema)){
|
|
|
- // 多租户schema切换方案一:通过 USE databaseName; 实现切换
|
|
|
- mSql = "USE " + schema + ";" + mSql;
|
|
|
- System.out.println("mSql:"+mSql);
|
|
|
- logger.info("mSql:"+mSql);
|
|
|
- // 多租户schema切换方案二:直接获取Connection设置schema
|
|
|
- /*Object[] objs = invocation.getArgs();
|
|
|
- Connection conn = (Connection)objs[0];
|
|
|
- conn.setSchema(schema);*/
|
|
|
- }else{
|
|
|
-// throw new Exception("SaaS模式下查不到相应schema");
|
|
|
- System.out.println("SaaS模式下查不到相应schema");
|
|
|
- logger.warn("SaaS模式下查不到相应schema");
|
|
|
- }
|
|
|
- /*Connection o = (Connection)invocation.getArgs()[0];
|
|
|
- System.out.println("o.getSchema():"+o.getSchema());
|
|
|
- o.setSchema(schema);
|
|
|
- System.out.println("o.getSchema():"+o.getSchema());*/
|
|
|
- }
|
|
|
-
|
|
|
field.set(boundSql, mSql);
|
|
|
- //sql语句类型 select、delete、insert、update
|
|
|
- /*if(SqlCommandType.SELECT == mappedStatement.getSqlCommandType()){
|
|
|
- System.out.println("sql:"+sql);
|
|
|
- }*/
|
|
|
-
|
|
|
- // 返回
|
|
|
return invocation.proceed();
|
|
|
}
|
|
|
|
|
@@ -122,79 +48,4 @@ public class QuerySqlAdaptationInterceptor implements Interceptor {
|
|
|
public void setProperties(Properties properties) {
|
|
|
|
|
|
}
|
|
|
-
|
|
|
- /**
|
|
|
- * SaaS模式下获取当前租户的数据库名
|
|
|
- * @return
|
|
|
- * @throws Exception
|
|
|
- */
|
|
|
- private String getSchema() throws Exception{
|
|
|
- Long startTime = System.currentTimeMillis();
|
|
|
- String schema = null;
|
|
|
- ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
|
|
- if(attributes == null){
|
|
|
- logger.error("ServletRequestAttributes为null");
|
|
|
- throw new Exception("ServletRequestAttributes为null");
|
|
|
- }
|
|
|
- HttpServletRequest request = attributes.getRequest();
|
|
|
- if(request == null){
|
|
|
- logger.error("HttpServletRequest为null");
|
|
|
- throw new Exception("HttpServletRequest为null");
|
|
|
- }
|
|
|
-
|
|
|
- schema = request.getHeader("schema");
|
|
|
- if(StringUtils.isNotBlank(schema)) {
|
|
|
- return schema;
|
|
|
- }
|
|
|
-
|
|
|
- String token = request.getHeader("token");
|
|
|
- System.out.println("token:"+token);
|
|
|
- logger.info("token:"+token);
|
|
|
-// if(StringUtils.isBlank(token)){
|
|
|
-// String incontrolToken = request.getHeader("incontrol-token");
|
|
|
-// Object tokenDskey = request.getAttribute(Constants.SAAS_LOGIN_TOKEN);
|
|
|
-// // 登录功能特殊处理获取DsKey
|
|
|
-// if(tokenDskey != null){
|
|
|
-// logger.info("tokenDskey:"+tokenDskey);
|
|
|
-// schema = (String) tokenDskey;
|
|
|
-// }
|
|
|
-// // 某些特殊功能incontrolToken也可以作为token
|
|
|
-// else if(StringUtils.isNotBlank(incontrolToken)){
|
|
|
-// logger.info("incontrolToken:"+incontrolToken);
|
|
|
-// schema = getSchemaByToken(incontrolToken);
|
|
|
-// }
|
|
|
-// // 某些特殊功能token放入线程全局变量中
|
|
|
-// else if(StringUtils.isNotBlank(ThreadLocalResource.token.get())){
|
|
|
-// logger.info("ThreadToken:"+ThreadLocalResource.token.get());
|
|
|
-// token = ThreadLocalResource.token.get();
|
|
|
-// schema = getSchemaByToken(token);
|
|
|
-// }
|
|
|
-// } else{
|
|
|
-// schema = getSchemaByToken(token);
|
|
|
-// System.out.println("Dskey:"+schema);
|
|
|
-// }
|
|
|
- schema = getSchemaByToken(token);
|
|
|
- System.out.println("Dskey:"+schema);
|
|
|
- Long endTime = System.currentTimeMillis();
|
|
|
- System.out.println("查找schema时间为:"+(endTime-startTime));
|
|
|
- return schema;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 根据token获取多租户模式的schema
|
|
|
- * @param token
|
|
|
- * @return
|
|
|
- */
|
|
|
- private String getSchemaByToken(String token){
|
|
|
- SysUserVo currUser = null;
|
|
|
- if(StringUtils.isNotEmpty(token)){
|
|
|
- currUser = redisService.getLoginUser(token);
|
|
|
- }
|
|
|
- String schema = null;
|
|
|
- if(currUser != null){
|
|
|
- schema = currUser.getTenantDo().getDskey();
|
|
|
- }
|
|
|
- return schema;
|
|
|
- }
|
|
|
-
|
|
|
}
|