|
@@ -1,13 +1,5 @@
|
|
|
package cn.com.qmth.examcloud.web.helpers;
|
|
|
|
|
|
-import java.util.List;
|
|
|
-import java.util.concurrent.TimeUnit;
|
|
|
-
|
|
|
-import org.apache.commons.lang.StringUtils;
|
|
|
-import org.assertj.core.util.Arrays;
|
|
|
-
|
|
|
-import com.google.common.collect.Lists;
|
|
|
-
|
|
|
import cn.com.qmth.examcloud.commons.util.ThreadLocalUtil;
|
|
|
import cn.com.qmth.examcloud.web.enums.HttpServletRequestAttribute;
|
|
|
import cn.com.qmth.examcloud.web.exception.SequenceLockException;
|
|
@@ -15,99 +7,100 @@ import cn.com.qmth.examcloud.web.interceptor.SeqlockInterceptor;
|
|
|
import cn.com.qmth.examcloud.web.redis.RedisClient;
|
|
|
import cn.com.qmth.examcloud.web.support.ServletUtil;
|
|
|
import cn.com.qmth.examcloud.web.support.SpringContextHolder;
|
|
|
+import com.google.common.collect.Lists;
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
+import org.assertj.core.util.Arrays;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
+import java.util.List;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
/**
|
|
|
* 并发顺序锁
|
|
|
*
|
|
|
* @author WANGWEI
|
|
|
* @date 2019年2月22日
|
|
|
- * @Copyright (c) 2018-2020 WANGWEI [QQ:522080330] All Rights Reserved.
|
|
|
*/
|
|
|
public class SequenceLockHelper {
|
|
|
|
|
|
- private static final Logger LOG = LoggerFactory.getLogger(SequenceLockHelper.class);
|
|
|
-
|
|
|
- private static final String LOCK_PREFIX = "$_LOCK_C:";
|
|
|
-
|
|
|
- private static RedisClient redisClient;
|
|
|
-
|
|
|
- private static RedisClient getRedisClient() {
|
|
|
- if (null == redisClient) {
|
|
|
- redisClient = SpringContextHolder.getBean(RedisClient.class);
|
|
|
- }
|
|
|
-
|
|
|
- return redisClient;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取顺序请求锁<br>
|
|
|
- *
|
|
|
- * @param args
|
|
|
- * @throws SequenceLockException
|
|
|
- * 获取锁失败时抛出异常
|
|
|
- */
|
|
|
- public static void getLock(Object... args) throws SequenceLockException {
|
|
|
-
|
|
|
- String key = LOCK_PREFIX + StringUtils.join(Arrays.asList(args), "_");
|
|
|
-
|
|
|
- int timeout = 60 * 2;
|
|
|
-
|
|
|
- if (getRedisClient().setIfAbsent(key, ThreadLocalUtil.getTraceId(), timeout)) {
|
|
|
- if (LOG.isDebugEnabled()) {
|
|
|
- LOG.debug("locked");
|
|
|
- }
|
|
|
- @SuppressWarnings("unchecked")
|
|
|
- List<String> keyList = (List<String>) ServletUtil.getRequest()
|
|
|
- .getAttribute(HttpServletRequestAttribute.$_CUSTOM_SEQUENCE_LOCK.name());
|
|
|
- if (null == keyList) {
|
|
|
- keyList = Lists.newArrayList();
|
|
|
- }
|
|
|
- keyList.add(key);
|
|
|
- ServletUtil.getRequest().setAttribute(
|
|
|
- HttpServletRequestAttribute.$_CUSTOM_SEQUENCE_LOCK.name(), keyList);
|
|
|
- } else {
|
|
|
- Long expire = getRedisClient().getExpire(key, TimeUnit.SECONDS);
|
|
|
- if (null == expire || expire > timeout) {
|
|
|
- getRedisClient().delete(key);
|
|
|
- }
|
|
|
-
|
|
|
- throw new SequenceLockException("请求等待,请稍后重试!");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 释放锁<br>
|
|
|
- * 接口调用不要调用此方法释放锁,此锁会在拦截器<{@link SeqlockInterceptor}中释放.
|
|
|
- *
|
|
|
- * @author WANGWEI
|
|
|
- * @param args
|
|
|
- */
|
|
|
- public static void releaseLock(Object... args) {
|
|
|
- String key = LOCK_PREFIX + StringUtils.join(Arrays.asList(args), "_");
|
|
|
- getRedisClient().expire((String) key, 100, TimeUnit.MILLISECONDS);
|
|
|
- @SuppressWarnings("unchecked")
|
|
|
- List<String> keyList = (List<String>) ServletUtil.getRequest()
|
|
|
- .getAttribute(HttpServletRequestAttribute.$_CUSTOM_SEQUENCE_LOCK.name());
|
|
|
- if (null != keyList) {
|
|
|
- if (keyList.contains(key)) {
|
|
|
- keyList.remove(key);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
+ private static final Logger LOG = LoggerFactory.getLogger(SequenceLockHelper.class);
|
|
|
+
|
|
|
+ private static RedisClient redisClient;
|
|
|
+
|
|
|
+ private static RedisClient getRedisClient() {
|
|
|
+ if (null == redisClient) {
|
|
|
+ redisClient = SpringContextHolder.getBean(RedisClient.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ return redisClient;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* 获取顺序请求锁<br>
|
|
|
- *
|
|
|
+ *
|
|
|
* @param args
|
|
|
- * @throws SequenceLockException
|
|
|
- * 获取锁失败时抛出异常
|
|
|
+ * @throws SequenceLockException 获取锁失败时抛出异常
|
|
|
+ */
|
|
|
+ public static void getLock(Object... args) throws SequenceLockException {
|
|
|
+
|
|
|
+ String key = StringUtils.join(Arrays.asList(args), "_");
|
|
|
+
|
|
|
+ int timeout = 60 * 2;
|
|
|
+
|
|
|
+ if (getRedisClient().setIfAbsent(key, ThreadLocalUtil.getTraceId(), timeout)) {
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
+ LOG.debug("locked");
|
|
|
+ }
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ List<String> keyList = (List<String>) ServletUtil.getRequest()
|
|
|
+ .getAttribute(HttpServletRequestAttribute.$_CUSTOM_SEQUENCE_LOCK.name());
|
|
|
+ if (null == keyList) {
|
|
|
+ keyList = Lists.newArrayList();
|
|
|
+ }
|
|
|
+ keyList.add(key);
|
|
|
+ ServletUtil.getRequest().setAttribute(
|
|
|
+ HttpServletRequestAttribute.$_CUSTOM_SEQUENCE_LOCK.name(), keyList);
|
|
|
+ } else {
|
|
|
+ Long expire = getRedisClient().getExpire(key, TimeUnit.SECONDS);
|
|
|
+ if (null == expire || expire > timeout) {
|
|
|
+ getRedisClient().delete(key);
|
|
|
+ }
|
|
|
+
|
|
|
+ throw new SequenceLockException("请求等待,请稍后重试!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 释放锁<br>
|
|
|
+ * 接口调用不要调用此方法释放锁,此锁会在拦截器<{@link SeqlockInterceptor}中释放.
|
|
|
+ *
|
|
|
+ * @param args
|
|
|
+ * @author WANGWEI
|
|
|
+ */
|
|
|
+ public static void releaseLock(Object... args) {
|
|
|
+ String key = StringUtils.join(Arrays.asList(args), "_");
|
|
|
+ getRedisClient().expire((String) key, 100, TimeUnit.MILLISECONDS);
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ List<String> keyList = (List<String>) ServletUtil.getRequest()
|
|
|
+ .getAttribute(HttpServletRequestAttribute.$_CUSTOM_SEQUENCE_LOCK.name());
|
|
|
+ if (null != keyList) {
|
|
|
+ if (keyList.contains(key)) {
|
|
|
+ keyList.remove(key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取顺序请求锁<br>
|
|
|
+ *
|
|
|
+ * @param args
|
|
|
+ * @throws SequenceLockException 获取锁失败时抛出异常
|
|
|
*/
|
|
|
public static void getLockSimple(Object... args) throws SequenceLockException {
|
|
|
|
|
|
- String key = LOCK_PREFIX + StringUtils.join(Arrays.asList(args), "_");
|
|
|
+ String key = StringUtils.join(Arrays.asList(args), "_");
|
|
|
|
|
|
int timeout = 60 * 2;
|
|
|
|
|
@@ -120,16 +113,16 @@ public class SequenceLockHelper {
|
|
|
throw new SequenceLockException("请求等待,请稍后重试!");
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
* 释放锁<br>
|
|
|
* 接口调用不要调用此方法释放锁,此锁会在拦截器<{@link SeqlockInterceptor}中释放.
|
|
|
*
|
|
|
- * @author WANGWEI
|
|
|
* @param args
|
|
|
+ * @author WANGWEI
|
|
|
*/
|
|
|
public static void releaseLockSimple(Object... args) {
|
|
|
- String key = LOCK_PREFIX + StringUtils.join(Arrays.asList(args), "_");
|
|
|
+ String key = StringUtils.join(Arrays.asList(args), "_");
|
|
|
getRedisClient().delete(key);
|
|
|
}
|
|
|
|