Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
S
sts网站
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
liyang
sts网站
Commits
5c155f5f
Commit
5c155f5f
authored
Aug 17, 2021
by
RuoYi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
支持自定义注解实现接口限流
parent
03cf98d3
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
225 additions
and
15 deletions
+225
-15
Excels.java
...mon/src/main/java/com/ruoyi/common/annotation/Excels.java
+1
-1
RateLimiter.java
...rc/main/java/com/ruoyi/common/annotation/RateLimiter.java
+40
-0
Constants.java
...on/src/main/java/com/ruoyi/common/constant/Constants.java
+5
-0
LimitType.java
...ommon/src/main/java/com/ruoyi/common/enums/LimitType.java
+20
-0
RateLimiterAspect.java
...n/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java
+116
-0
RedisConfig.java
...src/main/java/com/ruoyi/framework/config/RedisConfig.java
+29
-0
request.js
ruoyi-ui/src/utils/request.js
+3
-3
ruoyi.js
ruoyi-ui/src/utils/ruoyi.js
+11
-11
No files found.
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java
View file @
5c155f5f
...
@@ -14,5 +14,5 @@ import java.lang.annotation.Target;
...
@@ -14,5 +14,5 @@ import java.lang.annotation.Target;
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
Excels
public
@interface
Excels
{
{
Excel
[]
value
();
public
Excel
[]
value
();
}
}
ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java
0 → 100644
View file @
5c155f5f
package
com
.
ruoyi
.
common
.
annotation
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
import
com.ruoyi.common.constant.Constants
;
import
com.ruoyi.common.enums.LimitType
;
/**
* 限流注解
*
* @author ruoyi
*/
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
RateLimiter
{
/**
* 限流key
*/
public
String
key
()
default
Constants
.
RATE_LIMIT_KEY
;
/**
* 限流时间,单位秒
*/
public
int
time
()
default
60
;
/**
* 限流次数
*/
public
int
count
()
default
100
;
/**
* 限流类型
*/
public
LimitType
limitType
()
default
LimitType
.
DEFAULT
;
}
ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
View file @
5c155f5f
...
@@ -74,6 +74,11 @@ public class Constants
...
@@ -74,6 +74,11 @@ public class Constants
*/
*/
public
static
final
String
REPEAT_SUBMIT_KEY
=
"repeat_submit:"
;
public
static
final
String
REPEAT_SUBMIT_KEY
=
"repeat_submit:"
;
/**
* 限流 redis key
*/
public
static
final
String
RATE_LIMIT_KEY
=
"rate_limit:"
;
/**
/**
* 验证码有效期(分钟)
* 验证码有效期(分钟)
*/
*/
...
...
ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java
0 → 100644
View file @
5c155f5f
package
com
.
ruoyi
.
common
.
enums
;
/**
* 限流类型
*
* @author ruoyi
*/
public
enum
LimitType
{
/**
* 默认策略全局限流
*/
DEFAULT
,
/**
* 根据请求者IP进行限流
*/
IP
}
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java
0 → 100644
View file @
5c155f5f
package
com
.
ruoyi
.
framework
.
aspectj
;
import
java.lang.reflect.Method
;
import
java.util.Collections
;
import
java.util.List
;
import
org.aspectj.lang.JoinPoint
;
import
org.aspectj.lang.Signature
;
import
org.aspectj.lang.annotation.Aspect
;
import
org.aspectj.lang.annotation.Before
;
import
org.aspectj.lang.annotation.Pointcut
;
import
org.aspectj.lang.reflect.MethodSignature
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.script.RedisScript
;
import
org.springframework.stereotype.Component
;
import
com.ruoyi.common.annotation.RateLimiter
;
import
com.ruoyi.common.enums.LimitType
;
import
com.ruoyi.common.exception.ServiceException
;
import
com.ruoyi.common.utils.ServletUtils
;
import
com.ruoyi.common.utils.StringUtils
;
import
com.ruoyi.common.utils.ip.IpUtils
;
/**
* 限流处理
*
* @author ruoyi
*/
@Aspect
@Component
public
class
RateLimiterAspect
{
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
RateLimiterAspect
.
class
);
private
RedisTemplate
<
Object
,
Object
>
redisTemplate
;
private
RedisScript
<
Long
>
limitScript
;
@Autowired
public
void
setRedisTemplate1
(
RedisTemplate
<
Object
,
Object
>
redisTemplate
)
{
this
.
redisTemplate
=
redisTemplate
;
}
@Autowired
public
void
setLimitScript
(
RedisScript
<
Long
>
limitScript
)
{
this
.
limitScript
=
limitScript
;
}
// 配置织入点
@Pointcut
(
"@annotation(com.ruoyi.common.annotation.RateLimiter)"
)
public
void
rateLimiterPointCut
()
{
}
@Before
(
"rateLimiterPointCut()"
)
public
void
doBefore
(
JoinPoint
point
)
throws
Throwable
{
RateLimiter
rateLimiter
=
getAnnotationRateLimiter
(
point
);
String
key
=
rateLimiter
.
key
();
int
time
=
rateLimiter
.
time
();
int
count
=
rateLimiter
.
count
();
String
combineKey
=
getCombineKey
(
rateLimiter
,
point
);
List
<
Object
>
keys
=
Collections
.
singletonList
(
combineKey
);
try
{
Long
number
=
redisTemplate
.
execute
(
limitScript
,
keys
,
count
,
time
);
if
(
StringUtils
.
isNull
(
number
)
||
number
.
intValue
()
>
count
)
{
throw
new
ServiceException
(
"访问过于频繁,请稍后再试"
);
}
log
.
info
(
"限制请求'{}',当前请求'{}',缓存key'{}'"
,
count
,
number
.
intValue
(),
key
);
}
catch
(
ServiceException
e
)
{
throw
e
;
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"服务器限流异常,请稍后再试"
);
}
}
/**
* 是否存在注解,如果存在就获取
*/
private
RateLimiter
getAnnotationRateLimiter
(
JoinPoint
joinPoint
)
{
Signature
signature
=
joinPoint
.
getSignature
();
MethodSignature
methodSignature
=
(
MethodSignature
)
signature
;
Method
method
=
methodSignature
.
getMethod
();
if
(
method
!=
null
)
{
return
method
.
getAnnotation
(
RateLimiter
.
class
);
}
return
null
;
}
public
String
getCombineKey
(
RateLimiter
rateLimiter
,
JoinPoint
point
)
{
StringBuffer
stringBuffer
=
new
StringBuffer
(
rateLimiter
.
key
());
if
(
rateLimiter
.
limitType
()
==
LimitType
.
IP
)
{
stringBuffer
.
append
(
IpUtils
.
getIpAddr
(
ServletUtils
.
getRequest
()));
}
MethodSignature
signature
=
(
MethodSignature
)
point
.
getSignature
();
Method
method
=
signature
.
getMethod
();
Class
<?>
targetClass
=
method
.
getDeclaringClass
();
stringBuffer
.
append
(
"-"
).
append
(
targetClass
.
getName
()).
append
(
"- "
).
append
(
method
.
getName
());
return
stringBuffer
.
toString
();
}
}
ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java
View file @
5c155f5f
...
@@ -6,6 +6,7 @@ import org.springframework.context.annotation.Bean;
...
@@ -6,6 +6,7 @@ import org.springframework.context.annotation.Bean;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.data.redis.connection.RedisConnectionFactory
;
import
org.springframework.data.redis.connection.RedisConnectionFactory
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.script.DefaultRedisScript
;
import
org.springframework.data.redis.serializer.StringRedisSerializer
;
import
org.springframework.data.redis.serializer.StringRedisSerializer
;
import
com.fasterxml.jackson.annotation.JsonAutoDetect
;
import
com.fasterxml.jackson.annotation.JsonAutoDetect
;
import
com.fasterxml.jackson.annotation.JsonTypeInfo
;
import
com.fasterxml.jackson.annotation.JsonTypeInfo
;
...
@@ -47,4 +48,32 @@ public class RedisConfig extends CachingConfigurerSupport
...
@@ -47,4 +48,32 @@ public class RedisConfig extends CachingConfigurerSupport
template
.
afterPropertiesSet
();
template
.
afterPropertiesSet
();
return
template
;
return
template
;
}
}
@Bean
public
DefaultRedisScript
<
Long
>
limitScript
()
{
DefaultRedisScript
<
Long
>
redisScript
=
new
DefaultRedisScript
<>();
redisScript
.
setScriptText
(
limitScriptText
());
redisScript
.
setResultType
(
Long
.
class
);
return
redisScript
;
}
/**
* 限流脚本
*/
private
String
limitScriptText
()
{
return
"local key = KEYS[1]\n"
+
"local count = tonumber(ARGV[1])\n"
+
"local time = tonumber(ARGV[2])\n"
+
"local current = redis.call('get', key);\n"
+
"if current and tonumber(current) > count then\n"
+
" return current;\n"
+
"end\n"
+
"current = redis.call('incr', key)\n"
+
"if tonumber(current) == 1 then\n"
+
" redis.call('expire', key, time)\n"
+
"end\n"
+
"return current;"
;
}
}
}
ruoyi-ui/src/utils/request.js
View file @
5c155f5f
...
@@ -29,9 +29,9 @@ service.interceptors.request.use(config => {
...
@@ -29,9 +29,9 @@ service.interceptors.request.use(config => {
if
(
typeof
value
===
'object'
)
{
if
(
typeof
value
===
'object'
)
{
for
(
const
key
of
Object
.
keys
(
value
))
{
for
(
const
key
of
Object
.
keys
(
value
))
{
if
(
value
[
key
]
!==
null
&&
typeof
(
value
[
key
])
!==
'undefined'
)
{
if
(
value
[
key
]
!==
null
&&
typeof
(
value
[
key
])
!==
'undefined'
)
{
let
params
=
propName
+
'['
+
key
+
']'
let
params
=
propName
+
'['
+
key
+
']'
;
let
subPart
=
encodeURIComponent
(
params
)
+
'='
let
subPart
=
encodeURIComponent
(
params
)
+
'='
;
url
+=
subPart
+
encodeURIComponent
(
value
[
key
])
+
'&'
url
+=
subPart
+
encodeURIComponent
(
value
[
key
])
+
'&'
;
}
}
}
}
}
else
{
}
else
{
...
...
ruoyi-ui/src/utils/ruoyi.js
View file @
5c155f5f
...
@@ -55,17 +55,17 @@ export function resetForm(refName) {
...
@@ -55,17 +55,17 @@ export function resetForm(refName) {
// 添加日期范围
// 添加日期范围
export
function
addDateRange
(
params
,
dateRange
,
propName
)
{
export
function
addDateRange
(
params
,
dateRange
,
propName
)
{
let
search
=
params
let
search
=
params
;
search
.
params
=
typeof
(
search
.
params
)
===
'object'
&&
search
.
params
!==
null
&&
!
Array
.
isArray
(
search
.
params
)
?
search
.
params
:
{}
search
.
params
=
typeof
(
search
.
params
)
===
'object'
&&
search
.
params
!==
null
&&
!
Array
.
isArray
(
search
.
params
)
?
search
.
params
:
{};
dateRange
=
Array
.
isArray
(
dateRange
)
?
dateRange
:
[]
dateRange
=
Array
.
isArray
(
dateRange
)
?
dateRange
:
[];
if
(
typeof
(
propName
)
===
'undefined'
)
{
if
(
typeof
(
propName
)
===
'undefined'
)
{
search
.
params
[
'beginTime'
]
=
dateRange
[
0
]
search
.
params
[
'beginTime'
]
=
dateRange
[
0
];
search
.
params
[
'endTime'
]
=
dateRange
[
1
]
search
.
params
[
'endTime'
]
=
dateRange
[
1
];
}
else
{
}
else
{
search
.
params
[
'begin'
+
propName
]
=
dateRange
[
0
]
search
.
params
[
'begin'
+
propName
]
=
dateRange
[
0
];
search
.
params
[
'end'
+
propName
]
=
dateRange
[
1
]
search
.
params
[
'end'
+
propName
]
=
dateRange
[
1
];
}
}
return
search
return
search
;
}
}
// 回显数据字典
// 回显数据字典
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment