游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

SpringCloud(三十九)使用分布式锁实现微服务重复请

  通常我们可以在前端通过防抖和节流来解决短时间内请求重复提交的问题,如果因网络问题、Nginx重试机制、微服务Feign重试机制或者用户故意绕过前端防抖和节流设置,直接频繁发起请求,都会导致系统防重请求失败,甚至导致后台产生多条重复记录,此时我们需要考虑在后台增加防重设置。
  考虑到微服务分布式的场景,这里通过使用Redisson分布式锁自定义注解AOP的方式来实现后台防止重复请求的功能,基本实现思路:通过在需要防重的接口添加自定义防重注解,设置防重参数,通过AOP拦截请求参数,根据注解配置,生成分布式锁的Key,并设置有效时间。每次请求访问时,都会尝试获取锁,如果获取到,则执行,如果获取不到,那么说明请求在设置的重复请求间隔内,返回请勿频繁请求提示信息。1、自定义防止重复请求注解,根据业务场景设置了以下参数:interval:防止重复提交的时间间隔。timeUnit:防止重复提交的时间间隔的单位。currentSession:是否将sessionId作为防重参数(微服务及跨域前后端分离时,无法使用,Chrome等浏览器跨域时禁止携带cookie,每次sessionId都是新的)。currentUser:是否将用户id作为防重参数。keys:可以作为防重参数的字段(通过SpringExpression表达式,可以做到多参数时,具体取哪个参数的值)。ignoreKeys:需要忽略的防重参数字段,例如有些参数中的时间戳,此和keys互斥,当keys配置了之后,ignoreKeys失效。conditions:当参数中的某个字段达到条件时,执行防重配置,默认不需要配置。argsIndex:当没有配置keys参数时,防重拦截后会对所有参数取值作为分布式锁的key,这里时,当多参数时,配置取哪一个参数作为key,可以多个。此和keys互斥,当keys配置了之后,argsIndex配置失效。packagecom。gitegg。platform。base。annotation。resubmit;importjava。lang。annotation。;importjava。util。concurrent。TimeUnit;防止重复提交注解1、当设置了keys时,通过表达式确定取哪几个参数作为防重key2、当未设置keys时,可以设置argsIndex设置取哪几个参数作为防重key3、argsIndex和ignoreKeys是未设置keys时生效,排除不需要防重的参数4、因部分浏览器在跨域请求时,不允许request请求携带cookie,导致每次sessionId都是新的,所以这里默认使用用户id作为key的一部分,不使用sessionIdauthorGitEggTarget(ElementType。METHOD)Retention(RetentionPolicy。RUNTIME)DocumentedpublicinterfaceResubmitLock{防重复提交校验的时间间隔longinterval()default5;防重复提交校验的时间间隔的单位TimeUnittimeUnit()defaultTimeUnit。SECONDS;是否仅在当前session内进行防重复提交校验booleancurrentSession()defaultfalse;是否选用当前操作用户的信息作为防重复提交校验key的一部分booleancurrentUser()defaulttrue;keys和ignoreKeys不能同时使用参数SpringEL表达式例如{param。name},表达式的值作为防重复校验key的一部分String〔〕keys()default{};keys和ignoreKeys不能同时使用ignoreKeys不区分入参,所有入参拥有相同的字段时,都将过滤掉String〔〕ignoreKeys()default{};SpringEL表达式,决定是否进行重复提交校验,多个条件之间为且的关系,默认是进行校验String〔〕conditions()default{true};当未配置key时,设置哪几个参数作为防重对象,默认取所有参数returnint〔〕argsIndex()default{};}2、自定义AOP拦截防重请求的业务逻辑处理,详细逻辑处理请看代码注释。可以在Nacos中增加配置resubmitlock:enable:false使防重配置失效,默认不配置为生效状态。因为是ResubmitLockAspect是否初始化的ConditionalOnProperty配置,此配置修改需要重启服务生效。packagecom。gitegg。platform。boot。aspect;importcom。gitegg。platform。base。annotation。resubmit。ResubmitLock;importcom。gitegg。platform。base。enums。ResultCodeEnum;importcom。gitegg。platform。base。exception。SystemException;importcom。gitegg。platform。base。util。JsonUtils;importcom。gitegg。platform。boot。util。ExpressionUtils;importcom。gitegg。platform。boot。util。GitEggAuthUtils;importcom。gitegg。platform。boot。util。GitEggWebUtils;importcom。gitegg。platform。redis。lock。IDistributedLockService;importcom。google。common。collect。Maps;importlombok。RequiredArgsConstructor;importlombok。extern。log4j。Log4j2;importorg。apache。commons。lang3。ArrayUtils;importorg。aspectj。lang。JoinPoint;importorg。aspectj。lang。ProceedingJoinPoint;importorg。aspectj。lang。annotation。Aspect;importorg。aspectj。lang。annotation。Before;importorg。aspectj。lang。annotation。Pointcut;importorg。springframework。beans。factory。annotation。Autowired;importorg。springframework。boot。autoconfigure。condition。ConditionalOnProperty;importorg。springframework。lang。NonNull;importorg。springframework。stereotype。Component;importorg。springframework。util。DigestUtils;importjava。lang。reflect。Field;importjava。util。Arrays;importjava。util。Comparator;importjava。util。Map;importjava。util。TreeMap;authorGitEggdate2022410Log4j2ComponentAspectRequiredArgsConstructor(onConstructorAutowired)ConditionalOnProperty(nameenabled,prefixresubmitlock,havingValuetrue,matchIfMissingtrue)publicclassResubmitLockAspect{privatestaticfinalStringREDISSEPARATOR:;privatestaticfinalStringRESUBMITCHECKKEYPREFIXresubmitlockREDISSEPARATOR;privatefinalIDistributedLockServicedistributedLockService;Before切点Pointcut(annotation(com。gitegg。platform。base。annotation。resubmit。ResubmitLock))publicvoidresubmitLock(){}前置通知防止重复提交paramjoinPoint切点paramresubmitLock注解配置Before(annotation(resubmitLock))publicObjectresubmitCheck(JoinPointjoinPoint,ResubmitLockresubmitLock)throwsThrowable{finalObject〔〕argsjoinPoint。getArgs();finalString〔〕conditionsresubmitLock。conditions();根据条件判断是否需要进行防重复提交检查if(!ExpressionUtils。getConditionValue(args,conditions)ArrayUtils。isEmpty(args)){return((ProceedingJoinPoint)joinPoint)。proceed();}doCheck(resubmitLock,args);return((ProceedingJoinPoint)joinPoint)。proceed();}key的组成为:resubmitlock:userId:sessionId:uri:method:(根据springEL表达式对参数进行拼接)paramresubmitLock注解paramargs方法入参privatevoiddoCheck(NonNullResubmitLockresubmitLock,Object〔〕args){finalString〔〕keysresubmitLock。keys();finalbooleancurrentUserresubmitLock。currentUser();finalbooleancurrentSessionresubmitLock。currentSession();StringmethodGitEggWebUtils。getRequest()。getMethod();StringuriGitEggWebUtils。getRequest()。getRequestURI();StringBufferlockKeyBuffernewStringBuffer(RESUBMITCHECKKEYPREFIX);if(null!GitEggAuthUtils。getTenantId()){lockKeyBuffer。append(GitEggAuthUtils。getTenantId())。append(REDISSEPARATOR);}此判断暂时预留,适配后续无用户登录场景,因部分浏览器在跨域请求时,不允许request请求携带cookie,导致每次sessionId都是新的,所以这里默认使用用户id作为key的一部分,不使用sessionIdif(currentSession){lockKeyBuffer。append(GitEggWebUtils。getSessionId())。append(REDISSEPARATOR);}默认没有将user数据作为防重keyif(currentUsernull!GitEggAuthUtils。getCurrentUser()){lockKeyBuffer。append(GitEggAuthUtils。getCurrentUser()。getId())。append(REDISSEPARATOR);}lockKeyBuffer。append(uri)。append(REDISSEPARATOR)。append(method);StringBufferparametersBuffernewStringBuffer();优先判断是否设置防重字段,因keys试数组,取值时是按照顺序排列的,这里不需要重新排序if(ArrayUtils。isNotEmpty(keys)){Object〔〕argsForKeyExpressionUtils。getExpressionValue(args,keys);for(Objectobj:argsForKey){parametersBuffer。append(REDISSEPARATOR)。append(String。valueOf(obj));}}如果没有设置防重的字段,那么需要把所有的字段和值作为key,因通过反射获取字段时,顺序时不确定的,这里取出来之后需要进行排序else{只有当keys为空时,ignoreKeys和argsIndex生效finalString〔〕ignoreKeysresubmitLock。ignoreKeys();finalint〔〕argsIndexresubmitLock。argsIndex();if(ArrayUtils。isNotEmpty(argsIndex)){for(intindex:argsIndex){parametersBuffer。append(REDISSEPARATOR)。append(getKeyAndValueJsonStr(args〔index〕,ignoreKeys));}}else{for(Objectobj:args){parametersBuffer。append(REDISSEPARATOR)。append(getKeyAndValueJsonStr(obj,ignoreKeys));}}}将请求参数取md5值作为key的一部分,MD5理论上会重复,但是key中还包含session或者用户id,所以同用户在极端时间内请参数不同生成的相同md5值的概率极低StringparametersKeyDigestUtils。md5DigestAsHex(parametersBuffer。toString()。getBytes());lockKeyBuffer。append(parametersKey);try{booleanisLockdistributedLockService。tryLock(lockKeyBuffer。toString(),0,resubmitLock。interval(),resubmitLock。timeUnit());if(!isLock){thrownewSystemException(ResultCodeEnum。RESUBMITLOCK。code,ResultCodeEnum。RESUBMITLOCK。msg);}}catch(InterruptedExceptione){thrownewSystemException(ResultCodeEnum。RESUBMITLOCK。code,ResultCodeEnum。RESUBMITLOCK。msg);}}将字段转换为json字符串paramobjreturnpublicstaticStringgetKeyAndValueJsonStr(Objectobj,String〔〕ignoreKeys){MapString,ObjectmapMaps。newHashMap();得到类对象ClassobjCla(Class)obj。getClass();得到类中的所有属性集合Field〔〕fsobjCla。getDeclaredFields();for(inti0;ifs。length;i){Fieldffs〔i〕;设置些属性是可以访问的f。setAccessible(true);ObjectvalnewObject();try{StringfiledNamef。getName();如果字段在排除列表,那么不将字段放入mapif(null!ignoreKeysArrays。asList(ignoreKeys)。contains(filedName)){continue;}valf。get(obj);得到此属性的值设置键值map。put(filedName,val);}catch(IllegalArgumentExceptione){log。error(getKeyAndValueIllegalArgumentException,e);thrownewRuntimeException(您的操作太频繁,请稍后再试);}catch(IllegalAccessExceptione){log。error(getKeyAndValueIllegalAccessException,e);thrownewRuntimeException(您的操作太频繁,请稍后再试);}}MapString,ObjectsortMapsortMapByKey(map);StringmapStrJsonUtils。mapToJson(sortMap);returnmapStr;}privatestaticMapString,ObjectsortMapByKey(MapString,Objectmap){if(mapnullmap。isEmpty()){returnnull;}MapString,ObjectsortMapnewTreeMapString,Object(newComparatorString(){Overridepublicintcompare(Stringo1,Stringo2){return((String)o1)。compareTo((String)o2);}});sortMap。putAll(map);returnsortMap;}}3、Redisson分布式锁自定义接口packagecom。gitegg。platform。redis。lock;importjava。util。concurrent。TimeUnit;分布式锁接口authorGitEggdate2022410publicinterfaceIDistributedLockService{加锁paramlockKeykeyvoidlock(StringlockKey);释放锁paramlockKeykeyvoidunlock(StringlockKey);加锁并设置有效期paramlockKeykeyparamtimeout有效时间,默认时间单位在实现类传入voidlock(StringlockKey,inttimeout);加锁并设置有效期指定时间单位paramlockKeykeyparamtimeout有效时间paramunit时间单位voidlock(StringlockKey,inttimeout,TimeUnitunit);尝试获取锁,获取到则持有该锁返回true,未获取到立即返回falseparamlockKeyreturntrue获取锁成功false获取锁失败booleantryLock(StringlockKey);尝试获取锁,获取到则持有该锁leaseTime时间。若未获取到,在waitTime时间内一直尝试获取,超过watiTime还未获取到则返回falseparamlockKeykeyparamwaitTime尝试获取时间paramleaseTime锁持有时间paramunit时间单位returntrue获取锁成功false获取锁失败throwsInterruptedExceptionbooleantryLock(StringlockKey,longwaitTime,longleaseTime,TimeUnitunit)throwsInterruptedException;锁是否被任意一个线程锁持有paramlockKeyreturntrue被锁false未被锁booleanisLocked(StringlockKey);}4、Redisson分布式锁自定义接口实现类packagecom。gitegg。platform。redis。lock。impl;importcom。gitegg。platform。redis。lock。IDistributedLockService;importlombok。RequiredArgsConstructor;importorg。redisson。api。RLock;importorg。redisson。api。RedissonClient;importorg。springframework。beans。factory。annotation。Autowired;importorg。springframework。stereotype。Service;importjava。util。concurrent。TimeUnit;分布式锁的Redisson接口实现authorGitEggdate2022410ServiceRequiredArgsConstructor(onConstructorAutowired)publicclassDistributedLockServiceImplimplementsIDistributedLockService{privatefinalRedissonClientredissonClient;Overridepublicvoidlock(StringlockKey){RLocklockredissonClient。getLock(lockKey);lock。lock();}Overridepublicvoidunlock(StringlockKey){RLocklockredissonClient。getLock(lockKey);lock。unlock();}Overridepublicvoidlock(StringlockKey,inttimeout){RLocklockredissonClient。getLock(lockKey);lock。lock(timeout,TimeUnit。MILLISECONDS);}Overridepublicvoidlock(StringlockKey,inttimeout,TimeUnitunit){RLocklockredissonClient。getLock(lockKey);lock。lock(timeout,unit);}OverridepublicbooleantryLock(StringlockKey){RLocklockredissonClient。getLock(lockKey);returnlock。tryLock();}OverridepublicbooleantryLock(StringlockKey,longwaitTime,longleaseTime,TimeUnitunit)throwsInterruptedException{RLocklockredissonClient。getLock(lockKey);returnlock。tryLock(waitTime,leaseTime,unit);}OverridepublicbooleanisLocked(StringlockKey){RLocklockredissonClient。getLock(lockKey);returnlock。isLocked();}}5、SpringExpression自定义工具类,通过此工具类获取注解上的Expression表达式,以获取相应请求对象的值,如果请求对象有多个,可以通过Expression表达式精准获取。packagecom。gitegg。platform。boot。util;importorg。apache。commons。lang3。ArrayUtils;importorg。apache。commons。lang3。StringUtils;importorg。springframework。expression。Expression;importorg。springframework。expression。spel。standard。SpelExpressionParser;importorg。springframework。lang。NonNull;importorg。springframework。lang。Nullable;importjava。util。Map;importjava。util。concurrent。ConcurrentHashMap;SpringExpression工具类authorGitEggdate2022411publicclassExpressionUtils{privatestaticfinalMapString,ExpressionEXPRESSIONCACHEnewConcurrentHashMap(64);获取Expression对象paramexpressionStringSpringEL表达式字符串例如{param。id}returnExpressionNullablepublicstaticExpressiongetExpression(NullableStringexpressionString){if(StringUtils。isBlank(expressionString)){returnnull;}if(EXPRESSIONCACHE。containsKey(expressionString)){returnEXPRESSIONCACHE。get(expressionString);}ExpressionexpressionnewSpelExpressionParser()。parseExpression(expressionString);EXPRESSIONCACHE。put(expressionString,expression);returnexpression;}根据SpringEL表达式字符串从根对象中求值paramroot根对象paramexpressionStringSpringEL表达式paramclazz值得类型paramT泛型return值NullablepublicstaticTTgetExpressionValue(NullableObjectroot,NullableStringexpressionString,NonNullClasslt;?extendsTclazz){if(rootnull){returnnull;}ExpressionexpressiongetExpression(expressionString);if(expressionnull){returnnull;}returnexpression。getValue(root,clazz);}NullablepublicstaticTTgetExpressionValue(NullableObjectroot,NullableStringexpressionString){if(rootnull){returnnull;}ExpressionexpressiongetExpression(expressionString);if(expressionnull){returnnull;}noinspectionuncheckedreturn(T)expression。getValue(root);}求值paramroot根对象paramexpressionStringsSpringEL表达式paramT泛型这里的泛型要慎用,大多数情况下要使用Object接收避免出现转换异常return结果集publicstaticTT〔〕getExpressionValue(NullableObjectroot,NullableString。。。expressionStrings){if(rootnull){returnnull;}if(ArrayUtils。isEmpty(expressionStrings)){returnnull;}noinspectionConstantConditionsObject〔〕valuesnewObject〔expressionStrings。length〕;for(inti0;iexpressionStrings。length;i){noinspectionuncheckedvalues〔i〕(T)getExpressionValue(root,expressionStrings〔i〕);}noinspectionuncheckedreturn(T〔〕)values;}表达式条件求值如果为值为null则返回false,如果为布尔类型直接返回,如果为数字类型则判断是否大于0paramroot根对象paramexpressionStringSpringEL表达式return值NullablepublicstaticbooleangetConditionValue(NullableObjectroot,NullableStringexpressionString){ObjectvaluegetExpressionValue(root,expressionString);if(valuenull){returnfalse;}if(valueinstanceofBoolean){return(boolean)value;}if(valueinstanceofNumber){return((Number)value)。longValue()0;}returntrue;}表达式条件求值paramroot根对象paramexpressionStringsSpringEL表达式数组return值NullablepublicstaticbooleangetConditionValue(NullableObjectroot,NullableString。。。expressionStrings){if(rootnull){returnfalse;}if(ArrayUtils。isEmpty(expressionStrings)){returnfalse;}noinspectionConstantConditionsfor(StringexpressionString:expressionStrings){if(!getConditionValue(root,expressionString)){returnfalse;}}returntrue;}}5、防重测试,我们在系统的用户接口(GitEggCloud工程的UserController类)上进行测试,通过多参数接口以及配置keys,不配置keys等各种场景进行测试,在测试时为了达到效果,可以将interval时间设置为30秒。设置user参数的realName,mobile和page参数的size为key进行防重测试ResubmitLock(interval30,keys{〔0〕。realName,〔0〕。mobile,〔1〕。size})publicPageResultUserInfolist(ApiIgnoreQueryUserDTOuser,ApiIgnorePageUserInfopage){PageUserInfopageUseruserService。selectUserList(page,user);PageResultUserInfopageResultnewPageResult(pageUser。getTotal(),pageUser。getRecords());returnpageResult;}不设置防重参数的key,只取第一个参数user,配置排除的参数,不参与放重key的生成ResubmitLock(interval30,argsIndex{0},ignoreKeys{email,status})publicPageResultUserInfolist(ApiIgnoreQueryUserDTOuser,ApiIgnorePageUserInfopage){PageUserInfopageUseruserService。selectUserList(page,user);PageResultUserInfopageResultnewPageResult(pageUser。getTotal(),pageUser。getRecords());returnpageResult;}测试结果
  相关引用:
  1、防重配置项及通过SpringExpression获取相应参数:https:www。jianshu。comp77895a822237
  2、Redisson分布式锁及相关工具类:https:blog。csdn。netwshningjingarticledetails115326052源码地址:
  GitEgg:GitEgg是一款开源免费的企业级微服务应用开发框架,旨在整合目前主流稳定的开源技术框架,集成常用的最佳项目解决方案,实现可直接使用的微服务快速开发框架。
  GitHubwmz1930GitEgg:GitEgg是一款开源免费的企业级微服务应用开发框架,旨在整合目前主流稳定的开源技术框架,集成常用的最佳项目解决方案,实现可直接使用的微服务快速开发框架。

肝肾不足容易身体早衰!简单两味中药,阴阳双补强筋骨肝肾不足,容易身体早衰!简单两味中药,阴阳双补,强筋骨增气力!肝肾不足容易身体早衰,简单两味中药,阴阳双补强筋骨增气力!大家好我是李医生。现在有很多人,年纪看起来没有那么……冬季养好肺,来年少受罪!谨记2条关键路,肺部炎症不来扰山西省中医院肺病科关炜随着冬季来临,气温降低,肺炎支原体肺炎患者数量较以前增多。肺炎支原体感染全年散发,不同地区的流行季节有差异,我国北方地区秋冬季多见,南方地区则是夏秋……什么会导致反复腹泻?这5种情况要警惕在我们的日常生活中,有的人总是容易莫名其妙的反复拉肚子,那么什么会导致反复拉肚子呢?下面我们一起了解一下。1、脾胃虚弱脾胃虚弱是反复腹泻的常见原因,比如体质弱或者长……102136,首个12连败出炉!二节半就宣告输球,新秀核心仅11月16日上午,NBA继续进行,火箭对阵西部弱旅灰熊,但是因为本身已经沦落为鱼腩,此番比赛想要赢球的难度依旧巨大。上半场,火箭劣势明显,分差逐渐被拉大!小波特发挥太糟糕了,第……冬三九,我们要多吃这几样美食,温暖身心!今天是冬三九的第一天,俗话说三九、四九冰上走,到了三九天冷空气就开始发力了,这个时候一定要注意防寒保暖了,除了做好保暖的工作,在这数九寒天里还要多吃升阳的食物,从而更好的帮助身……养肾就是养命根,这里告诉你关于养肾的最全知识,建议收藏中国人对肾肯定有着别样的情怀,特别是男人,肾就是证明自己的能力名片,其实肾对女人也一样重要。肾是人体动力的源泉,男人补肾,女人也要养肾西医认为肾只是一个器官,它的基……海洋气溶胶对云凝结核的贡献研究取得进展海洋气溶胶是全球气候模式的重要组成部分,也是制约气候模型预测准确性的主要不确定性来源之一。海洋气溶胶由一次气溶胶和二次气溶胶组成,其中海洋一次气溶胶是在海气界面通过气泡破碎飞溅……滩钓应该属于最最最安全的海钓了海钓很刺激,也有很大的风险,装备也多,唯独沙滩这种很多人觉得没搞头的地方偏偏出好东西。沙尖鱼,换米鱼,黄脚鱼也叫黄墙,沙毛,白花鱼,等,都是一等一的味美,几乎每个季节都有,夏季……当代网友文采能有多绝有人在夜市或小吃摊的烟火气中长歌秋酒,也有人眼波洗转迎面撞进夏甘晚风。将生活嚼得有滋有味,把日子过得活色生香,往往靠的不只是嘴巴,还要有一颗不食人间烟火的心。烟花飞……吃榆钱的季节来了,不知道怎么吃,加点面粉一锅不够吃榆钱是我们山东人的美食,榆钱是纯天然食品,不打农药,不施化肥,提起榆钱窝窝,真是直咽口水,榆钱窝窝太好吃了,但是有好多朋友们爱吃又不会做,下边我就把做榆钱窝窝的方法分享给朋友们……球员锦标赛四强诞生3席,奥沙利文再输罗伯逊,颜丙涛惜败霍金斯北京时间2月11日,斯诺克球员锦标赛第14决赛继续进行,在已经结束的三场比赛中,马克威廉姆斯56爆冷遭里奇沃顿逆转,颜丙涛56惜败霍金斯,罗伯逊63淘汰奥沙利文,目前四强已经产……分享2021年我买的那些小米产品年关将近,大家应该也在盘算着自己这一年的收获吧。给大家分享一下我今年购买的小米产品吧(建议点击原图哦)红米RedmiK40一句话点评:k40在他这个价位做到了他所有……
NBA各个位置上谁挣得最多?福布斯公布的2021年度全球运动员收入排行榜上,前15名里有4名NBA球星,那么就目前来看,NBA各个位置上谁的年薪最高呢?控球后卫:斯蒂芬库里最强替补库里2……AMDR73800XT参数曝光300MHz提升,即将推出IT之家6月4日消息AMD即将推出的R73800XT参数已经流出,比去年发布的R73800X提高了300MHz,预计将于6月中旬与B550主板一同发布。根据爆料者roga……身体护理快看我的身体护理小心机凛冬将至每一寸的皮肤都在向干燥抗议手部、唇部、身体三部曲赶走鸡皮肤、干燥起皮、松弛紧绷皮肤滑嫩紧致全身发光水润舒适滑进冬日手是女人的第二张脸……吴兴涵小金子伤缺陈蒲时灵时不灵!刘彬彬状态平平刘厂长PK韦世现在来看,只有主帅郑智亲自登场,或许才能带领球队走出困境。《新快报》记者高京陈蒲租借至河南嵩山龙门期间,得到河南球迷的认可。在多拉多、卡兰加霸占锋线的情况下,陈蒲上赛季为……女人过了55岁,尽量远离这4种显老发型!其实这些更时尚洋气50岁对于女性来说算是一个分水岭,50岁之后大多已经成了奶奶姥姥辈儿的人,不用特别强调仅仅是身份的转变就可以改变她们的气质,服老俨然已经成为了常态。但是55岁真的并不老,……人民日报丨中国朋友的拼搏干劲让我们深受感动近年来,中国建筑坚定不移、全力以赴参与共建一带一路,实施企业大海外战略,建设企业大海外平台,在多个沿线国家探索建立合作对接机制,倾力建设重大基础设施,倾情谋划实施民生工程,打造……女孩取名玉柔花醉,美入心田的好听名字这个时代,大家倾向于让自己感到舒服的东西,就如好听的物品,好听的歌曲让人放松,好听的说话声让人心情愉快,好听的名字,则会给人一种美好的联想,让人产生美感愿意与之交往。所以子墨老……这两个网友惨了,被杨颖诉侵权要求赔礼道歉并赔款3万今天看到这则消息,很庆幸自己上周做了正确的决定,觉得自己删掉那篇关于董卿的文章的决定是对的。当天的微条记录虽然删掉之前那篇文章的展现量在发布之后的2小时内上升到了4……英伟达黄仁勋10月5日发表GTC2020主题演讲,或推新款TIT之家8月18日消息英伟达今天宣布,将于10月5日至9日举办GPU技术大会,首席执行官兼创始人黄仁勋将发表主题演讲。IT之家曾报道,早在5月份,黄仁勋就在线上发布了第一……13999元起,微星强袭2GE66笔记本开售RTX20701IT之家8月12日消息微星强袭2GE6615。6英寸笔记本电脑现已正式开售,采用240Hz电竞屏,十代i71TBSSDRTX2070版本售价13999元。IT之家了解到,……你什么都舍不得扔,还谈什么生活质量人在年轻的时候,总是习惯给生活做加法:见到喜欢的东西,不考虑需不需要,只管买买买;步入社会之后,人际关系越来越复杂,经历得多了,总有一些心事,堆积在心头。起初……苹果12英寸ARMMacBook配置曝光搭载A14X芯片,最IT之家8月2日消息外媒Wccftech报道,此前众多消息称,苹果MacBook12机型将采用定制ARM芯片推出,并且优先搭载A14XBionic。另外,这款A14X也会出现在……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网