import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Description: 禁止重复提交自定义注解
* @Param:
* @return:
*
*
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AvoidRepeatableCommit {
/**
* 指定时间内不可重复提交,单位秒
* @return
*/
int timeout() default 4 ;
}
import com.alibaba.fastjson.JSON;
import com.google.common.base.Strings;
import com.ziku.forte.bo.user.UserResult;
import com.ziku.forte.enums.ErrorCodeEnum;
import com.ziku.forte.exception.BizException;
import com.ziku.forte.util.CacheKit;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import redis.clients.jedis.Jedis;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
/**
*
* @description: 禁止重复提交aop
* @Date 2018-11-22 11:06
* @Version 1.0
**/
@Component
@Aspect
@Slf4j
public class AvoidRepeatableCommitAspect {
@Autowired
private CacheKit cacheKit;
/**
* @param point
*/
@Around("@annotation(com.ziku.forte.web.repeatableCommit.AvoidRepeatableCommit)")
public Object around(ProceedingJoinPoint point) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
Long userId = null;
String token = request.getHeader("token");
if (StringUtils.isNotBlank(token)) {
UserResult cacheUser = getCacheUser(token);
if (cacheUser != null) {
userId = cacheUser.getId();
}
}
String ip = this.getIpAdrress(request);
//获取注解
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
//目标类、方法
String className = method.getDeclaringClass().getName();
String name = method.getName();
StringBuilder param = new StringBuilder();
Object[] args = point.getArgs();
if (ArrayUtils.isNotEmpty(args)) {
for (int i = 0; i < args.length; i++) {
param.append(args[i].toString());
}
}
String ipKey = String.format("%s#%s#%s",className,name,param.toString());
int hashCode = ipKey.hashCode();
String key = String.format("%s_%d_%d", ip, userId, hashCode);
log.info("ip:{},用户id:{},请求参数为:{},key值为:{}",ip,userId,ipKey,key);
AvoidRepeatableCommit avoidRepeatableCommit = method.getAnnotation(AvoidRepeatableCommit.class);
int timeout = avoidRepeatableCommit.timeout();
if (timeout < 0){
timeout = 5;
}
//用多参数set方法保证对redis操作原子性
Jedis jedis = cacheKit.getJedis();
String set = jedis.set("ZK-XINJIA:LOCK:" + key, System.currentTimeMillis() + "", "NX", "PX", timeout*1000);
cacheKit.returnResource(jedis);
if (StringUtils.isBlank(set)) {
throw new BizException(ErrorCodeEnum.NOREPEATABLECOMMIT);
}
//执行方法
Object object = point.proceed();
return object;
}
/**
* 获取Ip地址
* @param request
* @return
*/
private String getIpAdrress(HttpServletRequest request) {
String Xip = request.getHeader("X-Real-IP");
String XFor = request.getHeader("X-Forwarded-For");
if(StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
//多次反向代理后会有多个ip值,第一个ip才是真实ip
int index = XFor.indexOf(",");
if(index != -1){
return XFor.substring(0,index);
}else{
return XFor;
}
}
XFor = Xip;
if(StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
return XFor;
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getRemoteAddr();
}
return XFor;
}
private UserResult getCacheUser(String token) {
UserResult userInfo = null;
if (Strings.isNullOrEmpty(token)) {
return null;
}
String userId = cacheKit.safeGet("ZK-YOULE:JWT_TOKEN:" + token);
if (Strings.isNullOrEmpty(userId)) {
return null;
}
String userJson = cacheKit.safeGet("ZK-YOULE:USER-ID:" + userId);
if (Strings.isNullOrEmpty(userJson)) {
return null;
}
userInfo = JSON.parseObject(userJson, UserResult.class);
return userInfo;
}
}