2024 年的付费软件:
TablePlus:
Typora:
ICloud:每月 6 元
B 站大会员:每月 15 元
More »
Java, Spring Boot, Microservice, Cloud, Architecture and DevOps Tutorials
2024 年的付费软件:
TablePlus:
Typora:
ICloud:每月 6 元
B 站大会员:每月 15 元
More »今天我做了什么?
更新文章 我的VPS服务部署记录
将 memos 中的书签导入 hoarder,并将 memos 版本退回到 0.21.0 ,因为 0.21.0 之后的版本去掉了分享功能。同时需要修改 memos api,同步修改 fetch_memos.py 文件,将 https://memos.chensoul.cc/api/v1/memos 改为 https://memos.chensoul.cc/api/v2/memos
More »Spring Boot 和 GraalVM 原生镜像应用程序,由出色的 Oracle GraalVM 开发倡导者 Alina Yurenko演示。
More »以下是 SivaLabs 博客 中的一些文章,记录在此,方便后面阅读。
如果你正在寻找使用 SpringBoot 实现微服务的详细实用指南,那么 Java 微服务:实用指南就是你的最佳选择
在使用 JPA 时,我们多少次希望看到使用实际参数值而不是占位符生成的 SQL 查询?我们可以使用p6spy-spring-boot-starter来记录使用实际参数生成的 SQL 语句。
More »今天做了什么:
ChatGPT 编写一个 RateLimitAspect 类,实现基于用户的 get 查询请求的限流功能
@Aspect
@Component
public class RateLimitAspect {
private final RedisTemplate<String, Object> redisTemplate;
private final Logger logger = LoggerFactory.getLogger(RateLimitAspect.class);
private final int maxRequests; // Maximum number of requests
private final int timeWindow; // Time window in seconds
@Autowired
public RateLimitAspect(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
this.maxRequests = 100; // Default maximum number of requests is 100
this.timeWindow = 60; // Default time window is 60 seconds
}
@Before("@annotation(getMapping)")
public void applyRateLimit(JoinPoint joinPoint, GetMapping getMapping) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
if (request != null && HttpMethod.GET.matches(request.getMethod())) {
String username = request.getUserPrincipal().getName(); // Get the username
if (username != null && !username.isEmpty()) {
String rateLimitKey = "rate_limit:" + username;
incrementAndCheckRateLimit(rateLimitKey, request);
}
}
}
private void incrementAndCheckRateLimit(String rateLimitKey, HttpServletRequest request) {
Long currentRequests = redisTemplate.execute((RedisCallback<Long>) connection -> {
Object nativeConnection = connection.getNativeConnection();
String script = "local current = redis.call('INCR', KEYS[1])\n"
+ "if tonumber(current) == 1 then\n"
+ " redis.call('EXPIRE', KEYS[1], ARGV[1])\n"
+ "end\n"
+ "return current";
return (Long) ((RedisOperations<?, ?>) nativeConnection).execute(
(RedisCallback<Object>) connection1 -> connection1.eval(
script.getBytes(),
redisTemplate.getKeySerializer(), // Use custom Key serializer
redisTemplate.getValueSerializer(), // Use custom Value serializer
Collections.singletonList(rateLimitKey.getBytes()),
Collections.singletonList(String.valueOf(timeWindow).getBytes())
)
);
});
if (currentRequests > maxRequests) {
String urlWithParams = getRequestUrlWithParams(request);
logger.warn("Rate limit exceeded for key: {}. Request URL with Params: {}",
rateLimitKey, urlWithParams);
throw new RateLimitException();
}
}
private String getRequestUrlWithParams(HttpServletRequest request) {
String url = request.getRequestURL().toString();
String queryString = request.getQueryString();
if (queryString != null && !queryString.isEmpty()) {
url += "?" + queryString;
}
return url;
}
}
调整 spring-cloud-examples 目录,通过源码分析 SpringBoot 2.7.18 启动过程
More »