Commit d58e74f3 authored by xiaoguang.xu's avatar xiaoguang.xu

optimizeImport

parent dd3d6343
package cn.quantgroup.xyqb.aspect.fplock;
import java.lang.annotation.*;
/**
* Created by Miraculous on 15/11/10.
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface FPLock {
String uniqueName();
FPRestriction[] restrictions() default {};
}
package cn.quantgroup.xyqb.aspect.fplock;
import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;
/**
* Created by Miraculous on 15/11/10.
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FPRestriction {
// 持续时间
int duration() default 1;
// 持续时间单位
TimeUnit type() default TimeUnit.MINUTES;
// 限制值, -1表示不限制
int limit() default -1;
// 使用可覆盖
boolean override() default true;
}
package cn.quantgroup.xyqb.aspect.fplock;
import cn.quantgroup.xyqb.exception.ResubmissionException;
import cn.quantgroup.xyqb.model.JsonResult;
import org.apache.commons.collections.FastHashMap;
import org.apache.commons.lang3.time.DateFormatUtils;
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.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
/**
* 第一参数锁
* Created by Miraculous on 15/11/10.
*/
@Aspect
@Component
@Order(value = Ordered.HIGHEST_PRECEDENCE)
public class FirstParamLockAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(FirstParamLockAspect.class);
private static final HashMap<String, FPRestrictionWraper> LOCK_PARAM;
private static final Long MAX_COUNTER = 1L;
private static final Long MAX_TO_LIVE = 10L;
static {
FastHashMap fastHashMap = new FastHashMap();
fastHashMap.setFast(true);
LOCK_PARAM = fastHashMap;
}
@Autowired
@Qualifier("stringRedisTemplate")
private RedisTemplate<String, String> stringRedisTemplate;
/* 自定义限制策略 (FPRestriction) 的情况下, 可配置的限制数值 */
@Value("${xyqb.fplock.limit.byhour:3}")
private Integer limitByHour; // 每小时限制值
@Value("${xyqb.fplock.limit.byday:5}")
private Integer limitByDay; // 每天限制值
@Pointcut("@annotation(cn.quantgroup.xyqb.aspect.fplock.FPLock)")
private void fplockPointCut() {
}
@Around("fplockPointCut()")
private Object preventDuplicateSubmit(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
if (args == null || args.length == 0) {
return pjp.proceed();
}
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
Method method = methodSignature.getMethod();
FPLock fpLock = method.getAnnotation(cn.quantgroup.xyqb.aspect.fplock.FPLock.class);
Object fp = args[0];
if (fpLock.restrictions().length < 1) {
String lockName = fpLock.uniqueName() + fp.toString();
Long ret = stringRedisTemplate.opsForValue().increment(lockName, 1L);
if (MAX_COUNTER < ret) {
stringRedisTemplate.expire(lockName, MAX_TO_LIVE, TimeUnit.SECONDS);
throw new ResubmissionException();
}
try {
return pjp.proceed();
} finally {
stringRedisTemplate.expire(lockName, MAX_TO_LIVE, TimeUnit.SECONDS);
}
} else {
String uniqueName = fpLock.uniqueName();
/* 加入自定义限制策略 */
FPRestrictionWraper[] restrictionWrapers = wrapFPRestrictions(uniqueName, fpLock.restrictions());
// 执行检查
boolean restrictionsPass = preRestrictionsCheck(uniqueName, String.valueOf(fp), restrictionWrapers);
if (restrictionsPass) {
// 检查通过
try {
Object proceed = pjp.proceed();
if (JsonResult.class == proceed.getClass()) {
JsonResult result = (JsonResult) proceed;
if (!"0000".equals(result.getCode()) || !"0000".equals(result.getBusinessCode())) {
// 业务操作失败
postRestrictionsCheck(uniqueName, String.valueOf(fp), restrictionWrapers);
}
}
return proceed;
} catch (Exception e) {
// 业务操作异常
postRestrictionsCheck(uniqueName, String.valueOf(fp), restrictionWrapers);
throw e;
}
} else {
// 检查不通过
LOGGER.warn("接口首参数保护! api:{}, variable:{}", method.getName(), String.valueOf(fp));
postRestrictionsCheck(uniqueName, String.valueOf(fp), restrictionWrapers);
throw new ResubmissionException();
}
}
}
public void parseFpLockAnnotaion(Method method) {
FPLock fpLock = method.getAnnotation(cn.quantgroup.xyqb.aspect.fplock.FPLock.class);
wrapFPRestrictions(fpLock.uniqueName(), fpLock.restrictions());
}
/**
* 重设限制参数
*/
public void setLimitation(String key, Integer duration, Integer limit) {
FPRestrictionWraper restriction = LOCK_PARAM.get(key);
if (restriction != null) {
if (duration != null) {
restriction.duration(duration);
}
if (limit != null) {
restriction.limit(limit);
}
}
}
/**
* 读取限制参数
*/
public FPRestrictionWraper readLimitation(String key) {
return LOCK_PARAM.get(key);
}
/**
* 包装注解
*
* @param uniqueName
* @param restrictions
* @return
*/
private FPRestrictionWraper[] wrapFPRestrictions(String uniqueName, FPRestriction[] restrictions) {
FPRestrictionWraper[] wrapers = new FPRestrictionWraper[restrictions.length];
for (int i = 0; i < wrapers.length; i++) {
FPRestriction restriction = restrictions[i];
// 将restriction 配置参数读入 map
String key = uniqueName + restriction.type().toString();
if (LOCK_PARAM.containsKey(key)) {
wrapers[i] = LOCK_PARAM.get(key);
} else {
FPRestrictionWraper wraper = new FPRestrictionWraper(restriction);
wrapers[i] = wraper;
LOCK_PARAM.put(key, wraper);
}
}
return wrapers;
}
/**
* 前置检查, 根据用户设置的锁策略进行锁检查
*
* @param uniqeName
* @param variable
* @param restrictions
* @return
*/
private boolean preRestrictionsCheck(String uniqeName, String variable, FPRestrictionWraper[] restrictions) {
for (FPRestrictionWraper restriction : restrictions) {
TimeUnit timeUnit = restriction.timeUnit();
int duration = restriction.duration();
int limit = restriction.limit();
String lockName = uniqeName + restriction.getLockKey() + ":" + variable;
// 根据锁名获取缓存的:已操作的次数
Long action = stringRedisTemplate.opsForValue().increment(lockName, 1L);
restriction.setProceed(true);
if (action > limit) {
// 已超过规定值, 本次操作不允许
return false;
}
restriction.setSuccess(true);
// 本条限制通过, 设置过期策略, 等待下次操作请求
stringRedisTemplate.expire(lockName, duration, timeUnit);
}
return true;
}
/**
* 后置检查, 用户锁值操作已成功, 但是业务操作失败的情况, 回滚 redis 计数
*
* @param uniqeName
* @param variable
* @param restrictions
* @return
*/
private boolean postRestrictionsCheck(String uniqeName, String variable, FPRestrictionWraper[] restrictions) {
Stream<FPRestrictionWraper> restrictions1 = Stream.of(restrictions);
restrictions1.filter(FPRestrictionWraper::isProceed).forEach(res -> {
// 由于业务操作失败, "回滚"计数值
String lockName = uniqeName + res.getLockKey() + ":" + variable;
stringRedisTemplate.opsForValue().increment(lockName, -1L);
});
return true;
}
/**
* 根据时间单位获取Redis锁名
*
* @return
*/
private String getLockKeyByTimeUnit(TimeUnit timeUnit) {
Calendar calendar = Calendar.getInstance();
String unit = timeUnit.toString();
switch (timeUnit) {
case DAYS:
return unit + DateFormatUtils.format(calendar, "yyyyMMdd");
case HOURS:
return unit + DateFormatUtils.format(calendar, "yyyyMMddHH");
case MINUTES:
return unit + DateFormatUtils.format(calendar, "yyyyMMddHHmm");
case SECONDS:
return unit + DateFormatUtils.format(calendar, "yyyyMMddHHmmss");
default:
return unit;
}
}
/**
* 注解包装类
*/
public class FPRestrictionWraper {
private FPRestriction restriction;
private int limit;
private int duration;
private TimeUnit timeUnit;
private boolean isSuccess;
private boolean isProceed;
public FPRestrictionWraper(FPRestriction restriction) {
this.restriction = restriction;
this.timeUnit = restriction.type();
this.limit = restriction.limit();
this.duration = restriction.duration();
}
public TimeUnit timeUnit() {
return this.timeUnit;
}
public int duration() {
return this.duration;
}
public void duration(int duration) {
this.duration = duration;
}
public int limit() {
return this.limit;
/* int _limit = this.restriction.limit();
switch (restriction.type()) {
case DAYS:
return _limit == limitByDay ? _limit : limitByHour;
case HOURS:
return _limit == limitByHour ? _limit : limitByDay;
default:
return -1;
}*/
}
public void limit(int limit) {
this.limit = limit;
}
public boolean isSuccess() {
return isSuccess;
}
public void setSuccess(boolean success) {
isSuccess = success;
}
public boolean isProceed() {
return isProceed;
}
public void setProceed(boolean proceed) {
isProceed = proceed;
}
public String getLockKey() {
return getLockKeyByTimeUnit(timeUnit());
}
public String desc() {
return "timeUnit:" + timeUnit + ", duration:" + this.duration + ", limit:" + limit;
}
}
}
package cn.quantgroup.xyqb.aspect.logcaller;
import java.lang.annotation.*;
/**
* Created by Administrator on 2017/5/15.
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogHttpCaller {
}
......@@ -18,7 +18,6 @@ import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.cookie.Cookie;
import org.apache.http.cookie.CookieOrigin;
import org.apache.http.cookie.CookieSpecProvider;
import org.apache.http.cookie.MalformedCookieException;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.StandardHttpRequestRetryHandler;
......
......@@ -3,7 +3,6 @@ package cn.quantgroup.xyqb.config.http;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import java.io.IOException;
import java.lang.reflect.Type;
import java.sql.Timestamp;
......
package cn.quantgroup.xyqb.controller.external.captcha;
import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.aspect.logcaller.LogHttpCaller;
import cn.quantgroup.xyqb.model.ClientType;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.service.captcha.IGeetestCaptchaService;
......
package cn.quantgroup.xyqb.controller.external.user;
import cn.quantgroup.xyqb.aspect.accessable.IpValidator;
import cn.quantgroup.xyqb.aspect.logcaller.LogHttpCaller;
import cn.quantgroup.xyqb.controller.IBaseController;
import cn.quantgroup.xyqb.entity.Merchant;
import cn.quantgroup.xyqb.entity.User;
......
......@@ -2,7 +2,6 @@ package cn.quantgroup.xyqb.controller.external.user;
import cn.quantgroup.user.enums.Relation;
import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.aspect.logcaller.LogHttpCaller;
import cn.quantgroup.xyqb.controller.IBaseController;
import cn.quantgroup.xyqb.entity.*;
import cn.quantgroup.xyqb.entity.enumerate.*;
......
......@@ -2,7 +2,6 @@ package cn.quantgroup.xyqb.controller.external.user;
import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.aspect.accessable.IpValidator;
import cn.quantgroup.xyqb.aspect.logcaller.LogHttpCaller;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.session.SessionStruct;
......
package cn.quantgroup.xyqb.controller.internal.login;
import cn.quantgroup.xyqb.aspect.logcaller.LogHttpCaller;
import cn.quantgroup.xyqb.controller.IBaseController;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.UserRet;
......
package cn.quantgroup.xyqb.controller.internal.user;
import cn.quantgroup.xyqb.aspect.logcaller.LogHttpCaller;
import cn.quantgroup.xyqb.entity.UserAuthorized;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.UserAuthorizedParam;
......
......@@ -4,7 +4,6 @@ import cn.quantgroup.tech.util.TechEnvironment;
import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.aspect.captcha.CaptchaFiniteValidator;
import cn.quantgroup.xyqb.aspect.lock.PasswordErrorFiniteValidator;
import cn.quantgroup.xyqb.aspect.logcaller.LogHttpCaller;
import cn.quantgroup.xyqb.controller.IBaseController;
import cn.quantgroup.xyqb.entity.Merchant;
import cn.quantgroup.xyqb.entity.User;
......
package cn.quantgroup.xyqb.exception;
/**
* @author mengfan.feng
* @time 2015-11-16 11:10
* @see cn.quantgroup.xyqb.model.JsonResult#msg
*/
public class ResponseException extends RuntimeException {
private static final long serialVersionUID = -1L;
public ResponseException(String message) {
super(message);
}
public ResponseException(String message, Throwable cause) {
super(message, cause);
}
}
package cn.quantgroup.xyqb.model.session;
import cn.quantgroup.motan.retbean.XLoginInfo;
import cn.quantgroup.xyqb.model.UserRet;
import com.alibaba.fastjson.JSON;
import lombok.Data;
/**
......
......@@ -6,7 +6,6 @@ import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
......
......@@ -5,12 +5,9 @@ import cn.quantgroup.xyqb.model.ClientType;
import cn.quantgroup.xyqb.service.captcha.GeetestLib;
import cn.quantgroup.xyqb.service.captcha.IGeetestCaptchaService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
......
......@@ -72,7 +72,8 @@ public class BaseUserRegisterHandler extends AbstractUserRegisterHandler {
user.setRegisteredFrom(registerFrom);
}
String password = StringUtils.defaultString(userRegisterParam.getPassword(), "");
if (userRegisterParam.isGenerateRandomPwd()) { // 如果需要生成随机密码
// 如果需要生成随机密码
if (userRegisterParam.isGenerateRandomPwd()) {
password = PasswordUtil.generateRandomPwd(Constants.RANDOM_PWD_LEN);
}
user.setPassword(PasswordUtil.MD5(password.toLowerCase() + Constants.PASSWORD_SALT));
......
package cn.quantgroup.xyqb.service.user;
import cn.quantgroup.xyqb.entity.UuidPhoneMapping;
/**
* Created by Miraculous on 15/10/29.
*/
......
......@@ -14,7 +14,6 @@ import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.sql.Timestamp;
import java.util.Iterator;
import java.util.List;
/**
......
......@@ -24,10 +24,7 @@ import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
......
package cn.quantgroup.xyqb.util;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
/**
......
import service.GeetestCaptchaServiceTest;
import service.QuantgroupCaptchaServiceTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import service.GeetestCaptchaServiceTest;
import service.QuantgroupCaptchaServiceTest;
@RunWith(Suite.class)
@Suite.SuiteClasses({GeetestCaptchaServiceTest.class, QuantgroupCaptchaServiceTest.class})
......
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import repsitory.UserAuthorizedRepsitoryTests;
import service.UserAuthorizedServiceTests;
import web.UserAuthorizedControllerTests;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({UserAuthorizedRepsitoryTests.class, UserAuthorizedServiceTests.class, UserAuthorizedControllerTests.class})
......
......@@ -15,7 +15,6 @@ import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
......@@ -24,7 +23,6 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
......
package service;
import cn.quantgroup.xyqb.Bootstrap;
import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.model.ClientType;
import cn.quantgroup.xyqb.service.captcha.IGeetestCaptchaService;
import cn.quantgroup.xyqb.util.PasswordUtil;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment