fix bugs
This commit is contained in:
34
blade-starter-actuate/README.md
Normal file
34
blade-starter-actuate/README.md
Normal file
@@ -0,0 +1,34 @@
|
||||
## 想法
|
||||
暴露一些端点,提供一些功能。
|
||||
|
||||
1. http-cache
|
||||
|
||||
2. RateLimiter
|
||||
|
||||
3. ... ...
|
||||
|
||||
### 不是用网关,单体应用
|
||||
拦截器处理,基于 redis 的 cache 时间或者 RateLimiter处理。
|
||||
|
||||
结构:serviceName:http-cache:/user/1?queryString If-Modified-Since
|
||||
结构:serviceName:RateLimiter:/user/1 99
|
||||
|
||||
### 使用网关
|
||||
将端点信息存储到 redis 里,供 网关使用。
|
||||
结构:serviceName:http-cache:endpoint:/user/{id} 100s
|
||||
|
||||
结构:serviceName:RateLimiter:endpoint:/user/{id} 100/s
|
||||
|
||||
## RateLimiter Headers
|
||||
```text
|
||||
#=============================#===================================================#
|
||||
# HTTP Header # Description #
|
||||
#=============================#===================================================#
|
||||
| X-RateLimit-Limit | Request limit per day / per 5 minutes |
|
||||
+-----------------------------+---------------------------------------------------+
|
||||
| X-RateLimit-Remaining | The number of requests left for the time window |
|
||||
+-----------------------------+---------------------------------------------------+
|
||||
| X-RateLimit-Reset | The remaining window before the rate limit resets |
|
||||
| | in UTC epoch seconds |
|
||||
+-----------------------------+---------------------------------------------------+
|
||||
```
|
||||
30
blade-starter-actuate/pom.xml
Normal file
30
blade-starter-actuate/pom.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>BladeX-Tool</artifactId>
|
||||
<groupId>org.springblade</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>blade-starter-actuate</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<version>${project.parent.version}</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-tool</artifactId>
|
||||
</dependency>
|
||||
<!-- Auto -->
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-auto</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.http.cache;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Http Cache 配置
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@ConfigurationProperties("blade.http.cache")
|
||||
public class BladeHttpCacheProperties {
|
||||
/**
|
||||
* Http-cache 的 spring cache名,默认:bladeHttpCache
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private String cacheName = "bladeHttpCache";
|
||||
/**
|
||||
* 默认拦截/**
|
||||
*/
|
||||
@Getter
|
||||
private final List<String> includePatterns = new ArrayList<String>() {{
|
||||
add("/**");
|
||||
}};
|
||||
/**
|
||||
* 默认排除静态文件目录
|
||||
*/
|
||||
@Getter
|
||||
private final List<String> excludePatterns = new ArrayList<>();
|
||||
}
|
||||
63
blade-starter-actuate/src/main/java/org/springblade/core/http/cache/HttpCacheAble.java
vendored
Normal file
63
blade-starter-actuate/src/main/java/org/springblade/core/http/cache/HttpCacheAble.java
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.http.cache;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Http cache
|
||||
* cache-control
|
||||
* <p>
|
||||
* max-age 大于0 时 直接从游览器缓存中 提取
|
||||
* max-age 小于或等于0 时 向server 发送http 请求确认 ,该资源是否有修改
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface HttpCacheAble {
|
||||
|
||||
/**
|
||||
* 缓存的时间,默认0,单位秒
|
||||
*
|
||||
* @return {long}
|
||||
*/
|
||||
@AliasFor("maxAge")
|
||||
long value();
|
||||
|
||||
/**
|
||||
* 缓存的时间,默认0,单位秒
|
||||
*
|
||||
* @return {long}
|
||||
*/
|
||||
@AliasFor("value")
|
||||
long maxAge() default 0;
|
||||
|
||||
}
|
||||
76
blade-starter-actuate/src/main/java/org/springblade/core/http/cache/HttpCacheConfiguration.java
vendored
Normal file
76
blade-starter-actuate/src/main/java/org/springblade/core/http/cache/HttpCacheConfiguration.java
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.http.cache;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Http Cache 配置
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@AllArgsConstructor
|
||||
@EnableConfigurationProperties(BladeHttpCacheProperties.class)
|
||||
@ConditionalOnProperty(value = "blade.http.cache.enabled", havingValue = "true")
|
||||
public class HttpCacheConfiguration implements WebMvcConfigurer {
|
||||
private static final String DEFAULT_STATIC_PATH_PATTERN = "/**";
|
||||
private final WebMvcProperties webMvcProperties;
|
||||
private final BladeHttpCacheProperties properties;
|
||||
private final CacheManager cacheManager;
|
||||
|
||||
@Bean
|
||||
public HttpCacheService httpCacheService() {
|
||||
return new HttpCacheService(properties, cacheManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(@NonNull InterceptorRegistry registry) {
|
||||
Set<String> excludePatterns = new HashSet<>(properties.getExcludePatterns());
|
||||
String staticPathPattern = webMvcProperties.getStaticPathPattern();
|
||||
// 如果静态 目录 不为 /**
|
||||
if (!DEFAULT_STATIC_PATH_PATTERN.equals(staticPathPattern.trim())) {
|
||||
excludePatterns.add(staticPathPattern);
|
||||
}
|
||||
HttpCacheInterceptor httpCacheInterceptor = new HttpCacheInterceptor(httpCacheService());
|
||||
registry.addInterceptor(httpCacheInterceptor)
|
||||
.addPathPatterns(properties.getIncludePatterns().toArray(new String[0]))
|
||||
.excludePathPatterns(excludePatterns.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
100
blade-starter-actuate/src/main/java/org/springblade/core/http/cache/HttpCacheInterceptor.java
vendored
Normal file
100
blade-starter-actuate/src/main/java/org/springblade/core/http/cache/HttpCacheInterceptor.java
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.http.cache;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.tool.utils.ClassUtil;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Http cache拦截器
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class HttpCacheInterceptor implements HandlerInterceptor {
|
||||
private final HttpCacheService httpCacheService;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {
|
||||
// 非控制器请求直接跳出
|
||||
if (!(handler instanceof HandlerMethod handlerMethod)) {
|
||||
return true;
|
||||
}
|
||||
// http cache 针对 HEAD 和 GET 请求
|
||||
String method = request.getMethod();
|
||||
HttpMethod httpMethod = HttpMethod.valueOf(method);
|
||||
List<HttpMethod> allowList = Arrays.asList(HttpMethod.HEAD, HttpMethod.GET);
|
||||
if (!allowList.contains(httpMethod)) {
|
||||
return true;
|
||||
}
|
||||
// 处理HttpCacheAble
|
||||
HttpCacheAble cacheAble = ClassUtil.getAnnotation(handlerMethod, HttpCacheAble.class);
|
||||
if (cacheAble == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 最后修改时间
|
||||
long ims = request.getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);
|
||||
long now = Clock.systemUTC().millis();
|
||||
// 缓存时间,秒
|
||||
long maxAge = cacheAble.maxAge();
|
||||
// 缓存时间,毫秒
|
||||
long maxAgeMicros = TimeUnit.SECONDS.toMillis(maxAge);
|
||||
String cacheKey = request.getRequestURI() + "?" + request.getQueryString();
|
||||
// 后端可控制http-cache超时
|
||||
boolean hasCache = httpCacheService.get(cacheKey);
|
||||
// 如果header头没有过期
|
||||
if (hasCache && ims + maxAgeMicros > now) {
|
||||
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
response.setHeader(HttpHeaders.CACHE_CONTROL, "max-age=" + maxAge);
|
||||
response.addDateHeader(HttpHeaders.EXPIRES, ims + maxAgeMicros);
|
||||
response.addDateHeader(HttpHeaders.LAST_MODIFIED, ims);
|
||||
log.info("{} 304 {}", method, request.getRequestURI());
|
||||
return false;
|
||||
}
|
||||
response.setHeader(HttpHeaders.CACHE_CONTROL, "max-age=" + maxAge);
|
||||
response.addDateHeader(HttpHeaders.EXPIRES, now + maxAgeMicros);
|
||||
response.addDateHeader(HttpHeaders.LAST_MODIFIED, now);
|
||||
httpCacheService.set(cacheKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
73
blade-starter-actuate/src/main/java/org/springblade/core/http/cache/HttpCacheService.java
vendored
Normal file
73
blade-starter-actuate/src/main/java/org/springblade/core/http/cache/HttpCacheService.java
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.http.cache;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Http Cache 服务
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
public class HttpCacheService implements InitializingBean {
|
||||
private final BladeHttpCacheProperties properties;
|
||||
private final CacheManager cacheManager;
|
||||
private Cache cache;
|
||||
|
||||
public HttpCacheService(BladeHttpCacheProperties properties, CacheManager cacheManager) {
|
||||
this.properties = properties;
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
|
||||
public boolean get(String key) {
|
||||
Boolean result = cache.get(key, Boolean.class);
|
||||
return Boolean.TRUE.equals(result);
|
||||
}
|
||||
|
||||
public void set(String key) {
|
||||
cache.put(key, Boolean.TRUE);
|
||||
}
|
||||
|
||||
public void remove(String key) {
|
||||
cache.evict(key);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(cacheManager, "cacheManager must not be null!");
|
||||
String cacheName = properties.getCacheName();
|
||||
this.cache = cacheManager.getCache(cacheName);
|
||||
Assert.notNull(this.cache, "HttpCacheCache cacheName: " + cacheName + " is not config.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user