程序员蜗牛
1 year ago
12 changed files with 300 additions and 0 deletions
@ -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/ |
@ -0,0 +1,11 @@ |
|||||
|
# demo-request-scope |
||||
|
|
||||
|
《基于ThreadLocal实现一个上下文管理组件》技术博客对应源码 |
||||
|
|
||||
|
https://juejin.cn/post/7153287656624324638 |
||||
|
|
||||
|
本文基于`ThreadLocal`原理,实现了一个上下文状态管理组件`Scope`,通过开启一个自定义的`Scope`,在`Scope`范围内,可以通过`Scope`各个方法读写数据; |
||||
|
|
||||
|
通过自定义线程池实现上下文状态数据的线程间传递; |
||||
|
|
||||
|
提出了一种基于`Filter`和`Scope`的`Request`粒度的上下文管理方案。 |
@ -0,0 +1,65 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
|
<modelVersion>4.0.0</modelVersion> |
||||
|
<parent> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-parent</artifactId> |
||||
|
<version>2.7.4</version> |
||||
|
<relativePath/> <!-- lookup parent from repository --> |
||||
|
</parent> |
||||
|
<groupId>com.example</groupId> |
||||
|
<artifactId>demo-request-scope</artifactId> |
||||
|
<version>0.0.1-SNAPSHOT</version> |
||||
|
<name>demo-request-scope</name> |
||||
|
<description>Demo project for Spring Boot</description> |
||||
|
<properties> |
||||
|
<java.version>8</java.version> |
||||
|
</properties> |
||||
|
|
||||
|
|
||||
|
<dependencies> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>com.google.guava</groupId> |
||||
|
<artifactId>guava</artifactId> |
||||
|
<version>30.1-jre</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-aop</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-data-redis</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-web</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-test</artifactId> |
||||
|
<scope>test</scope> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.projectlombok</groupId> |
||||
|
<artifactId>lombok</artifactId> |
||||
|
<optional>true</optional> |
||||
|
</dependency> |
||||
|
</dependencies> |
||||
|
|
||||
|
<build> |
||||
|
<plugins> |
||||
|
<plugin> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-maven-plugin</artifactId> |
||||
|
</plugin> |
||||
|
</plugins> |
||||
|
</build> |
||||
|
|
||||
|
</project> |
@ -0,0 +1,16 @@ |
|||||
|
package com.example.demo; |
||||
|
|
||||
|
import org.springframework.boot.SpringApplication; |
||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
|
|
||||
|
/** |
||||
|
* Guava自加载缓存LoadingCache |
||||
|
*/ |
||||
|
@SpringBootApplication |
||||
|
public class DemoRequestScopeApplication { |
||||
|
|
||||
|
public static void main(String[] args) { |
||||
|
SpringApplication.run(DemoRequestScopeApplication.class, args); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,33 @@ |
|||||
|
package com.example.demo.component; |
||||
|
|
||||
|
|
||||
|
import com.google.common.cache.CacheBuilder; |
||||
|
import com.google.common.cache.CacheLoader; |
||||
|
import com.google.common.cache.LoadingCache; |
||||
|
|
||||
|
import java.util.concurrent.TimeUnit; |
||||
|
|
||||
|
public class AutoRefreshCache { |
||||
|
public static void main(String[] args) throws Exception { |
||||
|
LoadingCache<String, String> cache = CacheBuilder |
||||
|
.newBuilder() |
||||
|
.refreshAfterWrite(5, TimeUnit.SECONDS) // 设置5s后刷新 更新缓存
|
||||
|
.build(new CacheLoader<String, String>() { |
||||
|
@Override |
||||
|
public String load(String key) { |
||||
|
return fetchDataFromDatabase(key); // 模拟从数据库加载数据
|
||||
|
} |
||||
|
}); |
||||
|
// 使用缓存
|
||||
|
System.out.println(cache.get("key1")); // 第一次加载
|
||||
|
// 5s钟后,尝试再次获取,将触发刷新操作
|
||||
|
TimeUnit.SECONDS.sleep(5); |
||||
|
System.out.println(cache.get("key1")); // 第二次加载
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
private static String fetchDataFromDatabase(String key) { |
||||
|
// 模拟数据库操作
|
||||
|
return "Data for " + key; |
||||
|
} |
||||
|
} |
@ -0,0 +1,27 @@ |
|||||
|
package com.example.demo.component; |
||||
|
|
||||
|
import com.google.common.cache.CacheBuilder; |
||||
|
import com.google.common.cache.CacheLoader; |
||||
|
import com.google.common.cache.LoadingCache; |
||||
|
import com.google.common.cache.RemovalListener; |
||||
|
|
||||
|
public class CacheMonitoring { |
||||
|
public static void main(String[] args) throws Exception { |
||||
|
RemovalListener<String, String> removalListener = notification -> { |
||||
|
System.out.println("Removed: " + notification.getKey() + ", Cause: " + notification.getCause()); |
||||
|
}; |
||||
|
LoadingCache<String, String> cache = CacheBuilder |
||||
|
.newBuilder() |
||||
|
.maximumSize(100) |
||||
|
.removalListener(removalListener) |
||||
|
.build(new CacheLoader<String, String>() { |
||||
|
@Override |
||||
|
public String load(String key) throws Exception { |
||||
|
return key; |
||||
|
} |
||||
|
}); |
||||
|
String value = cache.get("key"); |
||||
|
System.out.println(value); |
||||
|
cache.cleanUp(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,20 @@ |
|||||
|
package com.example.demo.component; |
||||
|
|
||||
|
|
||||
|
import com.google.common.cache.CacheBuilder; |
||||
|
import com.google.common.cache.CacheLoader; |
||||
|
import com.google.common.cache.LoadingCache; |
||||
|
|
||||
|
public class LoadingCacheExample { |
||||
|
public static void main(String[] args) { |
||||
|
LoadingCache<String, String> cache = CacheBuilder.newBuilder() |
||||
|
.maximumSize(100) // 最大缓存项数
|
||||
|
.build(new CacheLoader<String, String>() { |
||||
|
@Override |
||||
|
public String load(String key) throws Exception { |
||||
|
return "Hello, " + key; // 定义缓存加载的方式
|
||||
|
} |
||||
|
}); |
||||
|
System.out.println(cache.getUnchecked("Guava")); // 输出:Hello, Guava
|
||||
|
} |
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
package com.example.demo.component; |
||||
|
|
||||
|
|
||||
|
import com.example.demo.entity.User; |
||||
|
import com.example.demo.service.UserService; |
||||
|
import com.google.common.cache.CacheBuilder; |
||||
|
import com.google.common.cache.CacheLoader; |
||||
|
import com.google.common.cache.LoadingCache; |
||||
|
|
||||
|
public class UserCache { |
||||
|
// 假设有一个用户服务,用于获取用户信息
|
||||
|
private static UserService userService = new UserService(); |
||||
|
public static void main(String[] args) throws Exception { |
||||
|
CacheLoader<String, User> loader = new CacheLoader<String, User>() { |
||||
|
@Override |
||||
|
public User load(String userId) throws Exception { |
||||
|
return userService.getUserById(userId); |
||||
|
} |
||||
|
}; |
||||
|
// 创建LoadingCache
|
||||
|
LoadingCache<String, User> cache = CacheBuilder.newBuilder() |
||||
|
.maximumSize(100) // 设置最大缓存数
|
||||
|
.build(loader); |
||||
|
// 使用缓存获取用户信息
|
||||
|
User user = cache.get("123"); // 如果缓存中没有,会调用load方法加载数据
|
||||
|
System.out.println(user); |
||||
|
} |
||||
|
} |
@ -0,0 +1,45 @@ |
|||||
|
package com.example.demo.component; |
||||
|
|
||||
|
|
||||
|
import com.google.common.cache.CacheBuilder; |
||||
|
import com.google.common.cache.CacheLoader; |
||||
|
import com.google.common.cache.LoadingCache; |
||||
|
|
||||
|
import java.util.concurrent.TimeUnit; |
||||
|
|
||||
|
/** |
||||
|
* 缓存使用最佳实践 |
||||
|
*/ |
||||
|
public class ZuiJiaShiJian { |
||||
|
|
||||
|
public static void main(String[] args) { |
||||
|
LoadingCache<String, String> cache = CacheBuilder.newBuilder() |
||||
|
.maximumSize(1000) // 设置最大缓存项为1000 合理配置缓存大小
|
||||
|
.expireAfterWrite(10, TimeUnit.MINUTES) // 写入后10分钟过期 设置合适的过期策略
|
||||
|
.expireAfterAccess(5, TimeUnit.MINUTES) // 访问后5分钟过期 设置合适的过期策略
|
||||
|
.softValues() // 使用软引用存储值
|
||||
|
.weakKeys() // 使用弱引用存储键
|
||||
|
.removalListener(notification -> { |
||||
|
// 监听移除通知
|
||||
|
System.out.println("Removed: " + notification.getKey() + ", Cause: " + notification.getCause()); |
||||
|
}) |
||||
|
.build(new CacheLoader<String, String>() { |
||||
|
@Override |
||||
|
public String load(String key) throws Exception { |
||||
|
try { |
||||
|
// 异常处理策略
|
||||
|
return fetchData(key); |
||||
|
} catch (Exception e) { |
||||
|
// 处理异常
|
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
private String fetchData(String key) { |
||||
|
throw new RuntimeException(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,10 @@ |
|||||
|
package com.example.demo.entity; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
@Data |
||||
|
public class User { |
||||
|
|
||||
|
private String name; |
||||
|
private int age; |
||||
|
} |
@ -0,0 +1,9 @@ |
|||||
|
package com.example.demo.service; |
||||
|
|
||||
|
import com.example.demo.entity.User; |
||||
|
|
||||
|
public class UserService { |
||||
|
public User getUserById(String userId) { |
||||
|
return new User(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,3 @@ |
|||||
|
|
||||
|
spring.redis.host=192.168.56.10 |
||||
|
spring.redis.password=123456 |
Loading…
Reference in new issue