Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
L
ldp-docs
Project
Project
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
doc
ldp-docs
Commits
f7e12556
Commit
f7e12556
authored
Dec 30, 2020
by
马超
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
doc: 更新路径
parent
df915a1d
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1 addition
and
778 deletions
+1
-778
README.md
README.md
+1
-1
LDP 框架自定义注解.md
开发文档/LDP 框架自定义注解.md
+0
-777
No files found.
README.md
View file @
f7e12556
...
...
@@ -28,7 +28,7 @@
2、
[
Example样例工程开发文档
](
开发文档/Example样例工程开发文档.md
)
3、
[
LDP
框架自定义注解.md
](
http://gitlab.dev.shxrtech.com/doc/ldp-docs/blob/master/开发文档/LDP
框架自定义注解.md)
3、
[
LDP
框架自定义注解.md
](
http://gitlab.dev.shxrtech.com/doc/ldp-docs/blob/master/开发文档/LDP
框架自定义注解.md
)
4、
[
git提交规范说明
](
开发文档/git提交规范说明.md
)
...
...
开发文档/LDP 框架自定义注解.md
deleted
100644 → 0
View file @
df915a1d
# LDP 框架自定义注解使用说明文档
本文档是帮助开发者快速熟悉LDP框架中的自定义注解。
## 一、自动填充注解
### 1.1. @AutoComputed
依赖:base-api。
#### 1.1.1 注解介绍
**@AutoComputed**
是一个字段注解,标识
**实体类**
字段为自动填充的注解,需要配合服务层的
**@AutoService**
使用,拥有四个属性,command、ref、refs、format。注解可以通过command标识字段自动装配的方式,根据字段名查找对应计算方法,或根据command类型查找对应系统计算方法。command默认值为
**ComputedCommand.AUTO**
,以下是内置command每个值的解释:
**AUTO**
:根据字段名进行填充。
**MD5**
:将字段值进行一次md5加密。
**DATETIME**
:当前时间。
**USERID**
:当前登录用户。
**UUID**
:生成32位随机字符串。
**PINYIN**
:将ref字段的拼音填充到此字段中
**REFERENCE**
:将refs字段的值通过format规则填充到此字段
#### 1.1.2 使用案例
```
java
// 值为AUTO,通过属性名查找计算方式,这里的计算方式就是createId
@AutoComputed
private
String
createId
;
// 值为MD5,将原本的明文做一次md5加密并重新赋值到字段中
@AutoComputed
(
command
=
ComputedCommand
.
MD5
)
private
String
userPassword
;
// 值为DATETIME,将当前时间填充到字段中
@AutoComputed
(
command
=
ComputedCommand
.
DATETIME
)
private
Date
createTime
;
// 值为USERID,将当前登录用户ID填充到字段中
@AutoComputed
(
command
=
ComputedCommand
.
USERID
)
private
String
updateId
;
// 值为UUID,将随机生成的UUID填充到字段中
@AutoComputed
(
command
=
ComputedCommand
.
UUID
)
private
String
uuId
;
// 值为PINYIN,ref为userName,将userName字段的中文拼音自动填充到字段中
@AutoComputed
(
command
=
ComputedCommand
.
PINYIN
,
ref
=
"userName"
)
private
String
sortName
;
// 值为REFERENCE,refs是一个数组, 将数组中的字段值按照format的规则填充到字段中
@AutoComputed
(
command
=
ComputedCommand
.
REFERENCE
,
refs
=
{
"name"
,
"age"
,
"gender"
},
format
=
"%s-%s-%s"
)
private
String
referenceValue
;
```
#### 1.1.3 自定义填充算法
当command值为
**ComputedCommand.AUTO**
时,会通过字段名查找计算方式,这里介绍一下如何自定义填充算法。自动填充算法分为三种:
-
第一种是有参算法,例如MD5算法需要使用到原字段中的值作为参数:
```
java
// 值为MD5,将原本的明文做一次md5加密并重新赋值到字段中
@AutoComputed
(
command
=
ComputedCommand
.
MD5
)
private
String
userPassword
;
```
需要实现
**ComputerArgs**
接口,将自动填充算法写到computed中。例如Md5填充算法代码如下:
```
java
public
class
ComputerMd5
implements
ComputerArgs
{
@Override
public
String
computed
(
Object
plain
)
{
//这里进行处理,并返回自动填充内容
return
DigestUtils
.
md5Hex
(
plain
.
toString
());
}
}
```
-
第二种也是有参算法,主要是为了按照format进行自动填充,例如:
```
java
// 值为REFERENCE,refs是一个数组, 将数组中的字段值按照format的规则填充到字段中
@AutoComputed
(
command
=
ComputedCommand
.
REFERENCE
,
refs
=
{
"name"
,
"age"
,
"gender"
},
format
=
"%s-%s-%s"
)
private
String
referenceValue
;
```
需要实现
**ComputerFormatArgs**
接口,将自动填充算法写到computed中。例如REFERENCE填充算法如下:
```
java
public
class
ComputerReference
implements
ComputerFormatArgs
{
@Override
public
String
computed
(
Object
target
,
String
format
)
{
String
result
=
""
;
//核心代码如下,如果format为空则默认以下划线拼接,否则按fromat格式化
if
(
StringUtils
.
isEmpty
(
format
))
{
result
=
StringUtils
.
joinWith
(
"_"
,
objects
);
}
else
{
result
=
String
.
format
(
format
,
objects
);
}
return
result
;
}
}
```
-
第三种是无参算法,例如DATETIME算法就是一个无参算法,只需要获取当前时间:
```
java
// 值为DATETIME,将当前时间填充到字段中
@AutoComputed
(
command
=
ComputedCommand
.
DATETIME
)
private
Date
createTime
;
```
无参算法与有参类似,只是没有参数,需要实现
**ComputerNoArgs**
接口
```
java
public
class
ComputerDate
implements
ComputerNoArgs
<
Date
>
{
@Override
public
Date
computed
()
{
return
new
Date
();
}
}
```
-
完成算法编写后,还需要将计算类与字段名对应起来。
在service包中新建computed包(推荐),新建一个类,加上
**@Configuration**
注解,在
**@Bean**
注解中的name属性填上字段名。例如字段createId的填充算法是一个无参算法,方法返回类型为
**ComputerNoArgs**
,如果为有参算法,则应该返回
**ComputerArgs**
或者
**ComputerFormatArgs**
。
```
java
@Configuration
public
class
ComputedResolver
{
@Bean
(
name
=
"createId"
)
public
ComputerNoArgs
getCreateId
()
{
return
new
ComputerUser
();
}
}
```
当AOP在处理自动填充时,这个字段就会根据上面编辑的算法进行自动填充。
### 1.2. @AutoService
依赖:mcs-common
#### 1.2.1 注解介绍
**@AutoService**
是一个方法注解,被
**@AutoService**
注解的方法,都会被AOP拦截,并根据实体类字段中的
**@AutoComputed**
规则对字段自动填充。拥有两个属性 mode、init,mode为填充方式,默认为
**ComputedMode.COMPUTED**
,init为是否初始化,初始化则全部填充,否则只填充updateId、updateTime、sortName。
默认取方法的第一个参数进行填充,支持单个实体,也支持List集合。
#### 1.2.2 使用案例
一般@AutoService用于新增方法,以及更新方法
```
java
// 新增方法
@AutoService
public
void
add
(
LdpMcsElementInfo
elementInfo
)
{
genericDaoService
.
insert
(
elementInfo
);
}
// 更新方法
@AutoService
(
init
=
false
)
public
void
update
(
LdpMcsElementInfo
elementInfo
)
{
genericDaoService
.
dynamicUpdate
(
elementInfo
);
}
```
### 1.3. @AutoRelativeComputed
依赖:mcs-common
#### 1.3.1 注解介绍
**@AutoRelativeComputed**
是一个方法注解,对使用JPA配置了关联关系实体类进行自动填充,主要作用于Service层,对新增关联和移除关联方法参数进行自动填充。
@AutoRelativeComputed字段详解:
**mode**
:关联类型,目前支持RelativeMode.MTM(多对多)、RelativeMode.OTM(一对多)、RelativeMode.MTO(多对一)。
**PS:一对多、多对一暂时不建议使用**
**inverse**
:是否为逆向,false为单向绑定,true为双向绑定,默认为false。
**source**
:参数源类型。
**target**
:参数目标类型。
**joinField**
:关联字段。
**inverseField**
:逆向关联字段。
**exComputed**
:扩展的填充字段。
#### 1.3.2 使用案例
##### 1). 多对多关系
这里举例为用户和角色的多对多关系。
用户表(user):
| 字段名称 | 类型 | 备注 |
| --------- | ------ | ---------------- |
| id | String | 用户ID,唯一标识 |
| user_name | String | 用户名 |
角色表(role):
| 字段名称 | 类型 | 备注 |
| --------- | ------ | ---------------- |
| id | String | 角色ID,唯一标识 |
| role_name | String | 角色名称 |
用户角色关联表(user_role):
| 字段名称 | 类型 | 备注 |
| -------- | ------ | ------------ |
| id | String | ID,唯一标识 |
| user_id | String | 用户ID |
| role_id | String | 角色ID |
1.
使用JPA配置实体类关联关系
**User.java**
```
java
/**
* 与角色的多对多关联
*/
@JsonIgnoreProperties
(
"userInfos"
)
//避免互相关联死循环
@ManyToMany
(
fetch
=
FetchType
.
EAGER
)
@JoinTable
(
name
=
"user_role"
,
//中间表的名称
joinColumns
=
{
@JoinColumn
(
name
=
"user_id"
,
referencedColumnName
=
"id"
)},
inverseJoinColumns
=
{
@JoinColumn
(
name
=
"role_id"
,
referencedColumnName
=
"id"
)})
private
Set
<
Role
>
roleInfos
=
new
HashSet
<>();
```
**
Role
.
java
**
```
java
@JsonIgnoreProperties
(
"roleInfos"
)
@ManyToMany
(
mappedBy
=
"roleInfos"
,
fetch
=
FetchType
.
EAGER
,
targetEntity
=
User
.
class
)
private
Set
<
User
>
userInfos
=
new
HashSet
<>(
0
);
```
2
.
在
**
UserServiceImpl
**
中添加方法和注解
```
java
/**
* 添加角色关联
*
* @param id 用户ID
* @param list 通过注解将List<Role>转换为List<UserRole>
* @param param 作为删除条件,避免重复数据
*/
@AutoRelativeComputed
(
mode
=
RelativeMode
.
MTM
,
source
=
Role
.
class
,
target
=
UserRole
.
class
,
joinField
=
"userId"
,
inverseField
=
"roleId"
)
public
void
addRoleToUser
(
String
id
,
List
list
,
Map
<
String
,
Object
>
param
)
{
LinkedList
<
TranscationEntity
>
entityList
=
new
LinkedList
<>();
// 删除重复数据
entityList
.
add
(
new
TranscationEntity
(
TransItemExeType
.
DELETE_ENTITY
,
UserRole
.
class
,
param
));
// 新增
entityList
.
add
(
new
TranscationEntity
(
TransItemExeType
.
INSERT_ENTITY
,
list
));
genericDaoService
.
executeTrans
(
entityList
);
}
/**
* 移除角色关联
*
* @param id 用户ID
* @param list 通过注解将List<Role>转换为List<UserRole>
* @param param 作为删除条件,避免重复数据
*/
@AutoRelativeComputed
(
mode
=
RelativeMode
.
MTM
,
source
=
Role
.
class
,
target
=
UserRole
.
class
,
joinField
=
"userId"
,
inverseField
=
"roleId"
)
public
void
removeRoleFromUser
(
String
id
,
List
list
,
Map
<
String
,
Object
>
param
)
{
genericDaoService
.
deleteList
(
UserRole
.
class
,
param
);
}
```
####
1.3
.
3
扩展填充算法
**
@AutoRelativeComputed
**
注解主要填充中间关联数据,有部分数据和关联无关,但是又必须填充,这种时候就需要
**
exComputed
**
来扩展填充算法,可以通过算法来填充其它字段。例如,岗位和组织多对多关联自动填充,
exComputed
字段值为
**
orgPosition
**
:
```
java
@AutoRelativeComputed(mode = RelativeMode.MTM, source = LdpMcsOrganization.class, target = LdpMcsPositionOrganization.class,joinField = "postId", inverseField = "orgId", exComputed = "orgPosition")
```
编写扩展算法需要实现 **CustomComputer** 接口,并在computed方法中编写自动填充逻辑。computed方法有一个参数,这个参数是注解中target类的对象,可以在方法中拿到对象,并对对象中的其它字段进行填充。这里对manager字段进行填充:
```
java
public class ComputerOrgPosition implements CustomComputer {
@Override
public void computed(Object target) {
LdpMcsPositionOrganization positionOrganization = (LdpMcsPositionOrganization) target;
positionOrganization.setManager(false);
}
}
```
在有 **@Configuration** 注解类中完成Bean的装配:
```
java
@Configuration
public class ExtraComputer {
/
**
*
关联表其它业务数据填充
*
*
@return
*
/
@Bean(name = "orgPosition")
public CustomComputer getUserPositionComputer() {
return new ComputerOrgPosition();
}
}
```
## 二 、缓存注解
### 2.1. @ApplicationCacheable
依赖:common-cache
#### 2.1.1 注解介绍
**@ApplicationCacheable** 注解是方法注解,将注解添加到方法上,会自动将方法结果缓存下来,之后再次调用此接口,会直接从缓存中获取结果。缓存key是自动生成的,生成算法为application:+包名+类名+方法名+:参数长度。其它属性字段与Spring cache 注解 **@Cacheable** 属性字段一致。
#### 2.1.2 使用案例
一般此注解在REST层使用,需要注意的是Application缓存不会过期,会一直存在,如果需要刷新,需要另外写刷新方法,建议在数据变化较小,数据量大的接口使用。
```
java
/
**
*
rest获取用户分页数据
*
*
@return
*
/
@GetMapping("/rest/page")
@ApplicationCacheable
public RestResult getListByRest() {
return new RestResult(ResultMsg.SUCCESS, exampleService.getUserListByRest());
}
```
### 2.2. @SessionCacheable
依赖:common-cache
#### 2.2.1 注解介绍
**@SessionCacheable** 注解是方法注解,用法与 **@ApplicationCacheable** 注解基本一致,不一致的地方有两点:1、SessionCache生命周期是跟随登录的,也就是退出登录后失效; 2、缓存key生成规则不一致,生成算法:token:+包名+类名+方法名+:参数长度。
#### 2.2.2 使用案例
退出登录后,Session缓存失效
```
java
/
**
*
jdbc 获取用户list
*
*
@param paramMap
*
@return
*
@throws Exception
*
/
@GetMapping("/jdbc/list")
@SessionCacheable
public RestResult getListByJdbc(@RequestParamMap(typeCovertMapping = ExampleUserInfo.class) Map
<String
,
Object
>
paramMap) throws Exception {
List
<ExampleUserInfo>
userInfoList = exampleService.getUserListByJDBC(StringUtils.EMPTY, paramMap);
return new RestResult(ResultMsg.SUCCESS, userInfoList);
}
```
## 三、日志注解
### 3.1. @AvoidRepeatableSubmit
#### 3.1.1 注解介绍
此注解配合定时任务进行使用,在被需要定时任务调用的服务接口上,添加此注解防止接口由于网络波动或其他原因重复调用。
#### 3.2.2 使用案例
```
java
@PostMapping(value = "/testExampleJob")
@AvoidRepeatableSubmit
public RestResult testJob(@RequestParam String taskJobId, @RequestBody ExampleUserInfo userInfo){
exampleService.add(userInfo);
return new RestResult(ResultMsg.SUCCESS,"");
}
```
**使用时仅需要在被定时任务调用的接口上添加@AvoidRepeatableSubmit即可**
### 3.2. @SysAuditLog
#### 3.2.1 注解介绍
@SysAuditLog 是一个方法注解,需要放在controller方法上。 会拦截包裹的方法,会根据登陆信息自动获取当前用户。此注解进行被请求方法拦截,获取请求地址、请求参数、请求内容、请求方法(GET OR POST)、客户端浏览器信息。
根据请求状态,判断是异常请求还是正常请求。
#### 3.2.2 使用案例
```
java
/
**
*
用户列表(非分页)
*
*
@param paramMap 字段条件
*
@return
*
/
@GetMapping("/get/list")
@SysAuditLog(moduleKey = "example",subKey = "test")
public RestResult findList(@RequestParamMap(typeCovertMapping = ExampleUserInfo.class) Map
<String
,
Object
>
paramMap) throws Exception {
List
<ExampleUserInfo>
userInfoList = exampleService.findList(paramMap);
return new RestResult(ResultMsg.SUCCESS, userInfoList);
}
```
**使用时需传递 moduleKey(模块名称,如果是新模块需提前建立表,以ldp_audit_log_ 开头+ modulekey 录入的值结尾的表 如ldp_audit_log_example , 表结构可参考 ldp_audit_log_sys), subKey 子模块名称最终会保存在日志中作为二级子模块**;
### 3.3. @SysJobLog
#### 3.3.1 注解介绍
由于系统架构为微服务,服务与服务之间解耦合。因此定时任务设计之初,考虑为定时接口任务调用。
定时任务执行接口调用, 在被调用接口引用的Service具体业务方法添加此@SysJobLog 注解。
注解包含两大功能,1 异步执行,防止接口执行时间过长,否则定时任务调用机器一直连接被占用; 2 更新定时任务执行情况。
定时任务执行流程:
1 定时任务调度服务启动后,满足定时条件自动执行任务调度。 根据后台配置好的服务名称、接口信息调用其他服务接口。
2 被调用接口,必须添加@RequestParam String taskJobId 作为接收参数,此参数后续作为更新任务执行状态使用。由于在业务方法上添加@SysJobLog, 业务方法与Controller不在同一个线程中,无法
获取上一个线程中的信息。因此具体业务Service也必须添加名称为String taskJobId 的参数,后续会自动获取参数的值进行更新任务执行情况。
3 被调用接口也必须添加 @AvoidRepeatableSubmit 防止重复执行
#### 3.3.2 使用案例
Controller
```
java
@PostMapping(value = "/testExampleJob")
@AvoidRepeatableSubmit
public RestResult testJob(@RequestBody ExampleUserInfo userInfo, @RequestParam String taskJobId){
exampleService.doJob (userInfo, taskJobId);
return new RestResult(ResultMsg.SUCCESS,"");
}
```
具体Service
```
java
@Override
@AutoService
@SysJobLog
public void doJob(ExampleUserInfo exampleUserInfo, String taskJobId) {
genericDaoService.insert(exampleUserInfo);
}
```
**具体业务方法上添加@SysJobLog 进行异步任务及String taskJobId 参数,名称需要保持一致,系统会自动进行更新执行状态**``
## 四、数据库查询注解
### 4.1. @QueryBind
依赖:common-query
#### 4.1.1 注解介绍
@QueryBind是一个方法注解,将 **xxxxservice-query.xml** 中的参数SQL语句绑定到方法中的第一个参数中。需要先在 **xxxxservice-query.xml** 中将ref属性指向绑定的xxxServiceImpl类中。
#### 4.1.2 使用案例
**Service层代码:**
```
java
/
**
*
jdbc查询, QueryBind所对应的sql语句在resource/query/exampleservice中
*
调用时 getUserListByJDBC(StringUtils.EMPTY); 注解会将sql语句自动注入到参数中
*
*
@param sql
*
@return
*
/
@QueryBind("examplelist")
@Override
public List
<ExampleUserInfo>
getUserListByJDBC(String sql, Map
<String
,
Object
>
param) {
List
<ExampleUserInfo>
exampleUserInfos = jdbcDaoService.queryForList(sql, ExampleUserInfo.class, param);
return exampleUserInfos;
}
```
**REST层代码:**调用时 **getUserListByJDBC(StringUtils.EMPTY)**; 注解会将sql语句自动注入到参数中
```
java
Map
<String
,
Object
>
param = new HashMap
<>
(1);
param.put("userType", 0);
List
<ExampleUserInfo>
exampleUserInfos = exampleService.getUserListByJDBC(StringUtils.EMPTY, param);
```
### 4.2. @QueryContextComponent与 @QueryParams
依赖:common-query
#### 4.2.1 注解介绍
**@QueryContextComponent**是一个类注解, **@QueryParams** 是一个方法注解。除了使用 **@QueryBind** 注解注入sql到参数中,还可以使用 **@QueryContextComponent** 结合 **@QueryParams** 注解将xml中的sql全部注入到一个Map对象中。
#### 4.2.2 使用案例
首先在类名上添加 **@QueryContextComponent** 注解,定义一个sqlMap字段,加上 **@QueryParams** 注解,由于 **@QueryParams** 是一个方法注解,所以需要在字段上加上 **@Setter** ,这样会自动生成set方法,注解也会添加到自动生成的方法上
```
java
@QueryContextComponent
public class UserBizService {
// 由于@QueryParams是一个方法注解,所以此处需要加上@Setter注解
@Setter
@QueryParams
public Map<String,String> sqlMap;
public void getSqlKey() {
sqlMap.forEach((k,v)->{
log.info("id:{} {} {} ",k,String.format("%n"),v);
});
}
}
```
## 五、REST层参数解析注解
### 5.1. @RequestParamMap
依赖:mcs-common
#### 5.1.1 注解介绍
**@RequestParamMap**是一个参数注解,主要用于在REST层接收GET参数时保持参数类型与实体类一致,可以直接将GET参数接收到的map作为查询条件,另外也是为了将分页参数从查询参数中区分开来。
#### 5.1.2 使用案例
直接在Map参数前使用**@RequestParamMap(typeCovertMapping = XXXX.class)**,这里的XXX指实体类类型。
```
java
/
**
*
用户列表(非分页)
*
*
@param paramMap 字段条件
*
@return
*
/
@GetMapping("/get/list")
public List
<LdpMcsUserInfo> findList(@RequestParamMap(typeCovertMapping = LdpMcsUserInfo.class) Map<String, Object>
paramMap) throws Exception {
return userService.findList(paramMap);
}
```
### 5.2 @RequestParamPage
依赖:mcs-common
#### 5.2.1 注解介绍
**@RequestParamPage**是一个参数注解,主要用于GET请求时接收分页参数。
#### 5.2.2 使用案例
使用封装好的分页类 **Pagination** 来接收分页参数,在分页参数前添加 **@RequestParamPage** 即可。这里是将分页参数和查询参数进行拆分的案例:
```
java
/
**
*
用户列表(分页)
*
*
@param paramPage 分页参数为pageIndex,pageSize
*
@param paramMap 字段条件
*
@return
*
/
@GetMapping("/get/page")
public Pagination findPage(@RequestParamPage Pagination paramPage,
@RequestParamMap(typeCovertMapping = LdpMcsUserInfo.class) Map
<String
,
Object
>
paramMap)
throws Exception {
return userService.findPage(paramPage, paramMap);
}
```
## 六、Excel导入导出注解
### 6.1. @ExcelImport
依赖:common-biz-annotation
#### 6.1.1 注解介绍
**@ExcelImport** 是一个方法注解,主要用于实现Excel导入逻辑。
#### 6.1.2 使用案例
将注解直接加到导入方法上,会自动构建ExcelOptions参数。
```
java
/
**
*
通过注解导入Excel,注解完成三件事情:
*
1、上传文件
*
2、读取Excel数据
*
3、根据实体类导入到指定的表中
*
*
@param file
*
@param excelOptions
*
/
@ExcelImport(targetClass = ExampleUserInfo.class)
public void importExcelByAnnotation(MultipartFile file, ExcelOptions excelOptions) {
excelService.importExcel(excelOptions);
}
```
### 6.2. @ExcelExport
依赖:common-biz-annotation
#### 6.2.1 注解介绍
**@ExcelExport** 是一个方法注解,主要用于实现Excel导入逻辑。
#### 6.2.2 使用案例
将注解直接加到导出方法上,会自动构建ExcelOptions参数。
```
java
/
**
*
通过注解导出Excel,注解完成两件事情:
*
1、读取数据库数据
*
2、写入到Excel文件中
*
*
@param outputStream
*
@param excelOptions
*
/
@Override
@ExcelExport(sourceClass = ExampleUserInfo.class)
public void exportExcelByAnnotation(OutputStream outputStream, ExcelOptions excelOptions) {
excelService.exportExcel(excelOptions);
}
```
## 七、模糊查询注解
### 7.1. @HqlQueryFilter
依赖:common-biz-annotation
#### 7.1.1 注解介绍
**@HqlQueryFilter** 是一个字段注解,主要用于标识实体类字段作为列表过滤字段时,数据库查询的匹配方式。目前仅包含精确匹配(QueryFilterType.EQUAL)、模糊匹配(QueryFilterType.ELIKE)
#### 7.1.2 使用案例
在过滤字段上加上注解,以及匹配方式
```
java
/
**
*
名称
*
/
@HqlQueryFilter(type = QueryFilterType.LIKE)
@Column(name = "name")
private String name;
```
### 7.1. @HqlQueryFilterService
依赖:common-biz-annotation
#### 7.1.1 注解介绍
**@HqlQueryFilterService** 是一个方法注解,根据实体类字段中的 **@HqlQueryFilter** 规则自动构建查询条件数组LinkedList<Condition>。
#### 7.1.2 使用案例
当Rest层调用此方法时,Aop拦截会通过遍历参数Map,并从实体类中获取相应字段及注解,来构建Condition数组。
```
java
@Override
@HqlQueryFilterService(target = ExampleUserInfo.class)
public List
<ExampleUserInfo>
findListByLikeCondition(Map
<String
,
Object
>
param, LinkedList
<Condition>
conditionList) {
return genericDaoService.findByConditions(ExampleUserInfo.class, conditionList);
}
```
## 八、字典对象属性填充注解
### 8.1. @DictProperties
依赖:common-biz-annotation
#### 8.1.1 注解介绍
**@DictProperties** 是一个类注解,通过属性`propertyPref`标识字典项key的前缀,配合工具类DictCommonDto使用,通过构建一个DTO获取相同字典类型下所有的字典value。
#### 8.1.2 使用案例
这里使用读取邮箱配置相关字典值来举例,邮箱服务器相关字典类型编码为**sys.email.code**,其余属性分别为
| 字典项编码 | 备注 |
| -------------- | -------------- |
| email.host | 邮件服务器地址 |
| email.port | 邮件服务器端口 |
| email.account | 发件方账号 |
| email.password | 发件方密码 |
| email.ssl | 是否使用ssl |
第一步,对应字典项编写一个DTO,加上注解 **@DictProperties** ,`propertyPref`指定字典项的前缀,属性名称为除开前缀后的部分,如果有多段名称,需要使用驼峰命名,例:字典项为email.prof.demo时,属性名为profDemo。
```
java
@Getter
@Setter
@DictProperties(propertyPref = "email")
public class EmailServerDTO {
private String host;
private String port;
private String account;
private String password;
private String ssl;
private String testEmail;
}
```
第二步,通过字典接口,使用字典类型编码获取字典项列表,并使用工具类对DTO对象进行赋值
```
java
//getEmailDictList方法通过sys.email.code获取所有字典项列表
List
<DictInfo2>
emailDictList = getEmailDictList();
EmailServerDTO serverDTO = new EmailServerDTO();
try {
//通过工具类将值赋值到Dto对象中
serverDTO = DictCommonDto.toDictDto(emailDictList, serverDTO);
} catch (Exception e) {
e.printStackTrace();
}
```
### 8.2. @DictAlias
依赖:common-biz-annotation
#### 8.2.1 注解介绍
**@DictAlias** 是一个字段注解,需要配合**@DictProperties** 使用,由于使用统一的前缀要求属性名称与字典项编码一一对应,使用@DictAlias注解的字段可以不与字典项编码保持一致。
#### 8.2.2 使用案例
第一步仍然是编写DTO类,类似下方案例,没有通用的前缀,所以通过@DictAlias注解指定对应的字典项。
```
java
@Setter
@Getter
@NoArgsConstructor
@DictProperties(propertyPref = "")
public class RootCodeDTO {
@DictAlias(name = "org.root.code")
private String orgRoot;
@DictAlias(name = "func.app.root.code")
private String funcRoot;
@DictAlias(name = "func.manage.root.code")
private String manageRoot;
}
```
第二步与8.1.2中的填充方式一致。
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