Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
8
8timerapiv200
Overview
Overview
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
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
8timerv2
8timerapiv200
Commits
4b121214
Commit
4b121214
authored
a year ago
by
陶湘宇
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修复重复提交问题
parent
f792cf8d
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
162 additions
and
7 deletions
+162
-7
src/main/java/cn/timer/api/aspect/NoRepeatSubmitAspect.java
+122
-0
src/main/java/cn/timer/api/aspect/RequestAop.java
+1
-3
src/main/java/cn/timer/api/config/annotation/RepeatSubmit.java
+21
-0
src/main/java/cn/timer/api/config/interceptor/UserMethodArgumentResolver.java
+3
-0
src/main/java/cn/timer/api/controller/dzht/cn/tign/hz/constant/CacheKeyConstant.java
+2
-0
src/main/java/cn/timer/api/controller/kqgl/ClockInController.java
+13
-4
No files found.
src/main/java/cn/timer/api/aspect/NoRepeatSubmitAspect.java
0 → 100644
View file @
4b121214
package
cn
.
timer
.
api
.
aspect
;
import
cn.hutool.core.bean.BeanUtil
;
import
cn.hutool.crypto.digest.DigestUtil
;
import
cn.hutool.json.JSONUtil
;
import
cn.timer.api.config.annotation.RepeatSubmit
;
import
cn.timer.api.controller.dzht.cn.tign.hz.constant.CacheKeyConstant
;
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.annotation.Pointcut
;
import
org.aspectj.lang.reflect.MethodSignature
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
javax.servlet.http.HttpServletRequest
;
import
java.lang.reflect.Method
;
import
java.util.Objects
;
import
java.util.concurrent.TimeUnit
;
@Slf4j
@Component
@Aspect
public
class
NoRepeatSubmitAspect
{
@Autowired
private
RedisTemplate
redisTemplate
;
/**
* 定义切点
*/
@Pointcut
(
"@annotation(cn.timer.api.config.annotation.RepeatSubmit)"
)
public
void
preventDuplication
()
{}
@Around
(
"preventDuplication()"
)
public
Object
around
(
ProceedingJoinPoint
joinPoint
)
throws
Exception
{
/**
* 获取请求信息
*/
ServletRequestAttributes
attributes
=
(
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
();
HttpServletRequest
request
=
attributes
.
getRequest
();
// 获取执行方法
Method
method
=
((
MethodSignature
)
joinPoint
.
getSignature
()).
getMethod
();
//获取防重复提交注解
RepeatSubmit
annotation
=
method
.
getAnnotation
(
RepeatSubmit
.
class
);
// 获取token以及方法标记,生成redisKey和redisValue
String
token
=
BeanUtil
.
toBean
(
request
.
getSession
().
getAttribute
(
CacheKeyConstant
.
TOKEN
),
String
.
class
);
//String refreshToken = BeanUtil.toBean(request.getSession().getAttribute(CacheKeyConstant.REFRESH_TOKEN), String.class);
String
url
=
request
.
getRequestURI
();
/**
* 通过前缀 + url + token + 函数参数签名 来生成redis上的 key
*
*/
String
redisKey
=
CacheKeyConstant
.
PREVENT_DUPLICATION_PREFIX
.
concat
(
url
)
.
concat
(
token
)
.
concat
(
getMethodSign
(
method
,
joinPoint
.
getArgs
()));
// 这个值只是为了标记,不重要
String
redisValue
=
redisKey
.
concat
(
annotation
.
value
()).
concat
(
"submit duplication"
);
if
(!
redisTemplate
.
hasKey
(
redisKey
))
{
// 设置防重复操作限时标记(前置通知)
redisTemplate
.
opsForValue
()
.
set
(
redisKey
,
redisValue
,
annotation
.
expireSeconds
(),
TimeUnit
.
SECONDS
);
try
{
//正常执行方法并返回
//ProceedingJoinPoint类型参数可以决定是否执行目标方法,
// 且环绕通知必须要有返回值,返回值即为目标方法的返回值
return
joinPoint
.
proceed
();
}
catch
(
Throwable
throwable
)
{
//确保方法执行异常实时释放限时标记(异常后置通知)
redisTemplate
.
delete
(
redisKey
);
throw
new
RuntimeException
(
throwable
);
}
}
else
{
// 重复提交了抛出异常,如果是在项目中,根据具体情况处理。
throw
new
RuntimeException
(
"请勿重复提交"
);
}
}
/**
* 生成方法标记:采用数字签名算法SHA1对方法签名字符串加签
*
* @param method
* @param args
* @return
*/
private
String
getMethodSign
(
Method
method
,
Object
...
args
)
{
StringBuilder
sb
=
new
StringBuilder
(
method
.
toString
());
for
(
Object
arg
:
args
)
{
sb
.
append
(
toString
(
arg
));
}
return
DigestUtil
.
sha1Hex
(
sb
.
toString
());
}
private
String
toString
(
Object
arg
)
{
if
(
Objects
.
isNull
(
arg
))
{
return
"null"
;
}
if
(
arg
instanceof
Number
)
{
return
arg
.
toString
();
}
return
JSONUtil
.
toJsonStr
(
arg
);
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/main/java/cn/timer/api/aspect/RequestAop.java
View file @
4b121214
...
...
@@ -66,7 +66,7 @@ public class RequestAop {
long
endTime
=
System
.
currentTimeMillis
();
this
.
logInfo2Kafka
(
request
,
url
,
bodyArgs
,
urlArgs
,
"success"
,
0
,
endTime
-
startTime
,
true
);
}
catch
(
Throwable
e
)
{
e
.
printStackTrace
(
);
log
.
error
(
"requestAOPException:"
,
e
.
getStackTrace
()
);
long
endTime
=
System
.
currentTimeMillis
();
if
(
e
instanceof
CustomException
)
{
/**
...
...
@@ -97,8 +97,6 @@ public class RequestAop {
* @author Rex.Tan
* @date 2018年12月13日 下午2:51:31
* @param url 请求地址
* @param args requestBody中的参数
* @param args2 url中的参数
* @param message 消息
* @param status 接口调用返回状态
* @param executionTime 执行耗时
...
...
This diff is collapsed.
Click to expand it.
src/main/java/cn/timer/api/config/annotation/RepeatSubmit.java
0 → 100644
View file @
4b121214
package
cn
.
timer
.
api
.
config
.
annotation
;
import
java.lang.annotation.*
;
@Inherited
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
RepeatSubmit
{
/**
* 防重复操作限时标记数值(存储redis限时标记数值)
*/
String
value
()
default
"value"
;
/**
* 防重复操作过期时间(借助redis实现限时控制)
*/
long
expireSeconds
()
default
10
;
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/main/java/cn/timer/api/config/interceptor/UserMethodArgumentResolver.java
View file @
4b121214
...
...
@@ -3,6 +3,7 @@ package cn.timer.api.config.interceptor;
import
javax.annotation.Resource
;
import
javax.servlet.http.HttpSession
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.bind.support.WebDataBinderFactory
;
...
...
@@ -18,6 +19,7 @@ import cn.timer.api.config.annotation.UserBean;
import
cn.timer.api.controller.dzht.cn.tign.hz.constant.CacheKeyConstant
;
import
cn.timer.api.dto.yggl.UserInfo
;
@Slf4j
@Component
public
class
UserMethodArgumentResolver
implements
HandlerMethodArgumentResolver
{
...
...
@@ -49,6 +51,7 @@ public class UserMethodArgumentResolver implements HandlerMethodArgumentResolver
// NativeWebRequest.SCOPE_SESSION);
YgglMainEmp
mE
=
eld
.
getYgglMainEmp
();
log
.
info
(
"name="
+
mE
.
getName
()+
"Phone="
+
mE
.
getPhone
()+
"BmgwId"
+
mE
.
getBmgwId
());
UserInfo
userInfo
=
UserInfo
.
builder
().
name
(
mE
.
getName
()).
phone
(
mE
.
getPhone
()).
bmgwId
(
mE
.
getBmgwId
()).
build
();
return
UserBean
.
builder
().
token
(
token
).
refreshToken
(
refreshToken
).
empNum
(
eld
.
getId
())
...
...
This diff is collapsed.
Click to expand it.
src/main/java/cn/timer/api/controller/dzht/cn/tign/hz/constant/CacheKeyConstant.java
View file @
4b121214
...
...
@@ -17,4 +17,6 @@ public class CacheKeyConstant {
*/
public
static
final
String
REFRESH_TOKEN
=
"REFRESH_TOKEN"
;
public
static
final
String
PREVENT_DUPLICATION_PREFIX
=
"PREVENT_DUPLICATION_PREFIX:"
;
}
This diff is collapsed.
Click to expand it.
src/main/java/cn/timer/api/controller/kqgl/ClockInController.java
View file @
4b121214
...
...
@@ -12,6 +12,7 @@ import java.util.Date;
import
java.util.List
;
import
java.util.Locale
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.web.bind.annotation.GetMapping
;
...
...
@@ -76,6 +77,7 @@ import cn.timer.api.utils.ResultUtil;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
@Slf4j
@Api
(
tags
=
"3.0[3]考勤打卡"
)
@RestController
@Transactional
...
...
@@ -157,6 +159,12 @@ public class ClockInController {
ClockCollectData
clockt
=
new
ClockCollectData
();
//putime: 根据日期 得到打卡所需的详细信息
AttendanceCardListDto
attdate
=
MethodCall
(
qyid
,
userid
,
ClockInTool
.
paraseStringToDate
(
sStdIoTime
,
"yyyy-MM-dd HH:mm:SS"
));
if
(
attdate
==
null
||
attdate
.
getAttsch
()==
null
||
attdate
.
getAttsch
().
size
()<
1
){
msg
=
"没有排班信息"
;
log
.
error
(
"排班信息没取到attdate=null,qyid="
+
qyid
+
"userid="
+
userid
+
"时间="
+
ClockInTool
.
paraseStringToDate
(
sStdIoTime
,
"yyyy-MM-dd HH:mm:SS"
));
return
ResultUtil
.
error
(
msg
);
}
// = new SimpleDateFormat("yyyy-MM-dd").format(sStdIoTime);//转换打卡时间格式 年月日
Long
puttimeTmp
=
0L
;
if
(
attdate
!=
null
&&
attdate
.
getAttsch
()!=
null
&&
attdate
.
getAttsch
().
get
(
0
)!=
null
)
...
...
@@ -3422,13 +3430,14 @@ public class ClockInController {
KqglAssoDkjl
dk
=
KqglAssoDkjl
.
builder
().
build
().
selectOne
(
new
QueryWrapper
<
KqglAssoDkjl
>().
lambda
().
eq
(
KqglAssoDkjl:
:
getQyid
,
userBean
.
getOrgCode
())
.
eq
(
KqglAssoDkjl:
:
getUserId
,
userBean
.
getEmpNum
()).
ge
(
KqglAssoDkjl:
:
getDktime
,
startDate
).
le
(
KqglAssoDkjl:
:
getDktime
,
endDate
)
.
ne
(
KqglAssoDkjl:
:
getSort
,
0
).
ne
(
KqglAssoDkjl:
:
getStatus
,
2
).
ne
(
KqglAssoDkjl:
:
getStatus
,
0
)
.
orderByDesc
(
KqglAssoDkjl:
:
getSort
).
last
(
"
LIMIT
1"
));
.
orderByDesc
(
KqglAssoDkjl:
:
getSort
).
last
(
"
limit
1"
));
if
(
dk
!=
null
)
{
AttSchedule
att
=
attsch
.
get
(
dk
.
getSort
()-
1
);
att
.
setIsupdate
(
1
);
AttSchedule
attw
=
attsch
.
get
(
dk
.
getSort
()-
2
);
attw
.
setIsupdate
(
0
);
if
(
dk
.
getSort
()>
1
)
{
AttSchedule
attw
=
attsch
.
get
(
dk
.
getSort
()
-
2
);
attw
.
setIsupdate
(
0
);
}
}
}
...
...
This diff is collapsed.
Click to expand it.
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