Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yunjiao-admin
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
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
童普新
yunjiao-admin
Commits
28791d16
Commit
28791d16
authored
Jan 08, 2024
by
tongpuxin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
云教投放落地页配置后台、小程序短链接配置后台
parent
88745193
Show whitespace changes
Inline
Side-by-side
Showing
58 changed files
with
4074 additions
and
8 deletions
+4074
-8
pom.xml
pom.xml
+0
-8
ApiConstant.java
src/main/java/com/app/framework/core/api/constant/ApiConstant.java
+23
-0
ApiHttpServletRequestFilter.java
src/main/java/com/app/framework/core/api/filter/ApiHttpServletRequestFilter.java
+122
-0
ApiPaging.java
src/main/java/com/app/framework/core/api/paging/ApiPaging.java
+29
-0
ApiPagingData.java
src/main/java/com/app/framework/core/api/paging/ApiPagingData.java
+99
-0
ApiHttpServletRequest.java
src/main/java/com/app/framework/core/api/request/ApiHttpServletRequest.java
+67
-0
ApiLoginUser.java
src/main/java/com/app/framework/core/api/request/ApiLoginUser.java
+44
-0
ApiService.java
src/main/java/com/app/framework/core/api/service/ApiService.java
+71
-0
ApiExcludeRegisterCenter.java
src/main/java/com/app/framework/core/api/utils/ApiExcludeRegisterCenter.java
+52
-0
ApiLoginUserUtils.java
src/main/java/com/app/framework/core/api/utils/ApiLoginUserUtils.java
+20
-0
ValidException.java
src/main/java/com/app/framework/core/exception/ValidException.java
+25
-0
ValidUtils.java
src/main/java/com/app/framework/core/exception/ValidUtils.java
+34
-0
ExceptionAppenderBase.java
src/main/java/com/app/framework/core/exception/global/appender/ExceptionAppenderBase.java
+15
-0
ExceptionCenterController.java
src/main/java/com/app/framework/core/exception/global/controller/ExceptionCenterController.java
+109
-0
LogOps.java
src/main/java/com/app/framework/core/log/annotation/LogOps.java
+28
-0
LogOpsType.java
src/main/java/com/app/framework/core/log/constant/LogOpsType.java
+41
-0
LogInterceptCenter.java
src/main/java/com/app/framework/core/log/intercept/LogInterceptCenter.java
+25
-0
LogInterceptSupport.java
src/main/java/com/app/framework/core/log/intercept/LogInterceptSupport.java
+17
-0
LogColumn.java
src/main/java/com/app/framework/core/log/result/LogColumn.java
+49
-0
LogResult.java
src/main/java/com/app/framework/core/log/result/LogResult.java
+93
-0
LogResultTask.java
src/main/java/com/app/framework/core/log/task/LogResultTask.java
+57
-0
LoginUser.java
src/main/java/com/app/framework/core/support/auth/LoginUser.java
+62
-0
CrudBaseControllerSupport.java
src/main/java/com/app/framework/core/support/controller/CrudBaseControllerSupport.java
+83
-0
CrudControllerSupport.java
src/main/java/com/app/framework/core/support/controller/CrudControllerSupport.java
+30
-0
ConvertTreeNodeUtils.java
src/main/java/com/app/framework/core/support/convert/ConvertTreeNodeUtils.java
+164
-0
ConvertViewUtils.java
src/main/java/com/app/framework/core/support/convert/ConvertViewUtils.java
+116
-0
BaseEnum.java
src/main/java/com/app/framework/core/support/enums/BaseEnum.java
+98
-0
GenderEnum.java
src/main/java/com/app/framework/core/support/enums/common/GenderEnum.java
+19
-0
PlatformEnum.java
src/main/java/com/app/framework/core/support/enums/common/PlatformEnum.java
+16
-0
StateEnum.java
src/main/java/com/app/framework/core/support/enums/common/StateEnum.java
+19
-0
EnumItem.java
src/main/java/com/app/framework/core/support/enums/data/EnumItem.java
+25
-0
EnumItemPool.java
src/main/java/com/app/framework/core/support/enums/data/EnumItemPool.java
+35
-0
DictEnum.java
src/main/java/com/app/framework/core/support/enums/dict/DictEnum.java
+25
-0
DictMgt.java
src/main/java/com/app/framework/core/support/enums/dict/DictMgt.java
+28
-0
DictEnumConfig.java
src/main/java/com/app/framework/core/support/enums/dict/config/DictEnumConfig.java
+99
-0
DateConvertEditor.java
src/main/java/com/app/framework/core/support/filter/DateConvertEditor.java
+53
-0
CrudBaseMapper.java
src/main/java/com/app/framework/core/support/mapper/CrudBaseMapper.java
+12
-0
Resubmit.java
src/main/java/com/app/framework/core/support/resubmit/Resubmit.java
+31
-0
ResubmitLock.java
src/main/java/com/app/framework/core/support/resubmit/ResubmitLock.java
+90
-0
ResubmitAspect.java
src/main/java/com/app/framework/core/support/resubmit/aspect/ResubmitAspect.java
+102
-0
CrudBaseService.java
src/main/java/com/app/framework/core/support/service/CrudBaseService.java
+20
-0
SequenceService.java
src/main/java/com/app/framework/core/support/service/SequenceService.java
+56
-0
CrudBaseServiceSupport.java
src/main/java/com/app/framework/core/support/service/impl/CrudBaseServiceSupport.java
+82
-0
AjaxResult.java
src/main/java/com/app/framework/core/support/view/form/AjaxResult.java
+251
-0
ModelEditForm.java
src/main/java/com/app/framework/core/support/view/form/ModelEditForm.java
+65
-0
ExGridLoad.java
src/main/java/com/app/framework/core/support/view/grid/ExGridLoad.java
+93
-0
Paging.java
src/main/java/com/app/framework/core/support/view/grid/Paging.java
+261
-0
PagingUtils.java
src/main/java/com/app/framework/core/support/view/grid/PagingUtils.java
+78
-0
ExTreeNode.java
src/main/java/com/app/framework/core/support/view/tree/ExTreeNode.java
+117
-0
ZTreeNode.java
src/main/java/com/app/framework/core/support/view/tree/ZTreeNode.java
+104
-0
DBUtil.java
src/main/java/com/app/framework/core/utils/db/DBUtil.java
+143
-0
UploadUtil.java
src/main/java/com/app/framework/core/utils/file/UploadUtil.java
+208
-0
RangeUtil.java
src/main/java/com/app/framework/core/utils/number/RangeUtil.java
+82
-0
PasswordUtil.java
src/main/java/com/app/framework/core/utils/pwd/PasswordUtil.java
+63
-0
RequestUtil.java
src/main/java/com/app/framework/core/utils/request/RequestUtil.java
+91
-0
SessionUtil.java
src/main/java/com/app/framework/core/utils/request/SessionUtil.java
+84
-0
CaptchaUtil.java
src/main/java/com/app/framework/core/web/captcha/CaptchaUtil.java
+95
-0
WebHttpServletRequestFilter.java
src/main/java/com/app/framework/core/web/filter/WebHttpServletRequestFilter.java
+54
-0
No files found.
pom.xml
View file @
28791d16
...
...
@@ -34,14 +34,6 @@
</properties>
<dependencies>
<!-- 引用公共模块 -->
<dependency>
<groupId>
cn.gladiolus
</groupId>
<artifactId>
gladiolus-core
</artifactId>
<version>
3.0.0
</version>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
...
...
src/main/java/com/app/framework/core/api/constant/ApiConstant.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
api
.
constant
;
/**
* API接口常量类
*/
public
class
ApiConstant
{
/**
* 请求头信息 - 身份认证数据
*/
public
static
final
String
HEADER_AUTHORIZATION
=
"Authorization"
;
/**
* 请求头信息 - 平台
*/
public
static
final
String
HEADER_PLATFORM
=
"Platform"
;
/**
* 身份认证失败
*/
public
static
final
String
ID_AUTH_FAILURE
=
"401"
;
}
src/main/java/com/app/framework/core/api/filter/ApiHttpServletRequestFilter.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
api
.
filter
;
import
cn.hutool.extra.servlet.ServletUtil
;
import
cn.hutool.extra.spring.SpringUtil
;
import
cn.hutool.http.ContentType
;
import
com.alibaba.fastjson.JSON
;
import
com.app.framework.core.api.constant.ApiConstant
;
import
com.app.framework.core.api.request.ApiHttpServletRequest
;
import
com.app.framework.core.api.request.ApiLoginUser
;
import
com.app.framework.core.api.service.ApiService
;
import
com.app.framework.core.api.utils.ApiExcludeRegisterCenter
;
import
com.app.framework.core.support.view.form.AjaxResult
;
import
org.apache.commons.lang.StringUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
javax.servlet.*
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
import
java.nio.charset.StandardCharsets
;
/**
* API接口身份认证拦截器
* 所有资源都是受保护的,需要排除的资源通过ApiExcludeRegisterCenter注册。
* 根据请求头中的Authorization信息,验证用户身份,并将用户ID(apiLoginUserId参数)放入request
*/
public
class
ApiHttpServletRequestFilter
implements
Filter
{
private
Logger
logger
=
LoggerFactory
.
getLogger
(
ApiHttpServletRequestFilter
.
class
);
private
String
loginUri
=
"/login"
;
@Override
public
void
init
(
FilterConfig
filterConfig
)
throws
ServletException
{
String
loginUri
=
filterConfig
.
getInitParameter
(
"loginUri"
);
if
(
StringUtils
.
isNotBlank
(
loginUri
))
{
this
.
loginUri
=
loginUri
;
}
String
excludedUri
=
filterConfig
.
getInitParameter
(
"excludedUri"
);
if
(
StringUtils
.
isNotBlank
(
excludedUri
))
{
String
[]
excludedUris
=
excludedUri
.
split
(
","
);
ApiExcludeRegisterCenter
.
register
(
excludedUris
);
}
}
@Override
public
void
doFilter
(
ServletRequest
srequest
,
ServletResponse
sresponse
,
FilterChain
chain
)
throws
IOException
,
ServletException
{
HttpServletRequest
request
=
(
HttpServletRequest
)
srequest
;
HttpServletResponse
response
=
(
HttpServletResponse
)
sresponse
;
//跨域嗅探(跨域请求时会在真正的请求之前发送一次options请求,用于嗅探.此时是不携带请求头信息的,且不能做其他处理)
if
(
request
.
getMethod
().
equals
(
"OPTIONS"
))
{
chain
.
doFilter
(
srequest
,
sresponse
);
}
//正式请求
else
{
//获取请求的uri
String
uri
=
request
.
getRequestURI
();
//获取Authorization(初次登录时没有Authorization)
String
Authorization
=
request
.
getHeader
(
ApiConstant
.
HEADER_AUTHORIZATION
);
//获取Platform
String
Platform
=
request
.
getHeader
(
ApiConstant
.
HEADER_PLATFORM
);
// if(logger.isInfoEnabled()) {
// logger.info(String.format("身份认证[URI = %s][Authorization = %s][Platform = %s]:", uri, Authorization, Platform));
// }
//认证
if
(
StringUtils
.
isNotBlank
(
loginUri
)
&&
uri
.
indexOf
(
loginUri
)
>
-
1
)
{
//登录,不验证Authorization
chain
.
doFilter
(
srequest
,
sresponse
);
}
else
if
(
ApiExcludeRegisterCenter
.
isExcluded
(
uri
))
{
//被排除的uri,无需认证身份,但获取apiLoginUser值
if
(
StringUtils
.
isNotBlank
(
Authorization
))
{
AjaxResult
<
ApiLoginUser
>
result
=
this
.
IDAuth
(
Authorization
,
Platform
);
if
(
result
.
success
())
{
ApiLoginUser
apiLoginUser
=
result
.
getData
();
request
.
setAttribute
(
"apiLoginUser"
,
apiLoginUser
);
chain
.
doFilter
(
new
ApiHttpServletRequest
(
request
,
apiLoginUser
.
getId
()),
sresponse
);
}
else
{
chain
.
doFilter
(
srequest
,
sresponse
);
}
}
else
{
chain
.
doFilter
(
srequest
,
sresponse
);
}
}
else
{
//其他请求,需验证Authorization
//身份认证
AjaxResult
<
ApiLoginUser
>
result
=
this
.
IDAuth
(
Authorization
,
Platform
);
if
(
result
.
success
())
{
ApiLoginUser
apiLoginUser
=
result
.
getData
();
request
.
setAttribute
(
"apiLoginUser"
,
apiLoginUser
);
chain
.
doFilter
(
new
ApiHttpServletRequest
(
request
,
apiLoginUser
.
getId
()),
sresponse
);
}
else
{
ServletUtil
.
write
(
response
,
JSON
.
toJSONString
(
result
),
ContentType
.
JSON
.
toString
(
StandardCharsets
.
UTF_8
));
}
}
}
}
@Override
public
void
destroy
()
{
}
/**
* 身份认证
*
* @param Authorization
* @param Platform
*/
private
AjaxResult
<
ApiLoginUser
>
IDAuth
(
String
Authorization
,
String
Platform
)
{
AjaxResult
<
ApiLoginUser
>
result
=
AjaxResult
.
wrap
(
false
);
if
(
StringUtils
.
isNotBlank
(
Authorization
))
{
ApiService
apiService
=
SpringUtil
.
getBean
(
ApiService
.
class
);
result
=
apiService
.
checkToken
(
Platform
,
Authorization
);
if
(!
result
.
success
())
{
result
.
setCode
(
ApiConstant
.
ID_AUTH_FAILURE
);
result
.
setMsg
(
"身份认证失败"
);
}
}
else
{
result
.
setCode
(
ApiConstant
.
ID_AUTH_FAILURE
);
result
.
setMsg
(
"请在请求头中传入Authorization参数"
);
}
return
result
;
}
}
src/main/java/com/app/framework/core/api/paging/ApiPaging.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
api
.
paging
;
/**
* Api分页
*/
public
class
ApiPaging
{
/**当前页码*/
private
Integer
page
=
1
;
/**每页显示记录数*/
private
Integer
limit
=
10
;
public
Integer
getPage
()
{
return
page
;
}
public
void
setPage
(
Integer
page
)
{
this
.
page
=
page
;
}
public
Integer
getLimit
()
{
return
limit
;
}
public
void
setLimit
(
Integer
limit
)
{
this
.
limit
=
limit
;
}
}
src/main/java/com/app/framework/core/api/paging/ApiPagingData.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
api
.
paging
;
import
com.app.framework.core.support.view.grid.Paging
;
import
java.util.List
;
/**
* Api分页返回数据
* @param <T>
*/
public
class
ApiPagingData
<
T
>
{
/**
* 分页信息
*/
private
PagingResult
paging
;
/**
* 分页数据
*/
private
List
<
T
>
data
;
public
PagingResult
getPaging
()
{
return
paging
;
}
public
void
setPaging
(
PagingResult
paging
)
{
this
.
paging
=
paging
;
}
public
List
<
T
>
getData
()
{
return
data
;
}
public
void
setData
(
List
<
T
>
data
)
{
this
.
data
=
data
;
}
public
ApiPagingData
(
Paging
paging
,
List
<
T
>
data
){
PagingResult
pagingResult
=
new
PagingResult
();
if
(
paging
!=
null
)
{
pagingResult
.
setPageNo
(
paging
.
getPageNo
());
pagingResult
.
setLimit
(
paging
.
getLimit
());
pagingResult
.
setTotalCount
(
paging
.
getTotalCount
());
pagingResult
.
setTotalPage
(
paging
.
getTotalPage
());
}
this
.
setPaging
(
pagingResult
);
this
.
setData
(
data
);
}
public
class
PagingResult
{
/**当前页码*/
private
Integer
pageNo
;
/**每页显示记录数*/
private
Integer
limit
;
/**总记录*/
private
Long
totalCount
;
/**总页数*/
private
Long
totalPage
;
public
Integer
getPageNo
()
{
return
pageNo
;
}
public
void
setPageNo
(
Integer
pageNo
)
{
this
.
pageNo
=
pageNo
;
}
public
Integer
getLimit
()
{
return
limit
;
}
public
void
setLimit
(
Integer
limit
)
{
this
.
limit
=
limit
;
}
public
Long
getTotalCount
()
{
if
(
totalCount
==
null
){
totalCount
=
0L
;
}
return
totalCount
;
}
public
void
setTotalCount
(
Long
totalCount
)
{
this
.
totalCount
=
totalCount
;
}
public
Long
getTotalPage
()
{
if
(
totalPage
==
null
){
totalPage
=
0L
;
}
return
totalPage
;
}
public
void
setTotalPage
(
Long
totalPage
)
{
this
.
totalPage
=
totalPage
;
}
}
}
src/main/java/com/app/framework/core/api/request/ApiHttpServletRequest.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
api
.
request
;
import
java.util.Collections
;
import
java.util.Enumeration
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletRequestWrapper
;
/**
* Api的HttpServletRequest,主要是完成如下功能:
* 因API要求不直接传递用户信息,而是传递一个token用于身份认证。故通过重写request参数将认证后的用户信息传入请求的方法中,认证失败则直接返回401代码的错误
*
*/
@SuppressWarnings
({
"unchecked"
})
public
class
ApiHttpServletRequest
extends
HttpServletRequestWrapper
{
private
static
final
String
MEMBER_ID
=
"apiLoginUserId"
;
private
Long
apiLoginUserId
=
null
;
public
ApiHttpServletRequest
(
HttpServletRequest
request
)
{
super
(
request
);
}
public
ApiHttpServletRequest
(
HttpServletRequest
request
,
Long
apiLoginUserId
)
{
super
(
request
);
this
.
apiLoginUserId
=
apiLoginUserId
;
}
@Override
public
String
getParameter
(
String
name
)
{
String
value
=
super
.
getParameter
(
name
);
if
(
value
==
null
&&
MEMBER_ID
.
equals
(
name
)
&&
apiLoginUserId
!=
null
)
{
value
=
apiLoginUserId
.
toString
();
}
return
value
;
}
@Override
public
Map
getParameterMap
()
{
Map
map
=
super
.
getParameterMap
();
if
(!
map
.
containsKey
(
MEMBER_ID
)
&&
apiLoginUserId
!=
null
)
{
map
=
new
HashMap
(
map
);
map
.
put
(
MEMBER_ID
,
apiLoginUserId
.
toString
());
}
return
map
;
}
@Override
public
Enumeration
getParameterNames
()
{
if
(
super
.
getParameter
(
MEMBER_ID
)
==
null
&&
apiLoginUserId
!=
null
)
{
return
Collections
.
enumeration
(
getParameterMap
().
keySet
());
}
else
{
return
super
.
getParameterNames
();
}
}
@Override
public
String
[]
getParameterValues
(
String
name
)
{
String
[]
values
=
super
.
getParameterValues
(
name
);
if
(
values
==
null
&&
MEMBER_ID
.
equals
(
name
)
&&
apiLoginUserId
!=
null
)
{
values
=
new
String
[]{
apiLoginUserId
.
toString
()};
}
return
values
;
}
}
\ No newline at end of file
src/main/java/com/app/framework/core/api/request/ApiLoginUser.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
api
.
request
;
import
com.app.framework.core.support.auth.LoginUser
;
import
lombok.Data
;
import
java.io.Serializable
;
/**
* Api登录用户
*/
@Data
public
class
ApiLoginUser
implements
LoginUser
,
Serializable
{
/**
* 用户ID
*/
private
Long
id
;
/**
* 用户姓名
*/
private
String
realName
;
/**
* 用户登录名
*/
private
String
username
;
/**
* 用户类型(1:普通注册用户)
*/
private
Integer
userType
;
/**
* 所属机构ID
*/
private
Long
organizationId
;
public
static
ApiLoginUser
userId
(
Long
userId
)
{
ApiLoginUser
loginUser
=
new
ApiLoginUser
();
loginUser
.
setId
(
userId
);
return
loginUser
;
}
}
src/main/java/com/app/framework/core/api/service/ApiService.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
api
.
service
;
import
cn.hutool.core.date.DateUtil
;
import
com.app.framework.core.api.request.ApiLoginUser
;
import
com.app.framework.core.support.enums.common.PlatformEnum
;
import
com.app.framework.core.support.view.form.AjaxResult
;
import
com.auth0.jwt.JWT
;
import
com.auth0.jwt.JWTCreator
;
import
com.auth0.jwt.JWTVerifier
;
import
com.auth0.jwt.algorithms.Algorithm
;
import
com.auth0.jwt.interfaces.Claim
;
import
com.auth0.jwt.interfaces.DecodedJWT
;
import
java.util.Date
;
import
java.util.Map
;
/**
* Api接口
* 校验验令牌
*/
public
interface
ApiService
{
/**
* 根据平台生成token
*
* @param platform 平台类型{@link PlatformEnum}
* @param expires token有效时间(单位小时,0或null则永久有效)
* @param loginUser 登录用户信息
* @return token
*/
default
String
createToken
(
String
platform
,
Integer
expires
,
ApiLoginUser
loginUser
)
{
JWTCreator
.
Builder
builder
=
JWT
.
create
();
builder
.
withClaim
(
"platform"
,
platform
);
builder
.
withClaim
(
"userId"
,
loginUser
.
getId
());
if
(
expires
!=
null
&&
expires
>
0
)
builder
.
withExpiresAt
(
DateUtil
.
offsetHour
(
new
Date
(),
expires
));
//设置过期时间
return
builder
.
sign
(
Algorithm
.
HMAC256
(
"ApiUserToken"
));
//设置签名 密钥
}
/**
* 校验token并返回登录用户信息
*
* @param platform 平台类型{@link PlatformEnum}
* @param token 用户token
*/
default
AjaxResult
<
ApiLoginUser
>
checkToken
(
String
platform
,
String
token
)
{
try
{
//创建验证对象,这里使用的加密算法和密钥必须与生成TOKEN时的相同否则无法验证
JWTVerifier
jwtVerifier
=
JWT
.
require
(
Algorithm
.
HMAC256
(
"ApiUserToken"
)).
build
();
//验证JWT
DecodedJWT
decodedJWT
=
jwtVerifier
.
verify
(
token
);
Map
<
String
,
Claim
>
claims
=
decodedJWT
.
getClaims
();
Long
userId
=
claims
.
get
(
"userId"
).
asLong
();
return
AjaxResult
.
wrapData
(
ApiLoginUser
.
userId
(
userId
));
}
catch
(
Exception
e
)
{
return
AjaxResult
.
wrapError
(
"身份验证失败"
);
}
}
/**
* 移除用户信息
*
* @param platform 平台类型{@link PlatformEnum}
* @param loginUser 登录用户信息
*/
default
AjaxResult
removeToken
(
String
platform
,
ApiLoginUser
loginUser
)
{
return
AjaxResult
.
wrap
(
false
);
}
}
src/main/java/com/app/framework/core/api/utils/ApiExcludeRegisterCenter.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
api
.
utils
;
import
java.util.Arrays
;
import
java.util.HashSet
;
import
java.util.Set
;
/**
* API接口要排除的uri注册中心
* 通过ApiExcludeRegisterCenter.register(String uri)方法注册
* 在此注册过的uri不会被拦截器拦截
*
*/
public
class
ApiExcludeRegisterCenter
{
/**
* 要排除的uri集合
*/
private
static
Set
<
String
>
excludeList
=
new
HashSet
<>();
/**
* 注册要排除的uri
* @param uri 要排除的uri
*/
public
static
void
register
(
String
uri
){
excludeList
.
add
(
uri
);
}
/**
* 批量注册要排除的uri
* @param array 要排除的uri数组
*/
public
static
void
register
(
String
[]
array
){
if
(
array
!=
null
&&
array
.
length
>
0
){
excludeList
.
addAll
(
Arrays
.
asList
(
array
));
}
}
/**
* 判断请求的URL是否被排除拦截
* @param url 请求的URL
* @return 是否排除
*/
public
static
boolean
isExcluded
(
String
url
)
{
if
(!
excludeList
.
isEmpty
()){
for
(
String
u
:
excludeList
){
if
(
url
.
indexOf
(
u
)
>
-
1
)
return
true
;
}
}
return
false
;
}
}
src/main/java/com/app/framework/core/api/utils/ApiLoginUserUtils.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
api
.
utils
;
import
com.app.framework.core.api.request.ApiLoginUser
;
import
javax.servlet.http.HttpServletRequest
;
/**
* Api登录用户工具类
*/
public
class
ApiLoginUserUtils
{
/**
* 获取Api登录用户
* @param request
* @return
*/
public
static
ApiLoginUser
getLoginUser
(
HttpServletRequest
request
)
{
return
(
ApiLoginUser
)
request
.
getAttribute
(
"apiLoginUser"
);
}
}
src/main/java/com/app/framework/core/exception/ValidException.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
exception
;
/**
* 自定义异常类
* 用于验证失败抛出异常,该异常会通过AjaxResult对象输出至前端
* 此异常不会在控制台抛出(因为在异常控制中心ExceptionCenterController捕获了)
* eg.
* 1)参数必填、格式验证失败
* 2)Service中判断失败需事物回滚
*
*/
public
class
ValidException
extends
RuntimeException
{
private
static
final
long
serialVersionUID
=
1700233072924690954L
;
public
ValidException
(
String
message
,
Throwable
cause
)
{
super
(
message
,
cause
);
}
public
ValidException
(
String
message
)
{
super
(
message
);
}
public
ValidException
(
Throwable
cause
)
{
super
(
cause
);
}
}
src/main/java/com/app/framework/core/exception/ValidUtils.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
exception
;
import
org.apache.commons.lang.exception.ExceptionUtils
;
/**
* 验证异常工具类
*/
public
class
ValidUtils
{
/**
* 抛出异常,expression为true时抛出,否则什么都不做
* @param expression 是否抛出异常
* @param msg 异常消息
*/
public
static
void
valid
(
boolean
expression
,
String
msg
)
{
if
(
expression
)
throw
new
ValidException
(
msg
);
}
/**
* 抛出异常,expression为true时抛出,否则什么都不做
* @param expression 是否抛出异常
*/
public
static
void
validBlank
(
boolean
expression
)
{
if
(
expression
)
{
throw
new
ValidException
(
"必需项不能为空"
);
}
}
public
static
boolean
isValidException
(
Throwable
e
)
{
return
ExceptionUtils
.
indexOfThrowable
(
e
,
ValidException
.
class
)
!=
-
1
;
}
}
src/main/java/com/app/framework/core/exception/global/appender/ExceptionAppenderBase.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
exception
.
global
.
appender
;
import
org.springframework.web.method.HandlerMethod
;
import
javax.servlet.http.HttpServletRequest
;
/**
* 全局异常输出器
* 可自定义输出至DB或MongoDB
*/
public
interface
ExceptionAppenderBase
{
void
append
(
HttpServletRequest
request
,
HandlerMethod
handlerMethod
,
Exception
e
,
long
timeStamp
);
}
src/main/java/com/app/framework/core/exception/global/controller/ExceptionCenterController.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
exception
.
global
.
controller
;
import
cn.hutool.extra.spring.SpringUtil
;
import
com.app.framework.core.exception.ValidException
;
import
com.app.framework.core.exception.global.appender.ExceptionAppenderBase
;
import
com.app.framework.core.support.view.form.AjaxResult
;
import
org.apache.commons.lang.StringUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.dao.DataAccessException
;
import
org.springframework.dao.DataIntegrityViolationException
;
import
org.springframework.web.bind.annotation.ControllerAdvice
;
import
org.springframework.web.bind.annotation.ExceptionHandler
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
org.springframework.web.method.HandlerMethod
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.validation.ConstraintViolationException
;
/**
* 异常中心控制器
* 此处可将异常入库备查
*/
@ControllerAdvice
public
class
ExceptionCenterController
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ExceptionCenterController
.
class
.
getName
());
private
static
String
argEx
[]
=
{
"ClientAbortException"
};
@ExceptionHandler
(
value
=
ValidException
.
class
)
@ResponseBody
public
AjaxResult
exceptionHandler
(
HttpServletRequest
request
,
ValidException
ex
){
return
AjaxResult
.
wrapError
(
ex
.
getMessage
());
}
@ExceptionHandler
(
value
=
Exception
.
class
)
@ResponseBody
public
AjaxResult
exceptionHandler
(
HttpServletRequest
request
,
HandlerMethod
handlerMethod
,
Exception
ex
){
/*
* 处理忽略异常
*/
if
(
isIgnoreException
(
ex
))
{
return
null
;
}
//异常记录
ExceptionAppenderBase
appender
=
SpringUtil
.
getBean
(
ExceptionAppenderBase
.
class
);
if
(
appender
!=
null
){
appender
.
append
(
request
,
handlerMethod
,
ex
,
System
.
currentTimeMillis
());
}
//异常输出至控制台
ex
.
printStackTrace
();
String
error
=
this
.
processException
(
ex
);
return
AjaxResult
.
wrapError
(
error
);
}
private
boolean
isIgnoreException
(
Exception
e
)
{
for
(
String
name
:
argEx
)
{
if
(
name
.
equals
(
e
.
getClass
().
getSimpleName
()))
{
return
true
;
}
}
return
false
;
}
private
String
processException
(
Throwable
exception
)
{
String
resultError
=
""
;
if
(
exception
instanceof
DataIntegrityViolationException
)
{
String
errorMsg
=
exception
.
getMessage
();
if
(
errorMsg
.
indexOf
(
"ORA-02291"
)
>=
0
)
{
errorMsg
=
ExceptionMsgConst
.
MSG_INSERT_FAILED_NOPARENT
;
// 外键引用的表中无此记录(通常情况下可能不会出现此异常,因为前台页面上应该是从下拉列表框中选择而非手工输入数据)
}
else
if
(
errorMsg
.
indexOf
(
"ORA-02292"
)
>=
0
)
{
errorMsg
=
ExceptionMsgConst
.
MSG_DELETE_FAILED_REFERENCED
;
// 作为别的表中的外键且数据被引用
}
else
if
(
errorMsg
.
indexOf
(
"ORA-00001"
)
>=
0
)
{
errorMsg
=
ExceptionMsgConst
.
MSG_INSERT_FAILED_NOTUNIQUE
;
// 数据不唯一
}
else
{
errorMsg
=
ExceptionMsgConst
.
MSG_FAILED_OTHER
;
}
// log.error("数据违反唯一约束条件", exception);
resultError
=
errorMsg
;
}
else
if
(
exception
instanceof
DataAccessException
)
{
// log.error("数据访问异常", exception);
resultError
=
ExceptionMsgConst
.
MSG_FAILED_OTHER
;
}
else
if
(
exception
instanceof
ConstraintViolationException
)
{
// log.error("业务方法执行异常:", exception);
resultError
=
ExceptionMsgConst
.
MSG_DELETE_FAILED_REFERENCED
;
}
else
if
(
exception
instanceof
IllegalArgumentException
)
{
// log.error("业务方法执行异常:", exception);
resultError
=
ExceptionMsgConst
.
MSG_ILLEGAL_ARGUMENT
;
}
if
(
StringUtils
.
isBlank
(
resultError
))
resultError
=
"未知异常"
;
return
resultError
;
}
protected
final
class
ExceptionMsgConst
{
public
static
final
String
MSG_DELETE_FAILED_REFERENCED
=
"删除失败,该条记录被引用"
;
public
static
final
String
MSG_INSERT_FAILED_NOPARENT
=
"添加失败,引用记录不存在"
;
public
static
final
String
MSG_INSERT_FAILED_NOTUNIQUE
=
"添加失败,相同记录已存在"
;
public
static
final
String
MSG_FAILED_OTHER
=
"数据存取失败,请检查数据正确性"
;
public
static
final
String
MSG_ILLEGAL_ARGUMENT
=
"参数不合法"
;
}
}
src/main/java/com/app/framework/core/log/annotation/LogOps.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
log
.
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
;
/**
* 方法执行结束之后切入
*/
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Target
({
ElementType
.
METHOD
})
@Documented
public
@interface
LogOps
{
/**
* 操作类型
* 可自定义
*/
String
type
();
/**
* 操作内容
*/
String
description
()
default
""
;
}
src/main/java/com/app/framework/core/log/constant/LogOpsType.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
log
.
constant
;
/**
* 日志操作类型
*/
public
class
LogOpsType
{
/**
* 登录
*/
public
final
static
String
LOGIN
=
"LOGIN"
;
/**
* 注销
*/
public
final
static
String
LOGOUT
=
"LOGOUT"
;
/**
* 移动端登录
*/
public
final
static
String
MLOGIN
=
"MLOGIN"
;
/**
* 添加
*/
public
final
static
String
ADD
=
"ADD"
;
/**
* 更新
*/
public
final
static
String
UPDATE
=
"UPDATE"
;
/**
* 删除
*/
public
final
static
String
DELETE
=
"DELETE"
;
/**
* 同步
*/
public
final
static
String
PUSH
=
"PUSH"
;
}
src/main/java/com/app/framework/core/log/intercept/LogInterceptCenter.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
log
.
intercept
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* 日志记录器注册中心
* 用来关联拦截的class 与 具体的日志记录器
*/
public
class
LogInterceptCenter
{
private
static
Map
<
Class
<?>,
Class
<?>>
map
=
new
HashMap
<
Class
<?>,
Class
<?>>();
public
static
Class
<?>
getHandler
(
Class
<?>
c
)
{
return
map
.
get
(
c
);
}
/**
* 注册日志拦截器
* @param c 要拦截日志的class
* @param interceptClass 拦截器class
*/
public
static
void
register
(
Class
<?>
c
,
Class
<?>
interceptClass
){
map
.
put
(
c
,
interceptClass
);
}
}
src/main/java/com/app/framework/core/log/intercept/LogInterceptSupport.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
log
.
intercept
;
import
cn.hutool.core.util.TypeUtil
;
/**
* 日志拦截器基类
* [子类注意:拦截器中定义的方法必须与Controller中对应的方法同名同参]
*
* @param <Controller> 需要拦截的Controller
*/
public
class
LogInterceptSupport
<
Controller
>
{
public
LogInterceptSupport
(){
Class
<?>
controllerClass
=
(
Class
)
TypeUtil
.
getTypeArgument
(
getClass
());
LogInterceptCenter
.
register
(
controllerClass
,
getClass
());
}
}
src/main/java/com/app/framework/core/log/result/LogColumn.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
log
.
result
;
/**
* 日志列对象
* 操作的列信息
*/
public
class
LogColumn
{
private
String
columnKey
;
private
String
columnName
;
private
Object
columnValue
;
public
LogColumn
(
String
columnKey
,
String
columnName
,
Object
columnValue
)
{
super
();
this
.
columnKey
=
columnKey
;
this
.
columnName
=
columnName
;
this
.
columnValue
=
columnValue
;
}
public
String
getColumnKey
()
{
return
columnKey
;
}
public
void
setColumnKey
(
String
columnKey
)
{
this
.
columnKey
=
columnKey
;
}
public
String
getColumnName
()
{
return
columnName
;
}
public
void
setColumnName
(
String
columnName
)
{
this
.
columnName
=
columnName
;
}
public
Object
getColumnValue
()
{
return
columnValue
;
}
public
void
setColumnValue
(
Object
columnValue
)
{
this
.
columnValue
=
columnValue
;
}
public
boolean
isColumnValueEmpty
()
{
if
(
columnValue
==
null
||
columnValue
.
toString
().
equals
(
""
))
return
true
;
return
false
;
}
}
src/main/java/com/app/framework/core/log/result/LogResult.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
log
.
result
;
import
org.apache.commons.lang.StringUtils
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* 日志结果对象
* 操作类型和操作的列
*/
public
class
LogResult
{
/** 操作人ID */
private
Long
operatorId
;
/** 操作人姓名 */
private
String
operatorName
;
/** 操作类型 */
private
String
operType
;
/** 操作字段集合 */
private
List
<
LogColumn
>
logColumns
=
new
ArrayList
<
LogColumn
>();
public
LogResult
()
{}
public
LogResult
(
String
operType
)
{
this
.
operType
=
operType
;
}
public
Long
getOperatorId
()
{
return
operatorId
;
}
public
void
setOperatorId
(
Long
operatorId
)
{
this
.
operatorId
=
operatorId
;
}
public
String
getOperatorName
()
{
return
operatorName
;
}
public
void
setOperatorName
(
String
operatorName
)
{
this
.
operatorName
=
operatorName
;
}
public
String
getOperType
()
{
return
operType
;
}
public
void
setOperType
(
String
operType
)
{
this
.
operType
=
operType
;
}
public
LogResult
addColumn
(
String
key
,
String
column
,
Object
v
)
{
logColumns
.
add
(
new
LogColumn
(
key
,
column
,
v
));
return
this
;
}
public
LogResult
addColumn
(
LogColumn
column
)
{
logColumns
.
add
(
column
);
return
this
;
}
public
List
<
LogColumn
>
getLogColumns
()
{
return
logColumns
;
}
public
void
setLogColumns
(
List
<
LogColumn
>
logColumns
)
{
this
.
logColumns
=
logColumns
;
}
/**
* 处理 columnList
* @return
*/
public
String
processLogColmnList
()
{
StringBuilder
str
=
new
StringBuilder
();
for
(
int
i
=
0
,
size
=
logColumns
.
size
();
i
<
size
;
i
++)
{
LogColumn
column
=
logColumns
.
get
(
i
);
if
(
StringUtils
.
isNotBlank
(
column
.
getColumnName
())){
str
.
append
(
column
.
getColumnName
());
str
.
append
(
":"
);
}
if
(!
column
.
isColumnValueEmpty
())
{
str
.
append
(
column
.
getColumnValue
());
}
if
(
i
<
size
-
1
)
str
.
append
(
","
);
}
return
str
.
toString
();
}
}
src/main/java/com/app/framework/core/log/task/LogResultTask.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
log
.
task
;
import
cn.hutool.core.util.ClassUtil
;
import
cn.hutool.core.util.ReflectUtil
;
import
cn.hutool.extra.spring.SpringUtil
;
import
com.app.framework.core.log.intercept.LogInterceptCenter
;
import
com.app.framework.core.log.result.LogResult
;
import
org.aspectj.lang.JoinPoint
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.lang.reflect.Method
;
public
class
LogResultTask
{
Logger
logger
=
LoggerFactory
.
getLogger
(
LogResultTask
.
class
.
getName
());
public
LogResult
logResult
(
JoinPoint
jp
){
LogResult
logResult
=
null
;
//获取拦截方法信息
String
targetMethodName
=
jp
.
getSignature
().
getName
();
// 拦截方法名
Class
<?>
targetClass
=
jp
.
getTarget
().
getClass
();
// 拦截class
Object
[]
args
=
jp
.
getArgs
();
// 拦截参数
// 匹配interceptClass
Class
<?>
interceptClass
=
LogInterceptCenter
.
getHandler
(
targetClass
);
if
(
interceptClass
==
null
)
{
logger
.
warn
(
String
.
format
(
"don't find interceptClass, targetClass:[%s]"
,
targetClass
));
return
logResult
;
}
// 从容器中获取拦截器实例
Object
interceptObject
=
SpringUtil
.
getBean
(
interceptClass
);
if
(
interceptObject
==
null
){
logger
.
warn
(
"interceptObject is null"
);
return
logResult
;
}
// 利用反射从拦截器中取得对应的日志处理函数
Method
findMethod
=
ReflectUtil
.
getMethod
(
interceptClass
,
targetMethodName
,
ClassUtil
.
getClasses
(
args
));
if
(
findMethod
==
null
)
{
// logger.warn(String.format("class : [%s], paramTypes : [%s] find method : [%s] failure", interceptClass, Arrays.toString(paramsTypes), targetMethodName));
logger
.
warn
(
String
.
format
(
"class : [%s] find method : [%s] failure"
,
interceptClass
,
targetMethodName
));
return
logResult
;
}
// 处理具体日志方法
Object
resultObject
=
null
;
try
{
// 具体日志处理方法
resultObject
=
findMethod
.
invoke
(
interceptObject
,
args
);
}
catch
(
Exception
e
)
{
logger
.
error
(
String
.
format
(
"[%s] invoke method : [%s] failure"
,
interceptClass
,
targetMethodName
),
e
);
}
// 处理和解析对象输出日志
if
(
resultObject
!=
null
)
{
logResult
=
(
LogResult
)
resultObject
;
}
return
logResult
;
}
}
src/main/java/com/app/framework/core/support/auth/LoginUser.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
auth
;
/**
* 登录用户接口 存入session的登录用户对象必须实现该接口
*/
public
interface
LoginUser
{
/**
* 默认密码
*/
public
final
static
String
DEFAULT_PWD
=
"e10adc3949ba59abbe56e057f20f883e"
;
/**
* 机构(平台方)
*/
public
final
static
Long
ORGANIZATION_SUPER
=
0L
;
/**
* 用户类型(超级管理员)
*/
public
final
static
Integer
TYPE_SUPER
=
0
;
/**
* 用户类型(机构管理员,机构创建时同步创建)
*/
public
final
static
Integer
TYPE_ADMIN
=
1
;
/**
* 用户类型(普通管理员即员工)
*/
public
final
static
Integer
TYPE_EMP
=
2
;
/**
* 获取登录账号Id
*
* @return Long
*/
Long
getId
();
/**
* 获取登录用户姓名
*
* @return String
*/
String
getRealName
();
/**
* 获取登录名
*
* @return String
*/
String
getUsername
();
/**
* 获取用户类型
*/
Integer
getUserType
();
/**
* 获取所属机构ID
*/
Long
getOrganizationId
();
}
\ No newline at end of file
src/main/java/com/app/framework/core/support/controller/CrudBaseControllerSupport.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
controller
;
import
com.app.framework.core.log.annotation.LogOps
;
import
com.app.framework.core.log.constant.LogOpsType
;
import
com.app.framework.core.support.view.form.AjaxResult
;
import
com.app.framework.core.support.view.grid.ExGridLoad
;
import
com.app.framework.core.support.view.grid.Paging
;
import
org.springframework.util.Assert
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
javax.servlet.http.HttpServletRequest
;
import
java.util.List
;
/**
* Controller基类,所有Controller都必须继承该类
* 提供获取请求头信息的各种方法
* 提供获取参数的各种方法
* 提供基础的增删改查请求
*/
public
abstract
class
CrudBaseControllerSupport
<
E
>
extends
CrudControllerSupport
{
/**
* 查询列表的具体实现
* @param request HttpServletRequest
* @param view 查询条件
* @param paging 分页条件
* @return 查询结果
*/
public
abstract
<
V
>
List
<
V
>
list
(
HttpServletRequest
request
,
final
E
view
,
Paging
paging
);
/**
* 保存记录的具体实现
* @param request HttpServletRequest
* @param entity 实体对象
*/
public
abstract
AjaxResult
saveEntity
(
HttpServletRequest
request
,
E
entity
);
/**
* 批量删除记录,根据Id
* @param request HttpServletRequest
* @param oids 主键Id数组
*/
public
abstract
AjaxResult
batchDelete
(
HttpServletRequest
request
,
Long
oids
[]);
/**
* 查询所有记录,支持分页
*/
@RequestMapping
(
value
=
"/list"
)
public
@ResponseBody
ExGridLoad
listByPaging
(
HttpServletRequest
request
,
E
view
,
Paging
paging
)
{
List
<
E
>
views
=
this
.
list
(
request
,
view
,
paging
);
return
ExGridLoad
.
wrapExGridLoad
(
views
,
paging
);
}
/**
* 保存记录
*/
@RequestMapping
(
value
=
"/saveEntity"
)
@LogOps
(
type
=
LogOpsType
.
UPDATE
)
public
@ResponseBody
AjaxResult
saveByEntity
(
HttpServletRequest
request
,
E
entity
){
return
this
.
saveEntity
(
request
,
entity
);
}
/**
* 删除记录,根据Id
*/
@RequestMapping
(
value
=
"/deleteById"
)
@LogOps
(
type
=
LogOpsType
.
DELETE
)
public
@ResponseBody
AjaxResult
deleteById
(
HttpServletRequest
request
,
Long
oid
)
{
Assert
.
notNull
(
oid
,
"id不能为空."
);
return
this
.
batchDelete
(
request
,
new
Long
[]{
oid
});
}
/**
* 批量删除记录,根据Id
*/
@RequestMapping
(
value
=
"/batchDelete"
)
@LogOps
(
type
=
LogOpsType
.
DELETE
)
public
@ResponseBody
AjaxResult
deleteByBatch
(
HttpServletRequest
request
,
Long
oids
[])
{
Assert
.
notNull
(
oids
,
"ids不能为空."
);
return
this
.
batchDelete
(
request
,
oids
);
}
}
src/main/java/com/app/framework/core/support/controller/CrudControllerSupport.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
controller
;
import
com.app.framework.core.support.filter.DateConvertEditor
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.propertyeditors.StringTrimmerEditor
;
import
org.springframework.web.bind.WebDataBinder
;
import
org.springframework.web.bind.annotation.InitBinder
;
import
java.util.Date
;
/**
* Controller基类,所有Controller都必须继承该类
* 提供获取请求头信息的各种方法
* 提供获取参数的各种方法
*/
public
abstract
class
CrudControllerSupport
{
protected
Logger
logger
=
null
;
public
CrudControllerSupport
(){
logger
=
LoggerFactory
.
getLogger
(
getClass
().
getName
());
}
@InitBinder
public
void
initBinder
(
WebDataBinder
binder
)
{
binder
.
registerCustomEditor
(
Date
.
class
,
null
,
new
DateConvertEditor
());
binder
.
registerCustomEditor
(
String
.
class
,
new
StringTrimmerEditor
(
true
));
}
}
src/main/java/com/app/framework/core/support/convert/ConvertTreeNodeUtils.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
convert
;
import
cn.hutool.core.util.TypeUtil
;
import
com.app.framework.core.support.view.tree.ExTreeNode
;
import
java.util.ArrayList
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Set
;
/**
* Entity转TreeNode工具类
* 用法:继承该类,并实现convert(E entity, T view)方法
*
* @param <E> Entity
* @param <T> TreeNode
*/
public
abstract
class
ConvertTreeNodeUtils
<
E
,
T
extends
ExTreeNode
>
{
protected
Class
<
T
>
viewClass
;
private
LinkedHashMap
<
String
,
T
>
retp
=
new
LinkedHashMap
<
String
,
T
>();
@SuppressWarnings
(
"unchecked"
)
public
ConvertTreeNodeUtils
()
{
viewClass
=
(
Class
)
TypeUtil
.
getTypeArgument
(
getClass
(),
1
);
}
/**
* 将Entity转换为TreeNode
* @param entity 要转换的Entity对象
*/
public
T
transTreeNode
(
E
entity
)
{
try
{
T
node
=
viewClass
.
newInstance
();
if
(
entity
!=
null
)
{
convert
(
entity
,
node
);
}
return
node
;
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
/**
* 将Entity集合转换为TreeNode集合
* @param list 要转换的Entity集合
*/
public
List
<
T
>
transTreeNode
(
List
<
E
>
list
)
{
int
size
=
list
!=
null
?
list
.
size
()
:
0
;
List
<
T
>
result
=
new
ArrayList
<>(
size
);
try
{
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
E
entity
=
list
.
get
(
i
);
T
node
=
viewClass
.
newInstance
();
convert
(
entity
,
node
);
result
.
add
(
node
);
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
result
;
}
/**
* 将Entity集合转换为TreeNode集合,静态树
* @param list 要转换的Entity集合
*/
public
List
<
T
>
transStaticTree
(
List
<
E
>
list
)
{
return
transStaticTree
(
list
,
null
,
null
);
}
/**
* 将Entity集合转换为TreeNode集合,静态树
* @param list 要转换的Entity集合
* @param checkedOidSet 已选择的节点OID集合
*/
public
List
<
T
>
transStaticTree
(
List
<
E
>
list
,
Set
<
String
>
checkedOidSet
)
{
return
transStaticTree
(
list
,
null
,
checkedOidSet
);
}
/**
* 将Entity集合转换为TreeNode集合,静态树
* @param list 要转换的Entity集合
* @param root 添加一个根节点
* @param checkedOidSet 已选择的节点OID集合
*/
public
List
<
T
>
transStaticTree
(
List
<
E
>
list
,
T
root
,
Set
<
String
>
checkedOidSet
)
{
int
size
=
list
!=
null
?
list
.
size
()
:
0
;
ArrayList
<
T
>
treeNodes
;
if
(
null
!=
root
){
treeNodes
=
new
ArrayList
<
T
>(
size
+
1
);
root
.
setParentId
(
null
);
treeNodes
.
add
(
root
);
}
else
{
treeNodes
=
new
ArrayList
<>(
size
);
}
try
{
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
E
entity
=
list
.
get
(
i
);
T
node
=
viewClass
.
newInstance
();
convert
(
entity
,
node
);
if
(
node
.
getId
()
==
null
){
throw
new
Exception
(
"TreeNode id is null"
);
}
nodeCheck
(
node
,
checkedOidSet
);
if
(
null
!=
root
&&
node
.
getId
().
equals
(
root
.
getId
())){
//根节点
//此时根节点已在treeNodes中,不能再次加入
}
else
{
treeNodes
.
add
(
node
);
}
if
(
node
.
getParentId
()
!=
null
&&
!
node
.
getParentId
().
equals
(
"0"
)){
retp
.
put
(
node
.
getId
(),
node
);
}
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
transStaticTree
(
treeNodes
);
}
/**
* 将TreeNode集合生成静态树,静态树
* @param list 要转换的TreeNode集合
*/
private
List
<
T
>
transStaticTree
(
ArrayList
<
T
>
list
)
{
int
size
=
list
!=
null
?
list
.
size
()
:
0
;
if
(
retp
.
size
()
<
1
){
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
T
node
=
list
.
get
(
i
);
if
(
node
.
getParentId
()
!=
null
&&
!
node
.
getParentId
().
equals
(
"0"
)){
retp
.
put
(
node
.
getId
(),
node
);
}
}
}
List
<
T
>
completeTree
=
new
ArrayList
<
T
>();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
T
node
=
list
.
get
(
i
);
if
(
node
.
getParentId
()
==
null
||
node
.
getParentId
().
equals
(
"0"
))
{
node
=
node
.
buildTree
(
node
,
retp
);
completeTree
.
add
(
node
);
}
}
retp
.
clear
();
return
completeTree
;
}
/**
* 自定义转换
* @param entity Entity对象
* @param node TreeNode对象
*/
public
abstract
void
convert
(
E
entity
,
T
node
);
/**
* 设置节点是否选中
* 子类可自行重写
* @param node 节点
* @param checkedOidSet 选中的ID集合
*/
public
void
nodeCheck
(
T
node
,
Set
<
String
>
checkedOidSet
){
}
}
src/main/java/com/app/framework/core/support/convert/ConvertViewUtils.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
convert
;
import
cn.hutool.core.util.TypeUtil
;
import
org.springframework.beans.BeanUtils
;
import
java.text.ParseException
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* Entity转View工具类
* 用法:继承该类,并实现convert(E entity, V view)方法
*
* @param <E> Entity
* @param <V> View
*/
public
abstract
class
ConvertViewUtils
<
E
,
V
>
{
protected
Class
<
V
>
viewClass
;
@SuppressWarnings
(
"unchecked"
)
public
ConvertViewUtils
()
{
viewClass
=
(
Class
)
TypeUtil
.
getTypeArgument
(
getClass
(),
1
);
}
/**
* 将实体E转换成View,可忽略属性
* 返回页面时进行数据转换
* @param entity 需要转换的Entity
*/
public
V
transform
(
E
entity
)
{
try
{
V
view
=
viewClass
.
newInstance
();
if
(
entity
!=
null
)
{
BeanUtils
.
copyProperties
(
entity
,
view
);
convert
(
entity
,
view
);
}
return
view
;
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
/**
* 将实体E转换成View,可忽略属性
* 返回页面时进行数据转换
* @param entity 需要转换的Entity
* @param ignoreProperties 需要忽略的属性
*/
public
V
transform
(
E
entity
,
String
...
ignoreProperties
)
{
try
{
V
view
=
viewClass
.
newInstance
();
if
(
entity
!=
null
)
{
BeanUtils
.
copyProperties
(
entity
,
view
,
ignoreProperties
);
convert
(
entity
,
view
);
}
return
view
;
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
/**
* 将实体E的集合转换成View的集合,可忽略属性
*
* @param list 需要转换的数据集合
*/
public
List
<
V
>
transform
(
List
<
E
>
list
){
int
size
=
list
!=
null
?
list
.
size
()
:
0
;
List
<
V
>
result
=
new
ArrayList
<>(
size
);
try
{
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
E
entity
=
list
.
get
(
i
);
V
view
=
viewClass
.
newInstance
();
BeanUtils
.
copyProperties
(
entity
,
view
);
convert
(
entity
,
view
);
result
.
add
(
view
);
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
result
;
}
/**
* 将实体E的集合转换成View的集合,可忽略属性
*
* @param list 需要转换的数据集合
* @param ignoreProperties 需要忽略的属性, 可选参数
*/
public
List
<
V
>
transform
(
List
<
E
>
list
,
String
...
ignoreProperties
)
{
int
size
=
list
!=
null
?
list
.
size
()
:
0
;
List
<
V
>
result
=
new
ArrayList
<>(
size
);
try
{
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
E
entity
=
list
.
get
(
i
);
V
view
=
viewClass
.
newInstance
();
BeanUtils
.
copyProperties
(
entity
,
view
,
ignoreProperties
);
convert
(
entity
,
view
);
result
.
add
(
view
);
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
result
;
}
/**
* 自定义转换(基类中已实现实体E到V的转换,该方法只需要实现其他附加的转换功能即可)
* @param entity 实体类对象
* @param view View对象
*/
public
abstract
void
convert
(
E
entity
,
V
view
)
throws
ParseException
;
}
src/main/java/com/app/framework/core/support/enums/BaseEnum.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
enums
;
import
com.app.framework.core.support.enums.data.EnumItem
;
import
com.app.framework.core.support.enums.data.EnumItemPool
;
import
org.apache.commons.lang.StringUtils
;
import
java.io.Serializable
;
import
java.util.Objects
;
import
java.util.Optional
;
import
java.util.stream.Stream
;
/**
* 枚举基类,提供枚举常用的方法
* 提供实例方法:getValue、getText、equalValue、isNotEquals
* 提供静态方法:getByValue、getByText、getTextByValue
*
* @param <K> value数据类型
*/
public
interface
BaseEnum
<
K
extends
Serializable
>
{
default
void
putEnumItem
(
K
value
,
String
text
)
{
EnumItemPool
.
putEnumItem
(
this
,
value
,
text
);
}
default
EnumItem
getEnumItem
()
{
return
EnumItemPool
.
getEnumItem
(
this
);
}
default
K
getValue
()
{
return
(
K
)
getEnumItem
().
getValue
();
}
default
String
getText
()
{
return
getEnumItem
().
getText
();
}
/**
* 当前对象的 value 是否 和参数中的 value 相等
*
* @param value
* @return
*/
default
boolean
equalValue
(
K
value
)
{
return
this
.
getValue
().
equals
(
value
);
}
/**
* 当前对象是否和已知对象不等
*
* @param item
* @return
*/
default
boolean
isNotEquals
(
BaseEnum
item
)
{
return
this
!=
item
;
}
/**
* 通过 value 获取指定 枚举类型中的 枚举对象
*
* @param enumClass
* @param value
* @param <T>
* @return
*/
static
<
T
extends
BaseEnum
>
T
getByValue
(
Class
<
T
>
enumClass
,
Serializable
value
)
{
if
(
Objects
.
isNull
(
value
))
{
return
null
;
}
return
Stream
.
of
(
enumClass
.
getEnumConstants
()).
filter
(
x
->
x
.
getValue
().
equals
(
value
)).
findAny
().
orElse
(
null
);
}
/**
* 通过 text 获取指定 枚举类型中的 枚举对象
*
* @param enumClass 枚举类
* @param text
* @param <T>
* @return
*/
static
<
T
extends
BaseEnum
>
T
getByText
(
Class
<
T
>
enumClass
,
String
text
)
{
if
(
Objects
.
isNull
(
text
))
{
return
null
;
}
return
Stream
.
of
(
enumClass
.
getEnumConstants
()).
filter
(
x
->
x
.
getText
().
equals
(
text
)).
findAny
().
orElse
(
null
);
}
/**
* 通过 value 获取指定 枚举类型中的 text
*
* @param enumClass
* @param value
* @param <T>
* @return
*/
static
<
T
extends
BaseEnum
>
String
getTextByValue
(
Class
<
T
>
enumClass
,
Serializable
value
)
{
return
Optional
.
ofNullable
(
getByValue
(
enumClass
,
value
)).
map
(
BaseEnum:
:
getText
).
orElse
(
StringUtils
.
EMPTY
);
}
}
src/main/java/com/app/framework/core/support/enums/common/GenderEnum.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
enums
.
common
;
import
com.app.framework.core.support.enums.BaseEnum
;
import
com.app.framework.core.support.enums.dict.DictEnum
;
/**
* 性别枚举
* 性别(0-女 1-男 2-保密)
*/
@DictEnum
(
type
=
"genderEnum"
,
desc
=
"性别"
)
public
enum
GenderEnum
implements
BaseEnum
<
Integer
>
{
MAN
(
1
,
"男"
),
WOMAN
(
0
,
"女"
),
BAOMI
(
2
,
"保密"
);
GenderEnum
(
Integer
value
,
String
text
)
{
putEnumItem
(
value
,
text
);
}
}
src/main/java/com/app/framework/core/support/enums/common/PlatformEnum.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
enums
.
common
;
import
com.app.framework.core.support.enums.BaseEnum
;
/**
* 平台枚举
* 平台(ALL-全站 IOS-IOS ANDROID-安卓 3-web站 WAP-wap站)
*/
public
enum
PlatformEnum
implements
BaseEnum
<
String
>
{
ALL
(
"ALL"
,
"全站"
),
IOS
(
"IOS"
,
"IOS"
),
ANDROID
(
"ANDROID"
,
"安卓"
),
WEB
(
"WEB"
,
"web站"
),
WAP
(
"WAP"
,
"wap站"
);
PlatformEnum
(
String
value
,
String
text
)
{
putEnumItem
(
value
,
text
);
}
}
src/main/java/com/app/framework/core/support/enums/common/StateEnum.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
enums
.
common
;
import
com.app.framework.core.support.enums.BaseEnum
;
import
com.app.framework.core.support.enums.dict.DictEnum
;
/**
* 状态枚举
* 状态(1-启用 2-禁用 3-删除)
*/
@DictEnum
(
desc
=
"状态"
)
public
enum
StateEnum
implements
BaseEnum
<
Integer
>
{
NORMAL
(
1
,
"启用"
),
DISABLE
(
2
,
"禁用"
),
DELETE
(
3
,
"删除"
);
StateEnum
(
Integer
value
,
String
text
)
{
putEnumItem
(
value
,
text
);
}
}
src/main/java/com/app/framework/core/support/enums/data/EnumItem.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
enums
.
data
;
import
lombok.Getter
;
import
lombok.Setter
;
import
lombok.ToString
;
import
java.io.Serializable
;
/**
* 枚举项
*/
@Setter
@Getter
@ToString
public
class
EnumItem
implements
Serializable
{
private
Serializable
value
;
private
String
text
;
public
EnumItem
(
Serializable
value
,
String
text
)
{
this
.
value
=
value
;
this
.
text
=
text
;
}
}
src/main/java/com/app/framework/core/support/enums/data/EnumItemPool.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
enums
.
data
;
import
com.app.framework.core.support.enums.BaseEnum
;
import
java.io.Serializable
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
* 存储枚举数据
*/
public
class
EnumItemPool
{
private
EnumItemPool
()
{}
/**
* 用于存储枚举数据
*/
private
static
final
Map
<
BaseEnum
,
EnumItem
>
enumItemMap
=
new
ConcurrentHashMap
<>();
/**
* 往 map 中添加枚举项
*/
public
static
<
K
extends
Serializable
>
void
putEnumItem
(
BaseEnum
baseEnum
,
K
value
,
String
label
)
{
enumItemMap
.
put
(
baseEnum
,
new
EnumItem
(
value
,
label
));
}
/**
* 获取静态数据
*/
public
static
EnumItem
getEnumItem
(
BaseEnum
baseEnum
)
{
return
enumItemMap
.
get
(
baseEnum
);
}
}
src/main/java/com/app/framework/core/support/enums/dict/DictEnum.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
enums
.
dict
;
import
java.lang.annotation.*
;
/**
* 用于标记枚举需转换为字典使用
*/
@Target
({
ElementType
.
METHOD
,
ElementType
.
TYPE
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Inherited
@Documented
public
@interface
DictEnum
{
/**
* 字典标识
*/
String
type
()
default
""
;
/**
* 字典标识名称
*/
String
desc
()
default
""
;
}
src/main/java/com/app/framework/core/support/enums/dict/DictMgt.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
enums
.
dict
;
import
com.app.framework.core.support.enums.data.EnumItem
;
import
lombok.Data
;
import
java.util.List
;
/**
* 枚举转字典使用
*/
@Data
public
class
DictMgt
{
/**
* 字典标识
*/
private
String
type
;
/**
* 字典标识名称
*/
private
String
desc
;
/**
* 字典值列表
*/
private
List
<
EnumItem
>
dictItemList
;
}
src/main/java/com/app/framework/core/support/enums/dict/config/DictEnumConfig.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
enums
.
dict
.
config
;
import
cn.hutool.core.map.MapUtil
;
import
com.app.framework.core.support.enums.BaseEnum
;
import
com.app.framework.core.support.enums.data.EnumItem
;
import
com.app.framework.core.support.enums.dict.DictEnum
;
import
com.app.framework.core.support.enums.dict.DictMgt
;
import
org.apache.commons.lang.StringUtils
;
import
org.springframework.beans.factory.InitializingBean
;
import
org.springframework.beans.factory.annotation.AnnotatedBeanDefinition
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.config.BeanDefinition
;
import
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider
;
import
org.springframework.core.env.Environment
;
import
org.springframework.core.io.ResourceLoader
;
import
org.springframework.core.type.AnnotationMetadata
;
import
org.springframework.core.type.filter.AnnotationTypeFilter
;
import
org.springframework.stereotype.Component
;
import
java.util.*
;
import
java.util.stream.Collectors
;
@Component
public
class
DictEnumConfig
implements
InitializingBean
{
@Autowired
private
ResourceLoader
resourceLoader
;
@Autowired
private
Environment
environment
;
private
static
Map
<
String
,
DictMgt
>
dictMap
=
new
HashMap
<>();
public
static
Map
<
String
,
DictMgt
>
getDictMap
()
{
return
dictMap
;
}
public
static
DictMgt
getDict
(
String
type
)
{
return
dictMap
.
get
(
type
);
}
public
static
List
<
EnumItem
>
getDictItem
(
String
type
)
{
DictMgt
dictMgt
=
getDict
(
type
);
return
dictMgt
!=
null
?
dictMgt
.
getDictItemList
()
:
null
;
}
@Override
public
void
afterPropertiesSet
()
throws
ClassNotFoundException
{
String
basePackage
=
"com.app"
;
// 创建scanner
ClassPathScanningCandidateComponentProvider
scanner
=
getScanner
();
scanner
.
setResourceLoader
(
resourceLoader
);
// 设置扫描器scanner扫描的过滤条件
AnnotationTypeFilter
annotationTypeFilter
=
new
AnnotationTypeFilter
(
DictEnum
.
class
);
scanner
.
addIncludeFilter
(
annotationTypeFilter
);
// 通过scanner获取basePackage下的候选类(有标@SimpleRpcClient注解的类)
Set
<
BeanDefinition
>
candidateComponents
=
scanner
.
findCandidateComponents
(
basePackage
);
// 遍历每一个候选类
for
(
BeanDefinition
candidateComponent
:
candidateComponents
)
{
if
(
candidateComponent
instanceof
AnnotatedBeanDefinition
)
{
AnnotatedBeanDefinition
beanDefinition
=
(
AnnotatedBeanDefinition
)
candidateComponent
;
AnnotationMetadata
annotationMetadata
=
beanDefinition
.
getMetadata
();
Map
<
String
,
Object
>
attributes
=
annotationMetadata
.
getAnnotationAttributes
(
DictEnum
.
class
.
getCanonicalName
());
final
Class
<?>
cls
=
Class
.
forName
(
beanDefinition
.
getBeanClassName
());
BaseEnum
[]
enumConstants
=
(
BaseEnum
[])
cls
.
getEnumConstants
();
List
<
EnumItem
>
dictItemList
=
Arrays
.
stream
(
enumConstants
).
map
(
e
->
{
return
new
EnumItem
(
e
.
getValue
(),
e
.
getText
());
}).
collect
(
Collectors
.
toList
());
DictMgt
dictMgt
=
new
DictMgt
();
dictMgt
.
setType
(
StringUtils
.
defaultIfBlank
(
MapUtil
.
getStr
(
attributes
,
"type"
),
StringUtils
.
uncapitalize
(
cls
.
getSimpleName
())));
dictMgt
.
setDesc
(
MapUtil
.
getStr
(
attributes
,
"desc"
));
dictMgt
.
setDictItemList
(
dictItemList
);
dictMap
.
put
(
dictMgt
.
getType
(),
dictMgt
);
}
}
}
/**
* 创建扫描器
*/
protected
ClassPathScanningCandidateComponentProvider
getScanner
()
{
return
new
ClassPathScanningCandidateComponentProvider
(
false
,
environment
)
{
@Override
protected
boolean
isCandidateComponent
(
AnnotatedBeanDefinition
beanDefinition
)
{
boolean
isCandidate
=
false
;
if
(
beanDefinition
.
getMetadata
().
isIndependent
())
{
if
(!
beanDefinition
.
getMetadata
().
isAnnotation
())
{
isCandidate
=
true
;
}
}
return
isCandidate
;
}
};
}
}
src/main/java/com/app/framework/core/support/filter/DateConvertEditor.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
filter
;
import
java.beans.PropertyEditorSupport
;
import
java.text.ParseException
;
import
java.text.SimpleDateFormat
;
import
java.util.Date
;
import
org.springframework.util.StringUtils
;
/**
* Spring MVC 时间转换
*/
public
class
DateConvertEditor
extends
PropertyEditorSupport
{
private
SimpleDateFormat
datetimeFormat
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss"
);
private
SimpleDateFormat
dateFormat
=
new
SimpleDateFormat
(
"yyyy-MM-dd"
);
public
void
setAsText
(
String
text
)
throws
IllegalArgumentException
{
if
(
StringUtils
.
hasText
(
text
))
{
try
{
if
(
text
.
indexOf
(
":"
)
>
0
)
{
if
(
text
.
length
()
==
16
){
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm"
);
setValue
(
sdf
.
parse
(
text
));
}
else
if
(
text
.
length
()
==
19
){
setValue
(
this
.
datetimeFormat
.
parse
(
text
));
}
else
if
(
text
.
length
()
==
21
){
setValue
(
this
.
datetimeFormat
.
parse
(
text
));
}
else
{
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"EEE MMM dd HH:mm:ss z yyyy"
);
setValue
(
sdf
.
parse
(
text
));
}
}
else
if
(
text
.
indexOf
(
"-"
)
>
0
)
{
if
(
text
.
length
()
==
7
){
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"yyyy-MM"
);
setValue
(
sdf
.
parse
(
text
));
}
else
if
(
text
.
length
()
==
10
){
setValue
(
this
.
dateFormat
.
parse
(
text
));
}
else
{
setValue
(
null
);
}
}
else
{
Long
time
=
Long
.
parseLong
(
text
);
setValue
(
datetimeFormat
.
parse
(
datetimeFormat
.
format
(
new
Date
(
time
))));
}
}
catch
(
ParseException
ex
)
{
IllegalArgumentException
iae
=
new
IllegalArgumentException
(
"Could not parse date: "
+
ex
.
getMessage
());
iae
.
initCause
(
ex
);
throw
iae
;
}
}
else
{
setValue
(
null
);
}
}
}
src/main/java/com/app/framework/core/support/mapper/CrudBaseMapper.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
/**
* Mapper公共基类,请勿修改
* @param <T> The Model Class 这里是泛型不是Model类
*/
public
interface
CrudBaseMapper
<
T
>
extends
BaseMapper
<
T
>
{
}
\ No newline at end of file
src/main/java/com/app/framework/core/support/resubmit/Resubmit.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
resubmit
;
import
java.lang.annotation.*
;
/**
* 重复提交注解
*/
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
Resubmit
{
/**
* 支持两种形式:一个是方法参数,一个是令牌
*/
enum
Type
{
PARAM
,
TOKEN
}
/**
* 默认防重提交,是方法参数
* @return
*/
Type
type
()
default
Type
.
PARAM
;
/**
* 延时时间 在延时多久后可以再次提交
*
* @return Time unit is one second
*/
int
delaySeconds
()
default
3
;
}
src/main/java/com/app/framework/core/support/resubmit/ResubmitLock.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
resubmit
;
import
cn.hutool.core.util.IdUtil
;
import
java.util.Objects
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ScheduledThreadPoolExecutor
;
import
java.util.concurrent.ThreadPoolExecutor
;
import
java.util.concurrent.TimeUnit
;
/**
* 防重复提交锁
*/
public
interface
ResubmitLock
{
/**
* 防重复提交令牌的缓存key
*/
String
RESUBMIT_TOKEN_KEY
=
"resubmit-token:%s:%s"
;
/**
* resubmit-token 过期时间,防止数据永不过期
*/
Integer
EXPIRE_TIME_MINUTE
=
30
;
ConcurrentHashMap
<
String
,
Object
>
LOCK_CACHE
=
new
ConcurrentHashMap
<>(
200
);
ScheduledThreadPoolExecutor
EXECUTOR
=
new
ScheduledThreadPoolExecutor
(
5
,
new
ThreadPoolExecutor
.
DiscardPolicy
());
/**
* 参数形式防重提交 putIfAbsent 是原子操作保证线程安全
*
* @param key 对应的key
* @param value
* @param delaySeconds 延时时间
* @return
*/
default
boolean
lock
(
final
String
key
,
Object
value
,
final
int
delaySeconds
)
{
boolean
lock
=
Objects
.
isNull
(
LOCK_CACHE
.
putIfAbsent
(
key
,
value
));
if
(
lock
)
{
EXECUTOR
.
schedule
(()
->
{
LOCK_CACHE
.
remove
(
key
);
},
delaySeconds
,
TimeUnit
.
SECONDS
);
}
return
lock
;
}
/**
* 参数形式防重提交 用以控制短时间内的重复提交
*
* @param lock 是否需要解锁
* @param key 对应的key
*/
default
void
unLock
(
final
boolean
lock
,
final
String
key
)
{
if
(
lock
)
{
LOCK_CACHE
.
remove
(
key
);
}
}
/**
* 令牌形式防重复提交,生成令牌
*
* @param username 登录用户
* @return
*/
default
String
tokenCreate
(
final
String
username
)
{
String
token
=
IdUtil
.
randomUUID
();
String
key
=
String
.
format
(
RESUBMIT_TOKEN_KEY
,
username
,
token
);
boolean
lock
=
Objects
.
isNull
(
LOCK_CACHE
.
put
(
key
,
username
));
if
(
lock
)
{
EXECUTOR
.
schedule
(()
->
{
LOCK_CACHE
.
remove
(
key
);
},
EXPIRE_TIME_MINUTE
,
TimeUnit
.
MINUTES
);
}
return
token
;
}
/**
* 令牌形式防重复提交,删除令牌
*
* @param username 登录用户
* @return
*/
default
boolean
tokenDelete
(
final
String
username
,
final
String
token
)
{
String
key
=
String
.
format
(
RESUBMIT_TOKEN_KEY
,
username
,
token
);
Object
o
=
LOCK_CACHE
.
remove
(
key
);
return
!
Objects
.
isNull
(
o
);
}
}
src/main/java/com/app/framework/core/support/resubmit/aspect/ResubmitAspect.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
resubmit
.
aspect
;
import
cn.hutool.crypto.SecureUtil
;
import
com.app.framework.core.support.auth.LoginUser
;
import
com.app.framework.core.support.resubmit.Resubmit
;
import
com.app.framework.core.support.resubmit.ResubmitLock
;
import
com.app.framework.core.support.view.form.AjaxResult
;
import
com.app.framework.core.utils.request.RequestUtil
;
import
com.app.framework.core.utils.request.SessionUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang.StringUtils
;
import
org.aspectj.lang.ProceedingJoinPoint
;
import
org.aspectj.lang.annotation.Around
;
import
org.aspectj.lang.annotation.Aspect
;
import
org.aspectj.lang.reflect.MethodSignature
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.Resource
;
import
javax.servlet.http.HttpServletRequest
;
import
java.lang.reflect.Method
;
/**
* 重复提交校验
**/
@Slf4j
@Aspect
@Component
public
class
ResubmitAspect
{
private
final
static
Object
PRESENT
=
new
Object
();
@Resource
ResubmitLock
resubmitLock
;
public
String
buildKey
(
Method
method
,
LoginUser
loginUser
)
{
String
ip
=
RequestUtil
.
getIpAddr
(
RequestUtil
.
getRequest
());
//目标类、方法
String
className
=
method
.
getDeclaringClass
().
getName
();
String
methodName
=
method
.
getName
();
return
"resubmit:"
+
SecureUtil
.
md5
(
String
.
format
(
"%s-%s-%s-%s"
,
ip
,
className
,
methodName
,
loginUser
.
getUsername
()));
}
@Around
(
"execution(public * *(..)) && @annotation(com.app.framework.core.support.resubmit.Resubmit)"
)
public
Object
handleResubmit
(
ProceedingJoinPoint
joinPoint
)
throws
Throwable
{
HttpServletRequest
request
=
RequestUtil
.
getRequest
();
LoginUser
loginUser
=
SessionUtil
.
getCurrentUser
(
request
);
if
(
loginUser
==
null
)
{
loginUser
=
(
LoginUser
)
request
.
getAttribute
(
"apiLoginUser"
);
}
if
(
loginUser
==
null
)
{
//放行
return
joinPoint
.
proceed
();
}
MethodSignature
signature
=
(
MethodSignature
)
joinPoint
.
getSignature
();
Method
method
=
signature
.
getMethod
();
//执行锁
boolean
lock
=
false
;
//通过反射技术来获取注解对象
Resubmit
resubmit
=
method
.
getAnnotation
(
Resubmit
.
class
);
//防重提交类型
String
type
=
resubmit
.
type
().
name
();
if
(
type
.
equalsIgnoreCase
(
Resubmit
.
Type
.
PARAM
.
name
()))
{
//方式一,参数形式防重提交
int
delaySeconds
=
resubmit
.
delaySeconds
();
if
(
delaySeconds
<=
0
)
{
//放行
return
joinPoint
.
proceed
();
}
String
key
=
this
.
buildKey
(
method
,
loginUser
);
lock
=
resubmitLock
.
lock
(
key
,
PRESENT
,
delaySeconds
);
}
else
{
//方式二,令牌形式防重提交
String
resubmitToken
=
request
.
getHeader
(
"resubmit-token"
);
if
(
StringUtils
.
isBlank
(
resubmitToken
))
{
resubmitToken
=
request
.
getParameter
(
"resubmit-token"
);
}
if
(
StringUtils
.
isBlank
(
resubmitToken
))
{
return
AjaxResult
.
wrapError
(
"防重复提交令牌不能为空"
);
}
//提交表单的token key,直接删除成功则说明token正确
lock
=
resubmitLock
.
tokenDelete
(
loginUser
.
getUsername
(),
resubmitToken
);
}
if
(
lock
)
{
//放行
return
joinPoint
.
proceed
();
}
else
{
//响应重复提交异常
return
AjaxResult
.
wrap
(
"resubmit"
,
"请勿重复提交"
);
}
}
}
src/main/java/com/app/framework/core/support/service/CrudBaseService.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
service
;
import
com.app.framework.core.support.view.grid.Paging
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
java.util.List
;
/**
* 公共Service接口定义
* 所有定义的Service接口若要使用基类方法都必须继承此类
* 只能通过继承的方式使用
*/
public
interface
CrudBaseService
<
T
>
extends
IService
<
T
>
{
default
List
<
T
>
getPageList
(
T
view
,
Paging
paging
)
{
return
null
;
}
}
\ No newline at end of file
src/main/java/com/app/framework/core/support/service/SequenceService.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
service
;
import
cn.hutool.core.date.DateUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* ID生成接口
*/
public
interface
SequenceService
{
/**
* 锁对象,可以为任意对象
*/
Object
lockObj
=
"lockerOrder"
;
/**
* 订单号生成计数器
* <prefix, 计数器>
*/
Map
<
String
,
Long
>
IdCountMap
=
new
HashMap
<>();
/**
* 每毫秒生成订单号数量最大值
*/
int
maxPerMSECSize
=
100000
;
/**
* 根据yyMMdd生成非重复ID
* @param prefix ID前缀
* @return
*/
default
String
genIdByDate
(
String
prefix
)
{
String
p
=
ObjectUtil
.
defaultIfNull
(
prefix
,
"id"
);
// 最终生成的订单号
String
finOrderNum
=
""
;
synchronized
(
lockObj
)
{
Long
idCount
=
ObjectUtil
.
defaultIfNull
(
IdCountMap
.
get
(
p
),
0L
);
// 计数器到最大值归零,可扩展更大
if
(
idCount
>
maxPerMSECSize
)
{
idCount
=
0L
;
}
idCount
++;
// 组装订单号
finOrderNum
=
ObjectUtil
.
defaultIfNull
(
prefix
,
""
)
+
DateUtil
.
format
(
new
Date
(),
"yyMMdd"
)
+
(
maxPerMSECSize
+
idCount
);
IdCountMap
.
put
(
p
,
idCount
);
}
return
finOrderNum
;
}
}
src/main/java/com/app/framework/core/support/service/impl/CrudBaseServiceSupport.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
service
.
impl
;
import
com.app.framework.core.support.mapper.CrudBaseMapper
;
import
com.app.framework.core.support.service.CrudBaseService
;
import
com.app.framework.core.support.view.grid.Paging
;
import
com.baomidou.mybatisplus.core.conditions.ISqlSegment
;
import
com.baomidou.mybatisplus.core.conditions.Wrapper
;
import
com.baomidou.mybatisplus.core.toolkit.LambdaUtils
;
import
com.baomidou.mybatisplus.core.toolkit.support.ColumnCache
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
org.apache.commons.lang.StringUtils
;
import
java.util.List
;
import
java.util.Map
;
import
static
com
.
baomidou
.
mybatisplus
.
core
.
enums
.
SqlKeyword
.*;
/**
* Service实现类的基类
*
* @param <M>
* @param <T>
*/
public
class
CrudBaseServiceSupport
<
M
extends
CrudBaseMapper
<
T
>,
T
>
extends
ServiceImpl
<
M
,
T
>
implements
CrudBaseService
<
T
>
{
/**
* 设置排序
*
* @param wrapper
* @param paging
*/
private
void
setOrderBy
(
Wrapper
<
T
>
wrapper
,
Paging
paging
)
{
if
(
wrapper
==
null
||
paging
==
null
||
StringUtils
.
isBlank
(
paging
.
getSort
()))
{
return
;
}
wrapper
.
getExpression
().
getOrderBy
().
clear
();
Map
<
String
,
ColumnCache
>
columnMap
=
LambdaUtils
.
getColumnMap
(
entityClass
);
String
sorts
[]
=
paging
.
getSort
().
split
(
","
);
String
dirs
[]
=
null
;
if
(
StringUtils
.
isNotBlank
(
paging
.
getDir
()))
{
dirs
=
paging
.
getDir
().
split
(
","
);
}
for
(
int
i
=
0
;
i
<
sorts
.
length
;
i
++)
{
String
column
=
sorts
[
i
],
dir
=
"ASC"
;
if
(
dirs
!=
null
&&
dirs
.
length
>
i
)
{
dir
=
dirs
[
i
].
toUpperCase
();
}
ColumnCache
columnCache
=
columnMap
.
get
(
LambdaUtils
.
formatKey
(
column
));
if
(
columnCache
==
null
)
{
columnCache
=
columnMap
.
values
().
stream
().
filter
(
e
->
e
.
getColumn
().
equals
(
column
)).
findFirst
().
get
();
}
if
(
columnCache
==
null
)
{
throw
new
RuntimeException
(
"数据库中找不到 "
+
column
+
" 映射字段"
);
}
String
sqlColumn
=
columnCache
.
getColumn
();
ISqlSegment
[]
sqlSegments
=
{
ORDER_BY
,
()
->
sqlColumn
,
"DESC"
.
equals
(
dir
)
?
DESC
:
ASC
};
wrapper
.
getExpression
().
add
(
sqlSegments
);
}
}
/**
* 分页查询
* @param wrapper 查询条件
* @param paging 分页条件
* @return
*/
public
List
<
T
>
pageList
(
Wrapper
<
T
>
wrapper
,
Paging
paging
)
{
this
.
setOrderBy
(
wrapper
,
paging
);
if
(
Paging
.
isPage
(
paging
))
{
Page
<
T
>
page
=
new
Page
<>(
paging
.
getPageNo
(),
paging
.
getLimit
(),
paging
.
getIsCountPage
());
Page
<
T
>
result
=
this
.
page
(
page
,
wrapper
);
Paging
.
setPage
(
paging
,
result
);
return
result
.
getRecords
();
}
return
this
.
list
(
wrapper
);
}
}
src/main/java/com/app/framework/core/support/view/form/AjaxResult.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
view
.
form
;
import
cn.hutool.core.codec.Base64
;
import
cn.hutool.json.JSONUtil
;
import
java.util.Date
;
/**
* 请求返回结果
* code(200:成功 0或其他:失败)
*/
public
class
AjaxResult
<
T
>
{
/**
* 执行成功
*/
public
static
final
String
SUCCESS
=
"200"
;
/**
* 执行失败
*/
public
static
final
String
FAILURE
=
"0"
;
/**
* 执行结果(200: 成功 0或其它: 失败 401: 身份认证失败)
*/
private
String
code
;
/**
* 提示信息
*/
private
String
msg
=
""
;
/**
* 数据
*/
private
T
data
;
/**
* 时间
*/
private
Date
time
;
/**
* 获取执行结果
*
* @return true:执行成功,code代码为200 false:执行失败,code代码非200
*/
public
boolean
success
()
{
if
(
SUCCESS
.
equals
(
this
.
code
))
return
true
;
return
false
;
}
/**
* 获取执行结果
*
* @return 执行结果代码,200:成功 0:失败 其它:自定义的失败代码
*/
public
String
getCode
()
{
return
code
;
}
/**
* 设置执行结果
*
* @param code 执行结果代码
*/
public
void
setCode
(
String
code
)
{
this
.
code
=
code
;
}
/**
* 设置执行结果
*
* @param success 执行结果
*/
public
void
setCode
(
boolean
success
)
{
if
(
success
)
this
.
code
=
SUCCESS
;
else
this
.
code
=
FAILURE
;
}
/**
* 获取提示信息
*/
public
String
getMsg
()
{
if
(
msg
==
null
||
""
.
equals
(
msg
))
{
if
(
SUCCESS
.
equals
(
this
.
code
))
{
msg
=
"操作成功"
;
}
else
{
msg
=
"操作失败"
;
}
}
return
msg
;
}
/**
* 设置提示信息
*
* @param msg 提示信息
*/
public
void
setMsg
(
String
msg
)
{
this
.
msg
=
msg
;
}
/**
* 获取返回数据
*/
public
T
getData
()
{
return
data
;
}
/**
* 设置返回数据
*
* @param data 返回数据
*/
public
void
setData
(
T
data
)
{
this
.
data
=
data
;
}
/**
* 获取数据返回时间
*/
public
Date
getTime
()
{
if
(
this
.
time
==
null
)
{
this
.
time
=
new
Date
();
}
return
time
;
}
/**
* 设置数据返回时间
*/
public
void
setTime
(
Date
time
)
{
this
.
time
=
time
;
}
/**
* 实例化AjaxResult对象
*
* @param success 执行结果
*/
public
static
AjaxResult
wrap
(
boolean
success
)
{
AjaxResult
ajaxResult
=
new
AjaxResult
();
ajaxResult
.
setCode
(
success
);
return
ajaxResult
;
}
/**
* 实例化AjaxResult对象
*
* @param success 执行结果
* @param msg 提示信息
*/
public
static
AjaxResult
wrap
(
boolean
success
,
String
msg
)
{
AjaxResult
ajaxResult
=
new
AjaxResult
();
ajaxResult
.
setCode
(
success
);
ajaxResult
.
setMsg
(
msg
);
return
ajaxResult
;
}
/**
* 实例化AjaxResult对象
*
* @param success 执行结果
* @param msg 提示信息
* @param data 返回数据
*/
public
static
<
T
>
AjaxResult
wrap
(
boolean
success
,
String
msg
,
T
data
)
{
AjaxResult
ajaxResult
=
new
AjaxResult
();
ajaxResult
.
setCode
(
success
);
ajaxResult
.
setMsg
(
msg
);
ajaxResult
.
setData
(
data
);
return
ajaxResult
;
}
/**
* 实例化执行成功的AjaxResult对象
*
* @param msg 提示信息
*/
public
static
AjaxResult
wrapSuccess
(
String
msg
)
{
return
AjaxResult
.
wrap
(
true
,
msg
);
}
/**
* 实例化执行失败的AjaxResult对象
*
* @param msg 提示信息
*/
public
static
AjaxResult
wrapError
(
String
msg
)
{
return
AjaxResult
.
wrap
(
false
,
msg
);
}
/**
* 实例化执行成功的AjaxResult对象
*
* @param data 返回数据
*/
public
static
<
T
>
AjaxResult
wrapData
(
T
data
)
{
return
AjaxResult
.
wrap
(
true
,
null
,
data
);
}
/**
* 实例化AjaxResult对象
*
* @param code 执行结果
* @param msg 提示信息
*/
public
static
AjaxResult
wrap
(
String
code
,
String
msg
)
{
AjaxResult
ajaxResult
=
new
AjaxResult
();
ajaxResult
.
setCode
(
code
);
ajaxResult
.
setMsg
(
msg
);
return
ajaxResult
;
}
/**
* 实例化AjaxResult对象
*
* @param code 执行结果
* @param msg 提示信息
* @param data 返回数据
*/
public
static
<
T
>
AjaxResult
wrap
(
String
code
,
String
msg
,
T
data
)
{
AjaxResult
ajaxResult
=
new
AjaxResult
();
ajaxResult
.
setCode
(
code
);
ajaxResult
.
setMsg
(
msg
);
ajaxResult
.
setData
(
data
);
return
ajaxResult
;
}
/**
* 实例化AjaxResult对象,并对data进行Base64加密
*
* @param success 执行结果
* @param data 返回数据
*/
public
static
<
T
>
AjaxResult
wrapBase64
(
boolean
success
,
T
data
)
{
//对返回的data数据进行Base64加密
if
(
data
!=
null
)
{
if
(
data
instanceof
String
)
{
data
=
(
T
)
Base64
.
encode
(
data
.
toString
());
}
else
{
String
jsonData
=
JSONUtil
.
parseObj
(
data
,
false
).
toString
();
data
=
(
T
)
Base64
.
encode
(
jsonData
);
}
}
return
AjaxResult
.
wrap
(
success
,
null
,
data
);
}
}
src/main/java/com/app/framework/core/support/view/form/ModelEditForm.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
view
.
form
;
import
org.apache.commons.lang.StringUtils
;
/**
* 模型编辑form
*/
public
class
ModelEditForm
{
/**
* 菜单Id
*/
private
Long
moduleId
;
/**
* 编辑类型
* edit or view
*/
private
String
editType
;
/**
* 列表页面的页码
*/
private
Integer
pageNumber
;
/**
* tab选项卡索引
*/
private
Integer
tabIndex
;
public
Long
getModuleId
()
{
return
moduleId
;
}
public
void
setModuleId
(
Long
moduleId
)
{
this
.
moduleId
=
moduleId
;
}
public
String
getEditType
()
{
if
(
StringUtils
.
isBlank
(
editType
)){
editType
=
"edit"
;
}
return
editType
;
}
public
void
setEditType
(
String
editType
)
{
this
.
editType
=
editType
;
}
public
Integer
getPageNumber
()
{
return
pageNumber
;
}
public
void
setPageNumber
(
Integer
pageNumber
)
{
this
.
pageNumber
=
pageNumber
;
}
public
Integer
getTabIndex
()
{
return
tabIndex
;
}
public
void
setTabIndex
(
Integer
tabIndex
)
{
this
.
tabIndex
=
tabIndex
;
}
}
src/main/java/com/app/framework/core/support/view/grid/ExGridLoad.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
view
.
grid
;
import
java.util.Collection
;
/**
* Grid使用
*/
public
class
ExGridLoad
{
/**总记录*/
private
Long
totalCount
;
/**总页数*/
private
Long
totalPage
;
/**数据集合*/
private
Collection
<?>
result
;
/**
* 获取总记录数
*/
public
Long
getTotalCount
()
{
return
totalCount
;
}
/**
* 设置总记录数
* @param totalCount 总记录数
*/
public
void
setTotalCount
(
Long
totalCount
)
{
this
.
totalCount
=
totalCount
;
}
/**
* 获取总页数
*/
public
Long
getTotalPage
()
{
return
totalPage
;
}
/**
* 设置总页数
* @param totalPage 总页数
*/
public
void
setTotalPage
(
Long
totalPage
)
{
this
.
totalPage
=
totalPage
;
}
/**
* 实例化ExGridLoad对象
* @param list 数据集合
* @param page 分页对象
*/
public
static
ExGridLoad
wrapExGridLoad
(
Collection
<?>
list
,
Paging
page
)
{
Long
totalCount
=
page
.
getTotalCount
();
if
(
totalCount
==
null
||
totalCount
<=
0
)
totalCount
=
new
Long
(
list
.
size
());
ExGridLoad
exGridLoad
=
new
ExGridLoad
();
exGridLoad
.
setTotalCount
(
totalCount
);
exGridLoad
.
setTotalPage
(
page
.
getTotalPage
());
exGridLoad
.
setResult
(
list
);
return
exGridLoad
;
}
/**
* 实例化ExGridLoad对象
* @param list 数据集合
*/
public
static
ExGridLoad
wrapExGridLoad
(
Collection
<?>
list
)
{
ExGridLoad
exGridLoad
=
new
ExGridLoad
();
exGridLoad
.
setResult
(
list
);
return
exGridLoad
;
}
/**
* 计算总页数
* @param totalCount 总记录数
* @param limit 每页显示记录数
* @return 总页数
*/
public
static
Long
getTotalPage
(
Long
totalCount
,
Integer
limit
){
if
(
totalCount
!=
null
&&
limit
!=
null
){
return
(
totalCount
+
limit
-
1
)
/
limit
;
}
return
1
l
;
}
/**
* 获取数据集合
*/
public
Collection
<?>
getResult
()
{
return
result
;
}
/**
* 设置数据集合
* @param result 数据集合
*/
public
void
setResult
(
Collection
<?>
result
)
{
this
.
result
=
result
;
}
}
src/main/java/com/app/framework/core/support/view/grid/Paging.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
view
.
grid
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
java.io.Serializable
;
/**
* 分页参数对象
* 包含排序字段和排序方式
*/
public
class
Paging
implements
Serializable
{
private
static
final
long
serialVersionUID
=
2837480041430890963L
;
/**
* 构造函数
*/
public
Paging
(){}
/**
* 有参构造函数
* @param isPage 是否分页
*/
public
Paging
(
Boolean
isPage
){
this
.
isPage
=
isPage
;
}
/**
* 有参构造函数
* @param pageNo 当前页码
* @param limit 每页显示记录数
*/
public
Paging
(
Integer
pageNo
,
Integer
limit
){
this
.
pageNo
=
pageNo
;
this
.
limit
=
limit
;
}
/**当前页码*/
private
Integer
pageNo
=
null
;
/**起始记录数*/
private
Integer
start
=
null
;
/**每页显示记录数*/
private
Integer
limit
=
10
;
/**排序方式(desc || asc),多个用","分隔(与sort的每个字段对应)*/
private
String
dir
;
/**排序字段,多个字段用","分隔*/
private
String
sort
;
/**查询参数*/
private
Object
queryPara
;
/**总记录数*/
private
Long
totalCount
;
/**总页数*/
private
Long
totalPage
;
/**是否分页*/
private
Boolean
isPage
=
true
;
/**是否查询总记录数*/
private
Boolean
isCountPage
=
true
;
public
String
toString
(){
return
"Page [当前页码="
+
pageNo
+
", 起始记录数="
+
start
+
", 每页显示记录数="
+
limit
+
", 排序字段="
+
sort
+
", 排序方式="
+
dir
+
", 是否分页="
+
isPage
+
", 是否查询总记录数="
+
isCountPage
+
"]"
;
}
/**
* 获取起始记录数
*/
public
Integer
getStart
()
{
if
(
start
==
null
&&
pageNo
!=
null
&&
limit
!=
null
){
//根据页码计算起始记录数
start
=
(
pageNo
-
1
)
*
limit
;
}
if
(
start
==
null
)
start
=
0
;
return
start
;
}
/**
* 获取每页显示记录数
*/
public
Integer
getLimit
()
{
if
(
limit
==
null
)
limit
=
10
;
return
limit
;
}
/**
* 获取排序方式
*/
public
String
getDir
()
{
return
dir
;
}
/**
* 获取排序字段
*/
public
String
getSort
()
{
return
sort
;
}
/**
* 设置起始记录数
* @param start
*/
public
void
setStart
(
Integer
start
)
{
this
.
start
=
start
;
}
/**
* 设置每页显示记录数
* @param limit
*/
public
void
setLimit
(
Integer
limit
)
{
this
.
limit
=
limit
;
}
/**
* 设置排序方式
* @param dir
*/
public
void
setDir
(
String
dir
)
{
this
.
dir
=
dir
;
}
/**
* 设置排序字段
* @param sort
*/
public
void
setSort
(
String
sort
)
{
this
.
sort
=
sort
;
}
/**
* 获取查询参数
*/
public
Object
getQueryPara
()
{
return
queryPara
;
}
/**
* 设置查询参数
* @param queryPara
*/
public
void
setQueryPara
(
Object
queryPara
)
{
this
.
queryPara
=
queryPara
;
}
/**
* 获取总记录数
*/
public
Long
getTotalCount
()
{
return
totalCount
;
}
/**
* 设置总记录数
* @param totalCount
*/
public
void
setTotalCount
(
Long
totalCount
)
{
this
.
totalCount
=
totalCount
;
}
/**
* 获取是否分页
*/
public
Boolean
getIsPage
()
{
if
(
isPage
==
null
)
isPage
=
false
;
return
isPage
;
}
/**
* 设置是否分页
* @param isPage
*/
public
void
setIsPage
(
Boolean
isPage
)
{
if
(
isPage
==
null
)
isPage
=
false
;
this
.
isPage
=
isPage
;
if
(
false
==
isPage
){
this
.
isCountPage
=
false
;
}
}
/**
* 获取是否计算总记录数
*/
public
Boolean
getIsCountPage
()
{
if
(
isCountPage
==
null
)
isCountPage
=
false
;
return
isCountPage
;
}
/**
* 设置是否计算总记录数
* @param isCountPage
*/
public
void
setIsCountPage
(
Boolean
isCountPage
)
{
this
.
isCountPage
=
isCountPage
;
}
/**
* 获取当前显示的页码
*/
public
Integer
getPageNo
()
{
if
(
pageNo
==
null
&&
start
!=
null
&&
limit
!=
null
){
//根据起始记录数计算当前页码
pageNo
=
(
start
/
limit
)
+
1
;
}
if
(
pageNo
==
null
)
pageNo
=
1
;
return
pageNo
;
}
/**
* 设置当前显示的页码
* @param pageNo
*/
public
void
setPageNo
(
Integer
pageNo
)
{
this
.
pageNo
=
pageNo
;
}
/**
* 获取总页数
*/
public
Long
getTotalPage
()
{
if
(
totalCount
!=
null
&&
limit
!=
null
&&
limit
>
0
){
totalPage
=
(
totalCount
+
limit
-
1
)
/
limit
;
}
return
totalPage
;
}
/**
* 设置总页数
* @param totalPage
*/
public
void
setTotalPage
(
Long
totalPage
)
{
this
.
totalPage
=
totalPage
;
}
/**
* 判断是否分页
* @param paging 分页对象
* @return true:分页 false:不分页
*/
public
static
boolean
isPage
(
Paging
paging
){
if
(
paging
!=
null
&&
paging
.
getIsPage
()){
return
true
;
}
return
false
;
}
/**
* 判断是否查询总记录数
* @param paging 分页对象
* @return true:查询总记录数 false:不查询总记录数
*/
public
static
boolean
isCountPage
(
Paging
paging
){
if
(
paging
!=
null
&&
paging
.
getIsCountPage
()){
return
true
;
}
return
false
;
}
/**
* 设置Mybatis分页插件返回Page对象
* @param page
* @return Paging
*/
public
static
Paging
setPage
(
Paging
paging
,
Page
page
){
if
(
paging
==
null
){
paging
=
new
Paging
(
false
);
}
paging
.
setTotalPage
(
page
.
getPages
());
paging
.
setTotalCount
(
page
.
getTotal
());
return
paging
;
}
/**
* 判断是否分页
* @param paging 分页对象
* @return true:分页 false:不分页
*/
public
static
Page
page
(
Paging
paging
){
if
(
paging
!=
null
&&
paging
.
getIsPage
()){
return
new
Page
<>(
paging
.
getPageNo
(),
paging
.
getLimit
());
}
return
new
Page
<>(
1
,
-
1
);
}
}
src/main/java/com/app/framework/core/support/view/grid/PagingUtils.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
view
.
grid
;
import
org.apache.commons.lang.StringUtils
;
import
javax.servlet.http.HttpServletRequest
;
import
java.util.Enumeration
;
/**
* 分页参数工具类
* 主要是从HttpServletRequest中获取分页参数
* 用法:Paging paging = PagingUtils.getPaging(request);
*/
public
class
PagingUtils
{
/**
* 从request对象中获取分页参数、排序参数
* @param request
* @return Page
*/
public
static
Paging
getPaging
(
HttpServletRequest
request
){
return
getPaging
(
request
,
null
);
}
/**
* 从request对象中获取分页参数、排序参数
* @param request
* @param limit 每页显示记录数(用于设置每页显示记录数)
* @return Page
*/
public
static
Paging
getPaging
(
HttpServletRequest
request
,
Integer
limit
){
Paging
page
=
new
Paging
();
Enumeration
<?>
paramNames
=
request
.
getParameterNames
();
while
(
paramNames
!=
null
&&
paramNames
.
hasMoreElements
())
{
String
paramName
=
(
String
)
paramNames
.
nextElement
();
if
(
"pageNo"
.
equals
(
paramName
)){
String
pageNo
=
request
.
getParameter
(
"pageNo"
);
if
(
StringUtils
.
isNotBlank
(
pageNo
)){
page
.
setPageNo
(
Integer
.
parseInt
(
pageNo
));
}
}
else
if
(
"start"
.
equals
(
paramName
)){
String
start
=
request
.
getParameter
(
"start"
);
if
(
StringUtils
.
isNotBlank
(
start
)){
page
.
setStart
(
Integer
.
parseInt
(
start
));
}
}
else
if
(
"limit"
.
equals
(
paramName
)){
String
slimit
=
request
.
getParameter
(
"limit"
);
if
(
StringUtils
.
isNotBlank
(
slimit
)){
page
.
setLimit
(
Integer
.
parseInt
(
slimit
));
}
}
else
if
(
"isPage"
.
equals
(
paramName
)){
String
isPage
=
request
.
getParameter
(
"isPage"
);
if
(
StringUtils
.
isNotBlank
(
isPage
)){
page
.
setIsPage
(
Boolean
.
parseBoolean
(
isPage
));
}
}
else
if
(
"isCountPage"
.
equals
(
paramName
)){
String
isCountPage
=
request
.
getParameter
(
"isCountPage"
);
if
(
StringUtils
.
isNotBlank
(
isCountPage
)){
page
.
setIsCountPage
(
Boolean
.
parseBoolean
(
isCountPage
));
}
}
else
if
(
"sort"
.
equals
(
paramName
)){
String
sort
=
request
.
getParameter
(
"sort"
);
if
(
StringUtils
.
isNotBlank
(
sort
)){
page
.
setSort
(
sort
);
}
}
else
if
(
"dir"
.
equals
(
paramName
)){
String
dir
=
request
.
getParameter
(
"dir"
);
if
(
StringUtils
.
isNotBlank
(
dir
)){
page
.
setDir
(
dir
);
}
}
}
if
(
limit
!=
null
){
page
.
setLimit
(
limit
);
}
return
page
;
}
}
src/main/java/com/app/framework/core/support/view/tree/ExTreeNode.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
view
.
tree
;
import
java.io.Serializable
;
import
java.util.*
;
/**
* TreeNode基类
*/
public
class
ExTreeNode
implements
Serializable
{
/**节点ID*/
private
String
id
;
/**父节点ID*/
private
String
parentId
;
/**节点名称*/
private
String
name
;
/**
* 子节点集合
*/
private
List
children
;
/**
* 生成Tree
* 当构建节点的数据不在一张表时,ParentId和Id可能会一样,导致报错,此时需处理下
* @param topResource 父节点
* @param resources 所有的子节点
*/
public
<
X
extends
ExTreeNode
>
X
buildTree
(
X
topResource
,
LinkedHashMap
<
String
,
X
>
resources
)
{
Iterator
<
Map
.
Entry
<
String
,
X
>>
iter
=
resources
.
entrySet
().
iterator
();
while
(
iter
.
hasNext
())
{
Map
.
Entry
<
String
,
X
>
entry
=
iter
.
next
();
if
(
entry
.
getValue
().
getParentId
()
!=
null
&&
entry
.
getValue
().
getParentId
().
equals
(
topResource
.
getId
()))
{
topResource
.
addChild
(
entry
.
getValue
());
}
}
List
<
X
>
children
=
topResource
.
getChildren
();
if
(
children
==
null
||
children
.
size
()
<
1
){
return
topResource
;
}
for
(
X
re
:
children
)
{
buildTree
(
re
,
resources
);
}
return
topResource
;
}
/**
* 向子节点集合中添加节点
* @param exTreeNode 节点
*/
public
<
X
extends
ExTreeNode
>
void
addChild
(
X
exTreeNode
)
{
if
(
null
==
children
)
children
=
new
ArrayList
<
X
>();
children
.
add
(
exTreeNode
);
}
/**
* 获取节点ID
*/
public
String
getId
()
{
return
id
;
}
/**
* 设置节点ID
* @param id 节点ID
*/
public
void
setId
(
String
id
)
{
this
.
id
=
id
;
}
/**
* 获取父节点ID
*/
public
String
getParentId
()
{
return
parentId
;
}
/**
* 设置父节点ID
* @param parentId 父节点ID
*/
public
void
setParentId
(
String
parentId
)
{
this
.
parentId
=
parentId
;
}
/**
* 获取节点名称
*/
public
String
getName
()
{
return
name
;
}
/**
* 设置节点名称
* @param name 节点名称
*/
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
/**
* 获取子节点集合
*/
public
<
X
>
List
<
X
>
getChildren
()
{
return
children
;
}
/**
* 设置子节点集合
* @param children 子节点集合
*/
public
<
X
extends
ExTreeNode
>
void
setChildren
(
List
<
X
>
children
)
{
this
.
children
=
children
;
}
}
src/main/java/com/app/framework/core/support/view/tree/ZTreeNode.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
support
.
view
.
tree
;
import
java.io.Serializable
;
/**
* ZTree基类
*/
public
class
ZTreeNode
extends
ExTreeNode
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**数据库中实例对象id主键*/
private
String
oid
;
/**节点图标样式*/
private
String
iconCls
;
/**是否父节点(为使用zTree而加,功能同leaf,与之相反)(true:父节点,false:子节点)*/
private
Boolean
isParent
=
false
;
/**是否展开*/
private
Boolean
open
;
/**节点是否选中*/
private
Boolean
checked
;
/**节点是否可选(为使用zTree而加)(true:不显示复选框,false:显示复选框)*/
private
Boolean
nocheck
;
/**扩展数据*/
private
String
extData
;
/**
* 获取是否展开
*/
public
Boolean
getOpen
()
{
return
open
;
}
/**
* 设置是否展开
* @param open 是否展开
*/
public
void
setOpen
(
Boolean
open
)
{
this
.
open
=
open
;
}
/**
* 获取节点的选择状态
*/
public
Boolean
getChecked
()
{
return
checked
;
}
/**
* 设置节点的选择状态
* @param checked 节点的选择状态
*/
public
void
setChecked
(
Boolean
checked
)
{
this
.
checked
=
checked
;
}
/**
* 获取节点图标样式
*/
public
String
getIconCls
()
{
return
iconCls
;
}
/**
* 设置节点图标样式
* @param iconCls 图标样式
*/
public
void
setIconCls
(
String
iconCls
)
{
this
.
iconCls
=
iconCls
;
}
/**
* 获取是否是父节点
*/
public
Boolean
getIsParent
()
{
if
(
isParent
==
null
){
isParent
=
false
;
}
return
isParent
;
}
/**
* 设置是否是父节点
* @param isParent 是否是父节点
*/
public
void
setIsParent
(
Boolean
isParent
)
{
this
.
isParent
=
isParent
;
}
public
String
getOid
()
{
return
oid
;
}
public
void
setOid
(
String
oid
)
{
this
.
oid
=
oid
;
}
public
Boolean
getNocheck
()
{
return
nocheck
;
}
public
void
setNocheck
(
Boolean
nocheck
)
{
this
.
nocheck
=
nocheck
;
}
public
String
getExtData
()
{
return
extData
;
}
public
void
setExtData
(
String
extData
)
{
this
.
extData
=
extData
;
}
}
src/main/java/com/app/framework/core/utils/db/DBUtil.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
utils
.
db
;
import
org.apache.commons.lang.StringUtils
;
import
org.apache.ibatis.session.SqlSession
;
import
org.apache.ibatis.session.SqlSessionFactory
;
import
org.mybatis.spring.SqlSessionUtils
;
import
java.sql.*
;
import
java.util.ArrayList
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
/**
* 数据库工具类
*/
public
class
DBUtil
{
private
SqlSession
session
;
private
Connection
conn
=
null
;
private
PreparedStatement
ps
=
null
;
private
ResultSet
rs
=
null
;
private
String
driver
=
"com.mysql.jdbc.Driver"
;
private
String
url
;
private
String
username
;
private
String
password
;
public
DBUtil
(
SqlSessionFactory
sqlSessionFactory
)
{
session
=
SqlSessionUtils
.
getSqlSession
(
sqlSessionFactory
);
}
public
DBUtil
(
String
url
,
String
username
,
String
password
)
{
this
.
url
=
url
;
this
.
username
=
username
;
this
.
password
=
password
;
}
public
DBUtil
(
String
driver
,
String
url
,
String
username
,
String
password
)
{
this
.
driver
=
driver
;
this
.
url
=
url
;
this
.
username
=
username
;
this
.
password
=
password
;
}
public
SqlSession
getSqlSession
()
{
return
this
.
session
;
}
public
Connection
getConnection
()
throws
Exception
{
if
(
conn
==
null
||
conn
.
isClosed
())
{
if
(
this
.
session
!=
null
)
{
conn
=
this
.
session
.
getConnection
();
}
else
if
(
StringUtils
.
isNotBlank
(
url
)
&&
StringUtils
.
isNotBlank
(
username
)
&&
StringUtils
.
isNotBlank
(
password
))
{
Class
.
forName
(
driver
);
conn
=
DriverManager
.
getConnection
(
url
,
username
,
password
);
}
}
return
conn
;
}
/**
* 根据SQL更新
*
* @param sql SQL语句
* @param params 参数数组
* @return 更新行数
*/
public
int
executeUpdate
(
String
sql
,
Object
[]
params
)
{
int
rows
=
0
;
try
{
conn
=
this
.
getConnection
();
ps
=
conn
.
prepareStatement
(
sql
);
if
(
params
!=
null
&&
params
.
length
>
0
)
{
for
(
int
i
=
0
;
i
<
params
.
length
;
i
++)
{
ps
.
setObject
(
i
+
1
,
params
[
i
]);
}
}
rows
=
ps
.
executeUpdate
();
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
finally
{
this
.
close
();
}
return
rows
;
}
/**
* 根据SQL查询
*
* @param sql SQL语句
* @return List<Map < 字段名, 值>>
*/
public
List
<
Map
<
String
,
String
>>
executeQuery
(
String
sql
)
{
return
this
.
executeQuery
(
sql
,
null
);
}
/**
* 根据SQL查询
*
* @param sql SQL语句
* @param params 参数数组
* @return List<Map < 字段名, 值>>
*/
public
List
<
Map
<
String
,
String
>>
executeQuery
(
String
sql
,
Object
[]
params
)
{
List
<
Map
<
String
,
String
>>
list
=
new
ArrayList
<>();
try
{
conn
=
this
.
getConnection
();
ps
=
conn
.
prepareStatement
(
sql
);
if
(
params
!=
null
&&
params
.
length
>
0
)
{
for
(
int
i
=
0
;
i
<
params
.
length
;
i
++)
{
ps
.
setObject
(
i
+
1
,
params
[
i
]);
}
}
rs
=
ps
.
executeQuery
();
ResultSetMetaData
rsmd
=
rs
.
getMetaData
();
int
columnCount
=
rsmd
.
getColumnCount
();
while
(
rs
.
next
())
{
Map
<
String
,
String
>
map
=
new
LinkedHashMap
<>();
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
int
index
=
i
+
1
;
map
.
put
(
rsmd
.
getColumnName
(
index
).
toLowerCase
(),
rs
.
getString
(
index
));
}
list
.
add
(
map
);
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
finally
{
this
.
close
();
}
return
list
;
}
public
void
close
()
{
try
{
if
(
rs
!=
null
)
rs
.
close
();
if
(
ps
!=
null
)
ps
.
close
();
if
(
conn
!=
null
)
conn
.
close
();
}
catch
(
SQLException
e
)
{
e
.
printStackTrace
();
}
}
}
src/main/java/com/app/framework/core/utils/file/UploadUtil.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
utils
.
file
;
import
cn.hutool.core.img.ImgUtil
;
import
cn.hutool.core.io.FileUtil
;
import
cn.hutool.core.util.RandomUtil
;
import
com.app.framework.core.exception.ValidException
;
import
com.app.framework.core.utils.request.RequestUtil
;
import
lombok.Data
;
import
org.apache.commons.io.FileUtils
;
import
org.apache.commons.lang.StringUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.web.multipart.MultipartFile
;
import
org.springframework.web.multipart.MultipartHttpServletRequest
;
import
javax.imageio.ImageIO
;
import
javax.servlet.http.HttpServletRequest
;
import
java.awt.*
;
import
java.awt.image.BufferedImage
;
import
java.io.File
;
import
java.io.Serializable
;
import
java.text.SimpleDateFormat
;
import
java.util.Date
;
import
java.util.Map
;
/**
* 上传文件工具类
*/
public
class
UploadUtil
{
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
UploadUtil
.
class
);
private
final
static
SimpleDateFormat
DATE_FORMAT
=
new
SimpleDateFormat
(
"yyyyMMdd"
);
/**
* 上传路径
*/
private
static
String
uploadPath
;
/**
* 访问地址的baseUrl
*/
private
static
String
baseUrl
;
/**
* 根目录名称
* 默认uploadfiles
*/
private
static
String
rootDirName
;
public
static
void
init
(
String
uploadPath
,
String
baseUrl
)
{
if
(
UploadUtil
.
uploadPath
==
null
||
!
UploadUtil
.
uploadPath
.
equals
(
uploadPath
))
{
UploadUtil
.
uploadPath
=
uploadPath
;
}
if
(
UploadUtil
.
baseUrl
==
null
||
!
UploadUtil
.
baseUrl
.
equals
(
baseUrl
))
{
UploadUtil
.
baseUrl
=
baseUrl
;
}
}
public
static
String
getBaseUrl
(
HttpServletRequest
request
)
{
if
(
StringUtils
.
isBlank
(
baseUrl
))
{
baseUrl
=
RequestUtil
.
getBasePath
(
request
);
}
return
baseUrl
;
}
public
static
String
getRootDirName
()
{
if
(
StringUtils
.
isBlank
(
rootDirName
))
{
if
(
StringUtils
.
isBlank
(
uploadPath
)
||
"/"
.
equals
(
uploadPath
))
{
//上传到项目根目录
rootDirName
=
"/uploadfiles"
;
}
else
{
rootDirName
=
uploadPath
.
substring
(
uploadPath
.
lastIndexOf
(
"/"
));
}
}
return
rootDirName
;
}
public
static
String
getUploadPath
(
String
savePath
)
{
if
(
StringUtils
.
isBlank
(
savePath
))
{
savePath
=
DATE_FORMAT
.
format
(
new
Date
());
}
if
(!
savePath
.
startsWith
(
"/"
))
{
savePath
=
new
StringBuilder
().
append
(
"/"
).
append
(
savePath
).
toString
();
}
StringBuilder
builder
=
new
StringBuilder
();
if
(
StringUtils
.
isBlank
(
uploadPath
))
{
builder
.
append
(
getRootDirName
()).
append
(
savePath
);
}
else
{
builder
.
append
(
uploadPath
).
append
(
savePath
);
}
return
builder
.
toString
();
}
public
static
String
getBaseUrl
(
HttpServletRequest
request
,
String
savePath
)
{
if
(
StringUtils
.
isBlank
(
savePath
))
{
savePath
=
DATE_FORMAT
.
format
(
new
Date
());
}
if
(!
savePath
.
startsWith
(
"/"
))
{
savePath
=
new
StringBuilder
().
append
(
"/"
).
append
(
savePath
).
toString
();
}
String
baseUrl
=
getBaseUrl
(
request
);
StringBuilder
url
=
new
StringBuilder
(
baseUrl
);
if
(!
baseUrl
.
endsWith
(
getRootDirName
()))
{
url
.
append
(
getRootDirName
());
}
url
.
append
(
savePath
);
return
url
.
toString
();
}
public
static
String
upload
(
MultipartHttpServletRequest
multipartRequest
,
UploadConfig
uploadConfig
)
throws
Exception
{
init
(
uploadConfig
.
getUploadPath
(),
uploadConfig
.
getBaseUrl
());
Map
<
String
,
MultipartFile
>
fileMap
=
multipartRequest
.
getFileMap
();
MultipartFile
multipartFile
=
fileMap
.
values
().
iterator
().
next
();
if
(
multipartFile
==
null
)
{
throw
new
ValidException
(
"请选择文件"
);
}
long
size
=
multipartFile
.
getSize
();
if
(
uploadConfig
.
getFileSingleSizeLimit
()
>
0
&&
size
>
uploadConfig
.
getFileSingleSizeLimit
()){
//单个文件大小超过限制
throw
new
ValidException
(
"文件大小超过限制"
);
}
String
contentType
=
multipartFile
.
getContentType
();
String
ext
=
FileUtil
.
getSuffix
(
multipartFile
.
getOriginalFilename
());
log
.
info
(
"文件长度: "
+
size
);
log
.
info
(
"文件类型: "
+
contentType
);
log
.
info
(
"文件扩展名: "
+
ext
);
log
.
info
(
"文件原名: "
+
multipartFile
.
getOriginalFilename
());
String
fileName
=
new
StringBuilder
().
append
(
System
.
nanoTime
()).
append
(
RandomUtil
.
randomString
(
6
)).
append
(
"."
).
append
(
ext
).
toString
();
File
file
=
new
File
(
getUploadPath
(
null
));
if
(!
file
.
exists
())
{
file
.
mkdirs
();
log
.
info
(
"创建文件路径: "
+
file
.
getAbsolutePath
());
}
File
createFile
=
new
File
(
getUploadPath
(
null
),
fileName
);
//处理压缩
if
(
uploadConfig
!=
null
&&
uploadConfig
.
isCompress
()
&&
size
>
uploadConfig
.
getCompressSize
())
{
//判断是否压缩gif图片
if
(
ext
.
equalsIgnoreCase
(
"gif"
)
&&
!
uploadConfig
.
isCompressGif
())
{
//不压缩gif图片
FileUtils
.
copyInputStreamToFile
(
multipartFile
.
getInputStream
(),
createFile
);
}
else
{
BufferedImage
oldImage
=
ImageIO
.
read
(
multipartFile
.
getInputStream
());
if
(
uploadConfig
.
getCompressScale
()
>
0
)
{
Image
scale
=
ImgUtil
.
scale
(
oldImage
,
uploadConfig
.
getCompressScale
());
ImgUtil
.
write
(
scale
,
createFile
);
}
else
if
(
uploadConfig
.
getCompressWidth
()
>
0
&&
uploadConfig
.
getCompressHeight
()
>
0
)
{
Image
scale
=
ImgUtil
.
scale
(
oldImage
,
uploadConfig
.
getCompressWidth
(),
uploadConfig
.
getCompressHeight
());
ImgUtil
.
write
(
scale
,
createFile
);
}
else
{
Image
scale
=
ImgUtil
.
scale
(
oldImage
,
1
);
ImgUtil
.
write
(
scale
,
createFile
);
}
}
}
else
{
FileUtils
.
copyInputStreamToFile
(
multipartFile
.
getInputStream
(),
createFile
);
}
log
.
info
(
"创建成功: "
+
createFile
.
getAbsolutePath
());
return
getBaseUrl
(
multipartRequest
,
null
)
+
"/"
+
fileName
;
}
@Data
public
static
class
UploadConfig
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 上传路径
*/
private
String
uploadPath
;
/**
* 访问地址的baseUrl
*/
private
String
baseUrl
;
/**
* 单个文件大小限制
*/
private
long
fileSingleSizeLimit
;
/**
* 是否压缩
*/
private
boolean
compress
;
/**
* 压缩后的宽
*/
private
int
compressWidth
;
/**
* 压缩后的高
*/
private
int
compressHeight
;
/**
* 压缩比例
*/
private
float
compressScale
;
/**
* 如果图片大小小于此值,不再压缩,单位字节
*/
private
long
compressSize
;
/**
* 是否压缩gif图片,默认false
*/
private
boolean
compressGif
;
}
}
\ No newline at end of file
src/main/java/com/app/framework/core/utils/number/RangeUtil.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
utils
.
number
;
import
java.math.BigDecimal
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.regex.Pattern
;
import
java.util.stream.Collectors
;
/**
* 开闭区间工具类
*/
public
class
RangeUtil
{
/**
* 开闭区间正则表达式
*/
private
static
final
Pattern
NUM_RANGE_PATTERN
=
Pattern
.
compile
(
"[\\[|\\(]\\s?\\d+\\.?\\d*\\s?,\\s?\\d+\\.?\\d*\\s?[\\)|\\]]"
);
/**
* 左半区间正则表达式
*/
private
static
final
Pattern
LEFT_NUM_RANGE_PATTERN
=
Pattern
.
compile
(
"[\\[|\\(]\\s?\\d+\\.?\\d*\\s?,\\s?[\\)|\\]]"
);
/**
* 右半区间正则表达式
*/
private
static
final
Pattern
RIGHT_NUM_RANGE_PATTERN
=
Pattern
.
compile
(
"[\\[|\\(],\\s?\\d+\\.?\\d*\\s?[\\)|\\]]"
);
/**
* 判断是否为有效的数字区间范围
* @param numRange 数字区间,支持小数,左右皆允许为空,eg:(0, 2] or [1, 4] or [100, ]
* @return boolean
*/
public
static
boolean
isValidNumRange
(
String
numRange
)
{
return
NUM_RANGE_PATTERN
.
matcher
(
numRange
).
matches
()
||
LEFT_NUM_RANGE_PATTERN
.
matcher
(
numRange
).
matches
()
||
RIGHT_NUM_RANGE_PATTERN
.
matcher
(
numRange
).
matches
();
}
/**
* 判断数值是否在区间范围内
* @param number 数值
* @param numRange 开闭区间,支持小数,左右皆允许为空,eg:(0, 2] or [1, 4] or [100, ]
* @return boolean
*/
public
static
boolean
inNumRange
(
BigDecimal
number
,
String
numRange
)
{
Objects
.
requireNonNull
(
numRange
);
if
(!
isValidNumRange
(
numRange
))
{
return
false
;
}
String
[]
pairs
=
numRange
.
split
(
","
);
// 获取开闭区间的最小值和最大值
List
<
String
>
rangeNums
=
Arrays
.
stream
(
pairs
).
map
(
str
->
str
.
replaceAll
(
"[(|)|\\[|\\]]"
,
""
).
trim
()).
collect
(
Collectors
.
toList
());
BigDecimal
minValue
=
""
.
equals
(
rangeNums
.
get
(
0
))
?
null
:
new
BigDecimal
(
rangeNums
.
get
(
0
));
BigDecimal
maxValue
=
""
.
equals
(
rangeNums
.
get
(
1
))
?
null
:
new
BigDecimal
(
rangeNums
.
get
(
1
));
// 判定数值是否大于最小值
boolean
minMatched
=
(
minValue
==
null
)
||
(
pairs
[
0
].
startsWith
(
"["
)
?
number
.
compareTo
(
minValue
)
>=
0
:
number
.
compareTo
(
minValue
)
>
0
);
// 判定数值是否小于最大值
boolean
maxMatched
=
(
maxValue
==
null
)
||
(
pairs
[
1
].
endsWith
(
"]"
)
?
number
.
compareTo
(
maxValue
)
<=
0
:
number
.
compareTo
(
maxValue
)
<
0
);
return
minMatched
&&
maxMatched
;
}
public
static
void
main
(
String
[]
args
)
{
// System.out.println(inNumRange(1, "(0, 2]"));
// System.out.println(inNumRange(1, "(, 2]"));
// System.out.println(inNumRange(1, "(1, 4]"));
// System.out.println(inNumRange(1, "(0, ]"));
// System.out.println();
// System.out.println(inNumRange(190, "[100, 400]"));
// System.out.println(inNumRange(BigDecimal.valueOf(300), "[100, 400)"));
System
.
out
.
println
(
inNumRange
(
BigDecimal
.
valueOf
(
800.89
),
"[0, )"
));
}
}
src/main/java/com/app/framework/core/utils/pwd/PasswordUtil.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
utils
.
pwd
;
import
cn.hutool.crypto.SecureUtil
;
import
org.apache.commons.lang.StringUtils
;
/**
* 密码工具类
*
*/
public
class
PasswordUtil
{
/**
* 密码加密处理
*
* @param md5_password
* 标准md5加密后的密码
* @return 处理后的密码
*/
public
static
String
encrypt
(
String
md5_password
)
{
return
SecureUtil
.
md5
(
md5_password
+
"_"
+
md5_password
);
}
/**
* 判断密码是否与数据库中的密码一致
* @param md5_password 标准md5加密后的密码(用户输入的)
* @param db_password 数据库中存储的密码
* @return true:相等 false:不相等
*/
public
static
boolean
equalsPwd
(
String
md5_password
,
String
db_password
)
{
if
(
StringUtils
.
equals
(
encrypt
(
md5_password
),
db_password
))
{
return
true
;
}
else
{
return
false
;
}
}
/**
* 支付密码加密处理
*
* @param md5_password
* 标准md5加密后的密码
* @return 处理后的密码
*/
public
static
String
paypwd_encrypt
(
String
md5_password
)
{
return
SecureUtil
.
md5
(
md5_password
+
"$"
+
md5_password
);
}
/**
* 支付密码
* 判断密码是否与数据库中的密码一致
* @param md5_password 标准md5加密后的密码(用户输入的)
* @param db_password 数据库中存储的密码
* @return true:相等 false:不相等
*/
public
static
boolean
paypwd_equalsPwd
(
String
md5_password
,
String
db_password
)
{
if
(
StringUtils
.
equals
(
paypwd_encrypt
(
md5_password
),
db_password
))
{
return
true
;
}
else
{
return
false
;
}
}
}
src/main/java/com/app/framework/core/utils/request/RequestUtil.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
utils
.
request
;
import
org.apache.commons.lang.StringUtils
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
javax.servlet.http.HttpServletRequest
;
/**
* Request工具类
*/
public
class
RequestUtil
{
public
static
final
String
REQUEST_AJAX_HEADER
=
"X-Requested-With"
;
public
static
final
String
XML_HTTP_REQUEST
=
"XMLHttpRequest"
;
private
static
String
RequestServer
=
null
;
/**
* SpringMvc下获取request
*/
public
static
HttpServletRequest
getRequest
()
{
return
((
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
()).
getRequest
();
}
/**
* 获取BasePath
*
* @return request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath();
*/
public
static
String
getBasePath
(
HttpServletRequest
request
)
{
if
(
RequestServer
==
null
)
{
String
port
=
request
.
getServerPort
()
+
""
;
port
=
"80"
.
equals
(
port
)
?
""
:
(
":"
+
port
);
String
requestServer
=
request
.
getScheme
()
+
"://"
+
request
.
getServerName
()
+
port
;
RequestServer
=
requestServer
+
request
.
getContextPath
();
}
return
RequestServer
;
}
/**
* 获取IP地址
*
* 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
*/
public
static
String
getIpAddr
(
HttpServletRequest
request
)
{
String
Xip
=
request
.
getHeader
(
"X-Real-IP"
);
String
XFor
=
request
.
getHeader
(
"X-Forwarded-For"
);
if
(
StringUtils
.
isNotEmpty
(
XFor
)
&&
!
"unKnown"
.
equalsIgnoreCase
(
XFor
))
{
//多次反向代理后会有多个ip值,第一个ip才是真实ip
int
index
=
XFor
.
indexOf
(
","
);
if
(
index
!=
-
1
)
{
return
XFor
.
substring
(
0
,
index
);
}
else
{
return
XFor
;
}
}
XFor
=
Xip
;
if
(
StringUtils
.
isNotEmpty
(
XFor
)
&&
!
"unKnown"
.
equalsIgnoreCase
(
XFor
))
{
return
XFor
;
}
if
(
StringUtils
.
isBlank
(
XFor
)
||
"unknown"
.
equalsIgnoreCase
(
XFor
))
{
XFor
=
request
.
getHeader
(
"Proxy-Client-IP"
);
}
if
(
StringUtils
.
isBlank
(
XFor
)
||
"unknown"
.
equalsIgnoreCase
(
XFor
))
{
XFor
=
request
.
getHeader
(
"WL-Proxy-Client-IP"
);
}
if
(
StringUtils
.
isBlank
(
XFor
)
||
"unknown"
.
equalsIgnoreCase
(
XFor
))
{
XFor
=
request
.
getHeader
(
"HTTP_CLIENT_IP"
);
}
if
(
StringUtils
.
isBlank
(
XFor
)
||
"unknown"
.
equalsIgnoreCase
(
XFor
))
{
XFor
=
request
.
getHeader
(
"HTTP_X_FORWARDED_FOR"
);
}
if
(
StringUtils
.
isBlank
(
XFor
)
||
"unknown"
.
equalsIgnoreCase
(
XFor
))
{
XFor
=
request
.
getRemoteAddr
();
}
return
"0:0:0:0:0:0:0:1"
.
equals
(
XFor
)
?
"127.0.0.1"
:
XFor
;
}
/**
* 判断是否是Ajax请求
*
* @param request 请求
* @return true or false
*/
public
static
boolean
isAjaxRequest
(
HttpServletRequest
request
)
{
return
request
.
getHeader
(
REQUEST_AJAX_HEADER
)
!=
null
&&
request
.
getHeader
(
REQUEST_AJAX_HEADER
).
equalsIgnoreCase
(
XML_HTTP_REQUEST
);
}
}
src/main/java/com/app/framework/core/utils/request/SessionUtil.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
utils
.
request
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpSession
;
/**
* Session工具类
*/
public
class
SessionUtil
{
/**
* 登录会话名称
*/
public
static
final
String
OPERATOR_CONTEXT
=
"operator_context"
;
/**
* 将数据存放到session中
*
* @param request
* @param name 名称
* @param o 数据
*/
public
static
void
set
(
HttpServletRequest
request
,
String
name
,
Object
o
)
{
if
(
request
!=
null
&&
name
!=
null
&&
o
!=
null
)
{
request
.
getSession
().
setAttribute
(
name
,
o
);
}
}
/**
* 获取session中的数据
*
* @param request
*/
public
static
<
T
>
T
get
(
HttpServletRequest
request
,
String
name
)
{
if
(
request
==
null
||
name
==
null
)
return
null
;
try
{
HttpSession
session
=
request
.
getSession
();
if
(
session
==
null
)
return
null
;
Object
o
=
session
.
getAttribute
(
name
);
if
(
o
==
null
)
return
null
;
return
(
T
)
o
;
}
catch
(
Exception
e
)
{
}
return
null
;
}
/**
* 从session中移除数据
*/
public
static
void
remove
(
HttpServletRequest
request
,
String
name
)
{
HttpSession
session
=
request
.
getSession
();
if
(
session
!=
null
&&
name
!=
null
)
{
session
.
removeAttribute
(
name
);
}
}
/**
* 将当前用户存放到session中
*
* @param request
* @param loginUser
*/
public
static
<
T
>
void
setCurrentUser
(
HttpServletRequest
request
,
T
loginUser
)
{
set
(
request
,
OPERATOR_CONTEXT
,
loginUser
);
}
/**
* 获取当前登录的用户
*
* @param request
*/
public
static
<
T
>
T
getCurrentUser
(
HttpServletRequest
request
)
{
return
get
(
request
,
OPERATOR_CONTEXT
);
}
/**
* 从session中移除当前用户
*/
public
static
void
removeCurrentUser
(
HttpServletRequest
request
)
{
remove
(
request
,
OPERATOR_CONTEXT
);
}
}
src/main/java/com/app/framework/core/web/captcha/CaptchaUtil.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
web
.
captcha
;
import
cn.hutool.captcha.LineCaptcha
;
import
cn.hutool.captcha.generator.RandomGenerator
;
import
cn.hutool.core.img.ImgUtil
;
import
com.app.framework.core.utils.request.SessionUtil
;
import
org.apache.commons.lang.ObjectUtils
;
import
org.apache.commons.lang.StringUtils
;
import
javax.servlet.Servlet
;
import
javax.servlet.http.HttpServlet
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.awt.*
;
import
java.io.IOException
;
/**
* 图形验证码工具类
*
* 图形验证码用法:在全局配置中注册,如下:
*
* @Bean
* public ServletRegistrationBean captchaServletRegistration() {
* ServletRegistrationBean registration = new ServletRegistrationBean(CaptchaUtils.buildServlet());
* registration.addUrlMappings("/web/captcha.jpg");
* return registration;
* }
*
* 前端用法:
* <img src="${contextPath}/web/captcha.jpg" width="92" height="40" alt="点击刷新验证码"
* onclick="$(this).attr('src','${contextPath}/web/captcha.jpg?timestamp='+new Date());">
*
* 后端输入验证:
* CaptchaUtil.check(request, code);
*
*/
public
class
CaptchaUtil
{
private
static
final
String
SESSION_NAME
=
"CaptchaCode"
;
private
static
final
int
WIDTH
=
100
;
//生成的图片的宽度
private
static
final
int
HEIGHT
=
40
;
//生成的图片的高度
/**
* 创建图形验证码Servlet
* @return Servlet
*/
public
static
Servlet
buildServlet
()
{
return
buildServlet
(
WIDTH
,
HEIGHT
);
}
/**
* 创建图形验证码Servlet
* @return Servlet
*/
public
static
Servlet
buildServlet
(
int
width
,
int
height
)
{
return
new
HttpServlet
()
{
@Override
protected
void
doGet
(
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
IOException
{
response
.
setContentType
(
"image/jpeg"
);
String
codeLength
=
request
.
getParameter
(
"codeLength"
);
if
(
StringUtils
.
isBlank
(
codeLength
))
codeLength
=
"4"
;
// 产生验证码
String
code
=
new
RandomGenerator
(
Integer
.
parseInt
(
codeLength
)).
generate
();
// 将验证码存储起来,便于用户输入之后的验证
SessionUtil
.
set
(
request
,
SESSION_NAME
,
code
);
// 生成图形验证码
//CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(width, height);
LineCaptcha
captcha
=
cn
.
hutool
.
captcha
.
CaptchaUtil
.
createLineCaptcha
(
width
,
height
);
Image
image
=
captcha
.
createImage
(
code
);
ImgUtil
.
writeJpg
(
image
,
response
.
getOutputStream
());
}
};
}
/**
* 校验用户输入的验证码是否正确
* @param request
* @param code 用户输入的验证码
* @return
*/
public
static
boolean
check
(
HttpServletRequest
request
,
String
code
)
{
Object
o
=
SessionUtil
.
get
(
request
,
SESSION_NAME
);
boolean
equals
=
ObjectUtils
.
equals
(
o
,
code
);
if
(
equals
)
{
SessionUtil
.
remove
(
request
,
SESSION_NAME
);
}
return
equals
;
}
}
src/main/java/com/app/framework/core/web/filter/WebHttpServletRequestFilter.java
0 → 100644
View file @
28791d16
package
com
.
app
.
framework
.
core
.
web
.
filter
;
import
com.app.framework.core.utils.request.SessionUtil
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
javax.servlet.*
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
/**
* 前端接口身份认证拦截器
* 用于非前后端分离的项目,前端用户通过Session存储登录信息
* 默认所有资源都是开放的,只对受保护的资源进行登录认证,受保护的URL要求包含: /authc/
* 根据Session中的会话信息,验证用户是否登录,以及是否有权限访问当前URL
*
*/
public
class
WebHttpServletRequestFilter
implements
Filter
{
private
Logger
logger
=
LoggerFactory
.
getLogger
(
WebHttpServletRequestFilter
.
class
);
@Override
public
void
init
(
FilterConfig
filterConfig
)
throws
ServletException
{
}
@Override
public
void
doFilter
(
ServletRequest
srequest
,
ServletResponse
sresponse
,
FilterChain
chain
)
throws
IOException
,
ServletException
{
HttpServletRequest
request
=
(
HttpServletRequest
)
srequest
;
HttpServletResponse
response
=
(
HttpServletResponse
)
sresponse
;
String
uri
=
request
.
getRequestURI
();
// logger.info(String.format("前端身份认证[URI = %s]:", uri));
if
(
uri
.
indexOf
(
"/authc/"
)
>
-
1
)
{
//需要登录才能访问的资源,验证是否登录
if
(
SessionUtil
.
getCurrentUser
(
request
)
==
null
)
{
//未登录,跳转到登录页面
request
.
setAttribute
(
"redirectUrl"
,
uri
);
request
.
getRequestDispatcher
(
"/web/login"
).
forward
(
srequest
,
sresponse
);
// response.sendRedirect(request.getContextPath() + "/web/login");
}
else
{
chain
.
doFilter
(
srequest
,
sresponse
);
}
}
else
if
(
uri
.
indexOf
(
"/api/"
)
>
-
1
)
{
chain
.
doFilter
(
srequest
,
sresponse
);
}
else
if
(
uri
.
indexOf
(
"/web/"
)
>
-
1
)
{
chain
.
doFilter
(
srequest
,
sresponse
);
}
else
{
response
.
sendRedirect
(
"/404"
);
}
}
@Override
public
void
destroy
()
{
}
}
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