diff --git a/guavalimit/.gitignore b/guavalimit/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/guavalimit/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/guavalimit/README.md b/guavalimit/README.md
new file mode 100644
index 0000000..c912aec
--- /dev/null
+++ b/guavalimit/README.md
@@ -0,0 +1,11 @@
+# demo-request-scope
+
+《基于ThreadLocal实现一个上下文管理组件》技术博客对应源码
+
+https://juejin.cn/post/7153287656624324638
+
+本文基于`ThreadLocal`原理,实现了一个上下文状态管理组件`Scope`,通过开启一个自定义的`Scope`,在`Scope`范围内,可以通过`Scope`各个方法读写数据;
+
+通过自定义线程池实现上下文状态数据的线程间传递;
+
+提出了一种基于`Filter`和`Scope`的`Request`粒度的上下文管理方案。
diff --git a/guavalimit/pom.xml b/guavalimit/pom.xml
new file mode 100644
index 0000000..65b54a8
--- /dev/null
+++ b/guavalimit/pom.xml
@@ -0,0 +1,61 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.4
+
+
+ com.example
+ demo-request-scope
+ 0.0.1-SNAPSHOT
+ demo-request-scope
+ Demo project for Spring Boot
+
+ 8
+
+
+
+
+
+
+ com.google.guava
+ guava
+ 30.1-jre
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/guavalimit/src/main/java/com/example/demo/DemoRequestScopeApplication.java b/guavalimit/src/main/java/com/example/demo/DemoRequestScopeApplication.java
new file mode 100644
index 0000000..4c0d58d
--- /dev/null
+++ b/guavalimit/src/main/java/com/example/demo/DemoRequestScopeApplication.java
@@ -0,0 +1,13 @@
+package com.example.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class DemoRequestScopeApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(DemoRequestScopeApplication.class, args);
+ }
+
+}
diff --git a/guavalimit/src/main/java/com/example/demo/aop/LimitAop.java b/guavalimit/src/main/java/com/example/demo/aop/LimitAop.java
new file mode 100644
index 0000000..16cd939
--- /dev/null
+++ b/guavalimit/src/main/java/com/example/demo/aop/LimitAop.java
@@ -0,0 +1,73 @@
+package com.example.demo.aop;
+
+
+import com.example.demo.limit.Limit;
+import com.example.demo.util.WebUtils;
+import com.example.demo.vo.ResultData;
+import com.example.demo.vo.ReturnCode;
+import com.google.common.collect.Maps;
+import com.google.common.util.concurrent.RateLimiter;
+import lombok.extern.slf4j.Slf4j;
+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.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletResponse;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+@Slf4j
+@Aspect
+@Component
+public class LimitAop {
+ /**
+ * 不同的接口,不同的流量控制
+ * map的key为 Limiter.key
+ */
+ private final Map limitMap = Maps.newConcurrentMap();
+
+ @Around("@annotation(com.example.demo.limit.Limit)")
+ public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+ Method method = signature.getMethod();
+ //拿limit的注解
+ Limit limit = method.getAnnotation(Limit.class);
+ if (limit != null) {
+ //key作用:不同的接口,不同的流量控制
+ String key = limit.key();
+ RateLimiter rateLimiter = null;
+ //验证缓存是否有命中key
+ if (!limitMap.containsKey(key)) {
+ // 创建令牌桶
+ rateLimiter = RateLimiter.create(limit.permitsPerSecond());
+ limitMap.put(key, rateLimiter);
+ log.info("新建了令牌桶={},容量={}", key, limit.permitsPerSecond());
+ }
+ rateLimiter = limitMap.get(key);
+ // 拿令牌
+ boolean acquire = rateLimiter.tryAcquire(limit.timeout(), limit.timeunit());
+ // 拿不到命令,直接返回异常提示
+ if (!acquire) {
+ log.debug("令牌桶={},获取令牌失败", key);
+ this.responseFail(limit.msg());
+ return null;
+ }
+ }
+ return joinPoint.proceed();
+ }
+
+ /**
+ * 直接向前端抛出异常
+ *
+ * @param msg 提示信息
+ */
+ private void responseFail(String msg) {
+ HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
+ ResultData