java110 лет назад: 5
Родитель
Сommit
7b40273080

+ 24 - 16
java110-core/src/main/java/com/java110/core/base/controller/BaseController.java

@@ -2,17 +2,18 @@ package com.java110.core.base.controller;
 
 
 import com.alibaba.fastjson.JSONObject;
+import com.java110.core.base.AppBase;
+import com.java110.core.cache.Java110RedisConfig;
+import com.java110.core.context.BusinessServiceDataFlow;
 import com.java110.core.context.IPageData;
+import com.java110.core.context.PageData;
+import com.java110.core.factory.DataFlowFactory;
 import com.java110.utils.constant.CommonConstant;
 import com.java110.utils.constant.ResponseConstant;
 import com.java110.utils.constant.ServiceConstant;
 import com.java110.utils.exception.NoAuthorityException;
-
 import com.java110.utils.util.StringUtil;
-import com.java110.core.base.AppBase;
-import com.java110.core.context.BusinessServiceDataFlow;
-import com.java110.core.factory.DataFlowFactory;
-import com.java110.core.context.PageData;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
@@ -128,23 +129,23 @@ public class BaseController extends AppBase {
         headers.put("port", request.getLocalPort() + "");
 
         //处理app-id
-        if(headers.containsKey("app-id")){
-            headers.put("app_id",headers.get("app-id"));
+        if (headers.containsKey("app-id")) {
+            headers.put("app_id", headers.get("app-id"));
         }
 
         //处理transaction-id
-        if(headers.containsKey("transaction-id")){
-            headers.put("transaction_id",headers.get("transaction-id"));
+        if (headers.containsKey("transaction-id")) {
+            headers.put("transaction_id", headers.get("transaction-id"));
         }
 
         //处理req-time
-        if(headers.containsKey("req-time")){
-            headers.put("req_time",headers.get("req-time"));
+        if (headers.containsKey("req-time")) {
+            headers.put("req_time", headers.get("req-time"));
         }
 
         //处理req-time
-        if(headers.containsKey("user-id")){
-            headers.put("user_id",headers.get("user-id"));
+        if (headers.containsKey("user-id")) {
+            headers.put("user_id", headers.get("user-id"));
         }
 
     }
@@ -283,13 +284,20 @@ public class BaseController extends AppBase {
         JSONObject paramIn = new JSONObject();
         paramIn.put("resource", resource);
         paramIn.put("userId", pd.getUserId());
-        responseEntity = this.callCenterService(restTemplate, pd, paramIn.toJSONString(),
-                ServiceConstant.SERVICE_API_URL + "/api/basePrivilege.CheckUserHasResourceListener",
-                HttpMethod.POST);
 
+        responseEntity = checkUserHasResourceListener(restTemplate, pd, paramIn, resource + pd.getUserId());
         if (responseEntity.getStatusCode() != HttpStatus.OK) {
             throw new UnsupportedOperationException("用户没有权限操作");
         }
     }
 
+    @Cacheable(value = "checkUserHasResourceListener" + Java110RedisConfig.DEFAULT_EXPIRE_TIME_KEY, key = "#cacheKey")
+    private ResponseEntity<String> checkUserHasResourceListener(RestTemplate restTemplate, IPageData pd, JSONObject paramIn, String cacheKey) {
+        ResponseEntity<String> responseEntity = null;
+        responseEntity = this.callCenterService(restTemplate, pd, paramIn.toJSONString(),
+                ServiceConstant.SERVICE_API_URL + "/api/basePrivilege.CheckUserHasResourceListener",
+                HttpMethod.POST);
+        return responseEntity;
+    }
+
 }

+ 268 - 0
java110-core/src/main/java/com/java110/core/cache/Java110RedisCacheWriter.java

@@ -0,0 +1,268 @@
+package com.java110.core.cache;
+
+import com.java110.utils.util.Assert;
+import org.springframework.dao.PessimisticLockingFailureException;
+import org.springframework.data.redis.cache.RedisCacheWriter;
+import org.springframework.data.redis.connection.RedisConnection;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.connection.RedisStringCommands;
+import org.springframework.data.redis.core.types.Expiration;
+import org.springframework.lang.Nullable;
+
+import java.nio.charset.StandardCharsets;
+import java.time.Duration;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+/**
+ * 自定义redis 缓存器
+ */
+public class Java110RedisCacheWriter implements RedisCacheWriter {
+
+
+    private final RedisConnectionFactory connectionFactory;
+
+    private final Duration sleepTime;
+
+    /**
+     * @param connectionFactory must not be {@literal null}.
+     */
+    Java110RedisCacheWriter(RedisConnectionFactory connectionFactory) {
+        this(connectionFactory, Duration.ZERO);
+    }
+
+    /**
+     * @param connectionFactory must not be {@literal null}.
+     * @param sleepTime         sleep time between lock request attempts. Must not be {@literal null}. Use {@link Duration#ZERO}
+     *                          to disable locking.
+     */
+    Java110RedisCacheWriter(RedisConnectionFactory connectionFactory, Duration sleepTime) {
+
+        Assert.notNull(connectionFactory, "ConnectionFactory must not be null!");
+        Assert.notNull(sleepTime, "SleepTime must not be null!");
+
+        this.connectionFactory = connectionFactory;
+        this.sleepTime = sleepTime;
+    }
+
+    @Override
+    public void put(String name, byte[] key, byte[] value, @Nullable Duration ttl) {
+
+        Assert.notNull(name, "Name must not be null!");
+        Assert.notNull(key, "Key must not be null!");
+        Assert.notNull(value, "Value must not be null!");
+
+        execute(name, connection -> {
+
+            //当设置了过期时间,则修改取出
+            //@Cacheable(value="user-key#key_expire=1200",key = "#id",condition = "#id != 2")
+            //name 对应 value
+            //key 对应 value :: key
+
+            //判断name里面是否设置了过期时间,如果设置了则对key进行缓存,并设置过期时间
+            int index = name.lastIndexOf(Java110RedisConfig.REDIS_EXPIRE_TIME_KEY);
+            if (index > 0) {
+                //取出对应的时间 1200 index + 1是还有一个=号
+                String expireString = name.substring(index + 1 + Java110RedisConfig.REDIS_EXPIRE_TIME_KEY.length());
+                long expireTime = Long.parseLong(expireString);
+                connection.set(key, value, Expiration.from(expireTime, TimeUnit.SECONDS), RedisStringCommands.SetOption.upsert());
+            } else if (shouldExpireWithin(ttl)) {
+                connection.set(key, value, Expiration.from(ttl.toMillis(), TimeUnit.MILLISECONDS), RedisStringCommands.SetOption.upsert());
+            } else {
+                connection.set(key, value);
+            }
+            return "OK";
+        });
+    }
+    /*
+     * (non-Javadoc)
+     * @see org.springframework.data.redis.cache.RedisCacheWriter#get(java.lang.String, byte[])
+     */
+    @Override
+    public byte[] get(String name, byte[] key) {
+
+        org.springframework.util.Assert.notNull(name, "Name must not be null!");
+        org.springframework.util.Assert.notNull(key, "Key must not be null!");
+
+        return execute(name, connection -> connection.get(key));
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.springframework.data.redis.cache.RedisCacheWriter#putIfAbsent(java.lang.String, byte[], byte[], java.time.Duration)
+     */
+    @Override
+    public byte[] putIfAbsent(String name, byte[] key, byte[] value, @Nullable Duration ttl) {
+
+        org.springframework.util.Assert.notNull(name, "Name must not be null!");
+        org.springframework.util.Assert.notNull(key, "Key must not be null!");
+        org.springframework.util.Assert.notNull(value, "Value must not be null!");
+
+        return execute(name, connection -> {
+
+            if (isLockingCacheWriter()) {
+                doLock(name, connection);
+            }
+
+            try {
+                if (connection.setNX(key, value)) {
+
+                    if (shouldExpireWithin(ttl)) {
+                        connection.pExpire(key, ttl.toMillis());
+                    }
+                    return null;
+                }
+
+                return connection.get(key);
+            } finally {
+
+                if (isLockingCacheWriter()) {
+                    doUnlock(name, connection);
+                }
+            }
+        });
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.springframework.data.redis.cache.RedisCacheWriter#remove(java.lang.String, byte[])
+     */
+    @Override
+    public void remove(String name, byte[] key) {
+
+        org.springframework.util.Assert.notNull(name, "Name must not be null!");
+        org.springframework.util.Assert.notNull(key, "Key must not be null!");
+
+        execute(name, connection -> connection.del(key));
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.springframework.data.redis.cache.RedisCacheWriter#clean(java.lang.String, byte[])
+     */
+    @Override
+    public void clean(String name, byte[] pattern) {
+
+        Assert.notNull(name, "Name must not be null!");
+        Assert.notNull(pattern, "Pattern must not be null!");
+
+        execute(name, connection -> {
+
+            boolean wasLocked = false;
+
+            try {
+
+                if (isLockingCacheWriter()) {
+                    doLock(name, connection);
+                    wasLocked = true;
+                }
+
+                byte[][] keys = Optional.ofNullable(connection.keys(pattern)).orElse(Collections.emptySet())
+                        .toArray(new byte[0][]);
+
+                if (keys.length > 0) {
+                    connection.del(keys);
+                }
+            } finally {
+
+                if (wasLocked && isLockingCacheWriter()) {
+                    doUnlock(name, connection);
+                }
+            }
+
+            return "OK";
+        });
+    }
+
+    /**
+     * Explicitly set a write lock on a cache.
+     *
+     * @param name the name of the cache to lock.
+     */
+    void lock(String name) {
+        execute(name, connection -> doLock(name, connection));
+    }
+
+    /**
+     * Explicitly remove a write lock from a cache.
+     *
+     * @param name the name of the cache to unlock.
+     */
+    void unlock(String name) {
+        executeLockFree(connection -> doUnlock(name, connection));
+    }
+
+    private Boolean doLock(String name, RedisConnection connection) {
+        return connection.setNX(createCacheLockKey(name), new byte[0]);
+    }
+
+    private Long doUnlock(String name, RedisConnection connection) {
+        return connection.del(createCacheLockKey(name));
+    }
+
+    boolean doCheckLock(String name, RedisConnection connection) {
+        return connection.exists(createCacheLockKey(name));
+    }
+
+    /**
+     * @return {@literal true} if {@link RedisCacheWriter} uses locks.
+     */
+    private boolean isLockingCacheWriter() {
+        return !sleepTime.isZero() && !sleepTime.isNegative();
+    }
+
+    private <T> T execute(String name, Function<RedisConnection, T> callback) {
+
+        RedisConnection connection = connectionFactory.getConnection();
+        try {
+
+            checkAndPotentiallyWaitUntilUnlocked(name, connection);
+            return callback.apply(connection);
+        } finally {
+            connection.close();
+        }
+    }
+
+    private void executeLockFree(Consumer<RedisConnection> callback) {
+
+        RedisConnection connection = connectionFactory.getConnection();
+
+        try {
+            callback.accept(connection);
+        } finally {
+            connection.close();
+        }
+    }
+
+    private void checkAndPotentiallyWaitUntilUnlocked(String name, RedisConnection connection) {
+
+        if (!isLockingCacheWriter()) {
+            return;
+        }
+
+        try {
+
+            while (doCheckLock(name, connection)) {
+                Thread.sleep(sleepTime.toMillis());
+            }
+        } catch (InterruptedException ex) {
+
+            // Re-interrupt current thread, to allow other participants to react.
+            Thread.currentThread().interrupt();
+
+            throw new PessimisticLockingFailureException(String.format("Interrupted while waiting to unlock cache %s", name),
+                    ex);
+        }
+    }
+
+    private static boolean shouldExpireWithin(@Nullable Duration ttl) {
+        return ttl != null && !ttl.isZero() && !ttl.isNegative();
+    }
+
+    private static byte[] createCacheLockKey(String name) {
+        return (name + "~lock").getBytes(StandardCharsets.UTF_8);
+    }
+}

+ 56 - 0
java110-core/src/main/java/com/java110/core/cache/Java110RedisConfig.java

@@ -0,0 +1,56 @@
+package com.java110.core.cache;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.RedisSerializationContext;
+
+import java.time.Duration;
+
+@Configuration
+
+@EnableCaching //开启缓存,默认是rendis缓存,继承CachingConfigurerSupport ,直接重写里面的方法
+public class Java110RedisConfig extends CachingConfigurerSupport {
+
+    public final static String REDIS_EXPIRE_TIME_KEY = "#key_expire_time";
+
+    public final static String DEFAULT_EXPIRE_TIME_KEY = "#key_expire_time=600";
+    public final static String GET_STORE_ENTER_COMMUNITYS_EXPIRE_TIME_KEY = "#key_expire_time=7200";
+    public final static String GET_STORE_INFO_EXPIRE_TIME_KEY = "#key_expire_time=5400";
+
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+    @Override
+    @Bean
+    public CacheManager cacheManager() {
+
+        RedisConnectionFactory connectionFactory = redisTemplate.getConnectionFactory();
+        //上面实现的缓存读写
+        Java110RedisCacheWriter java110RedisCacheWriter
+                = new Java110RedisCacheWriter(connectionFactory);
+
+        CacheManager cm
+                = new RedisCacheManager(java110RedisCacheWriter, redisCacheConfiguration());
+
+        return cm;
+    }
+
+    @Bean
+    public RedisCacheConfiguration redisCacheConfiguration() {
+
+        RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
+
+        configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())).entryTtl(Duration.ofSeconds(30));
+
+        return configuration;
+    }
+}

+ 29 - 3
java110-core/src/main/java/com/java110/core/component/BaseComponentSMO.java

@@ -3,6 +3,7 @@ package com.java110.core.component;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.java110.core.base.smo.BaseServiceSMO;
+import com.java110.core.cache.Java110RedisConfig;
 import com.java110.core.context.IPageData;
 import com.java110.entity.component.ComponentValidateResult;
 import com.java110.utils.cache.MappingCache;
@@ -16,6 +17,7 @@ import com.java110.utils.util.Assert;
 import com.java110.utils.util.StringUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
@@ -155,10 +157,11 @@ public class BaseComponentSMO extends BaseServiceSMO {
      *
      * @return
      */
-    protected ResponseEntity<String> getStoreInfo(IPageData pd, RestTemplate restTemplate) {
+    @Cacheable(value = "getStoreInfo" + Java110RedisConfig.GET_STORE_INFO_EXPIRE_TIME_KEY, key = "#userId")
+    protected ResponseEntity<String> getStoreInfo(IPageData pd, RestTemplate restTemplate, String userId) {
         Assert.hasLength(pd.getUserId(), "用户未登录请先登录");
         ResponseEntity<String> responseEntity = null;
-        responseEntity = this.callCenterService(restTemplate, pd, "", ServiceConstant.SERVICE_API_URL + "/api/query.store.byuser?userId=" + pd.getUserId(), HttpMethod.GET);
+        responseEntity = this.callCenterService(restTemplate, pd, "", ServiceConstant.SERVICE_API_URL + "/api/query.store.byuser?userId=" + userId, HttpMethod.GET);
 
         return responseEntity;
     }
@@ -168,12 +171,35 @@ public class BaseComponentSMO extends BaseServiceSMO {
      *
      * @return
      */
-    protected void checkStoreEnterCommunity(IPageData pd, String storeId, String storeTypeCd, String communityId, RestTemplate restTemplate) {
+    protected ResponseEntity<String> getStoreInfo(IPageData pd, RestTemplate restTemplate) {
         Assert.hasLength(pd.getUserId(), "用户未登录请先登录");
+
+        return getStoreInfo(pd, restTemplate, pd.getUserId());
+//        ResponseEntity<String> responseEntity = null;
+//        responseEntity = this.callCenterService(restTemplate, pd, "", ServiceConstant.SERVICE_API_URL + "/api/query.store.byuser?userId=" + pd.getUserId(), HttpMethod.GET);
+//
+//        return responseEntity;
+    }
+
+    @Cacheable(value = "getStoreEnterCommunitys" + Java110RedisConfig.GET_STORE_ENTER_COMMUNITYS_EXPIRE_TIME_KEY, key = "#storeId")
+    private ResponseEntity<String> getStoreEnterCommunitys(IPageData pd, String storeId, String storeTypeCd, RestTemplate restTemplate) {
         ResponseEntity<String> responseEntity = null;
         responseEntity = this.callCenterService(restTemplate, pd, "",
                 ServiceConstant.SERVICE_API_URL + "/api/query.myCommunity.byMember?memberId=" + storeId + "&memberTypeCd="
                         + MappingCache.getValue(MappingConstant.DOMAIN_STORE_TYPE_2_COMMUNITY_MEMBER_TYPE, storeTypeCd), HttpMethod.GET);
+
+        return responseEntity;
+    }
+
+    /**
+     * 查询商户信息
+     *
+     * @return
+     */
+    protected void checkStoreEnterCommunity(IPageData pd, String storeId, String storeTypeCd, String communityId, RestTemplate restTemplate) {
+        Assert.hasLength(pd.getUserId(), "用户未登录请先登录");
+        ResponseEntity<String> responseEntity = null;
+        responseEntity = getStoreEnterCommunitys(pd, storeId, storeTypeCd, restTemplate);
         if (responseEntity.getStatusCode() != HttpStatus.OK) {
             throw new SMOException(ResponseConstant.RESULT_CODE_ERROR, "还未入驻小区,请先入驻小区");
         }

+ 1 - 1
service-api/src/main/java/com/java110/api/listener/basePrivilege/CheckUserHasResourceListener.java

@@ -54,7 +54,7 @@ public class CheckUserHasResourceListener extends AbstractServiceApiDataFlowList
         int count = menuInnerServiceSMOImpl.queryBasePrivilegesCount(basePrivilegeDto);
         //没有配置权限,都能访问
         if (count < 1) {
-            responseEntity = new ResponseEntity<String>("该资源路径没有配置权限", HttpStatus.OK);
+            responseEntity = new ResponseEntity<String>("校验成功,该资源路径未配置权限,建议开发者账户配置权限", HttpStatus.OK);
             dataFlowContext.setResponseEntity(responseEntity);
             return;
         }