| | |
| | | package com.ruoyi.framework.aspectj; |
| | | |
| | | import cn.dev33.satoken.SaManager; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.hutool.crypto.SecureUtil; |
| | | import com.baomidou.lock.LockInfo; |
| | | import com.baomidou.lock.LockTemplate; |
| | | import com.ruoyi.common.annotation.RepeatSubmit; |
| | | import com.ruoyi.common.constant.Constants; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.JsonUtils; |
| | | import com.ruoyi.common.utils.RedisUtils; |
| | | import com.ruoyi.common.utils.ServletUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.framework.config.properties.RepeatSubmitProperties; |
| | |
| | | import org.aspectj.lang.annotation.Before; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.validation.BindingResult; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.util.Collection; |
| | | import java.util.Map; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * 防止重复提交 |
| | |
| | | public class RepeatSubmitAspect { |
| | | |
| | | private final RepeatSubmitProperties repeatSubmitProperties; |
| | | private final LockTemplate lockTemplate; |
| | | |
| | | @Before("@annotation(repeatSubmit)") |
| | | public void doBefore(JoinPoint point, RepeatSubmit repeatSubmit) throws Throwable { |
| | |
| | | throw new ServiceException("重复提交间隔时间不能小于'1'秒"); |
| | | } |
| | | HttpServletRequest request = ServletUtils.getRequest(); |
| | | String nowParams = StrUtil.join(",", point.getArgs()); |
| | | String nowParams = argsArrayToString(point.getArgs()); |
| | | |
| | | // 请求地址(作为存放cache的key值) |
| | | String url = request.getRequestURI(); |
| | |
| | | submitKey = SecureUtil.md5(submitKey + ":" + nowParams); |
| | | // 唯一标识(指定key + 消息头) |
| | | String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey; |
| | | LockInfo lock = lockTemplate.lock(cacheRepeatKey, interval, interval / 2); |
| | | if (lock == null) { |
| | | String key = RedisUtils.getCacheObject(cacheRepeatKey); |
| | | if (key == null) { |
| | | RedisUtils.setCacheObject(cacheRepeatKey, "", interval, TimeUnit.MILLISECONDS); |
| | | } else { |
| | | throw new ServiceException(repeatSubmit.message()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 参数拼装 |
| | | */ |
| | | private String argsArrayToString(Object[] paramsArray) { |
| | | StringBuilder params = new StringBuilder(); |
| | | if (paramsArray != null && paramsArray.length > 0) { |
| | | for (Object o : paramsArray) { |
| | | if (StringUtils.isNotNull(o) && !isFilterObject(o)) { |
| | | try { |
| | | params.append(JsonUtils.toJsonString(o)).append(" "); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return params.toString().trim(); |
| | | } |
| | | |
| | | /** |
| | | * 判断是否需要过滤的对象。 |
| | | * |
| | | * @param o 对象信息。 |
| | | * @return 如果是需要过滤的对象,则返回true;否则返回false。 |
| | | */ |
| | | @SuppressWarnings("rawtypes") |
| | | public boolean isFilterObject(final Object o) { |
| | | Class<?> clazz = o.getClass(); |
| | | if (clazz.isArray()) { |
| | | return clazz.getComponentType().isAssignableFrom(MultipartFile.class); |
| | | } else if (Collection.class.isAssignableFrom(clazz)) { |
| | | Collection collection = (Collection) o; |
| | | for (Object value : collection) { |
| | | return value instanceof MultipartFile; |
| | | } |
| | | } else if (Map.class.isAssignableFrom(clazz)) { |
| | | Map map = (Map) o; |
| | | for (Object value : map.entrySet()) { |
| | | Map.Entry entry = (Map.Entry) value; |
| | | return entry.getValue() instanceof MultipartFile; |
| | | } |
| | | } |
| | | return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse |
| | | || o instanceof BindingResult; |
| | | } |
| | | |
| | | } |