package xiaoqu.home.open.aop;


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import xiaoqu.home.open.redis.RedisDistributedLock;
import xiaoqu.home.open.utils.ResultResponseBeanUtil;

import javax.servlet.http.HttpServletRequest;


/**
 * 防止重复提交的切面
 */
@Aspect
@Component
public class RepeatSubmitAspect {
	private Logger log = LoggerFactory.getLogger("Controller");
 
    @Autowired
    private RedisDistributedLock redisDistributedLock;
 
 
    /**
     * 切点
     *
     * @param avoidRepeatSubmit
     */
    @Pointcut("@annotation(avoidRepeatSubmit)")
    public void pointCut(AvoidRepeatSubmit avoidRepeatSubmit) {
    }
 
    /**
     * 利用环绕通知进行处理重复提交问题
     *
     * @param pjp
     * @param avoidRepeatSubmit
     * @return
     * @throws Throwable
     */
    @Around("pointCut(avoidRepeatSubmit)")
    public Object around(ProceedingJoinPoint pjp, AvoidRepeatSubmit avoidRepeatSubmit) throws Throwable {
 
        /**
         * 获取锁的时间
         */
 
        //获得request对象
        HttpServletRequest request = httpServletRequest();
 
        Assert.notNull(request, "request can not null");
 
        // 此处可以用token或者JSessionId
        String token = request.getHeader("uuid");
        String path = request.getServletPath();
        String key = getKey(token, path);
 
        //锁定多少秒
        boolean isSuccess = redisDistributedLock.lock(key,token,avoidRepeatSubmit.lockTime());
 
        if (isSuccess) {
 
            // 获取锁成功, 执行进程
            Object result;
            try {
                result = pjp.proceed();
 
            } finally {
                //解锁
                redisDistributedLock.unLock(key,token);
            }
 
            return result;
 
        } else {
            // 获取锁失败，认为是重复提交的请求
            log.error("URL加锁="+path+"tryLock fail, key = [{}]", key);
            return ResultResponseBeanUtil.fail("重复请求，请稍后再试");
        }
 
    }
 
    /**
     * 获得request对象
     *
     * @return
     */
    private HttpServletRequest httpServletRequest() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return requestAttributes.getRequest();
    }
 
 
    /**
     * 获得请求key
     *
     * @param token
     * @param path
     * @return
     */
    private String getKey(String token, String path) {
        return token + path;
    }
 
 
}