|
@@ -0,0 +1,126 @@
|
|
|
+package cn.com.qmth.examcloud.web.interceptor;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+
|
|
|
+import org.springframework.http.HttpStatus;
|
|
|
+import org.springframework.web.method.HandlerMethod;
|
|
|
+import org.springframework.web.servlet.HandlerInterceptor;
|
|
|
+import org.springframework.web.servlet.ModelAndView;
|
|
|
+
|
|
|
+import cn.com.qmth.examcloud.api.commons.security.bean.User;
|
|
|
+import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
|
|
|
+import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
|
|
|
+import cn.com.qmth.examcloud.commons.util.ThreadLocalUtil;
|
|
|
+import cn.com.qmth.examcloud.web.enums.HttpServletRequestAttribute;
|
|
|
+import cn.com.qmth.examcloud.web.redis.RedisClient;
|
|
|
+import cn.com.qmth.examcloud.web.support.ServletUtil;
|
|
|
+import cn.com.qmth.examcloud.web.support.StatusResponse;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 顺序锁拦截器
|
|
|
+ *
|
|
|
+ * @author WANGWEI
|
|
|
+ * @date 2019年2月22日
|
|
|
+ * @Copyright (c) 2018-2020 WANGWEI [QQ:522080330] All Rights Reserved.
|
|
|
+ */
|
|
|
+public class SeqlockInterceptor implements HandlerInterceptor {
|
|
|
+
|
|
|
+ private static final ExamCloudLog LOG = ExamCloudLogFactory.getLog(SeqlockInterceptor.class);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * redis client
|
|
|
+ */
|
|
|
+ private RedisClient redisClient;
|
|
|
+
|
|
|
+ private static final String GLOBAL_LOCK_PREFIX = "$_LOCK_G:";
|
|
|
+
|
|
|
+ private static final String SESSION_LOCK_PREFIX = "$_LOCK_S:";
|
|
|
+
|
|
|
+ private static final String LOCK_ATTRIBUTE = "$sequenceLock";
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构造函数
|
|
|
+ *
|
|
|
+ * @param redisClient
|
|
|
+ * @param exclusions
|
|
|
+ */
|
|
|
+ public SeqlockInterceptor(RedisClient redisClient) {
|
|
|
+ super();
|
|
|
+ this.redisClient = redisClient;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
|
|
|
+ Object handler) throws Exception {
|
|
|
+ LOG.debug("preHandle... ...");
|
|
|
+
|
|
|
+ if (handler instanceof HandlerMethod) {
|
|
|
+
|
|
|
+ HandlerMethod handlerMethod = (HandlerMethod) handler;
|
|
|
+ GlobalSequenceLock globalSeqlock = handlerMethod
|
|
|
+ .getMethodAnnotation(GlobalSequenceLock.class);
|
|
|
+ SessionSequenceLock sessionSeqlock = handlerMethod
|
|
|
+ .getMethodAnnotation(SessionSequenceLock.class);
|
|
|
+
|
|
|
+ String mapping = (String) request
|
|
|
+ .getAttribute(HttpServletRequestAttribute.$_MAPPING.name());
|
|
|
+
|
|
|
+ if (null != globalSeqlock) {
|
|
|
+ String key = GLOBAL_LOCK_PREFIX + mapping;
|
|
|
+
|
|
|
+ if (redisClient.setIfAbsent(key, ThreadLocalUtil.getTraceId(), 60 * 5)) {
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
+ LOG.debug("partition locked");
|
|
|
+ }
|
|
|
+
|
|
|
+ request.setAttribute(LOCK_ATTRIBUTE, key);
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ response.setStatus(HttpStatus.CONFLICT.value());
|
|
|
+ ServletUtil.returnJson(new StatusResponse("409", "请稍后重试... ..."), response);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ } else if (null != sessionSeqlock) {
|
|
|
+
|
|
|
+ User user = (User) request
|
|
|
+ .getAttribute(HttpServletRequestAttribute.$_ACCESS_USER.name());
|
|
|
+
|
|
|
+ String key = SESSION_LOCK_PREFIX + user.getKey();
|
|
|
+
|
|
|
+ if (redisClient.setIfAbsent(key, ThreadLocalUtil.getTraceId(), 60 * 5)) {
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
+ LOG.debug("sesssion locked");
|
|
|
+ }
|
|
|
+ request.setAttribute(LOCK_ATTRIBUTE, key);
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ response.setStatus(HttpStatus.CONFLICT.value());
|
|
|
+ ServletUtil.returnJson(new StatusResponse("409", "请稍后重试... ..."), response);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
|
|
|
+ ModelAndView modelAndView) throws Exception {
|
|
|
+ LOG.debug("postHandle... ...");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
|
|
|
+ Object handler, Exception ex) throws Exception {
|
|
|
+ LOG.debug("afterCompletion... ...");
|
|
|
+
|
|
|
+ Object key = request.getAttribute(LOCK_ATTRIBUTE);
|
|
|
+ if (null != key) {
|
|
|
+ redisClient.delete((String) key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|