Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
jinli gu
Eladmin
Commits
fd9fb2a6
"eladmin-system/src/vscode:/vscode.git/clone" did not exist on "931ecb3ba769fe2dbfb8fec15b51efe263331157"
Commit
fd9fb2a6
authored
Nov 01, 2019
by
dqjdda
Browse files
Merge branch '2.3dev'
parents
7895e547
1839ef8d
Changes
227
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
fd9fb2a6
...
...
@@ -21,13 +21,12 @@ eladmin基于 Spring Boot 2.1.0 、 Jpa、 Spring Security、redis、Vue的前
| | 后端源码 | 前端源码 |
|--- |--- | --- |
| github | https://github.com/elunez/eladmin | https://github.com/elunez/eladmin-
qd
|
| 码云 | https://gitee.com/elunez/eladmin | https://gitee.com/elunez/eladmin-
qt
|
| github | https://github.com/elunez/eladmin | https://github.com/elunez/eladmin-
web
|
| 码云 | https://gitee.com/elunez/eladmin | https://gitee.com/elunez/eladmin-
web
|
#### 系统功能
-
用户管理:提供用户的相关配置,新增用户后,默认密码为123456
-
角色管理:对权限与菜单进行分配,可根据部门设置角色的数据权限
-
权限管理:权限细化到接口,可以理解成按钮权限
-
菜单管理:已实现菜单动态路由,后端可配置化,支持多级菜单
-
部门管理:可配置系统组织架构,树形表格展示
-
岗位管理:配置各个部门的职位
...
...
@@ -44,16 +43,19 @@ eladmin基于 Spring Boot 2.1.0 、 Jpa、 Spring Security、redis、Vue的前
-
支付宝支付:整合了支付宝支付并且提供了测试账号,可自行测试
#### 项目结构
项目采用分模块开发方式,将通用的配置放在公共模块,
```system```
模块为系统核心模块也是项目入口模块,
```logging```
模块为系统的日志模块,
```tools```
为第三方工具模块,包含了图床、邮件、七牛云、支付宝,
```generator```
为系统的代码生成模块
项目采用按功能分模块开发方式,将通用的配置放在公共模块,
```system```
模块为系统核心模块也是项目入口模块,
```logging```
模块为系统的日志模块,
```tools```
为第三方工具模块,包含了图床、邮件、七牛云、支付宝,
```generator```
为系统的代码生成模块
-
eladmin-common 公共模块
-
exception 项目统一异常的处理
-
mapper mapstruct的通用mapper
-
redis redis缓存相关配置
-
swagger2 接口文档配置
-
utils 系统通用工具类
-
annotation 为系统自定义注解
-
aspect 自定义注解的切面
-
base 提供了Entity、DTO基类和mapstruct的通用mapper
-
config 自定义权限实现、redis配置、swagger配置
-
exception 项目统一异常的处理
-
utils 系统通用工具类
-
eladmin-system 系统核心模块(系统启动入口)
-
config 配置跨域与静态资源,与数据权限
-
modules 系统相关模块(登录授权、定时任务等)
-
config 配置跨域与静态资源,与数据权限
-
thread 线程池相关
-
modules 系统相关模块(登录授权、系统监控、定时任务等)
-
eladmin-logging 系统日志模块
-
eladmin-tools 系统第三方工具模块
-
eladmin-generator 系统代码生成模块
...
...
@@ -78,6 +80,6 @@ eladmin基于 Spring Boot 2.1.0 、 Jpa、 Spring Security、redis、Vue的前
</table>
#### 项目捐赠
项目的发展离不开你的支持,请作者喝杯咖啡吧 ☕!
[
Donate
](
https://docs.auauz.net/#/jz
)
项目的发展离不开你的支持,请作者喝杯咖啡吧
!ps:辣条也行
☕!
[
Donate
](
https://docs.auauz.net/#/jz
)
#### 反馈交流
-
QQ交流群:891137268
eladmin-common/pom.xml
View file @
fd9fb2a6
...
...
@@ -5,11 +5,10 @@
<parent>
<artifactId>
eladmin
</artifactId>
<groupId>
me.zhengjie
</groupId>
<version>
2.
2
</version>
<version>
2.
3
</version>
</parent>
<modelVersion>
4.0.0
</modelVersion>
<artifactId>
eladmin-common
</artifactId>
<name>
公共模块
</name>
</project>
\ No newline at end of file
eladmin-common/src/main/java/me/zhengjie/annotation/AnonymousAccess.java
0 → 100644
View file @
fd9fb2a6
package
me.zhengjie.annotation
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
/**
* @author jacky
* 用于标记匿名访问方法
*/
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
AnonymousAccess
{
}
eladmin-common/src/main/java/me/zhengjie/annotation/Query.java
View file @
fd9fb2a6
...
...
@@ -13,45 +13,42 @@ import java.lang.annotation.Target;
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
Query
{
/
**
Dong ZhaoYang 2017/8/7 基本对象的属性名
*/
/
/
Dong ZhaoYang 2017/8/7 基本对象的属性名
String
propName
()
default
""
;
/
**
Dong ZhaoYang 2017/8/7 查询方式
*/
/
/
Dong ZhaoYang 2017/8/7 查询方式
Type
type
()
default
Type
.
EQUAL
;
/**
* 连接查询的属性名,如User类中的dept
* @return
*/
String
joinName
()
default
""
;
/**
* 默认左连接
* @return
*/
Join
join
()
default
Join
.
LEFT
;
/**
* 多字段模糊搜索,仅支持String类型字段,多个用逗号隔开, 如@Query(blurry = "email,username")
* @return
*/
String
blurry
()
default
""
;
enum
Type
{
/
**
jie 2019/6/4 相等
*/
/
/
jie 2019/6/4 相等
EQUAL
/
**
Dong ZhaoYang 2017/8/7 大于等于
*/
/
/
Dong ZhaoYang 2017/8/7 大于等于
,
GREATER_THAN
/
**
Dong ZhaoYang 2017/8/7 小于等于
*/
/
/
Dong ZhaoYang 2017/8/7 小于等于
,
LESS_THAN
/
**
Dong ZhaoYang 2017/8/7 中模糊查询
*/
/
/
Dong ZhaoYang 2017/8/7 中模糊查询
,
INNER_LIKE
/
**
Dong ZhaoYang 2017/8/7 左模糊查询
*/
/
/
Dong ZhaoYang 2017/8/7 左模糊查询
,
LEFT_LIKE
/
**
Dong ZhaoYang 2017/8/7 右模糊查询
*/
/
/
Dong ZhaoYang 2017/8/7 右模糊查询
,
RIGHT_LIKE
/
**
Dong ZhaoYang 2017/8/7 小于
*/
/
/
Dong ZhaoYang 2017/8/7 小于
,
LESS_THAN_NQ
//
**
jie 2019/6/4 包含
*/
// jie 2019/6/4 包含
,
IN
}
...
...
eladmin-common/src/main/java/me/zhengjie/aspect/LimitAspect.java
View file @
fd9fb2a6
...
...
@@ -12,7 +12,6 @@ import org.aspectj.lang.annotation.Pointcut;
import
org.aspectj.lang.reflect.MethodSignature
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.script.DefaultRedisScript
;
import
org.springframework.data.redis.core.script.RedisScript
;
...
...
@@ -23,10 +22,13 @@ import java.lang.reflect.Method;
@Aspect
@Component
public
class
LimitAspect
{
@Autowired
private
RedisTemplate
redisTemplate
;
private
final
RedisTemplate
<
Object
,
Object
>
redisTemplate
;
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
LimitAspect
.
class
);
public
LimitAspect
(
RedisTemplate
<
Object
,
Object
>
redisTemplate
)
{
this
.
redisTemplate
=
redisTemplate
;
}
@Pointcut
(
"@annotation(me.zhengjie.annotation.Limit)"
)
public
void
pointcut
()
{
...
...
@@ -41,20 +43,18 @@ public class LimitAspect {
LimitType
limitType
=
limit
.
limitType
();
String
key
=
limit
.
key
();
if
(
StringUtils
.
isEmpty
(
key
))
{
switch
(
limitType
)
{
case
IP:
key
=
StringUtils
.
getIP
(
request
);
break
;
default
:
key
=
signatureMethod
.
getName
();
if
(
limitType
==
LimitType
.
IP
)
{
key
=
StringUtils
.
getIp
(
request
);
}
else
{
key
=
signatureMethod
.
getName
();
}
}
ImmutableList
keys
=
ImmutableList
.
of
(
StringUtils
.
join
(
limit
.
prefix
(),
"_"
,
key
,
"_"
,
request
.
getRequestURI
().
replaceAll
(
"/"
,
"_"
)));
ImmutableList
<
Object
>
keys
=
ImmutableList
.
of
(
StringUtils
.
join
(
limit
.
prefix
(),
"_"
,
key
,
"_"
,
request
.
getRequestURI
().
replaceAll
(
"/"
,
"_"
)));
String
luaScript
=
buildLuaScript
();
RedisScript
<
Number
>
redisScript
=
new
DefaultRedisScript
<>(
luaScript
,
Number
.
class
);
Number
count
=
(
Number
)
redisTemplate
.
execute
(
redisScript
,
keys
,
limit
.
count
(),
limit
.
period
());
Number
count
=
redisTemplate
.
execute
(
redisScript
,
keys
,
limit
.
count
(),
limit
.
period
());
if
(
null
!=
count
&&
count
.
intValue
()
<=
limit
.
count
())
{
logger
.
info
(
"第{}次访问key为 {},描述为 [{}] 的接口"
,
count
,
keys
,
limit
.
name
());
return
joinPoint
.
proceed
();
...
...
eladmin-common/src/main/java/me/zhengjie/aspect/LimitType.java
View file @
fd9fb2a6
package
me.zhengjie.aspect
;
/**
* 限流枚举
* @author /
*/
public
enum
LimitType
{
// 默认
CUSTOMER
,
//
by ip addr
//
by ip addr
IP
;
}
eladmin-common/src/main/java/me/zhengjie/base/BaseDTO.java
0 → 100644
View file @
fd9fb2a6
package
me.zhengjie.base
;
import
lombok.Getter
;
import
lombok.Setter
;
import
java.io.Serializable
;
import
java.sql.Timestamp
;
/**
* @author Zheng Jie
* @Date 2019年10月24日20:48:53
*/
@Getter
@Setter
public
class
BaseDTO
implements
Serializable
{
private
Boolean
isDelete
;
private
Timestamp
createTime
;
private
Timestamp
updateTime
;
}
eladmin-common/src/main/java/me/zhengjie/base/BaseEntity.java
0 → 100644
View file @
fd9fb2a6
package
me.zhengjie.base
;
import
lombok.*
;
import
org.apache.commons.lang3.builder.ToStringBuilder
;
import
org.hibernate.annotations.CreationTimestamp
;
import
org.hibernate.annotations.UpdateTimestamp
;
import
javax.persistence.Column
;
import
javax.persistence.MappedSuperclass
;
import
java.io.Serializable
;
import
java.sql.Timestamp
;
import
java.lang.reflect.Field
;
/**
* @author Zheng Jie
* @Date 2019年10月24日20:46:32
*/
@Getter
@Setter
@MappedSuperclass
public
class
BaseEntity
implements
Serializable
{
// 删除标识
@Column
(
name
=
"is_delete"
,
columnDefinition
=
"bit default 0"
)
private
Boolean
isDelete
=
false
;
@Column
(
name
=
"create_time"
)
@CreationTimestamp
private
Timestamp
createTime
;
@Column
(
name
=
"update_time"
)
@UpdateTimestamp
private
Timestamp
updateTime
;
public
@interface
Update
{}
@Override
public
String
toString
()
{
ToStringBuilder
builder
=
new
ToStringBuilder
(
this
);
Field
[]
fields
=
this
.
getClass
().
getDeclaredFields
();
try
{
for
(
Field
f
:
fields
)
{
f
.
setAccessible
(
true
);
builder
.
append
(
f
.
getName
(),
f
.
get
(
this
)).
append
(
"\n"
);
}
}
catch
(
Exception
e
)
{
builder
.
append
(
"toString builder encounter an error"
);
}
return
builder
.
toString
();
}
}
eladmin-common/src/main/java/me/zhengjie/
mapper/Entity
Mapper.java
→
eladmin-common/src/main/java/me/zhengjie/
base/Base
Mapper.java
View file @
fd9fb2a6
package
me.zhengjie.
mapper
;
package
me.zhengjie.
base
;
import
java.util.List
;
...
...
@@ -6,33 +6,25 @@ import java.util.List;
* @author Zheng Jie
* @date 2018-11-23
*/
public
interface
Entity
Mapper
<
D
,
E
>
{
public
interface
Base
Mapper
<
D
,
E
>
{
/**
* DTO转Entity
* @param dto
* @return
*/
E
toEntity
(
D
dto
);
/**
* Entity转DTO
* @param entity
* @return
*/
D
toDto
(
E
entity
);
/**
* DTO集合转Entity集合
* @param dtoList
* @return
*/
List
<
E
>
toEntity
(
List
<
D
>
dtoList
);
/**
* Entity集合转DTO集合
* @param entityList
* @return
*/
List
<
D
>
toDto
(
List
<
E
>
entityList
);
}
eladmin-common/src/main/java/me/zhengjie/config/ElPermissionConfig.java
0 → 100644
View file @
fd9fb2a6
package
me.zhengjie.config
;
import
me.zhengjie.utils.SecurityUtils
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.stereotype.Service
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.stream.Collectors
;
@Service
(
value
=
"el"
)
public
class
ElPermissionConfig
{
public
Boolean
check
(
String
...
permissions
){
// 如果是匿名访问的,就放行
String
anonymous
=
"anonymous"
;
if
(
Arrays
.
asList
(
permissions
).
contains
(
anonymous
)){
return
true
;
}
// 获取当前用户的所有权限
List
<
String
>
elPermissions
=
SecurityUtils
.
getUserDetails
().
getAuthorities
().
stream
().
map
(
GrantedAuthority:
:
getAuthority
).
collect
(
Collectors
.
toList
());
// 判断当前用户的所有权限是否包含接口上定义的权限
List
<
String
>
list
=
Arrays
.
stream
(
permissions
).
filter
(
elPermissions:
:
contains
).
collect
(
Collectors
.
toList
());
return
elPermissions
.
contains
(
"admin"
)
||
list
.
size
()
!=
0
;
}
}
eladmin-common/src/main/java/me/zhengjie/
redis
/RedisConfig.java
→
eladmin-common/src/main/java/me/zhengjie/
config
/RedisConfig.java
View file @
fd9fb2a6
package
me.zhengjie.
redis
;
package
me.zhengjie.
config
;
import
cn.hutool.core.lang.Assert
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.parser.ParserConfig
;
import
com.alibaba.fastjson.serializer.SerializerFeature
;
import
lombok.extern.slf4j.Slf4j
;
import
me.zhengjie.utils.StringUtils
;
import
org.apache.commons.codec.digest.DigestUtils
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnClass
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.boot.autoconfigure.data.redis.RedisProperties
;
...
...
@@ -19,7 +23,12 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
import
org.springframework.data.redis.core.RedisOperations
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.serializer.RedisSerializationContext
;
import
org.springframework.data.redis.serializer.RedisSerializer
;
import
java.nio.charset.Charset
;
import
java.nio.charset.StandardCharsets
;
import
java.time.Duration
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* @author Zheng Jie
...
...
@@ -28,21 +37,19 @@ import java.time.Duration;
@Slf4j
@Configuration
@EnableCaching
// 自动配置
@ConditionalOnClass
(
RedisOperations
.
class
)
@EnableConfigurationProperties
(
RedisProperties
.
class
)
public
class
RedisConfig
extends
CachingConfigurerSupport
{
/**
* 设置 redis 数据默认过期时间,默认
1天
* 设置 redis 数据默认过期时间,默认
6小时
* 设置@cacheable 序列化方式
* @return
*/
@Bean
public
RedisCacheConfiguration
redisCacheConfiguration
(){
FastJsonRedisSerializer
<
Object
>
fastJsonRedisSerializer
=
new
FastJsonRedisSerializer
<>(
Object
.
class
);
RedisCacheConfiguration
configuration
=
RedisCacheConfiguration
.
defaultCacheConfig
();
configuration
=
configuration
.
serializeValuesWith
(
RedisSerializationContext
.
SerializationPair
.
fromSerializer
(
fastJsonRedisSerializer
)).
entryTtl
(
Duration
.
of
Day
s
(
1
));
configuration
=
configuration
.
serializeValuesWith
(
RedisSerializationContext
.
SerializationPair
.
fromSerializer
(
fastJsonRedisSerializer
)).
entryTtl
(
Duration
.
of
Hour
s
(
6
));
return
configuration
;
}
...
...
@@ -51,21 +58,20 @@ public class RedisConfig extends CachingConfigurerSupport {
public
RedisTemplate
<
Object
,
Object
>
redisTemplate
(
RedisConnectionFactory
redisConnectionFactory
)
{
RedisTemplate
<
Object
,
Object
>
template
=
new
RedisTemplate
<>();
//序列化
FastJsonRedisSerializer
fastJsonRedisSerializer
=
new
FastJsonRedisSerializer
(
Object
.
class
);
FastJsonRedisSerializer
<
Object
>
fastJsonRedisSerializer
=
new
FastJsonRedisSerializer
<>
(
Object
.
class
);
// value值的序列化采用fastJsonRedisSerializer
template
.
setValueSerializer
(
fastJsonRedisSerializer
);
template
.
setHashValueSerializer
(
fastJsonRedisSerializer
);
// 全局开启AutoType,不建议使用
// ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
// 全局开启AutoType,这里方便开发,使用全局的方式
ParserConfig
.
getGlobalInstance
().
setAutoTypeSupport
(
true
);
// 建议使用这种方式,小范围指定白名单
ParserConfig
.
getGlobalInstance
().
addAccept
(
"me.zhengjie.domain"
);
ParserConfig
.
getGlobalInstance
().
addAccept
(
"me.zhengjie.modules.system.service.dto"
);
ParserConfig
.
getGlobalInstance
().
addAccept
(
"me.zhengjie.service.dto"
);
ParserConfig
.
getGlobalInstance
().
addAccept
(
"me.zhengjie.modules.system.domain"
);
ParserConfig
.
getGlobalInstance
().
addAccept
(
"me.zhengjie.modules.quartz.domain"
);
ParserConfig
.
getGlobalInstance
().
addAccept
(
"me.zhengjie.modules.monitor.domain"
);
ParserConfig
.
getGlobalInstance
().
addAccept
(
"me.zhengjie.modules.security.security"
);
//
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.domain");
//
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.service.dto");
//
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.service.dto");
//
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.domain");
//
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.quartz.domain");
//
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.monitor.domain");
//
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.security.security");
// key的序列化采用StringRedisSerializer
template
.
setKeySerializer
(
new
StringRedisSerializer
());
template
.
setHashKeySerializer
(
new
StringRedisSerializer
());
...
...
@@ -75,20 +81,27 @@ public class RedisConfig extends CachingConfigurerSupport {
/**
* 自定义缓存key生成策略,默认将使用该策略
* 使用方法 @Cacheable
* @return
*/
@Bean
@Override
public
KeyGenerator
keyGenerator
()
{
return
(
target
,
method
,
params
)
->
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
target
.
getClass
().
getName
());
sb
.
append
(
method
.
getName
());
for
(
Object
obj
:
params
)
{
sb
.
append
(
JSON
.
toJSONString
(
obj
).
hashCode
());
Map
<
String
,
Object
>
container
=
new
HashMap
<>();
Class
<?>
targetClassClass
=
target
.
getClass
();
// 类地址
container
.
put
(
"class"
,
targetClassClass
.
toGenericString
());
// 方法名称
container
.
put
(
"methodName"
,
method
.
getName
());
// 包名称
container
.
put
(
"package"
,
targetClassClass
.
getPackage
());
// 参数列表
for
(
int
i
=
0
;
i
<
params
.
length
;
i
++)
{
container
.
put
(
String
.
valueOf
(
i
),
params
[
i
]);
}
return
sb
.
toString
();
// 转为JSON字符串
String
jsonString
=
JSON
.
toJSONString
(
container
);
// 做SHA256 Hash计算,得到一个SHA256摘要作为Key
return
DigestUtils
.
sha256Hex
(
jsonString
);
};
}
...
...
@@ -97,7 +110,7 @@ public class RedisConfig extends CachingConfigurerSupport {
public
CacheErrorHandler
errorHandler
()
{
// 异常处理,当Redis发生异常时,打印日志,但是程序正常走
log
.
info
(
"初始化 -> [{}]"
,
"Redis CacheErrorHandler"
);
CacheErrorHandler
cacheErrorHandler
=
new
CacheErrorHandler
()
{
return
new
CacheErrorHandler
()
{
@Override
public
void
handleCacheGetError
(
RuntimeException
e
,
Cache
cache
,
Object
key
)
{
log
.
error
(
"Redis occur handleCacheGetError:key -> [{}]"
,
key
,
e
);
...
...
@@ -118,7 +131,74 @@ public class RedisConfig extends CachingConfigurerSupport {
log
.
error
(
"Redis occur handleCacheClearError:"
,
e
);
}
};
return
cacheErrorHandler
;
}
}
/**
* Value 序列化
*
* @author /
* @param <T>
*/
class
FastJsonRedisSerializer
<
T
>
implements
RedisSerializer
<
T
>
{
private
Class
<
T
>
clazz
;
FastJsonRedisSerializer
(
Class
<
T
>
clazz
)
{
super
();
this
.
clazz
=
clazz
;
}
@Override
public
byte
[]
serialize
(
T
t
)
{
if
(
t
==
null
)
{
return
new
byte
[
0
];
}
return
JSON
.
toJSONString
(
t
,
SerializerFeature
.
WriteClassName
).
getBytes
(
StandardCharsets
.
UTF_8
);
}
@Override
public
T
deserialize
(
byte
[]
bytes
)
{
if
(
bytes
==
null
||
bytes
.
length
<=
0
)
{
return
null
;
}
String
str
=
new
String
(
bytes
,
StandardCharsets
.
UTF_8
);
return
JSON
.
parseObject
(
str
,
clazz
);
}
}
/**
* 重写序列化器
*
* @author /
*/
class
StringRedisSerializer
implements
RedisSerializer
<
Object
>
{
private
final
Charset
charset
;
StringRedisSerializer
()
{
this
(
StandardCharsets
.
UTF_8
);
}
private
StringRedisSerializer
(
Charset
charset
)
{
Assert
.
notNull
(
charset
,
"Charset must not be null!"
);
this
.
charset
=
charset
;
}
@Override
public
String
deserialize
(
byte
[]
bytes
)
{
return
(
bytes
==
null
?
null
:
new
String
(
bytes
,
charset
));
}
@Override
public
byte
[]
serialize
(
Object
object
)
{
String
string
=
JSON
.
toJSONString
(
object
);
if
(
StringUtils
.
isBlank
(
string
))
{
return
null
;
}
string
=
string
.
replace
(
"\""
,
""
);
return
string
.
getBytes
(
charset
);
}
}
eladmin-common/src/main/java/me/zhengjie/
swagger2
/SwaggerConfig.java
→
eladmin-common/src/main/java/me/zhengjie/
config
/SwaggerConfig.java
View file @
fd9fb2a6
package
me.zhengjie.
swagger2
;
package
me.zhengjie.
config
;
import
com.fasterxml.classmate.TypeResolver
;
import
com.google.common.base.Predicates
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.core.Ordered
;
import
org.springframework.data.domain.Pageable
;
import
springfox.documentation.builders.ApiInfoBuilder
;
import
springfox.documentation.builders.ParameterBuilder
;
import
springfox.documentation.builders.PathSelectors
;
import
springfox.documentation.schema.AlternateTypeRule
;
import
springfox.documentation.schema.AlternateTypeRuleConvention
;
import
springfox.documentation.schema.ModelRef
;
import
springfox.documentation.service.ApiInfo
;
import
springfox.documentation.service.Parameter
;
...
...
@@ -15,6 +23,8 @@ import springfox.documentation.spring.web.plugins.Docket;
import
springfox.documentation.swagger2.annotations.EnableSwagger2
;
import
java.util.ArrayList
;
import
java.util.List
;
import
static
com
.
google
.
common
.
collect
.
Lists
.
newArrayList
;
import
static
springfox
.
documentation
.
schema
.
AlternateTypeRules
.
newRule
;
/**
* api页面 /swagger-ui.html
...
...
@@ -33,9 +43,10 @@ public class SwaggerConfig {
private
Boolean
enabled
;
@Bean
@SuppressWarnings
(
"all"
)
public
Docket
createRestApi
()
{
ParameterBuilder
ticketPar
=
new
ParameterBuilder
();
List
<
Parameter
>
pars
=
new
ArrayList
<
Parameter
>();
List
<
Parameter
>
pars
=
new
ArrayList
<>();
ticketPar
.
name
(
tokenHeader
).
description
(
"token"
)
.
modelRef
(
new
ModelRef
(
"string"
))
.
parameterType
(
"header"
)
...
...
@@ -55,8 +66,43 @@ public class SwaggerConfig {
private
ApiInfo
apiInfo
()
{
return
new
ApiInfoBuilder
()
.
title
(
"eladmin 接口文档"
)
.
version
(
"2.
1
"
)
.
version
(
"2.
3
"
)
.
build
();
}
}
/**
* 将Pageable转换展示在swagger中
*/
@Configuration
class
SwaggerDataConfig
{
@Bean
public
AlternateTypeRuleConvention
pageableConvention
(
final
TypeResolver
resolver
)
{
return
new
AlternateTypeRuleConvention
()
{
@Override
public
int
getOrder
()
{
return
Ordered
.
HIGHEST_PRECEDENCE
;
}
@Override
public
List
<
AlternateTypeRule
>
rules
()
{
return
newArrayList
(
newRule
(
resolver
.
resolve
(
Pageable
.
class
),
resolver
.
resolve
(
Page
.
class
)));
}
};
}
@ApiModel
@Data
private
static
class
Page
{
@ApiModelProperty
(
"页码 (0..N)"
)
private
Integer
page
;
@ApiModelProperty
(
"每页显示的数目"
)
private
Integer
size
;
@ApiModelProperty
(
"以下列格式排序标准:property[,asc | desc]。 默认排序顺序为升序。 支持多种排序条件:如:id,asc"
)
private
List
<
String
>
sort
;
}
}
eladmin-common/src/main/java/me/zhengjie/exception/BadRequestException.java
View file @
fd9fb2a6
...
...
@@ -2,7 +2,6 @@ package me.zhengjie.exception;
import
lombok.Getter
;
import
org.springframework.http.HttpStatus
;
import
static
org
.
springframework
.
http
.
HttpStatus
.
BAD_REQUEST
;
/**
...
...
eladmin-common/src/main/java/me/zhengjie/exception/EntityExistException.java
View file @
fd9fb2a6
...
...
@@ -2,33 +2,18 @@ package me.zhengjie.exception;
import
org.springframework.util.StringUtils
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.stream.IntStream
;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
public
class
EntityExistException
extends
RuntimeException
{
public
EntityExistException
(
Class
clazz
,
Object
...
saveBodyParamsMap
)
{
super
(
EntityExistException
.
generateMessage
(
clazz
.
getSimpleName
(),
toMap
(
String
.
class
,
String
.
class
,
saveBodyParamsMap
)));
}
private
static
String
generateMessage
(
String
entity
,
Map
<
String
,
String
>
saveBodyParams
)
{
return
StringUtils
.
capitalize
(
entity
)
+
" 已存在 "
+
saveBodyParams
;
public
EntityExistException
(
Class
clazz
,
String
field
,
String
val
)
{
super
(
EntityExistException
.
generateMessage
(
clazz
.
getSimpleName
(),
field
,
val
));
}
private
static
<
K
,
V
>
Map
<
K
,
V
>
toMap
(
Class
<
K
>
keyType
,
Class
<
V
>
valueType
,
Object
...
entries
)
{
if
(
entries
.
length
%
2
==
1
)
throw
new
IllegalArgumentException
(
"Invalid entries"
);
return
IntStream
.
range
(
0
,
entries
.
length
/
2
).
map
(
i
->
i
*
2
)
.
collect
(
HashMap:
:
new
,
(
m
,
i
)
->
m
.
put
(
keyType
.
cast
(
entries
[
i
]),
valueType
.
cast
(
entries
[
i
+
1
])),
Map:
:
putAll
);
private
static
String
generateMessage
(
String
entity
,
String
field
,
String
val
)
{
return
StringUtils
.
capitalize
(
entity
)
+
" with "
+
field
+
" "
+
val
+
" existed"
;
}
}
\ No newline at end of file
eladmin-common/src/main/java/me/zhengjie/exception/EntityNotFoundException.java
View file @
fd9fb2a6
...
...
@@ -2,34 +2,18 @@ package me.zhengjie.exception;
import
org.springframework.util.StringUtils
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.stream.IntStream
;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
public
class
EntityNotFoundException
extends
RuntimeException
{
public
EntityNotFoundException
(
Class
clazz
,
Object
...
searchParamsMap
)
{
super
(
EntityNotFoundException
.
generateMessage
(
clazz
.
getSimpleName
(),
toMap
(
String
.
class
,
String
.
class
,
searchParamsMap
)));
}
private
static
String
generateMessage
(
String
entity
,
Map
<
String
,
String
>
searchParams
)
{
return
StringUtils
.
capitalize
(
entity
)
+
" 不存在 "
+
searchParams
;
public
EntityNotFoundException
(
Class
clazz
,
String
field
,
String
val
)
{
super
(
EntityNotFoundException
.
generateMessage
(
clazz
.
getSimpleName
(),
field
,
val
));
}
private
static
<
K
,
V
>
Map
<
K
,
V
>
toMap
(
Class
<
K
>
keyType
,
Class
<
V
>
valueType
,
Object
...
entries
)
{
if
(
entries
.
length
%
2
==
1
)
throw
new
IllegalArgumentException
(
"Invalid entries"
);
return
IntStream
.
range
(
0
,
entries
.
length
/
2
).
map
(
i
->
i
*
2
)
.
collect
(
HashMap:
:
new
,
(
m
,
i
)
->
m
.
put
(
keyType
.
cast
(
entries
[
i
]),
valueType
.
cast
(
entries
[
i
+
1
])),
Map:
:
putAll
);
private
static
String
generateMessage
(
String
entity
,
String
field
,
String
val
)
{
return
StringUtils
.
capitalize
(
entity
)
+
" with "
+
field
+
" "
+
val
+
" does not exist"
;
}
}
\ No newline at end of file
eladmin-common/src/main/java/me/zhengjie/exception/handler/ApiError.java
View file @
fd9fb2a6
...
...
@@ -12,7 +12,7 @@ import java.time.LocalDateTime;
@Data
class
ApiError
{
private
Integer
status
;
private
Integer
status
=
400
;
@JsonFormat
(
pattern
=
"yyyy-MM-dd HH:mm:ss"
)
private
LocalDateTime
timestamp
;
private
String
message
;
...
...
@@ -21,10 +21,17 @@ class ApiError {
timestamp
=
LocalDateTime
.
now
();
}
public
ApiError
(
Integer
status
,
String
message
)
{
this
();
this
.
status
=
status
;
this
.
message
=
message
;
public
static
ApiError
error
(
String
message
){
ApiError
apiError
=
new
ApiError
();
apiError
.
setMessage
(
message
);
return
apiError
;
}
public
static
ApiError
error
(
Integer
status
,
String
message
){
ApiError
apiError
=
new
ApiError
();
apiError
.
setStatus
(
status
);
apiError
.
setMessage
(
message
);
return
apiError
;
}
}
...
...
eladmin-common/src/main/java/me/zhengjie/exception/handler/GlobalExceptionHandler.java
View file @
fd9fb2a6
...
...
@@ -11,6 +11,7 @@ import org.springframework.security.access.AccessDeniedException;
import
org.springframework.web.bind.MethodArgumentNotValidException
;
import
org.springframework.web.bind.annotation.ExceptionHandler
;
import
org.springframework.web.bind.annotation.RestControllerAdvice
;
import
java.util.Objects
;
import
static
org
.
springframework
.
http
.
HttpStatus
.*;
/**
...
...
@@ -23,91 +24,73 @@ public class GlobalExceptionHandler {
/**
* 处理所有不可知的异常
* @param e
* @return
*/
@ExceptionHandler
(
Throwable
.
class
)
public
ResponseEntity
handleException
(
Throwable
e
){
// 打印堆栈信息
log
.
error
(
ThrowableUtil
.
getStackTrace
(
e
));
ApiError
apiError
=
new
ApiError
(
BAD_REQUEST
.
value
(),
e
.
getMessage
());
return
buildResponseEntity
(
apiError
);
return
buildResponseEntity
(
ApiError
.
error
(
e
.
getMessage
()));
}
/**
* 处理 接口无权访问异常AccessDeniedException
* @param e
* @return
*/
@ExceptionHandler
(
AccessDeniedException
.
class
)
public
ResponseEntity
handleAccessDeniedException
(
AccessDeniedException
e
){
// 打印堆栈信息
log
.
error
(
ThrowableUtil
.
getStackTrace
(
e
));
ApiError
apiError
=
new
ApiError
(
FORBIDDEN
.
value
(),
e
.
getMessage
());
return
buildResponseEntity
(
apiError
);
return
buildResponseEntity
(
ApiError
.
error
(
FORBIDDEN
.
value
(),
e
.
getMessage
()));
}
/**
* 处理自定义异常
* @param e
* @return
*/
@ExceptionHandler
(
value
=
BadRequestException
.
class
)
public
ResponseEntity
<
ApiError
>
badRequestException
(
BadRequestException
e
)
{
// 打印堆栈信息
log
.
error
(
ThrowableUtil
.
getStackTrace
(
e
));
ApiError
apiError
=
new
ApiError
(
e
.
getStatus
(),
e
.
getMessage
());
return
buildResponseEntity
(
apiError
);
return
buildResponseEntity
(
ApiError
.
error
(
e
.
getStatus
(),
e
.
getMessage
()));
}
/**
* 处理 EntityExist
* @param e
* @return
*/
@ExceptionHandler
(
value
=
EntityExistException
.
class
)
public
ResponseEntity
<
ApiError
>
entityExistException
(
EntityExistException
e
)
{
// 打印堆栈信息
log
.
error
(
ThrowableUtil
.
getStackTrace
(
e
));
ApiError
apiError
=
new
ApiError
(
BAD_REQUEST
.
value
(),
e
.
getMessage
());
return
buildResponseEntity
(
apiError
);
return
buildResponseEntity
(
ApiError
.
error
(
e
.
getMessage
()));
}
/**
* 处理 EntityNotFound
* @param e
* @return
*/
@ExceptionHandler
(
value
=
EntityNotFoundException
.
class
)
public
ResponseEntity
<
ApiError
>
entityNotFoundException
(
EntityNotFoundException
e
)
{
// 打印堆栈信息
log
.
error
(
ThrowableUtil
.
getStackTrace
(
e
));
ApiError
apiError
=
new
ApiError
(
NOT_FOUND
.
value
(),
e
.
getMessage
());
return
buildResponseEntity
(
apiError
);
return
buildResponseEntity
(
ApiError
.
error
(
NOT_FOUND
.
value
(),
e
.
getMessage
()));
}
/**
* 处理所有接口数据验证异常
* @param e
* @returns
*/
@ExceptionHandler
(
MethodArgumentNotValidException
.
class
)
public
ResponseEntity
<
ApiError
>
handleMethodArgumentNotValidException
(
MethodArgumentNotValidException
e
){
// 打印堆栈信息
log
.
error
(
ThrowableUtil
.
getStackTrace
(
e
));
String
[]
str
=
e
.
getBindingResult
().
getAllErrors
().
get
(
0
).
getCodes
()[
1
].
split
(
"\\."
);
StringBuffer
msg
=
new
StringBuffer
(
str
[
1
]+
":"
);
msg
.
append
(
e
.
getBindingResult
().
getAllErrors
().
get
(
0
).
getDefaultMessage
());
ApiError
apiError
=
new
ApiError
(
BAD_REQUEST
.
value
(),
msg
.
toString
());
return
buildResponseEntity
(
apiError
);
String
[]
str
=
Objects
.
requireNonNull
(
e
.
getBindingResult
().
getAllErrors
().
get
(
0
).
getCodes
())[
1
].
split
(
"\\."
);
String
message
=
e
.
getBindingResult
().
getAllErrors
().
get
(
0
).
getDefaultMessage
();
if
(
"不能为空"
.
equals
(
message
)){
message
=
str
[
1
]
+
":"
+
message
;
}
return
buildResponseEntity
(
ApiError
.
error
(
message
));
}
/**
* 统一返回
* @param apiError
* @return
*/
private
ResponseEntity
<
ApiError
>
buildResponseEntity
(
ApiError
apiError
)
{
return
new
ResponseEntity
(
apiError
,
HttpStatus
.
valueOf
(
apiError
.
getStatus
()));
return
new
ResponseEntity
<>
(
apiError
,
HttpStatus
.
valueOf
(
apiError
.
getStatus
()));
}
}
eladmin-common/src/main/java/me/zhengjie/redis/FastJsonRedisSerializer.java
deleted
100644 → 0
View file @
7895e547
package
me.zhengjie.redis
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.serializer.SerializerFeature
;
import
org.springframework.data.redis.serializer.RedisSerializer
;
import
org.springframework.data.redis.serializer.SerializationException
;
import
java.nio.charset.Charset
;
/**
* Value 序列化
*
* @author /
* @param <T>
*/
public
class
FastJsonRedisSerializer
<
T
>
implements
RedisSerializer
<
T
>
{
public
static
final
Charset
DEFAULT_CHARSET
=
Charset
.
forName
(
"UTF-8"
);
private
Class
<
T
>
clazz
;
public
FastJsonRedisSerializer
(
Class
<
T
>
clazz
)
{
super
();
this
.
clazz
=
clazz
;
}
@Override
public
byte
[]
serialize
(
T
t
)
throws
SerializationException
{
if
(
t
==
null
)
{
return
new
byte
[
0
];
}
return
JSON
.
toJSONString
(
t
,
SerializerFeature
.
WriteClassName
).
getBytes
(
DEFAULT_CHARSET
);
}
@Override
public
T
deserialize
(
byte
[]
bytes
)
throws
SerializationException
{
if
(
bytes
==
null
||
bytes
.
length
<=
0
)
{
return
null
;
}
String
str
=
new
String
(
bytes
,
DEFAULT_CHARSET
);
return
(
T
)
JSON
.
parseObject
(
str
,
clazz
);
}
}
eladmin-common/src/main/java/me/zhengjie/redis/StringRedisSerializer.java
deleted
100644 → 0
View file @
7895e547
package
me.zhengjie.redis
;
import
cn.hutool.core.lang.Assert
;
import
com.alibaba.fastjson.JSON
;
import
org.springframework.data.redis.serializer.RedisSerializer
;
import
java.nio.charset.Charset
;
/**
* 重写序列化器
*
* @author /
*/
public
class
StringRedisSerializer
implements
RedisSerializer
<
Object
>
{
private
final
Charset
charset
;
private
final
String
target
=
"\""
;
private
final
String
replacement
=
""
;
public
StringRedisSerializer
()
{
this
(
Charset
.
forName
(
"UTF8"
));
}
public
StringRedisSerializer
(
Charset
charset
)
{
Assert
.
notNull
(
charset
,
"Charset must not be null!"
);
this
.
charset
=
charset
;
}
@Override
public
String
deserialize
(
byte
[]
bytes
)
{
return
(
bytes
==
null
?
null
:
new
String
(
bytes
,
charset
));
}
@Override
public
byte
[]
serialize
(
Object
object
)
{
String
string
=
JSON
.
toJSONString
(
object
);
if
(
string
==
null
)
{
return
null
;
}
string
=
string
.
replace
(
target
,
replacement
);
return
string
.
getBytes
(
charset
);
}
}
\ No newline at end of file
eladmin-common/src/main/java/me/zhengjie/swagger2/SwaggerDataConfig.java
deleted
100644 → 0
View file @
7895e547
package
me.zhengjie.swagger2
;
import
com.fasterxml.classmate.TypeResolver
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.core.Ordered
;
import
org.springframework.data.domain.Pageable
;
import
springfox.documentation.schema.AlternateTypeRule
;
import
springfox.documentation.schema.AlternateTypeRuleConvention
;
import
java.util.List
;
import
static
com
.
google
.
common
.
collect
.
Lists
.
newArrayList
;
import
static
springfox
.
documentation
.
schema
.
AlternateTypeRules
.
newRule
;
/** * 将Pageable转换展示在swagger中 */
@Configuration
public
class
SwaggerDataConfig
{
@Bean
public
AlternateTypeRuleConvention
pageableConvention
(
final
TypeResolver
resolver
)
{
return
new
AlternateTypeRuleConvention
()
{
@Override
public
int
getOrder
()
{
return
Ordered
.
HIGHEST_PRECEDENCE
;
}
@Override
public
List
<
AlternateTypeRule
>
rules
()
{
return
newArrayList
(
newRule
(
resolver
.
resolve
(
Pageable
.
class
),
resolver
.
resolve
(
Page
.
class
)));
}
};
}
@ApiModel
static
class
Page
{
@ApiModelProperty
(
"页码 (0..N)"
)
private
Integer
page
;
@ApiModelProperty
(
"每页显示的数目"
)
private
Integer
size
;
@ApiModelProperty
(
"以下列格式排序标准:property[,asc | desc]。 默认排序顺序为升序。 支持多种排序条件:如:id,asc"
)
private
List
<
String
>
sort
;
public
Integer
getPage
()
{
return
page
;
}
public
void
setPage
(
Integer
page
)
{
this
.
page
=
page
;
}
public
Integer
getSize
()
{
return
size
;
}
public
void
setSize
(
Integer
size
)
{
this
.
size
=
size
;
}
public
List
<
String
>
getSort
()
{
return
sort
;
}
public
void
setSort
(
List
<
String
>
sort
)
{
this
.
sort
=
sort
;
}
}
}
\ No newline at end of file
Prev
1
2
3
4
5
…
12
Next
Write
Preview
Supports
Markdown
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