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
Sep 01, 2023
by
陶湘宇
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修复重复提交问题
parent
f792cf8d
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
161 additions
and
6 deletions
+161
-6
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
+12
-3
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
src/main/java/cn/timer/api/aspect/RequestAop.java
View file @
4b121214
...
@@ -66,7 +66,7 @@ public class RequestAop {
...
@@ -66,7 +66,7 @@ public class RequestAop {
long
endTime
=
System
.
currentTimeMillis
();
long
endTime
=
System
.
currentTimeMillis
();
this
.
logInfo2Kafka
(
request
,
url
,
bodyArgs
,
urlArgs
,
"success"
,
0
,
endTime
-
startTime
,
true
);
this
.
logInfo2Kafka
(
request
,
url
,
bodyArgs
,
urlArgs
,
"success"
,
0
,
endTime
-
startTime
,
true
);
}
catch
(
Throwable
e
)
{
}
catch
(
Throwable
e
)
{
e
.
printStackTrace
(
);
log
.
error
(
"requestAOPException:"
,
e
.
getStackTrace
()
);
long
endTime
=
System
.
currentTimeMillis
();
long
endTime
=
System
.
currentTimeMillis
();
if
(
e
instanceof
CustomException
)
{
if
(
e
instanceof
CustomException
)
{
/**
/**
...
@@ -97,8 +97,6 @@ public class RequestAop {
...
@@ -97,8 +97,6 @@ public class RequestAop {
* @author Rex.Tan
* @author Rex.Tan
* @date 2018年12月13日 下午2:51:31
* @date 2018年12月13日 下午2:51:31
* @param url 请求地址
* @param url 请求地址
* @param args requestBody中的参数
* @param args2 url中的参数
* @param message 消息
* @param message 消息
* @param status 接口调用返回状态
* @param status 接口调用返回状态
* @param executionTime 执行耗时
* @param executionTime 执行耗时
...
...
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
src/main/java/cn/timer/api/config/interceptor/UserMethodArgumentResolver.java
View file @
4b121214
...
@@ -3,6 +3,7 @@ package cn.timer.api.config.interceptor;
...
@@ -3,6 +3,7 @@ package cn.timer.api.config.interceptor;
import
javax.annotation.Resource
;
import
javax.annotation.Resource
;
import
javax.servlet.http.HttpSession
;
import
javax.servlet.http.HttpSession
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.bind.support.WebDataBinderFactory
;
import
org.springframework.web.bind.support.WebDataBinderFactory
;
...
@@ -18,6 +19,7 @@ import cn.timer.api.config.annotation.UserBean;
...
@@ -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.controller.dzht.cn.tign.hz.constant.CacheKeyConstant
;
import
cn.timer.api.dto.yggl.UserInfo
;
import
cn.timer.api.dto.yggl.UserInfo
;
@Slf4j
@Component
@Component
public
class
UserMethodArgumentResolver
implements
HandlerMethodArgumentResolver
{
public
class
UserMethodArgumentResolver
implements
HandlerMethodArgumentResolver
{
...
@@ -49,6 +51,7 @@ public class UserMethodArgumentResolver implements HandlerMethodArgumentResolver
...
@@ -49,6 +51,7 @@ public class UserMethodArgumentResolver implements HandlerMethodArgumentResolver
// NativeWebRequest.SCOPE_SESSION);
// NativeWebRequest.SCOPE_SESSION);
YgglMainEmp
mE
=
eld
.
getYgglMainEmp
();
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
();
UserInfo
userInfo
=
UserInfo
.
builder
().
name
(
mE
.
getName
()).
phone
(
mE
.
getPhone
()).
bmgwId
(
mE
.
getBmgwId
()).
build
();
return
UserBean
.
builder
().
token
(
token
).
refreshToken
(
refreshToken
).
empNum
(
eld
.
getId
())
return
UserBean
.
builder
().
token
(
token
).
refreshToken
(
refreshToken
).
empNum
(
eld
.
getId
())
...
...
src/main/java/cn/timer/api/controller/dzht/cn/tign/hz/constant/CacheKeyConstant.java
View file @
4b121214
...
@@ -17,4 +17,6 @@ public class CacheKeyConstant {
...
@@ -17,4 +17,6 @@ public class CacheKeyConstant {
*/
*/
public
static
final
String
REFRESH_TOKEN
=
"REFRESH_TOKEN"
;
public
static
final
String
REFRESH_TOKEN
=
"REFRESH_TOKEN"
;
public
static
final
String
PREVENT_DUPLICATION_PREFIX
=
"PREVENT_DUPLICATION_PREFIX:"
;
}
}
src/main/java/cn/timer/api/controller/kqgl/ClockInController.java
View file @
4b121214
...
@@ -12,6 +12,7 @@ import java.util.Date;
...
@@ -12,6 +12,7 @@ import java.util.Date;
import
java.util.List
;
import
java.util.List
;
import
java.util.Locale
;
import
java.util.Locale
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.GetMapping
;
...
@@ -76,6 +77,7 @@ import cn.timer.api.utils.ResultUtil;
...
@@ -76,6 +77,7 @@ import cn.timer.api.utils.ResultUtil;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
io.swagger.annotations.ApiOperation
;
@Slf4j
@Api
(
tags
=
"3.0[3]考勤打卡"
)
@Api
(
tags
=
"3.0[3]考勤打卡"
)
@RestController
@RestController
@Transactional
@Transactional
...
@@ -157,6 +159,12 @@ public class ClockInController {
...
@@ -157,6 +159,12 @@ public class ClockInController {
ClockCollectData
clockt
=
new
ClockCollectData
();
ClockCollectData
clockt
=
new
ClockCollectData
();
//putime: 根据日期 得到打卡所需的详细信息
//putime: 根据日期 得到打卡所需的详细信息
AttendanceCardListDto
attdate
=
MethodCall
(
qyid
,
userid
,
ClockInTool
.
paraseStringToDate
(
sStdIoTime
,
"yyyy-MM-dd HH:mm:SS"
));
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);//转换打卡时间格式 年月日
// = new SimpleDateFormat("yyyy-MM-dd").format(sStdIoTime);//转换打卡时间格式 年月日
Long
puttimeTmp
=
0L
;
Long
puttimeTmp
=
0L
;
if
(
attdate
!=
null
&&
attdate
.
getAttsch
()!=
null
&&
attdate
.
getAttsch
().
get
(
0
)!=
null
)
if
(
attdate
!=
null
&&
attdate
.
getAttsch
()!=
null
&&
attdate
.
getAttsch
().
get
(
0
)!=
null
)
...
@@ -3422,15 +3430,16 @@ public class ClockInController {
...
@@ -3422,15 +3430,16 @@ public class ClockInController {
KqglAssoDkjl
dk
=
KqglAssoDkjl
.
builder
().
build
().
selectOne
(
new
QueryWrapper
<
KqglAssoDkjl
>().
lambda
().
eq
(
KqglAssoDkjl:
:
getQyid
,
userBean
.
getOrgCode
())
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
)
.
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
)
.
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
)
{
if
(
dk
!=
null
)
{
AttSchedule
att
=
attsch
.
get
(
dk
.
getSort
()-
1
);
AttSchedule
att
=
attsch
.
get
(
dk
.
getSort
()-
1
);
att
.
setIsupdate
(
1
);
att
.
setIsupdate
(
1
);
if
(
dk
.
getSort
()>
1
)
{
AttSchedule
attw
=
attsch
.
get
(
dk
.
getSort
()-
2
);
AttSchedule
attw
=
attsch
.
get
(
dk
.
getSort
()
-
2
);
attw
.
setIsupdate
(
0
);
attw
.
setIsupdate
(
0
);
}
}
}
}
}
//全部为缺卡时 没有打卡按钮显示
//全部为缺卡时 没有打卡按钮显示
if
(
attsch
.
get
(
0
).
getDajl
().
getId
()
!=
null
&&
iscrdk
)
{
if
(
attsch
.
get
(
0
).
getDajl
().
getId
()
!=
null
&&
iscrdk
)
{
...
...
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