Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
查尔斯-BUG万象集
Continew Admin
提交
1e5eaab9
Continew Admin
项目概览
查尔斯-BUG万象集
/
Continew Admin
11 个月 前同步成功
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
分析
仓库
DevOps
项目成员
Pages
Continew Admin
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
1e5eaab9
编写于
12月 11, 2022
作者:
查尔斯-BUG万象集
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
新增:新增获取图片验证码 API(引入 Redisson、Hutool、Easy Captcha 依赖,详情可见 README 介绍)
上级
8967542a
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
875 addition
and
17 deletion
+875
-17
README.md
README.md
+46
-8
continew-admin-common/pom.xml
continew-admin-common/pom.xml
+7
-0
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/jackson/BigNumberSerializer.java
...7c/cnadmin/common/config/jackson/BigNumberSerializer.java
+55
-0
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/jackson/JacksonConfiguration.java
...c/cnadmin/common/config/jackson/JacksonConfiguration.java
+91
-0
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/vo/R.java
...rc/main/java/top/charles7c/cnadmin/common/model/vo/R.java
+101
-0
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/RedisUtils.java
...in/java/top/charles7c/cnadmin/common/util/RedisUtils.java
+215
-0
continew-admin-system/pom.xml
continew-admin-system/pom.xml
+6
-0
continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/config/properties/CaptchaProperties.java
...s7c/cnadmin/auth/config/properties/CaptchaProperties.java
+136
-0
continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/model/vo/CaptchaVO.java
...n/java/top/charles7c/cnadmin/auth/model/vo/CaptchaVO.java
+45
-0
continew-admin-webapi/src/main/java/top/charles7c/cnadmin/ContinewAdminApplication.java
.../java/top/charles7c/cnadmin/ContinewAdminApplication.java
+8
-4
continew-admin-webapi/src/main/java/top/charles7c/cnadmin/webapi/controller/auth/CaptchaController.java
...s7c/cnadmin/webapi/controller/auth/CaptchaController.java
+69
-0
continew-admin-webapi/src/main/resources/application-dev.yml
continew-admin-webapi/src/main/resources/application-dev.yml
+30
-0
continew-admin-webapi/src/main/resources/application-prod.yml
...inew-admin-webapi/src/main/resources/application-prod.yml
+30
-0
continew-admin-webapi/src/main/resources/application.yml
continew-admin-webapi/src/main/resources/application.yml
+2
-4
pom.xml
pom.xml
+34
-1
未找到文件。
README.md
浏览文件 @
1e5eaab9
...
...
@@ -5,28 +5,66 @@
### 简介
ContiNew-Admin (incubating) 中后台管理框架,Continue New Admin,持续以最新流行技术栈构建。当前阶段采用的技术栈:Spring Boot、Undertow 等。
ContiNew-Admin (incubating) 中后台管理框架,Continue New Admin,持续以最新流行技术栈构建。当前阶段采用的技术栈:Spring Boot、Undertow
、Redis、Redisson、Hutool
等。
### 技术栈
| 名称 | 版本 | 简介 |
| :---------------------------------------------------- | :----------- | :----------------------------------------------------------- |
|
[
Spring Boot
](
https://spring.io/projects/spring-boot
)
| 2.7.6 | 简化新 Spring 应用的初始搭建以及开发过程。 |
|
[
Undertow
](
https://undertow.io/
)
| 2.2.20.Final | 采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。 |
|
[
Lombok
](
https://projectlombok.org/
)
| 1.18.24 | 在 Java 开发过程中用注解的方式,简化了 JavaBean 的编写,避免了冗余和样板式代码,让编写的类更加简洁。 |
| 名称 | 版本 | 简介 |
| :----------------------------------------------------------- | :----------- | :----------------------------------------------------------- |
|
[
Spring Boot
](
https://spring.io/projects/spring-boot
)
| 2.7.6 | 简化新 Spring 应用的初始搭建以及开发过程。 |
|
[
Undertow
](
https://undertow.io/
)
| 2.2.20.Final | 采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。 |
|
[
Redis
](
https://redis.io/
)
| 6.2.7 | 高性能的 key-value 数据库。 |
|
[
Redisson
](
https://github.com/redisson/redisson/wiki/Redisson%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D
)
| 3.18.1 | 不仅仅是一个 Redis Java 客户端,同其他 Redis Java 客户端有着很大的区别,相比之下其他客户端提供的功能还仅仅停留在作为数据库驱动层面上,比如仅针对 Redis 提供连接方式,发送命令和处理返回结果等。而 Redisson 充分的利用了 Redis 键值数据库提供的一系列优势,基于 Java 实用工具包中常用接口,为使用者提供了一系列具有分布式特性的常用工具类。使得原本作为协调单机多线程并发程序的工具包获得了协调分布式多机多线程并发系统的能力,大大降低了设计和研发大规模分布式系统的难度。同时结合各富特色的分布式服务,更进一步简化了分布式环境中程序相互之间的协作。 |
| Easy Captcha | 1.6.2 | Java 图形验证码,支持 gif、中文、算术等类型,可用于 Java Web、JavaSE 等项目。 |
|
[
Hutool
](
https://www.hutool.cn/
)
| 5.8.10 | 小而全的 Java 工具类库,通过静态方法封装,降低相关 API 的学习成本,提高工作效率,使 Java 拥有函数式语言般的优雅,让 Java 语言也可以“甜甜的”。 |
|
[
Lombok
](
https://projectlombok.org/
)
| 1.18.24 | 在 Java 开发过程中用注解的方式,简化了 JavaBean 的编写,避免了冗余和样板式代码,让编写的类更加简洁。 |
### 项目结构
采用按功能拆分模块的开发方式,项目结构如下:
采用按功能拆分模块的开发方式,项目
目录
结构如下:
>
项目结构按模块的层次顺序介绍,实际 IDE 中 `continew-admin-common` 模块会因为字母排序原因排在上方
>
下方项目目录结构是按照模块的层次顺序进行介绍的,实际 IDE 中 `continew-admin-common` 模块会因为字母排序原因排在上方。
>
```
continew-admin 全局通用项目配置及依赖版本管理
├─continew-admin-webapi API 模块(存放 Controller 层代码,打包部署的模块)
│ ├─src
│ │ ├─main
│ │ │ ├─java 工程源文件代码目录
│ │ │ │ └─top
│ │ │ │ └─charles7c
│ │ │ │ └─cnadmin
│ │ │ │ └─webapi
│ │ │ │ └─controller
│ │ │ │ └─auth 认证相关 API
│ │ │ │ └─ContinewAdminApplication.java 启动入口
│ │ │ ├─resources 工程配置目录
├─continew-admin-system 系统管理模块(存放系统管理模块相关功能,例如:部门管理、角色管理、用户管理等)
│ ├─src 工程源文件代码目录
│ │ ├─main
│ │ │ ├─java
│ │ │ │ └─top
│ │ │ │ └─charles7c
│ │ │ │ └─cnadmin
│ │ │ │ └─auth 认证相关业务及配置
│ │ │ │ └─config 认证相关配置
│ │ │ │ └─properties 配置属性
│ │ │ │ └─model 认证相关模型
│ │ │ │ └─vo 认证相关 VO(View Object)
├─continew-admin-common 公共模块(存放公共工具类,公共配置等)
│ ├─src 工程源文件代码目录
│ │ ├─main
│ │ │ ├─java
│ │ │ │ └─top
│ │ │ │ └─charles7c
│ │ │ │ └─cnadmin
│ │ │ │ └─common
│ │ │ │ └─config 公共配置
│ │ │ │ └─jackson Jackson 配置
│ │ │ │ └─model 公共模型
│ │ │ │ └─vo 公共 VO(View Object)
│ │ │ │ └─util 公共工具类
```
### License
...
...
continew-admin-common/pom.xml
浏览文件 @
1e5eaab9
...
...
@@ -58,5 +58,12 @@ limitations under the License.
</exclusion>
</exclusions>
</dependency>
<!-- ################ 工具库相关 ################ -->
<!-- Redisson(不仅仅是一个 Redis Java 客户端) -->
<dependency>
<groupId>
org.redisson
</groupId>
<artifactId>
redisson-spring-boot-starter
</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/jackson/BigNumberSerializer.java
0 → 100644
浏览文件 @
1e5eaab9
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
top.charles7c.cnadmin.common.config.jackson
;
import
java.io.IOException
;
import
com.fasterxml.jackson.core.JsonGenerator
;
import
com.fasterxml.jackson.databind.SerializerProvider
;
import
com.fasterxml.jackson.databind.annotation.JacksonStdImpl
;
import
com.fasterxml.jackson.databind.ser.std.NumberSerializer
;
/**
* 大数值序列化器(针对数值超出 JS 最大或最小值的情况,将其转换为字符串)
*
* @author Charles7c
* @since 2022/12/11 13:22
*/
@JacksonStdImpl
public
class
BigNumberSerializer
extends
NumberSerializer
{
/** 静态实例 */
public
static
final
BigNumberSerializer
SERIALIZER_INSTANCE
=
new
BigNumberSerializer
(
Number
.
class
);
/** JS:Number.MAX_SAFE_INTEGER */
private
static
final
long
MAX_SAFE_INTEGER
=
9007199254740991L
;
/** JS:Number.MIN_SAFE_INTEGER */
private
static
final
long
MIN_SAFE_INTEGER
=
-
9007199254740991L
;
public
BigNumberSerializer
(
Class
<?
extends
Number
>
rawType
)
{
super
(
rawType
);
}
@Override
public
void
serialize
(
Number
value
,
JsonGenerator
gen
,
SerializerProvider
provider
)
throws
IOException
{
// 序列化为字符串
if
(
value
.
longValue
()
>
MIN_SAFE_INTEGER
&&
value
.
longValue
()
<
MAX_SAFE_INTEGER
)
{
super
.
serialize
(
value
,
gen
,
provider
);
}
else
{
gen
.
writeString
(
value
.
toString
());
}
}
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/jackson/JacksonConfiguration.java
0 → 100644
浏览文件 @
1e5eaab9
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
top.charles7c.cnadmin.common.config.jackson
;
import
java.math.BigDecimal
;
import
java.math.BigInteger
;
import
java.time.LocalDate
;
import
java.time.LocalDateTime
;
import
java.time.LocalTime
;
import
java.time.format.DateTimeFormatter
;
import
java.util.Locale
;
import
java.util.TimeZone
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
com.fasterxml.jackson.databind.ser.std.ToStringSerializer
;
import
com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
;
import
com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer
;
import
com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer
;
import
com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer
;
import
com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer
;
import
com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer
;
import
com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer
;
/**
* Jackson 配置
*
* @author Charles7c
* @since 2022/12/11 13:23
*/
@Slf4j
@Configuration
public
class
JacksonConfiguration
{
/**
* 全局配置序列化返回 JSON 处理
*/
@Bean
public
Jackson2ObjectMapperBuilderCustomizer
customizer
()
{
String
dateTimeFormatPattern
=
"yyyy-MM-dd HH:mm:ss"
;
String
dateFormatPattern
=
"yyyy-MM-dd"
;
String
timeFormatPattern
=
"HH:mm:ss"
;
return
builder
->
{
// 针对 java.util.Date 的转换
builder
.
locale
(
Locale
.
CHINA
);
builder
.
timeZone
(
TimeZone
.
getDefault
());
builder
.
simpleDateFormat
(
dateTimeFormatPattern
);
// 针对 Long、BigInteger、BigDecimal 的转换
JavaTimeModule
javaTimeModule
=
new
JavaTimeModule
();
javaTimeModule
.
addSerializer
(
Long
.
class
,
BigNumberSerializer
.
SERIALIZER_INSTANCE
);
javaTimeModule
.
addSerializer
(
Long
.
TYPE
,
BigNumberSerializer
.
SERIALIZER_INSTANCE
);
javaTimeModule
.
addSerializer
(
BigInteger
.
class
,
BigNumberSerializer
.
SERIALIZER_INSTANCE
);
javaTimeModule
.
addSerializer
(
BigDecimal
.
class
,
ToStringSerializer
.
instance
);
// 针对 LocalDateTime、LocalDate、LocalTime 的转换
DateTimeFormatter
dateTimeFormatter
=
DateTimeFormatter
.
ofPattern
(
dateTimeFormatPattern
);
javaTimeModule
.
addSerializer
(
LocalDateTime
.
class
,
new
LocalDateTimeSerializer
(
dateTimeFormatter
));
javaTimeModule
.
addDeserializer
(
LocalDateTime
.
class
,
new
LocalDateTimeDeserializer
(
dateTimeFormatter
));
DateTimeFormatter
dateFormatter
=
DateTimeFormatter
.
ofPattern
(
dateFormatPattern
);
javaTimeModule
.
addSerializer
(
LocalDate
.
class
,
new
LocalDateSerializer
(
dateFormatter
));
javaTimeModule
.
addDeserializer
(
LocalDate
.
class
,
new
LocalDateDeserializer
(
dateFormatter
));
DateTimeFormatter
timeFormatter
=
DateTimeFormatter
.
ofPattern
(
timeFormatPattern
);
javaTimeModule
.
addSerializer
(
LocalTime
.
class
,
new
LocalTimeSerializer
(
timeFormatter
));
javaTimeModule
.
addDeserializer
(
LocalTime
.
class
,
new
LocalTimeDeserializer
(
timeFormatter
));
builder
.
modules
(
javaTimeModule
);
log
.
info
(
">>>初始化 Jackson 配置<<<"
);
};
}
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/vo/R.java
0 → 100644
浏览文件 @
1e5eaab9
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
top.charles7c.cnadmin.common.model.vo
;
import
java.io.Serializable
;
import
java.time.LocalDateTime
;
import
lombok.AccessLevel
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
org.springframework.http.HttpStatus
;
import
com.fasterxml.jackson.annotation.JsonFormat
;
/**
* 响应信息
*
* @author Charles7c
* @since 2022/12/10 23:31
*/
@Data
@NoArgsConstructor
(
access
=
AccessLevel
.
PRIVATE
)
public
class
R
<
V
extends
Serializable
>
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/** 是否成功 */
private
boolean
success
;
/** 状态码 */
private
int
code
;
/** 状态信息 */
private
String
msg
;
/** 返回数据 */
private
V
data
;
/** 时间戳 */
@JsonFormat
(
pattern
=
"yyyy-MM-dd HH:mm:ss"
)
private
LocalDateTime
timestamp
=
LocalDateTime
.
now
();
/** 成功状态码 */
private
static
final
int
SUCCESS_CODE
=
HttpStatus
.
OK
.
value
();
/** 失败状态码 */
private
static
final
int
FAIL_CODE
=
HttpStatus
.
INTERNAL_SERVER_ERROR
.
value
();
private
R
(
boolean
success
,
int
code
,
String
msg
,
V
data
)
{
this
.
success
=
success
;
this
.
code
=
code
;
this
.
msg
=
msg
;
this
.
data
=
data
;
}
public
static
<
V
extends
Serializable
>
R
<
V
>
ok
()
{
return
new
R
<>(
true
,
SUCCESS_CODE
,
"操作成功"
,
null
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
ok
(
V
data
)
{
return
new
R
<>(
true
,
SUCCESS_CODE
,
"操作成功"
,
data
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
ok
(
String
msg
)
{
return
new
R
<>(
true
,
SUCCESS_CODE
,
msg
,
null
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
ok
(
String
msg
,
V
data
)
{
return
new
R
<>(
true
,
SUCCESS_CODE
,
msg
,
data
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
fail
()
{
return
new
R
<>(
false
,
FAIL_CODE
,
"操作失败"
,
null
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
fail
(
String
msg
)
{
return
new
R
<>(
false
,
FAIL_CODE
,
msg
,
null
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
fail
(
V
data
)
{
return
new
R
<>(
false
,
FAIL_CODE
,
"操作失败"
,
data
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
fail
(
String
msg
,
V
data
)
{
return
new
R
<>(
false
,
FAIL_CODE
,
msg
,
data
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
fail
(
int
code
,
String
msg
)
{
return
new
R
<>(
false
,
code
,
msg
,
null
);
}
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/RedisUtils.java
0 → 100644
浏览文件 @
1e5eaab9
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
top.charles7c.cnadmin.common.util
;
import
java.time.Duration
;
import
java.util.Collection
;
import
java.util.stream.Collectors
;
import
java.util.stream.Stream
;
import
lombok.AccessLevel
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
org.redisson.api.*
;
import
org.redisson.config.Config
;
import
cn.hutool.extra.spring.SpringUtil
;
/**
* Redis 工具类
*
* @author Charles7c
* @since 2022/12/11 12:00
*/
@Data
@NoArgsConstructor
(
access
=
AccessLevel
.
PRIVATE
)
public
class
RedisUtils
{
private
static
final
RedissonClient
REDISSON_CLIENT
=
SpringUtil
.
getBean
(
RedissonClient
.
class
);
/* ################ 查询操作 ################ */
/**
* 获取缓存的基本对象列表
*
* @param keyPattern
* 缓存键表达式
* @return 基本对象列表
*/
public
static
Collection
<
String
>
keys
(
final
String
keyPattern
)
{
Stream
<
String
>
stream
=
REDISSON_CLIENT
.
getKeys
().
getKeysStreamByPattern
(
getNameMapper
().
map
(
keyPattern
));
return
stream
.
map
(
key
->
getNameMapper
().
unmap
(
key
)).
collect
(
Collectors
.
toList
());
}
/**
* 是否存在指定缓存
*
* @param key
* 缓存键
*/
public
static
Boolean
hasKey
(
String
key
)
{
RKeys
rKeys
=
REDISSON_CLIENT
.
getKeys
();
return
rKeys
.
countExists
(
getNameMapper
().
map
(
key
))
>
0
;
}
/**
* 获取缓存剩余存活时间
*
* @param key
* 缓存键
* @return 剩余存活时间
*/
public
static
<
T
>
long
getTimeToLive
(
final
String
key
)
{
RBucket
<
T
>
rBucket
=
REDISSON_CLIENT
.
getBucket
(
key
);
return
rBucket
.
remainTimeToLive
();
}
/**
* 获取缓存的基本对象
*
* @param key
* 缓存键
* @return 缓存值
*/
public
static
<
T
>
T
getCacheObject
(
final
String
key
)
{
RBucket
<
T
>
rBucket
=
REDISSON_CLIENT
.
getBucket
(
key
);
return
rBucket
.
get
();
}
/* ################ 操作有效期 ################ */
/**
* 设置过期时间
*
* @param key
* 缓存键
* @param timeout
* 过期时间
* @return true 设置成功;false 设置失败
*/
public
static
boolean
expire
(
final
String
key
,
final
long
timeout
)
{
return
expire
(
key
,
Duration
.
ofSeconds
(
timeout
));
}
/**
* 设置过期时间
*
* @param key
* 缓存键
* @param duration
* 过期时间
* @return true 设置成功;false 设置失败
*/
public
static
boolean
expire
(
final
String
key
,
final
Duration
duration
)
{
RBucket
rBucket
=
REDISSON_CLIENT
.
getBucket
(
key
);
return
rBucket
.
expire
(
duration
);
}
/* ################ 操作基本对象 ################ */
/**
* 缓存基本对象(Integer、String、实体类等)
*
* @param key
* 缓存键
* @param value
* 缓存值
*/
public
static
<
T
>
void
setCacheObject
(
final
String
key
,
final
T
value
)
{
setCacheObject
(
key
,
value
,
false
);
}
/**
* 缓存基本对象,保留当前对象 TTL 有效期
*
* @param key
* 缓存键
* @param value
* 缓存值
* @param isSaveTtl
* 是否保留 TTL 有效期(例如: set 之前 ttl 剩余 90,set 之后还是为 90)
* @since Redis 6.X 以上使用 setAndKeepTTL 兼容 5.X 方案
*/
public
static
<
T
>
void
setCacheObject
(
final
String
key
,
final
T
value
,
final
boolean
isSaveTtl
)
{
RBucket
<
T
>
bucket
=
REDISSON_CLIENT
.
getBucket
(
key
);
if
(
isSaveTtl
)
{
try
{
bucket
.
setAndKeepTTL
(
value
);
}
catch
(
Exception
e
)
{
long
timeToLive
=
bucket
.
remainTimeToLive
();
setCacheObject
(
key
,
value
,
Duration
.
ofMillis
(
timeToLive
));
}
}
else
{
bucket
.
set
(
value
);
}
}
/**
* 缓存基本对象(Integer、String、实体类等)
*
* @param key
* 缓存键
* @param value
* 缓存值
* @param duration
* 时间
*/
public
static
<
T
>
void
setCacheObject
(
final
String
key
,
final
T
value
,
final
Duration
duration
)
{
RBatch
batch
=
REDISSON_CLIENT
.
createBatch
();
RBucketAsync
<
T
>
bucket
=
batch
.
getBucket
(
key
);
bucket
.
setAsync
(
value
);
bucket
.
expireAsync
(
duration
);
batch
.
execute
();
}
/**
* 删除缓存的基本对象
*
* @param key
* 缓存键
*/
public
static
boolean
deleteCacheObject
(
final
String
key
)
{
return
REDISSON_CLIENT
.
getBucket
(
key
).
delete
();
}
/**
* 删除缓存的基本对象列表
*
* @param keyPattern
* 缓存键表达式
*/
public
static
void
deleteKeys
(
final
String
keyPattern
)
{
REDISSON_CLIENT
.
getKeys
().
deleteByPattern
(
getNameMapper
().
map
(
keyPattern
));
}
/**
* 格式化缓存键,将各子键用 : 拼接起来
*
* @param subKeys
* 子键列表
* @return 缓存键
*/
public
static
String
formatKey
(
String
...
subKeys
)
{
return
String
.
join
(
":"
,
subKeys
);
}
public
static
NameMapper
getNameMapper
()
{
Config
config
=
REDISSON_CLIENT
.
getConfig
();
if
(
config
.
isClusterConfig
())
{
return
config
.
useClusterServers
().
getNameMapper
();
}
return
config
.
useSingleServer
().
getNameMapper
();
}
}
continew-admin-system/pom.xml
浏览文件 @
1e5eaab9
...
...
@@ -32,6 +32,12 @@ limitations under the License.
<description>
系统管理模块(存放系统管理模块相关功能,例如:部门管理、角色管理、用户管理等)
</description>
<dependencies>
<!-- Easy Captcha(Java 图形验证码,支持 gif、中文、算术等类型,可用于 Java Web、JavaSE 等项目) -->
<dependency>
<groupId>
com.github.whvcse
</groupId>
<artifactId>
easy-captcha
</artifactId>
</dependency>
<!-- 公共模块(存放公共工具类,公共配置等) -->
<dependency>
<groupId>
top.charles7c
</groupId>
...
...
continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/config/properties/CaptchaProperties.java
0 → 100644
浏览文件 @
1e5eaab9
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
top.charles7c.cnadmin.auth.config.properties
;
import
java.awt.*
;
import
lombok.Data
;
import
lombok.Getter
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.stereotype.Component
;
import
com.wf.captcha.*
;
import
com.wf.captcha.base.Captcha
;
import
cn.hutool.core.util.ReflectUtil
;
import
cn.hutool.core.util.StrUtil
;
/**
* 验证码配置属性
*
* @author Charles7c
* @since 2022/12/11 13:35
*/
@Data
@Component
@ConfigurationProperties
(
prefix
=
"captcha"
)
public
class
CaptchaProperties
{
/**
* 类型
*/
private
CaptchaTypeEnum
type
;
/**
* 缓存键的前缀
*/
private
String
keyPrefix
;
/**
* 过期时间
*/
private
Long
expirationInMinutes
=
2L
;
/**
* 内容长度
*/
private
int
length
=
4
;
/**
* 宽度
*/
private
int
width
=
111
;
/**
* 高度
*/
private
int
height
=
36
;
/**
* 字体
*/
private
String
fontName
;
/**
* 字体大小
*/
private
int
fontSize
=
25
;
/**
* 获取验证码对象
*
* @return 验证码对象
*/
public
Captcha
getCaptcha
()
{
Captcha
captcha
=
ReflectUtil
.
newInstance
(
type
.
getClazz
(),
this
.
width
,
this
.
height
);
captcha
.
setLen
(
length
);
if
(
StrUtil
.
isNotBlank
(
this
.
fontName
))
{
captcha
.
setFont
(
new
Font
(
this
.
fontName
,
Font
.
PLAIN
,
this
.
fontSize
));
}
return
captcha
;
}
/**
* 验证码类型枚举
*/
@Getter
@RequiredArgsConstructor
public
enum
CaptchaTypeEnum
{
/**
* 算术
*/
ARITHMETIC
(
ArithmeticCaptcha
.
class
),
/**
* 中文
*/
CHINESE
(
ChineseCaptcha
.
class
),
/**
* 中文闪图
*/
CHINESE_GIF
(
ChineseGifCaptcha
.
class
),
/**
* 闪图
*/
GIF
(
GifCaptcha
.
class
),
/**
* 特殊类型
*/
SPEC
(
SpecCaptcha
.
class
),;
/**
* 验证码字节码类型
*/
private
final
Class
<?
extends
Captcha
>
clazz
;
}
}
continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/model/vo/CaptchaVO.java
0 → 100644
浏览文件 @
1e5eaab9
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
top.charles7c.cnadmin.auth.model.vo
;
import
java.io.Serializable
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
/**
* 验证码信息
*
* @author Charles7c
* @since 2022/12/11 13:55
*/
@Data
@Accessors
(
chain
=
true
)
public
class
CaptchaVO
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 验证码唯一标识
*/
private
String
uuid
;
/**
* 验证码图片(Base64编码,带图片格式:data:image/gif;base64)
*/
private
String
img
;
}
continew-admin-webapi/src/main/java/top/charles7c/ContinewAdminApplication.java
→
continew-admin-webapi/src/main/java/top/charles7c/
cnadmin/
ContinewAdminApplication.java
浏览文件 @
1e5eaab9
...
...
@@ -14,20 +14,22 @@
* limitations under the License.
*/
package
top.charles7c
;
package
top.charles7c
.cnadmin
;
import
java.net.InetAddress
;
import
lombok.SneakyThrows
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.context.ConfigurableApplicationContext
;
import
org.springframework.context.annotation.ComponentScan
;
import
org.springframework.context.annotation.Import
;
import
org.springframework.core.env.Environment
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
lombok.SneakyThrows
;
import
lombok.extern.slf4j.Slf4j
;
/**
* 启动程序
*
...
...
@@ -37,6 +39,8 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestController
@SpringBootApplication
@Import
(
cn
.
hutool
.
extra
.
spring
.
SpringUtil
.
class
)
@ComponentScan
(
basePackages
=
{
"top.charles7c.cnadmin"
,
"cn.hutool.extra.spring"
})
public
class
ContinewAdminApplication
{
private
static
Environment
env
;
...
...
continew-admin-webapi/src/main/java/top/charles7c/cnadmin/webapi/controller/auth/CaptchaController.java
0 → 100644
浏览文件 @
1e5eaab9
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
top.charles7c.cnadmin.webapi.controller.auth
;
import
java.time.Duration
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
com.wf.captcha.base.Captcha
;
import
cn.hutool.core.util.IdUtil
;
import
top.charles7c.cnadmin.auth.config.properties.CaptchaProperties
;
import
top.charles7c.cnadmin.auth.model.vo.CaptchaVO
;
import
top.charles7c.cnadmin.common.model.vo.R
;
import
top.charles7c.cnadmin.common.util.RedisUtils
;
/**
* 验证码 API
*
* @author Charles7c
* @since 2022/12/11 14:00
*/
@RestController
@RequiredArgsConstructor
@RequestMapping
(
"/captcha"
)
public
class
CaptchaController
{
private
final
CaptchaProperties
captchaProperties
;
/**
* 获取图片验证码
*
* @return 验证码信息
*/
@GetMapping
(
"/img"
)
public
R
<
CaptchaVO
>
getImageCaptcha
()
{
// 生成验证码
Captcha
captcha
=
captchaProperties
.
getCaptcha
();
// 保存验证码
String
uuid
=
IdUtil
.
simpleUUID
();
String
captchaKey
=
RedisUtils
.
formatKey
(
captchaProperties
.
getKeyPrefix
(),
uuid
);
RedisUtils
.
setCacheObject
(
captchaKey
,
captcha
.
text
(),
Duration
.
ofMinutes
(
captchaProperties
.
getExpirationInMinutes
()));
// 返回验证码
CaptchaVO
captchaVo
=
new
CaptchaVO
().
setUuid
(
uuid
).
setImg
(
captcha
.
toBase64
());
return
R
.
ok
(
captchaVo
);
}
}
continew-admin-webapi/src/main/resources/application-dev.yml
浏览文件 @
1e5eaab9
...
...
@@ -3,3 +3,33 @@ server:
# HTTP 端口(默认 8080)
port
:
8000
---
### Redis 单机配置
spring
:
redis
:
# 地址
host
:
${REDIS_HOST:127.0.0.1}
# 端口(默认 6379)
port
:
${REDIS_PORT:6379}
# 密码(未设置密码时可为空或注释掉)
password
:
${REDIS_PWD:123456}
# 数据库索引
database
:
${REDIS_DB:0}
# 连接超时时间
timeout
:
10s
# 是否开启 SSL
ssl
:
false
---
### 验证码配置
captcha
:
# 类型
type
:
SPEC
# 缓存键的前缀
keyPrefix
:
CAPTCHA
# 过期时间
expirationInMinutes
:
2
# 内容长度
length
:
4
# 宽度
width
:
111
# 高度
height
:
36
\ No newline at end of file
continew-admin-webapi/src/main/resources/application-prod.yml
浏览文件 @
1e5eaab9
...
...
@@ -3,3 +3,33 @@ server:
# HTTP 端口(默认 8080)
port
:
18000
---
### Redis 单机配置
spring
:
redis
:
# 地址
host
:
${REDIS_HOST:127.0.0.1}
# 端口(默认 6379)
port
:
${REDIS_PORT:6379}
# 密码(未设置密码时可为空或注释掉)
password
:
${REDIS_PWD:123456}
# 数据库索引
database
:
${REDIS_DB:0}
# 连接超时时间
timeout
:
10s
# 是否开启 SSL
ssl
:
false
---
### 验证码配置
captcha
:
# 类型
type
:
SPEC
# 缓存键的前缀
keyPrefix
:
CAPTCHA
# 过期时间
expirationInMinutes
:
2
# 内容长度
length
:
4
# 宽度
width
:
111
# 高度
height
:
36
\ No newline at end of file
continew-admin-webapi/src/main/resources/application.yml
浏览文件 @
1e5eaab9
...
...
@@ -52,11 +52,9 @@ spring:
date-format
:
yyyy-MM-dd HH:mm:ss
# 序列化配置(Bean -> JSON)
serialization
:
# 是否格式化输出
indent_output
:
false
# 忽略无法转换的对象
# 允许序列化无属性的 Bean
fail_on_empty_beans
:
false
# 反序列化配置(JSON -> Bean)
deserialization
:
#
忽略 JSON 中
不存在的属性
#
允许反序列化
不存在的属性
fail_on_unknown_properties
:
false
\ No newline at end of file
pom.xml
浏览文件 @
1e5eaab9
...
...
@@ -42,6 +42,11 @@ limitations under the License.
</parent>
<properties>
<!-- ### 工具库相关 ### -->
<redisson.version>
3.18.1
</redisson.version>
<easy-captcha.version>
1.6.2
</easy-captcha.version>
<hutool.version>
5.8.10
</hutool.version>
<!-- ### 基础环境相关 ### -->
<revision>
0.0.1-SNAPSHOT
</revision>
<java.version>
1.8
</java.version>
...
...
@@ -54,6 +59,28 @@ limitations under the License.
<!-- 全局依赖版本管理 -->
<dependencyManagement>
<dependencies>
<!-- ################ 工具库相关 ################ -->
<!-- Redisson(不仅仅是一个 Redis Java 客户端) -->
<dependency>
<groupId>
org.redisson
</groupId>
<artifactId>
redisson-spring-boot-starter
</artifactId>
<version>
${redisson.version}
</version>
</dependency>
<!-- Easy Captcha(Java 图形验证码,支持 gif、中文、算术等类型,可用于 Java Web、JavaSE 等项目) -->
<dependency>
<groupId>
com.github.whvcse
</groupId>
<artifactId>
easy-captcha
</artifactId>
<version>
${easy-captcha.version}
</version>
</dependency>
<!-- Hutool(小而全的 Java 工具类库,通过静态方法封装,降低相关 API 的学习成本,提高工作效率,使 Java 拥有函数式语言般的优雅,让 Java 语言也可以“甜甜的”) -->
<dependency>
<groupId>
cn.hutool
</groupId>
<artifactId>
hutool-all
</artifactId>
<version>
${hutool.version}
</version>
</dependency>
<!-- ################ 本项目子模块相关 ################ -->
<!-- API 模块(存放 Controller 层代码,打包部署的模块) -->
<dependency>
...
...
@@ -92,6 +119,12 @@ limitations under the License.
<optional>
true
</optional>
</dependency>
<!-- Hutool(小而全的 Java 工具类库,通过静态方法封装,降低相关 API 的学习成本,提高工作效率,使 Java 拥有函数式语言般的优雅,让 Java 语言也可以“甜甜的”) -->
<dependency>
<groupId>
cn.hutool
</groupId>
<artifactId>
hutool-all
</artifactId>
</dependency>
<!-- Lombok(在 Java 开发过程中用注解的方式,简化了 JavaBean 的编写,避免了冗余和样板式代码,让编写的类更加简洁) -->
<dependency>
<groupId>
org.projectlombok
</groupId>
...
...
@@ -118,7 +151,7 @@ limitations under the License.
<configuration>
<java>
<importOrder>
<order>
java,javax,
org,com
,top.charles7c,
</order>
<order>
java,javax,
lombok,org,com,cn
,top.charles7c,
</order>
</importOrder>
<removeUnusedImports/>
<eclipse>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录