diff --git a/README.md b/README.md
index 149c9aa5..74f5fe9a 100644
--- a/README.md
+++ b/README.md
@@ -9,12 +9,18 @@
本框架基于springboot为提供领域驱动设计与事件风暴开发落地,提供的范式开源框架。
+## Project Version | 项目版本说明
+
+v.2.x 为springboot 2.x版本,使用jdk8版本
+v.3.x 为springboot 3.x版本,使用jdk17版本
+
## Project Modules Description | 项目模块介绍
* springboot-starter | Springboot领域驱动框架
* springboot-starter-data-fast | 快速数据呈现框架
-* springboot-starter-id-generator | Id自增策略框架
-* springboot-starter-security-jwt | security&jwt权限框架
+* springboot-starter-data-authorization | 数据权限框架
+* springboot-starter-flow | 流程引擎框架
+* springboot-starter-security | security权限框架支持基于JWT的无状态权限认证与Redis的有状态权限认证
## SpringBoot DDD Architecture | SpringBoot DDD 框架图
@@ -37,17 +43,24 @@
${last.version}
-
-
+
+
+ com.codingapi.springboot
+ springboot-starter-data-authorization
+ ${last.version}
+
+
+
+
com.codingapi.springboot
- springboot-starter-id-generator
+ springboot-starter-flow
${last.version}
com.codingapi.springboot
- springboot-starter-security-jwt
+ springboot-starter-security
${last.version}
@@ -66,7 +79,7 @@ https://github.com/codingapi/springboot-framework/wiki
## Example
-见 [springboot-example](https://github.com/codingapi/springboot-example)
+见 [springboot-example](https://github.com/codingapi/springboot-example)
## Reference Documentation
diff --git a/docs/wiki/home.md b/docs/wiki/home.md
index df4ad067..4387f03d 100644
--- a/docs/wiki/home.md
+++ b/docs/wiki/home.md
@@ -16,14 +16,7 @@ maven install
com.codingapi.springboot
springboot-starter-data-fast
${last.version}
-
-
-
-
- com.codingapi.springboot
- springboot-starter-id-generator
- ${last.version}
-
+
@@ -36,6 +29,5 @@ maven install
[springboot-starter](./springboot-starter)
[springboot-starter-security-jwt](./springboot-starter-security-jwt)
-[springboot-starter-id-generator](./springboot-starter-id-generator)
[springboot-starter-data-fast](./springboot-starter-data-fast.md)
\ No newline at end of file
diff --git a/docs/wiki/springboot-starter-data-fast.md b/docs/wiki/springboot-starter-data-fast.md
index 0466431d..aa35baca 100644
--- a/docs/wiki/springboot-starter-data-fast.md
+++ b/docs/wiki/springboot-starter-data-fast.md
@@ -2,46 +2,240 @@ springboot-starter-data-fast
基于JPA的快速API能力服务
+## FastRepository 的使用教程
+
+继承FastRepository接口,实现自定义的接口,即可使用FastRepository的能力
```java
-package com.codingapi.springboot.example.query;
-import com.codingapi.springboot.example.infrastructure.jpa.entity.DemoEntity;
-import com.codingapi.springboot.example.infrastructure.jpa.pojo.PageSearch;
-import com.codingapi.springboot.fast.annotation.FastController;
-import com.codingapi.springboot.fast.annotation.FastMapping;
-import com.codingapi.springboot.framework.dto.response.MultiResponse;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.RequestMethod;
-@FastController
-public interface FastDemoApi {
+import com.codingapi.springboot.fast.entity.Demo;
+import com.codingapi.springboot.fast.query.FastRepository;
+
+public interface DemoRepository extends FastRepository {
+
+}
+
+
+```
+动态FastRepository的能力展示
+
+```
+
+ // 重写findAll,通过Example查询
+ @Test
+ void findAll() {
+ demoRepository.deleteAll();
+ Demo demo1 = new Demo();
+ demo1.setName("123");
+ demoRepository.save(demo1);
+
+ Demo demo2 = new Demo();
+ demo2.setName("456");
+ demoRepository.save(demo2);
+
+ PageRequest request = new PageRequest();
+ request.setCurrent(1);
+ request.setPageSize(10);
+ request.addFilter("name", "123");
+
+ Page page = demoRepository.findAll(request);
+ assertEquals(1, page.getTotalElements());
+ }
+
+
+ // pageRequest 自定义条件查询
+ @Test
+ void pageRequest1() {
+ demoRepository.deleteAll();
+ Demo demo1 = new Demo();
+ demo1.setName("123");
+ demoRepository.save(demo1);
+
+ Demo demo2 = new Demo();
+ demo2.setName("456");
+ demoRepository.save(demo2);
+
+ PageRequest request = new PageRequest();
+ request.setCurrent(1);
+ request.setPageSize(10);
+ request.addFilter("name", PageRequest.FilterRelation.LIKE, "%2%");
+ //sql: select demo0_.id as id1_0_, demo0_.name as name2_0_, demo0_.sort as sort3_0_ from t_demo demo0_ where demo0_.name like ? limit ?
+
+ Page page = demoRepository.pageRequest(request);
+ assertEquals(1, page.getTotalElements());
+ }
+
+ // pageRequest 自定义条件查询
+ @Test
+ void pageRequest2() {
+ demoRepository.deleteAll();
+ Demo demo1 = new Demo();
+ demo1.setName("123");
+ demoRepository.save(demo1);
+
+ Demo demo2 = new Demo();
+ demo2.setName("456");
+ demoRepository.save(demo2);
+
+ PageRequest request = new PageRequest();
+ request.setCurrent(1);
+ request.setPageSize(10);
+ request.orFilters(Filter.as("name","123"),Filter.as("name","456"));
+ //sql: select demo0_.id as id1_0_, demo0_.name as name2_0_, demo0_.sort as sort3_0_ from t_demo demo0_ where demo0_.name=? or demo0_.name=? limit ?
+
+ Page page = demoRepository.pageRequest(request);
+ assertEquals(1, page.getTotalElements());
+ }
+
+
+ // 动态sql的List查询
+ @Test
+ void dynamicListQuery() {
+ demoRepository.deleteAll();
+ Demo demo1 = new Demo();
+ demo1.setName("123");
+ demoRepository.save(demo1);
+
+ Demo demo2 = new Demo();
+ demo2.setName("456");
+ demoRepository.save(demo2);
+ List list = demoRepository.dynamicListQuery("from Demo where name = ?1", "123");
+ assertEquals(1, list.size());
+ }
- @PreAuthorize(value = "hasRole('ROLE_ADMIN')")
- @FastMapping(
- method = RequestMethod.GET,
- mapping = "/api/demo/findByName1",
- value = "select d from DemoEntity d where name = :name",
- countQuery = "select count(d) from DemoEntity d where name = :name")
- MultiResponse findByName1(PageSearch query);
+ // 动态sql的分页查询
+ @Test
+ void dynamicPageQuery() {
+ demoRepository.deleteAll();
+ Demo demo1 = new Demo();
+ demo1.setName("123");
+ demoRepository.save(demo1);
+ Demo demo2 = new Demo();
+ demo2.setName("456");
+ demoRepository.save(demo2);
- @PreAuthorize(value = "hasRole('ROLE_USER')")
- @FastMapping(
- method = RequestMethod.GET,
- mapping = "/api/demo/findByName2",
- value = "select d from DemoEntity d where name = :name",
- countQuery = "select count(d) from DemoEntity d where name = :name")
- MultiResponse findByName2(PageSearch query);
+ Page page = demoRepository.dynamicPageQuery("from Demo where name = ?1", PageRequest.of(1, 2), "123");
+ assertEquals(1, page.getTotalElements());
+ }
+ // 增加排序查询
+ @Test
+ void sortQuery() {
+ demoRepository.deleteAll();
+ Demo demo1 = new Demo();
+ demo1.setName("123");
+ demoRepository.save(demo1);
+
+ Demo demo2 = new Demo();
+ demo2.setName("456");
+ demoRepository.save(demo2);
+
+ PageRequest request = new PageRequest();
+ request.setCurrent(1);
+ request.setPageSize(10);
+
+ request.addSort(Sort.by("id").descending());
+ Page page = demoRepository.findAll(request);
+ assertEquals(page.getContent().get(0).getName(), "456");
+ assertEquals(2, page.getTotalElements());
+ }
+
+```
+
+## ScriptMapping 教程
+
+通过动态添加mvc mapping实现查询功能.
+
+
+```
+ScriptMapping scriptMapping = new ScriptMapping({mapinggUrl}, {mapinggMethod}, {mappingGrovvry});
+scriptMappingRegister.addMapping(scriptMapping);
+
+```
+mapinggUrl 是mvc接口的地址
+mapinggMethod 是mvc接口的请求方式
+mappingGrovvry 是执行的查询脚本
+
+脚本实例代码:
+* 动态分页查询
+```
+// 获取name的请求参数
+var name = $request.getParameter("name","");
+var pageNumber = $request.getParameter("pageNumber",0);
+var pageSize = $request.getParameter("pageSize",10);
+// 创建分页对象
+var pageRequest = $request.pageRequest(pageNumber,pageSize);
+// 动态组织sql
+var sql = "select * from api_mapping where 1 =1 ";
+var countSql = "select count(1) from api_mapping where 1 =1 ";
+// 动态组织参数
+var params = [];
+if(!"".equals(name)){
+ sql += " and name = ? ";
+ countSql += " and name = ? ";
+ params.push(name);
+}
+sql += " limit ?,?";
+// 添加分页参数
+params.add(pageRequest.getOffset());
+params.add(pageRequest.getPageSize());
+// 执行分页查询
+return $jdbc.queryForPage(sql,countSql,pageRequest,params.toArray());
+```
+* 动态条件查询
+```
+// 获取name的请求参数
+var name = $request.getParameter("name","");
+// 动态组织sql
+String sql = "select * from api_mapping where 1=1 ";
+// 动态组织参数
+var params = [];
+if(!"".equals(name)){
+ sql += " and name = ? ";
+ params.add(name);
}
+// 执行查询
+return $jdbc.queryForList(sql,params.toArray());
+```
+脚本语法介绍:
+* $request
+```
+// 获取参数name的值,如果参数不存在,则返回默认值
+var name = $request.getParameter("name","");
+// 获取分页对象
+var pageRequest = $request.pageRequest(0,10);
+// 获取分页对象的页码
+var pageNumber = pageRequest.getPageNumber();
+// 获取分页对象的每页记录数
+var pageSize = pageRequest.getPageSize();
+// 获取分页对象的偏移量
+var offset = pageRequest.getOffset();
+```
+* $jdbc
+```
+// 查询jdbcSQL $jdbc.queryForList({sql},{params})
+
+// 查询无条件的数据
+var res = $jdbc.queryForList("select * from api_mapping");
+// 查询有条件的数据
+var res = $jdbc.queryForList("select * from api_mapping where name = ?",name);
+// 查询多条件的数据
+var res = $jdbc.queryForList("select * from api_mapping where name = ? and url = ?",name,url);
+
+// 分页查询 $jdbc.queryForPage({sql},{countSql},{pageRequest},{params})
+var res = $jdbc.queryForPage("select * from api_mapping where name = ? and url = ?",
+"select count(1) from api_mapping where name = ? and url = ?",pageRequest,params.toArray());
+```
+* $jpa
```
-@FastController 用于标记当前接口为Fast接口
-@FastMapping 用于标记当前接口的映射关系
-mapping为接口映射路径,method为接口请求方法
-value为查询语句,countQuery为查询总数语句,query为查询参数,支持分页查询,排序查询,查询参数等等
-MultiResponse为返回结果
-@PreAuthorize(value = "hasRole('ROLE_USER')") 用于标记当前接口的权限,如果不需要权限可以不用添加
+// 查询jpa $jpa.listQuery({clazz},{sql},{params})
+// 查询无条件的数据
+var res = $jpa.listQuery(com.example.entity.NodeEntity.class,"from NodeEntity");
+// 查询有条件的数据
+var res = $jpa.listQuery(com.example.entity.NodeEntity.class,"from NodeEntity where name = ?",name);
+```
\ No newline at end of file
diff --git a/docs/wiki/springboot-starter-id-generator.md b/docs/wiki/springboot-starter-id-generator.md
deleted file mode 100644
index 27bb96a9..00000000
--- a/docs/wiki/springboot-starter-id-generator.md
+++ /dev/null
@@ -1,34 +0,0 @@
-springboot-starter-id-generator
-
-一个单服务下的id自增构造器,为了解决id由数据库生成的问题,如果是分布式服务,可以使用snowflake算法生成id,如果是单服务,可以使用这个构造器生成id
-
-```java
-
-import com.codingapi.springboot.generator.IdGenerate;
-import lombok.Getter;
-
-/**
- * @author lorne
- * @since 1.0.0
- */
-public class Demo implements IdGenerate {
-
- @Getter
- private Integer id;
-
- @Getter
- private String name;
-
- public Demo(String name) {
- this.id = generateIntId();
- this.name = name;
- }
-
-}
-
-```
-
-只需要实现IdGenerate接口即可,然后调用generateIntId()方法即可生成id。
-
-IdGenerate接口提供了两个方法,generateIntId()和generateLongId(),分别用于生成int类型和long类型的id。
-也可以使用generateStringId()方法生成String类型的id。
\ No newline at end of file
diff --git a/docs/wiki/springboot-starter-security-jwt.md b/docs/wiki/springboot-starter-security.md
similarity index 61%
rename from docs/wiki/springboot-starter-security-jwt.md
rename to docs/wiki/springboot-starter-security.md
index dd984683..d33c5c4a 100644
--- a/docs/wiki/springboot-starter-security-jwt.md
+++ b/docs/wiki/springboot-starter-security.md
@@ -1,18 +1,28 @@
-springboot-starter-security-jwt 功能介绍
+springboot-starter-security 功能介绍
+
+支持无状态的JWT和有状态的redis两种不同的token机制
配置文件,默认参数即说明
```properties
+# JWT开关
+codingapi.security.jwt.enable=true
# JWT密钥 需大于32位的字符串
-codingapi.security.jwt-secret=codingapi.security.jwt.secretkey
+codingapi.security.jwt.secret-key=codingapi.security.jwt.secretkey
+
+# JWT 有效时间(毫秒) 15分钟有效期 1000*60*15=900000
+codingapi.security.jwt.valid-time=900000
+# JWT 更换令牌时间(毫秒) 10分钟后更换令牌 1000*60*10=600000
+codingapi.security.jwt.rest-time=600000
+
# JWT AES密钥
codingapi.security.ase-key=QUNEWCQlXiYqJCNYQ1phc0FDRFgkJV4mKiQjWENaYXM=
# JWT AES IV
-codingapi.security.aes-iv=QUNYRkdIQEVEUyNYQ1phcw==
+codingapi.security.ase-iv=QUNYRkdIQEVEUyNYQ1phcw==
-# JWT 有效时间(毫秒) 15分钟有效期 1000*60*15=900000
-codingapi.security.jwt-time=900000
-# JWT 更换令牌时间(毫秒) 10分钟后更换令牌 1000*60*10=600000
-codingapi.security.jwt-rest-time=600000
+# Redis开关
+#codingapi.security.redis.enable=true
+#spring.data.redis.host=localhost
+#spring.data.redis.port=6379
# Security 配置 请求权限拦截地址
codingapi.security.authenticated-urls=/api/**
@@ -51,14 +61,22 @@ security默认的账户密码为admin/admin,可以通过重写UserDetailsServi
也可以通过数据库账户获取账户数据,请自己实现UserDetailsService接口
## 登录拦截
-可以通过重写SecurityLoginHandler来实现自定义登录拦截
-```java
+可以通过重写SecurityLoginHandler来实现自定义登录拦截,preHandle登录前的拦截处理,postHandle登录后的拦截处理
+```
@Bean
- public SecurityLoginHandler securityLoginHandler(){
- return (request, response, handler) -> {
- //TODO 自定义登录拦截
- };
- }
+ public SecurityLoginHandler securityLoginHandler() {
+ return new SecurityLoginHandler() {
+ @Override
+ public void preHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest handler) throws Exception {
+
+ }
+
+ @Override
+ public void postHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest handler, Token token) {
+
+ }
+ };
+}
```
## 获取当前用户
@@ -66,15 +84,15 @@ security默认的账户密码为admin/admin,可以通过重写UserDetailsServi
通过TokenContext获取当前用户信息
```java
@GetMapping("/user")
- public String user(){
- return TokenContext.current().getUsername();
- }
+public String user(){
+ return TokenContext.current().getUsername();
+}
```
可以通过Token的extra字段来存储用户的更多信息,然后通过TokenContext获取
```java
@GetMapping("/user")
- public String user(){
- return TokenContext.current().getExtra("user");
- }
+public String user(){
+ return TokenContext.current().getExtra("user");
+}
```
diff --git a/event.md b/event.md
new file mode 100644
index 00000000..d632f4a7
--- /dev/null
+++ b/event.md
@@ -0,0 +1,38 @@
+# 流程事件触发机制
+
+* 发起流程
+事件: CREATE TODO SAVE
+* 保存流程
+事件: SAVE
+* 提交流程
+事件: PASS TODO(下一个节点记录数据)
+* 驳回流程
+事件: REJECT TODO(下一个节点记录数据)
+* 撤回流程
+事件: RECALL
+* 删除流程
+事件: DELETE
+* 作废流程
+事件: VOIDED
+* 退回流程
+事件:BACK
+* 流程结束
+事件: FINISH
+* 转办流程
+事件:TRANSFER TODO(下一个节点记录数据)
+* 唤醒流程
+事件: TODO
+* 催办流程
+事件: URGE 当前审批人
+* 延期流程
+事件: 未发送事件
+* 停止流程
+事件: STOP 当前审批人
+
+---------------------
+自定义事件:是前端自己触法的逻辑
+自定义接口:是执行后端按钮配置的脚本
+
+在开始节点点击任何按钮的时候,若流程不存在则会先执行流程的创建,然后再执行对应的按钮操作。
+
+
diff --git a/pom.xml b/pom.xml
index 3ba9ed9b..4938e446 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,43 +3,52 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
pom
+
+ springboot-starter-data-authorization
+
org.springframework.boot
spring-boot-starter-parent
- 3.1.2
+ 2.7.18
com.codingapi.springboot
springboot-parent
- 2.1.11
+ 2.10.26
https://github.com/codingapi/springboot-framewrok
springboot-parent
springboot-parent project for Spring Boot
- 17
+ 8
yyyy-MM-dd HH:mm:ss
- 17
- 17
+ 8
+ 8
3.0.1
3.11.0
- 2.10.3
- 1.6.3
- 1.6
+ 3.6.1
+ 1.6.13
+ 3.1.0
${project.version}
- 2.0.28
- 0.11.5
- 2.11.0
- 1.7
+ 2.0.53
+ 0.12.6
+ 2.17.0
+ 3.17.0
+ 1.8.1
+ 1.12.0
0.10.2
0.9.16
- 1.70
+ 1.79
1.2.0
- 2.0
+ 2.2
+ 4.0.24
+ 2.3.232
+ 5.6.2
+ 5.0
@@ -72,10 +81,22 @@
+
+ com.esotericsoftware
+ kryo
+ ${esotericsoftware.kryo.version}
+
+
+
+ com.h2database
+ h2
+ ${h2.version}
+
+
org.bouncycastle
- bcprov-jdk15on
- ${bcprov-jdk15on.version}
+ bcprov-jdk18on
+ ${bcprov-jdk18on.version}
@@ -90,6 +111,18 @@
${commons-crypto.version}
+
+ commons-io
+ commons-io
+ ${commons-io.version}
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
org.perf4j
perf4j
@@ -134,7 +167,7 @@
com.codingapi.springboot
- springboot-starter-security-jwt
+ springboot-starter-security
${codingapi.framework.version}
@@ -156,6 +189,36 @@
${commons-dbutils.version}
+
+ org.apache.commons
+ commons-text
+ ${commons-text.version}
+
+
+
+ org.apache.groovy
+ groovy
+ ${apache-groovy.version}
+
+
+
+ org.apache.groovy
+ groovy-json
+ ${apache-groovy.version}
+
+
+
+ org.apache.groovy
+ groovy-xml
+ ${apache-groovy.version}
+
+
+
+ com.github.jsqlparser
+ jsqlparser
+ ${jsqlparser.version}
+
+
@@ -172,6 +235,20 @@
-Xlint:deprecation
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ ${maven-jar-plugin.version}
+
+
+
+ ${project.version}
+ ${project.name}
+
+
+
+
@@ -216,9 +293,10 @@
springboot-starter
- springboot-starter-security-jwt
+ springboot-starter-security
+ springboot-starter-data-authorization
springboot-starter-data-fast
- springboot-starter-id-generator
+ springboot-starter-flow
@@ -228,9 +306,10 @@
springboot-starter
- springboot-starter-security-jwt
+ springboot-starter-security
+ springboot-starter-data-authorization
springboot-starter-data-fast
- springboot-starter-id-generator
+ springboot-starter-flow
@@ -238,7 +317,7 @@
org.jacoco
jacoco-maven-plugin
- 0.8.9
+ 0.8.12
@@ -258,7 +337,7 @@
org.openclover
clover-maven-plugin
- 4.4.1
+ 4.5.2
true
true
@@ -271,6 +350,7 @@
+
@@ -278,27 +358,15 @@
springboot-starter
- springboot-starter-security-jwt
+ springboot-starter-security
+ springboot-starter-data-authorization
springboot-starter-data-fast
- springboot-starter-id-generator
+ springboot-starter-flow
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- ${maven-compiler-plugin.version}
-
- ${maven.compile.source}
- ${maven.compile.target}
- ${project.build.sourceEncoding}
- -Xlint:deprecation
-
-
org.apache.maven.plugins
maven-source-plugin
@@ -312,20 +380,18 @@
-
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.6.13
+ org.sonatype.central
+ central-publishing-maven-plugin
+ 0.8.0
true
- ossrh
- https://oss.sonatype.org/
- true
+ central
+ true
+ published
-
org.apache.maven.plugins
maven-javadoc-plugin
@@ -344,7 +410,6 @@
-
org.apache.maven.plugins
maven-gpg-plugin
@@ -363,8 +428,6 @@
-
-
diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml
new file mode 100644
index 00000000..0a2a24a8
--- /dev/null
+++ b/springboot-starter-data-authorization/pom.xml
@@ -0,0 +1,78 @@
+
+
+ 4.0.0
+
+ springboot-parent
+ com.codingapi.springboot
+ 2.10.26
+
+
+ springboot-starter-data-authorization
+ springboot-starter-data-authorization
+ springboot-starter-data-authorization project for Spring Boot
+
+
+ 8
+
+
+
+
+
+ com.github.jsqlparser
+ jsqlparser
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+ test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jdbc
+ test
+
+
+
+ com.h2database
+ h2
+ test
+
+
+
+ com.mysql
+ mysql-connector-j
+ test
+
+
+
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.12
+
+
+
+ prepare-agent
+
+
+
+ report
+ test
+
+ report
+
+
+
+
+
+
+
+
diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/DataAuthorizationConfiguration.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/DataAuthorizationConfiguration.java
new file mode 100644
index 00000000..e36e604a
--- /dev/null
+++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/DataAuthorizationConfiguration.java
@@ -0,0 +1,48 @@
+package com.codingapi.springboot.authorization;
+
+
+import com.codingapi.springboot.authorization.filter.DataAuthorizationFilter;
+import com.codingapi.springboot.authorization.handler.ColumnHandler;
+import com.codingapi.springboot.authorization.handler.RowHandler;
+import com.codingapi.springboot.authorization.interceptor.SQLInterceptor;
+import com.codingapi.springboot.authorization.properties.DataAuthorizationProperties;
+import com.codingapi.springboot.authorization.register.ConditionHandlerRegister;
+import com.codingapi.springboot.authorization.register.DataAuthorizationContextRegister;
+import com.codingapi.springboot.authorization.register.ResultSetHandlerRegister;
+import com.codingapi.springboot.authorization.register.SQLInterceptorRegister;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.List;
+
+@Configuration
+public class DataAuthorizationConfiguration {
+
+ @Bean
+ @ConfigurationProperties(prefix = "codingapi.data-authorization")
+ public DataAuthorizationProperties dataAuthorizationProperties(){
+ return new DataAuthorizationProperties();
+ }
+
+ @Bean
+ public ConditionHandlerRegister conditionHandlerRegister(@Autowired(required = false) RowHandler rowHandler) {
+ return new ConditionHandlerRegister(rowHandler);
+ }
+
+ @Bean
+ public ResultSetHandlerRegister resultSetHandlerRegister(@Autowired(required = false) ColumnHandler columnHandler) {
+ return new ResultSetHandlerRegister(columnHandler);
+ }
+
+ @Bean
+ public SQLInterceptorRegister sqlInterceptorRegister(@Autowired(required = false) SQLInterceptor sqlInterceptor) {
+ return new SQLInterceptorRegister(sqlInterceptor);
+ }
+
+ @Bean
+ public DataAuthorizationContextRegister dataAuthorizationContextRegister(@Autowired(required = false) List dataAuthorizationFilters) {
+ return new DataAuthorizationContextRegister(dataAuthorizationFilters);
+ }
+}
diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/DataAuthorizationContext.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/DataAuthorizationContext.java
new file mode 100644
index 00000000..9af58d8a
--- /dev/null
+++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/DataAuthorizationContext.java
@@ -0,0 +1,81 @@
+package com.codingapi.springboot.authorization;
+
+import com.codingapi.springboot.authorization.filter.DataAuthorizationFilter;
+import com.codingapi.springboot.authorization.handler.Condition;
+import com.codingapi.springboot.authorization.interceptor.SQLInterceptState;
+import lombok.Getter;
+import org.springframework.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 数据权限上下文
+ */
+public class DataAuthorizationContext {
+
+ @Getter
+ private final static DataAuthorizationContext instance = new DataAuthorizationContext();
+
+ private final List filters;
+
+ private DataAuthorizationContext() {
+ this.filters = new ArrayList<>();
+ }
+
+ /**
+ * 添加数据权限过滤器
+ * @param filter 数据权限过滤器
+ */
+ public void addDataAuthorizationFilter(DataAuthorizationFilter filter) {
+ this.filters.add(filter);
+ }
+
+ /**
+ * 清空数据权限过滤器
+ */
+ public void clearDataAuthorizationFilters() {
+ this.filters.clear();
+ }
+
+ /**
+ * 列权限
+ * @param interceptState 拦截状态
+ * @param tableName 表名(或别名)
+ * @param columnName 列名 (或别名)
+ * @param value 值
+ * @return T
+ * @param 泛型
+ */
+ public T columnAuthorization(SQLInterceptState interceptState, String tableName, String columnName, T value) {
+ if (interceptState != null && interceptState.hasIntercept()) {
+ String realTableName = interceptState.getTableName(tableName);
+ String realColumnName = interceptState.getColumnName(tableName,columnName);
+
+ for (DataAuthorizationFilter filter : filters) {
+ if (filter.supportColumnAuthorization(realTableName, realColumnName, value)) {
+ return filter.columnAuthorization(realTableName, realColumnName, value);
+ }
+ }
+ }
+ return value;
+ }
+
+ /**
+ * 行权限
+ * @param tableName 表名
+ * @param tableAlias 别名
+ * @return Condition 增加的过滤条件
+ */
+ public Condition rowAuthorization(String tableName, String tableAlias) {
+ if (StringUtils.hasText(tableName) && StringUtils.hasText(tableAlias)) {
+ for (DataAuthorizationFilter filter : filters) {
+ if (filter.supportRowAuthorization(tableName, tableAlias)) {
+ return filter.rowAuthorization(tableName, tableAlias);
+ }
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java
new file mode 100644
index 00000000..3915d39b
--- /dev/null
+++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java
@@ -0,0 +1,167 @@
+package com.codingapi.springboot.authorization.enhancer;
+
+
+import com.codingapi.springboot.authorization.handler.Condition;
+import com.codingapi.springboot.authorization.handler.RowHandler;
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
+import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
+import net.sf.jsqlparser.expression.operators.relational.InExpression;
+import net.sf.jsqlparser.parser.CCJSqlParserUtil;
+import net.sf.jsqlparser.schema.Table;
+import net.sf.jsqlparser.statement.Statement;
+import net.sf.jsqlparser.statement.select.*;
+
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * 数据权限 SQL 增强器
+ */
+public class DataPermissionSQLEnhancer {
+
+ private final String sql;
+ private final RowHandler rowHandler;
+ private final TableColumnAliasHolder tableColumnAliasHolder;
+ private final Statement statement;
+
+
+ // 构造函数
+ public DataPermissionSQLEnhancer(String sql, RowHandler rowHandler) throws SQLException {
+ try {
+ // 如何sql中存在? 则在?后面添加空格
+ this.sql = sql.replaceAll("\\?", " ? ");
+ this.rowHandler = rowHandler;
+ this.statement = CCJSqlParserUtil.parse(this.sql);
+ this.tableColumnAliasHolder = new TableColumnAliasHolder(statement);
+ } catch (Exception e) {
+ throw new SQLException(e);
+ }
+ }
+
+ // 获取增强后的SQL
+ public String getNewSQL() throws SQLException {
+ try {
+ if (statement instanceof Select) {
+ tableColumnAliasHolder.holderAlias();
+ Select select = (Select) statement;
+ this.deepMatch(select);
+ return statement.toString();
+ }
+ } catch (Exception e) {
+ throw new SQLException(e);
+ }
+ return sql;
+ }
+
+
+ private void deepMatch(Select select) throws Exception {
+ if (select instanceof PlainSelect) {
+ PlainSelect plainSelect = select.getPlainSelect();
+ this.enhanceDataPermissionInSelect(plainSelect);
+ }
+ if (select instanceof SetOperationList) {
+ SetOperationList setOperationList = select.getSetOperationList();
+ List