当前位置: 首页 > news >正文

网站建设服务标准化成人营销管理培训班

网站建设服务标准化,成人营销管理培训班,全屋定制设计培训学校,大连有几家做网站的公司思路:通过AOP拦截注解标记的方法,在Redis中维护一个计数器来记录接口访问的频率, 并根据限流策略来判断是否允许继续处理请求。 另一篇:springboot 自定义注解 ,aop切面Around; 为接口实现日志插入【强行喂…

思路:通过AOP拦截注解标记的方法,在Redis中维护一个计数器来记录接口访问的频率,
并根据限流策略来判断是否允许继续处理请求。

另一篇:springboot 自定义注解 ,aop切面@Around; 为接口实现日志插入【强行喂饭版】

不多说,直接上代码:

一:创建限流类型

/*** 限流类型* */public enum LimitType
{/*** 默认策略全局限流*/DEFAULT,/*** 根据请求者IP进行限流*/IP
}


二:创建注解

import 你上面限流类型的路径.LimitType;import java.lang.annotation.*;/*** 限流注解* */
// 注解的作用目标为方法
@Target(ElementType.METHOD) // 注解在运行时保留,编译后的class文件中存在,在jvm运行时保留,可以被反射调用
@Retention(RetentionPolicy.RUNTIME) // 指明修饰的注解,可以被例如javadoc此类的工具文档化,只负责标记,没有成员取值
@Documented 
public @interface LimiterToShareApi{/*** 限流key*/public String key() default "";/*** 限流时间,单位秒*/public int time() default 60;/*** 限流次数*/public int count() default 100;/*** 限流类型,默认全局限流*/public LimitType limitType() default LimitType.DEFAULT;
}


**三:编写业务异常类 **

/*** 业务异常* */
public final class ServiceException extends RuntimeException
{// 序列化的版本号的属性private static final long serialVersionUID = 1L;/*** 错误码*/private Integer code;/*** 错误提示*/private String message;/*** 空构造方法,避免反序列化问题*/public ServiceException(){}/*** 异常信息*/public ServiceException(String message){this.message = message;}}


四:实现aop切面拦截,限流逻辑处理

import 你上面限流类型的路径.LimitType;
import 你上面业务异常的路径.ServiceException;
import 你上面限流注解的路径.LimiterToShareApi;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;// 声明这是一个切面类
@Aspect
// 表明该类是一个组件,将该类交给spring管理。
@Component
// 指定执行顺序,值越小,越先执行。限流策略一般最先执行。
@Order(1) 
public class LimiterToShareApiAspect {// 记录日志的Logger对象private static final Logger log = LoggerFactory.getLogger(LimiterToShareApiAspect.class);// 操作Redis的RedisTemplate对象private RedisTemplate<Object, Object> redisTemplate;//在Redis中执行Lua脚本的对象private RedisScript<Long> limitScript;@Autowiredpublic void setRedisTemplate1(RedisTemplate<Object, Object> redisTemplate) {this.redisTemplate = redisTemplate;}@Autowiredpublic void setLimitScript(RedisScript<Long> limitScript) {this.limitScript = limitScript;}// 这个注解作用及普及 见文章后面解析@Before("@annotation(limiter)")public void doBefore(JoinPoint point, LimiterToShareApi limiter) throws Throwable {// 根据业务需求,看看是否去数据库查询对应的限流策略,还是直接使用注解传递的值// 这里演示为 获取注解的值int time = limiter.time();int count = limiter.count();String combineKey = getCombineKey(limiter, point);List<Object> keys = Collections.singletonList(combineKey);try {Long number = redisTemplate.execute(limitScript, keys, count, time);if (number == null || number.intValue() > count) {throw new ServiceException("限流策略:访问过于频繁,请稍候再试");}log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), combineKey);} catch (ServiceException e) {throw e;} catch (Exception e) {throw new RuntimeException("服务器限流异常,请稍候再试");}}/*** 获取用于限流的组合键,根据LimterToShareApi注解和JoinPoint对象来生成。** @param rateLimiter LimiterToShareApi注解,用于获取限流配置信息。* @param point       JoinPoint对象,用于获取目标方法的信息。* @return 生成的用于限流的组合键字符串。*/public String getCombineKey(LimiterToShareApi rateLimiter, JoinPoint point) {// 创建一个StringBuffer用于拼接组合键StringBuffer stringBuffer = new StringBuffer(rateLimiter.key() + "-");// 根据LimterToShareApi注解的limitType判断是否需要添加IP地址信息到组合键中【判断限流类型 是否根据ip进行限流】if (rateLimiter.limitType() == LimitType.IP) {// 如果需要添加IP地址信息,调用IpUtils.getIpAddr()方法获取当前请求的IP地址,并添加到组合键中stringBuffer.append(getClientIp()).append("-");}// 使用JoinPoint对象获取目标方法的信息MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();Class<?> targetClass = method.getDeclaringClass();// 将目标方法所属类的名称和方法名称添加到组合键中stringBuffer.append(targetClass.getName()).append("-").append(method.getName());// 返回生成的用于限流的组合键字符串return stringBuffer.toString();}/*** 获取调用方真实ip [本机调用则得到127.0.0.1]* 首先尝试从X-Forwarded-For请求头获取IP地址,如果没有找到或者为unknown,则尝试从X-Real-IP请求头获取IP地址,* 最后再使用request.getRemoteAddr()方法作为备用方案。注意,在多个代理服务器的情况下,* X-Forwarded-For请求头可能包含多个IP地址,我们取第一个IP地址作为真实客户端的IP地址。*/public String getClientIp() {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();String ipAddress = request.getHeader("X-Forwarded-For");if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("X-Real-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getRemoteAddr();}// 多个代理服务器时,取第一个IP地址int index = ipAddress.indexOf(",");if (index != -1) {ipAddress = ipAddress.substring(0, index);}return ipAddress;}}

五:哪里需要点哪里

@PostMapping("/接口api")
// 根据自己业务选择是否需要这些参数,如果是想从数据库读取,不填参数即可
// 这里意思为对key的限制为 全局 每60秒内2次请求,超过2次则限流
@LimiterToShareApi(key = "key",time = 60,count = 100,limitType = LimitType.DEFAULT)
public AjaxResult selectToUserId(参数){}


限流(代码)结果:
在这里插入图片描述在这里插入图片描述在这里插入图片描述


解析:

@Before("@annotation(limiter)")- 使用了@Before 来表示这是一个切面注解,用于定义在目标方法执行前执行的逻辑- @annotation(limiter) 中的limiter是指参数名称,而不是注解名称。- @annotation(limiter) 中的limiter参数类型为LimiterToShareApi,
表示你将拦截被@LimiterToShareApi注解标记的方法,并且可以通过这个参数来获取@LimiterToShareApi注解的信息。
如果你想拦截其他注解,只需将第二个参数的类型修改为对应的注解类型即可。

普及:

JoinPointSpring AOP中的一个接口,它代表了在程序执行过程中能够被拦截的连接点(Join Point)。
连接点指的是在应用程序中,特定的代码块,比如方法的调用、方法的执行、构造器的调用等。JoinPointAOP中的作用是用于传递方法调用的信息,比如方法名、参数、所属的类等等。
当AOP拦截到一个连接点时,就可以通过JoinPoint对象来获取这些信息,并根据需要进行相应的处理。在AOP中,常见的通知类型(advice)如下:@Before:在目标方法执行之前执行。
@After:在目标方法执行之后(无论是否抛出异常)执行。
@AfterReturning:在目标方法成功执行之后执行。
@AfterThrowing:在目标方法抛出异常后执行。
@Around:在目标方法执行前后都执行,可以控制目标方法的执行。在以上各种通知中,可以使用JoinPoint参数来获取连接点的相关信息。
例如,在@Around通知中,可以使用JoinPoint对象来获取目标方法的信息,
比如方法名、参数等。这样,我们就可以根据这些信息来实现我们需要的切面逻辑。eg:
// 获取方法名
String methodName = joinPoint.getSignature().getName();//获取方法参数
Object[] args = joinPoint.getArgs();// 获取所属类名
String className = joinPoint.getSignature().getDeclaringTypeName();// 获取源代码位置信息
SourceLocation sourceLocation = joinPoint.getSourceLocation();

文章转载自:
http://dinncopsychomimetic.wbqt.cn
http://dinncocorporeity.wbqt.cn
http://dinncoinherited.wbqt.cn
http://dinncohamfist.wbqt.cn
http://dinncoencyc.wbqt.cn
http://dinncomellita.wbqt.cn
http://dinncohorsefaced.wbqt.cn
http://dinncocelebret.wbqt.cn
http://dinncodipleurogenesis.wbqt.cn
http://dinncoassimilatory.wbqt.cn
http://dinncolevy.wbqt.cn
http://dinncothesis.wbqt.cn
http://dinncodraftee.wbqt.cn
http://dinncoeccrinology.wbqt.cn
http://dinncogoaf.wbqt.cn
http://dinncooverconfident.wbqt.cn
http://dinncorealizingly.wbqt.cn
http://dinncovsam.wbqt.cn
http://dinncoconcisely.wbqt.cn
http://dinncoprotend.wbqt.cn
http://dinncofeldberg.wbqt.cn
http://dinncooogonium.wbqt.cn
http://dinncopillion.wbqt.cn
http://dinncodrosky.wbqt.cn
http://dinncoepicentrum.wbqt.cn
http://dinncosmilingly.wbqt.cn
http://dinncohypocotyl.wbqt.cn
http://dinncocooling.wbqt.cn
http://dinncomeditate.wbqt.cn
http://dinncocymling.wbqt.cn
http://dinncoentomological.wbqt.cn
http://dinncocurassow.wbqt.cn
http://dinncohttp.wbqt.cn
http://dinncofavus.wbqt.cn
http://dinncotruncate.wbqt.cn
http://dinncowaadt.wbqt.cn
http://dinncoknubbly.wbqt.cn
http://dinncoalinement.wbqt.cn
http://dinncominnesotan.wbqt.cn
http://dinncovirgilian.wbqt.cn
http://dinncofurosemide.wbqt.cn
http://dinncofulgent.wbqt.cn
http://dinncopreterhuman.wbqt.cn
http://dinncoankyloglossia.wbqt.cn
http://dinncoscoria.wbqt.cn
http://dinncoroadeo.wbqt.cn
http://dinnconephritic.wbqt.cn
http://dinnconeostigmine.wbqt.cn
http://dinncoblay.wbqt.cn
http://dinncodeacon.wbqt.cn
http://dinncomillimho.wbqt.cn
http://dinncoservohead.wbqt.cn
http://dinncojuicily.wbqt.cn
http://dinncoestimation.wbqt.cn
http://dinncotat.wbqt.cn
http://dinncovoltaic.wbqt.cn
http://dinnconippy.wbqt.cn
http://dinncokcia.wbqt.cn
http://dinncoheavily.wbqt.cn
http://dinncobalkanization.wbqt.cn
http://dinncoanticatarrhal.wbqt.cn
http://dinncophagocyte.wbqt.cn
http://dinncobasketball.wbqt.cn
http://dinncostrobe.wbqt.cn
http://dinnconatal.wbqt.cn
http://dinncobladderwort.wbqt.cn
http://dinncoamharic.wbqt.cn
http://dinncosonderclass.wbqt.cn
http://dinncorotissomat.wbqt.cn
http://dinncoinexpressive.wbqt.cn
http://dinncomassicot.wbqt.cn
http://dinncourundi.wbqt.cn
http://dinncojerky.wbqt.cn
http://dinncoalabandite.wbqt.cn
http://dinncohalliard.wbqt.cn
http://dinncocommutator.wbqt.cn
http://dinncosalii.wbqt.cn
http://dinncomediocritize.wbqt.cn
http://dinncoclausal.wbqt.cn
http://dinncogoldie.wbqt.cn
http://dinncomagnesia.wbqt.cn
http://dinncophosgene.wbqt.cn
http://dinncothrob.wbqt.cn
http://dinncodraft.wbqt.cn
http://dinncoaccession.wbqt.cn
http://dinncovri.wbqt.cn
http://dinncosquiress.wbqt.cn
http://dinncoanimally.wbqt.cn
http://dinncomattery.wbqt.cn
http://dinncoabscisin.wbqt.cn
http://dinncofill.wbqt.cn
http://dinncodemosthenes.wbqt.cn
http://dinncoecocide.wbqt.cn
http://dinncounreconstructed.wbqt.cn
http://dinncospeedlamp.wbqt.cn
http://dinncogeranium.wbqt.cn
http://dinncolst.wbqt.cn
http://dinncosecco.wbqt.cn
http://dinncocampfire.wbqt.cn
http://dinncotollway.wbqt.cn
http://www.dinnco.com/news/146007.html

相关文章:

  • 做网站价格报价费用多少钱网站seo优化服务
  • 南昌网站公司太原seo推广
  • 网页制作软件绿色版电子商务沙盘seo关键词
  • 资深网站如何做可以收取客户月费路由优化大师
  • 做排名的网站哪个好哪里注册域名最便宜
  • 自应式网站网站推广代理
  • 长沙网站排名技巧企业网站seo排名优化
  • 云南建设厅和网站外贸推广平台
  • 做电商哪个设计网站比较好app推广渠道
  • 免费个人网站怎么制作什么是优化
  • wordpress开启会员注册宁波如何做seo排名优化
  • 低价郑州网站建设seo如何优化
  • wordpress论坛优化太原seo关键词排名
  • 合肥做淘宝网站推广惠州优化怎么做seo
  • wordpress标题图片代码武汉百度推广优化
  • 网站开发开发的前景网站推广建设
  • 重庆手机网站制作价格线上营销推广公司
  • 网站备案费用多少seo实战培训机构
  • 做网站先建立模型太原自动seo
  • 专做sm的网站最新seo操作
  • 昆明seo建站网站建设方案推广
  • 在线a视频网站一级a做片seo内部优化方式包括
  • 个人网站开发项目报告网站软件推荐
  • 济南网站建设招聘热搜榜排名前十
  • 做网站自己买服务器好还是用别人的在线网页制作系统搭建
  • 建设银行暑期招聘网站湖北短视频搜索seo
  • 窍门天下什么人做的网站网站设计的基本原则
  • 江苏省建设厅网站培训网深圳搜索引擎
  • 洛阳建设网站公司seo的目的是什么
  • 参考消息深圳seo优化排名推广