fanli/src/main/java/com/yeshi/fanli/aspect/RequestSerializableAspect.java
@@ -2,7 +2,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; @@ -14,25 +13,55 @@ import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.cache.Cache; import org.springframework.cache.Cache.ValueWrapper; import org.springframework.cache.ehcache.EhCacheCacheManager; import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.annotation.Order; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.stereotype.Component; import org.yeshi.utils.JsonUtil; import com.yeshi.fanli.log.LogHelper; import com.yeshi.fanli.util.Constant; import com.yeshi.fanli.util.StringUtil; import com.yeshi.fanli.util.annotation.RequestSerializableByKey; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; @Component @Aspect @Order(4) public class RequestSerializableAspect { @Resource private EhCacheCacheManager cacheManager; private JedisPool jedisPool; @Around("execution(public * com.yeshi.fanli.controller.client.*.*(..))") private ExpressionParser parser = new SpelExpressionParser(); private DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer(); /** * 获取表达的值 * * @param spELString * @param joinPoint * @return */ public String generateKeyBySpEL(String spELString, ProceedingJoinPoint joinPoint) { MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); String[] paramNames = nameDiscoverer.getParameterNames(methodSignature.getMethod()); Expression expression = parser.parseExpression(spELString); EvaluationContext context = new StandardEvaluationContext(); Object[] args = joinPoint.getArgs(); for (int i = 0; i < args.length; i++) { context.setVariable(paramNames[i], args[i]); } return expression.getValue(context).toString(); } @Around("execution(public * com.yeshi.fanli.controller.client.*.*.*(..))") public Object requestSerializable(ProceedingJoinPoint joinPoint) throws IOException { Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; @@ -41,64 +70,73 @@ try { Method realMethod = joinPoint.getTarget().getClass().getDeclaredMethod(joinPoint.getSignature().getName(), targetMethod.getParameterTypes()); Object[] args = joinPoint.getArgs(); PrintWriter out = null; String[] strings = methodSignature.getParameterNames(); Map<String, ParamsTypeValue> map = new HashMap<>(); Class<?>[] types = methodSignature.getParameterTypes(); for (int i = 0; i < strings.length; i++) { map.put(strings[i], new ParamsTypeValue(types[i], args[i])); if (args[i] instanceof PrintWriter) { out = (PrintWriter) args[i]; } } if (realMethod.isAnnotationPresent(RequestSerializableByKey.class)) { RequestSerializableByKey rs = realMethod.getAnnotation(RequestSerializableByKey.class); String[] strings = methodSignature.getParameterNames(); Class<?>[] types = methodSignature.getParameterTypes(); Map<String, ParamsTypeValue> map = new HashMap<>(); Object[] args = joinPoint.getArgs(); PrintWriter out = null; for (int i = 0; i < strings.length; i++) { map.put(strings[i], new ParamsTypeValue(types[i], args[i])); if (args[i] instanceof PrintWriter) { out = (PrintWriter) args[i]; } } String key = rs.key(); ParamsTypeValue tv = null; if (key.indexOf(".") > -1) { tv = map.get(key.split("\\.")[0]); } else { tv = map.get(key); } Object value = tv.value; Class<?> type = tv.type; // 暂时只支持2层嵌套 if (key.indexOf(".") > -1) { String child = key.split("\\.")[1]; cacheKey = generateKeyBySpEL(key, joinPoint); try {// redis做原子性保护 if (!StringUtil.isNullOrEmpty(cacheKey)) { cacheKey = joinPoint.getTarget().getClass().getName() + "." + targetMethod.getName() + "-" + cacheKey; cacheKey = "rs-" + StringUtil.Md5(cacheKey); // jiedis原子性做拦截 Jedis jedis = jedisPool.getResource(); try { Constant.waitingThreadSet.add(Thread.currentThread().getId()); long result = 0; long startTime = System.currentTimeMillis(); // 等待响应 while (result <= 0) { result = jedis.setnx(cacheKey, "1"); if (result <= 0) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } if (System.currentTimeMillis() - startTime > 1000 * 60L) { Constant.waitingThreadSet.remove(Thread.currentThread().getId()); out.print(JsonUtil.loadFalseResult("连接超时")); return null; } } } if (result > 0) { try { return joinPoint.proceed(); } catch (Throwable e) { e.printStackTrace(); LogHelper.errorDetailInfo(e); } finally { jedis.del(cacheKey); Constant.waitingThreadSet.remove(Thread.currentThread().getId()); } } } finally { jedisPool.returnResource(jedis); } } } catch (Exception e) {// 原子性保护出错 try { Field f = type.getDeclaredField(child); f.setAccessible(true); Object obj = f.get(value); if (obj != null) { cacheKey = obj.toString(); } } catch (NoSuchFieldException e) { return joinPoint.proceed(); } catch (Throwable e1) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } else { if (value != null) { cacheKey = value.toString(); } } if (!StringUtil.isNullOrEmpty(cacheKey)) { cacheKey = joinPoint.getTarget().getClass().getName() + "." + targetMethod.getName() + "-" + cacheKey; Cache cache = cacheManager.getCache("rsCache"); ValueWrapper element = cache.get(cacheKey); if (element != null && element.get() != null) { // 服务器繁忙 if (out != null) { out.print(JsonUtil.loadFalseResult(2001, "服务器繁忙")); } return null; } else { cache.put(cacheKey, "1"); LogHelper.errorDetailInfo(e1); } } } @@ -114,16 +152,16 @@ } catch (Throwable e) { e.printStackTrace(); LogHelper.errorDetailInfo(e); } finally { if (!StringUtil.isNullOrEmpty(cacheKey)) { Cache cache = cacheManager.getCache("rsCache"); cache.put(cacheKey, null); } } return null; } // 测试代码 public void test() { } class ParamsTypeValue { Class<?> type; Object value; fanli/src/main/java/com/yeshi/fanli/controller/TestController.java
@@ -56,6 +56,7 @@ import com.yeshi.fanli.util.FileUtil; import com.yeshi.fanli.util.RedisManager; import com.yeshi.fanli.util.StringUtil; import com.yeshi.fanli.util.TimeUtil; import com.yeshi.fanli.util.db.MongoDBManager; import com.yeshi.fanli.util.factory.goods.GoodsDetailVOFactory; import com.yeshi.fanli.util.jd.JDApiUtil; @@ -63,6 +64,8 @@ import net.sf.json.JSONArray; import net.sf.json.JSONObject; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; @Controller @RequestMapping("test") @@ -93,12 +96,15 @@ @Resource private ConfigService configService; @Resource private HongBaoManageService hongBaoManageService; @Resource private InviteMaterialService inviteMaterialService; @Resource private JedisPool jedisPool; @RequestMapping(value = "testimg") public void testImg(HttpServletRequest request, PrintWriter out) { @@ -423,9 +429,10 @@ e.printStackTrace(); } } /** * 插入邀请素材 * * @param out */ @RequestMapping(value = "getJingFenList") @@ -448,7 +455,7 @@ Gson gson = JsonUtil.getConvertBigDecimalToStringSubZeroBuilder(new GsonBuilder()) .excludeFieldsWithoutExposeAnnotation().setDateFormat("yyyy-MM-dd").create(); for (JDGoods goods : goodsList) { GoodsDetailVO goodsDetailVO = GoodsDetailVOFactory.convertJDGoods(goods, fanLiRate, shareRate); GoodsDetailVO goodsDetailVO = GoodsDetailVOFactory.convertJDGoods(goods, fanLiRate, shareRate); array.add(gson.toJson(goodsDetailVO)); } } @@ -462,4 +469,9 @@ e.printStackTrace(); } } @RequestMapping(value = "getWaitingThreadsCount") public void getWaitingThreadsCount(PrintWriter out) { out.print(Constant.waitingThreadSet.size()); } } fanli/src/main/java/com/yeshi/fanli/controller/client/v1/SMSController.java
@@ -31,18 +31,18 @@ @Resource private UserInfoService userInfoService; @Resource private ForbiddenUserIdentifyCodeService forbiddenUserIdentifyCodeService; // 发送短信 @RequestSerializableByKey(key = "#phone+'-'+#uid+'-'+#type") @RequestMapping(value = "sendSMS", method = RequestMethod.POST) public void sendMSM(AcceptData acceptData, String phone, Long uid, Integer type, PrintWriter out) { sendMSM(acceptData, phone, uid, type, StringUtil.Md5(phone + "-" + "-" + uid + "-" + type), out); } @RequestSerializableByKey(key = "key") public void sendMSM(AcceptData acceptData, String phone, Long uid, Integer type, String key, PrintWriter out) { try { if (phone.contains("**") && uid != null && uid > 0) { @@ -68,10 +68,10 @@ out.print(JsonUtil.loadFalseResult(e.getCode(), e.getMsg())); } } /** * 1.5.3 登录发送短信 * 1.5.3 登录发送短信 * * @param acceptData * @param phone * @param uid @@ -84,18 +84,19 @@ return; } phone = phone.replaceAll(" ", ""); sendMSNnew(phone,slideVerify, 1, StringUtil.Md5(phone + "-" + acceptData.getDevice()), out); sendMSNnew(phone, slideVerify, 1, StringUtil.Md5(phone + "-" + acceptData.getDevice()), out); } /** * 1.5.3 绑定发送短信 * * @param acceptData * @param phone * @param uid * @param out */ @RequestSerializableByKey(key = "#acceptData.device+'-'+#phone") @RequestMapping(value = "sendMSMBind", method = RequestMethod.POST) public void sendMSMBind(AcceptData acceptData, String phone, boolean slideVerify, PrintWriter out) { if (phone == null || !StringUtil.isMobile(phone.replaceAll(" ", ""))) { @@ -103,27 +104,28 @@ return; } phone = phone.replaceAll(" ", ""); // 判断手机号码是否被封禁 // ForbiddenUserIdentifyCode identifyCode1 = forbiddenUserIdentifyCodeService // .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.phone, phone); // if (identifyCode1 != null && identifyCode1.getEffective() != null && identifyCode1.getEffective()) { // out.print(JsonUtil.loadFalseResult(9001,"该电话号码被占用")); // return; // } // // ForbiddenUserIdentifyCode identifyCode1 = // forbiddenUserIdentifyCodeService // .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.phone, // phone); // if (identifyCode1 != null && identifyCode1.getEffective() != null && // identifyCode1.getEffective()) { // out.print(JsonUtil.loadFalseResult(9001,"该电话号码被占用")); // return; // } // // 判断手机号码是否被封禁 UserInfo phoneUser = userInfoService.getEffectiveUserInfoByPhone(phone); if (phoneUser != null) { out.print(JsonUtil.loadFalseResult(9001,"该电话号码被占用")); out.print(JsonUtil.loadFalseResult(9001, "该电话号码被占用")); return; } sendMSNnew(phone,slideVerify, 2, StringUtil.Md5(phone + "-" + acceptData.getDevice()), out); sendMSNnew(phone, slideVerify, 2, StringUtil.Md5(phone + "-" + acceptData.getDevice()), out); } @RequestSerializableByKey(key = "key") public void sendMSNnew(String phone, boolean slideVerify, int type, String key, PrintWriter out) { try { int count = 0; @@ -135,31 +137,30 @@ // 绑定验证码 cachekey = "sendMSNBindCount" + phone; } if (cachekey == null) { out.print(JsonUtil.loadFalseResult(1,"发送失败")); out.print(JsonUtil.loadFalseResult(1, "发送失败")); return; } String cacheValue = redisManager.getCommonString(cachekey); if (!StringUtil.isNullOrEmpty(cacheValue)) { count = Integer.parseInt(cacheValue); // 限制3次 if (count >= 3) { out.print(JsonUtil.loadFalseResult(3,"验证码次数超限,请稍后再试")); out.print(JsonUtil.loadFalseResult(3, "验证码次数超限,请稍后再试")); return; } } if (count == 2 && !slideVerify) { out.print(JsonUtil.loadFalseResult(2,"需要滑动验证")); out.print(JsonUtil.loadFalseResult(2, "需要滑动验证")); return; } } // 缓存一个小时 count ++; count++; redisManager.cacheCommonString(cachekey, count + "", 60 * 60); if (type == 1) { // 登录验证码 smsService.sendLoginVCode(phone, 4); @@ -167,9 +168,9 @@ // 绑定验证码 smsService.sendBindVCode(phone, 4); } out.print(JsonUtil.loadTrueResult("发送成功")); } catch (SMSException e) { out.print(JsonUtil.loadFalseResult(e.getCode(), e.getMsg())); } catch (Exception e) { fanli/src/main/java/com/yeshi/fanli/controller/client/v1/UserInfoController.java
@@ -1077,7 +1077,7 @@ * @param type * @param out */ @RequestSerializableByKey(key = "uid") @RequestSerializableByKey(key = "#uid") @RequestMapping(value = "extractmoneynew", method = RequestMethod.POST) public void extractMoneyNew(AcceptData acceptData, long uid, BigDecimal money, String vcode, HttpServletRequest request, int type, PrintWriter out) { fanli/src/main/java/com/yeshi/fanli/controller/client/v1/UserMsgController.java
@@ -79,6 +79,7 @@ import com.yeshi.fanli.util.TimeUtil; import com.yeshi.fanli.util.VersionUtil; import com.yeshi.fanli.util.account.UserUtil; import com.yeshi.fanli.util.annotation.RequestSerializableByKey; import com.yeshi.fanli.util.factory.CommonGoodsFactory; import com.yeshi.fanli.util.factory.msg.UserMsgVOFactory; import com.yeshi.fanli.util.taobao.TaoKeApiUtil; @@ -635,6 +636,7 @@ * @param type * @param out */ @RequestSerializableByKey(key="#acceptData.device") @RequestMapping(value = "getHomeMsgListNew", method = RequestMethod.POST) public void getHomeMsgListNew(AcceptData acceptData, Long uid, PrintWriter out) { if (uid != null && uid == 0) fanli/src/main/java/com/yeshi/fanli/service/impl/monitor/BusinessEmergent110ServiceImpl.java
@@ -17,7 +17,7 @@ @Service public class BusinessEmergent110ServiceImpl implements BusinessEmergent110Service { String[] phones = new String[] { "18581318252", "15025351808", "18696787365" }; String[] phones = new String[] { "18581318252", "15025351808" }; private static Map<String, List<String>> map = new HashMap<>(); private static long shareTime = 0L; fanli/src/main/java/com/yeshi/fanli/util/Constant.java
@@ -1,6 +1,10 @@ package com.yeshi.fanli.util; import java.util.HashSet; import java.util.Properties; import java.util.Set; import org.yeshi.utils.annotation.MapUtil; import com.yeshi.fanli.entity.config.AlipayConfig; import com.yeshi.fanli.entity.config.ConstantConfig; @@ -9,7 +13,6 @@ import com.yeshi.fanli.entity.config.WXGZConfig; import com.yeshi.fanli.entity.config.ZNXConfig; import com.yeshi.fanli.util.taobao.TaoBaoUtil; import org.yeshi.utils.annotation.MapUtil; public class Constant { public static boolean IS_TASK = false; @@ -161,12 +164,12 @@ public static final String WEBPAGE_SIGN_KEY = "@?,223Hbb88lll"; // public static final String TAOKE_ANDROID_APPKEY = "24587154"; // public static final String TAOKE_IOS_APPKEY = "24838852"; // 新人抽奖-最大次数 public static final int MAX_COUNT_LOTTERY_NEWBIES = 5; // 线程等待数量 public static Set<Long> waitingThreadSet = new HashSet<>(); static { if (smsConfig == null) {