diff --git a/APIJSON-Java-Server/APIJSONBoot-MultiDataSource/pom.xml b/APIJSON-Java-Server/APIJSONBoot-MultiDataSource/pom.xml index 44f75363..1cf9d41b 100755 --- a/APIJSON-Java-Server/APIJSONBoot-MultiDataSource/pom.xml +++ b/APIJSON-Java-Server/APIJSONBoot-MultiDataSource/pom.xml @@ -15,6 +15,7 @@ UTF-8 UTF-8 1.8 + 2.5.13 @@ -142,6 +143,24 @@ 1.2.9 + + redis.clients + jedis + 3.9.0 + + + + org.springframework.data + spring-data-redis + 2.4.0 + + + redis.clients + jedis + + + + diff --git a/APIJSON-Java-Server/APIJSONBoot-MultiDataSource/src/main/java/apijson/demo/DemoSQLExecutor.java b/APIJSON-Java-Server/APIJSONBoot-MultiDataSource/src/main/java/apijson/demo/DemoSQLExecutor.java index 9ada8f81..baab9cea 100644 --- a/APIJSON-Java-Server/APIJSONBoot-MultiDataSource/src/main/java/apijson/demo/DemoSQLExecutor.java +++ b/APIJSON-Java-Server/APIJSONBoot-MultiDataSource/src/main/java/apijson/demo/DemoSQLExecutor.java @@ -14,14 +14,20 @@ package apijson.demo; +import apijson.JSON; +import apijson.RequestMethod; import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer; import com.vesoft.nebula.jdbc.impl.NebulaDriver; import com.zaxxer.hikari.HikariDataSource; +import java.io.Serializable; import java.sql.Connection; -import java.sql.DriverManager; +import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.concurrent.TimeUnit; import javax.sql.DataSource; @@ -29,6 +35,14 @@ import apijson.boot.DemoApplication; import apijson.framework.APIJSONSQLExecutor; import apijson.orm.SQLConfig; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericToStringSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import static apijson.framework.APIJSONConstant.PRIVACY_; +import static apijson.framework.APIJSONConstant.USER_; /**SQL 执行器,支持连接池及多数据源 @@ -38,19 +52,71 @@ public class DemoSQLExecutor extends APIJSONSQLExecutor { public static final String TAG = "DemoSQLExecutor"; + // Redis 缓存 <<<<<<<<<<<<<<<<<<<<<<< + public static final RedisTemplate REDIS_TEMPLATE; + static { + REDIS_TEMPLATE = new RedisTemplate<>(); + REDIS_TEMPLATE.setConnectionFactory(new JedisConnectionFactory(new RedisStandaloneConfiguration("127.0.0.1", 6379))); + REDIS_TEMPLATE.setKeySerializer(new StringRedisSerializer()); + REDIS_TEMPLATE.setHashValueSerializer(new GenericToStringSerializer<>(Serializable.class)); + REDIS_TEMPLATE.setValueSerializer(new GenericToStringSerializer<>(Serializable.class)); +// REDIS_TEMPLATE.setValueSerializer(new FastJsonRedisSerializer>(List.class)); + REDIS_TEMPLATE.afterPropertiesSet(); + } + // 可重写以下方法,支持 Redis 等单机全局缓存或分布式缓存 - // @Override - // public List getCache(String sql, int type) { - // return super.getCache(sql, type); - // } - // @Override - // public synchronized void putCache(String sql, List list, int type) { - // super.putCache(sql, list, type); - // } - // @Override - // public synchronized void removeCache(String sql, int type) { - // super.removeCache(sql, type); - // } + @Override + public List getCache(String sql, SQLConfig config) { + List list = super.getCache(sql, config); + if (list == null) { + list = JSON.parseArray(REDIS_TEMPLATE.opsForValue().get(sql), JSONObject.class); + } + return list; + } + @Override + public synchronized void putCache(String sql, List list, SQLConfig config) { + super.putCache(sql, list, config); + if (config != null && config.isMain()) { + if (config.isExplain() || RequestMethod.isHeadMethod(config.getMethod(), true)) { + REDIS_TEMPLATE.opsForValue().set(sql, JSON.toJSONString(list), 10*60, TimeUnit.SECONDS); + } else { + String table = config.getTable(); + REDIS_TEMPLATE.opsForValue().set(sql, JSON.toJSONString(list), USER_.equals(table) || PRIVACY_.equals(table) ? 10*60 : 60, TimeUnit.SECONDS); + } + } + } + @Override + public synchronized void removeCache(String sql, SQLConfig config) { + super.removeCache(sql, config); + if (config.getMethod() == RequestMethod.DELETE) { // 避免缓存击穿 + REDIS_TEMPLATE.expire(sql, 60, TimeUnit.SECONDS); + } else { + REDIS_TEMPLATE.delete(sql); + } + } + + @Override + public JSONObject execute(SQLConfig config, boolean unknownType) throws Exception { + JSONObject result = super.execute(config, unknownType); + RequestMethod method = config.getMethod(); + if (method == RequestMethod.POST) { // 没必要,直接查就行了 +// Object id = result.get(config.getIdKey()); +// Object idIn = result.get(config.getIdKey() + "[]"); +// SQLConfig cacheConfig = APIJSONRouterApplication.DEFAULT_APIJSON_CREATOR.createSQLConfig(); +// cacheConfig.setMethod(RequestMethod.GET); +// + } + else if (method == RequestMethod.PUT || method == RequestMethod.DELETE) { // RequestMethod.isQueryMethod(method) == false) { + config.setMethod(RequestMethod.GET); + boolean isPrepared = config.isPrepared(); + removeCache(config.getSQL(false), config); + config.setPrepared(isPrepared); + config.setMethod(method); + } + return result; + } + + // Redis 缓存 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // 适配连接池,如果这里能拿到连接池的有效 Connection,则 SQLConfig 不需要配置 dbVersion, dbUri, dbAccount, dbPassword @Override diff --git a/APIJSON-Java-Server/APIJSONBoot-MultiDataSource/src/main/resources/static/js/main.js b/APIJSON-Java-Server/APIJSONBoot-MultiDataSource/src/main/resources/static/js/main.js index c5889ebf..ddbb9ce7 100755 --- a/APIJSON-Java-Server/APIJSONBoot-MultiDataSource/src/main/resources/static/js/main.js +++ b/APIJSON-Java-Server/APIJSONBoot-MultiDataSource/src/main/resources/static/js/main.js @@ -3592,6 +3592,7 @@ '[]': { 'count': this.testCaseCount || 100, //200 条测试直接卡死 0, 'page': this.testCasePage || 0, + 'join': '@/TestRecord,@/Script:pre,@/Script:post', 'Document': { '@order': 'version-,date-', 'userId': this.User.id,