随着公司业务的增加,公司需要一个java+python人工智能相互配合架构,正常网站业务用java来做,而ai,例如电价预测等回归任务,以及大模型预测全网负荷,新能源出力等任务,使用python通过fastapi暴露接口来做,那么就需要springcloud架构注册发现。前端统一使用Vue进行效果的展示
因此本文会将我的解决思路中,关于架构(不涉及核心业务代码)的通用逻辑分享给大家
在此,感谢各位领导满足我对知识开源分享的执拗,同意我将部分通用代码进行开源分享
文章目录
一、java后端SpringCloud架构
1. 必要的需要单独下载的第三方包
1.1 安装启动
1. nacos,阿里巴巴开源的服务注册中心:https://github.com/alibaba/nacos/tags,点进去下载nacos-server.zip压缩包解压缩即可(注意不要下载源码)
解压后进入bin目录,打开cmd窗口,输入命令
.\startup.cmd -m standalone
(其中,-m standalone表示单机启动,因为目前没有集群)
进入其给出的地址,即可进入可视化界面
2. seata,做数据一致性的强大工具,因为分布式服务对数据一致性的要求很高:https://seata.apache.org/zh-cn
2.2之前的版本,直接进入bin目录下双击
seata-server.bat
运行即可
2.2版本,先进入seata-server,然后进入bin目录运行
seata-server.bat
3. redis,大佬请进!redis大佬的知名度就不用过多介绍了吧,https://github.com/tporadowski/redis/releases
解压后,双击redis-server.exe运行即可
1.2 配置
1. 进入seata官网,进入文档,配置中心章节中,有Nacos配置中心,文档中给出了配置文件应该怎么配置,并给出了配置文件的github地址
2. nacos配置中心新增配置seataServer.properties,将上面复制的内容粘贴过去,并修改数据库相关的配置
#For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html
#Transport configuration, for client and server
transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableTmClientBatchSendRequest=false
transport.enableRmClientBatchSendRequest=true
transport.enableTcServerBatchSendResponse=false
transport.rpcRmRequestTimeout=30000
transport.rpcTmRequestTimeout=30000
transport.rpcTcRequestTimeout=30000
transport.threadFactory.bossThreadPrefix=NettyBoss
transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
transport.threadFactory.shareBossWorker=false
transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
transport.threadFactory.clientSelectorThreadSize=1
transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
transport.threadFactory.bossThreadSize=1
transport.threadFactory.workerThreadSize=default
transport.shutdown.wait=3
transport.serialization=seata
transport.compressor=none
#Transaction routing rules configuration, only for the client
service.vgroupMapping.default_tx_group=default
#If you use a registry, you can ignore it
service.default.grouplist=127.0.0.1:8091
service.enableDegrade=false
service.disableGlobalTransaction=false
#Transaction rule configuration, only for the client
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=true
client.rm.tableMetaCheckerInterval=60000
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.rm.sagaJsonParser=fastjson
client.rm.tccActionInterceptorOrder=-2147482648
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
client.tm.interceptorOrder=-2147482648
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
client.undo.logTable=undo_log
client.undo.compress.enable=true
client.undo.compress.type=zip
client.undo.compress.threshold=64k
#For TCC transaction mode
tcc.fence.logTableName=tcc_fence_log
tcc.fence.cleanPeriod=1h
#Log rule configuration, for client and server
log.exceptionRate=100
#Transaction storage configuration, only for the server. The file, db, and redis configuration values are optional.
store.mode=file
store.lock.mode=file
store.session.mode=file
#Used for password encryption
store.publicKey=
#If `store.mode,store.lock.mode,store.session.mode` are not equal to `file`, you can remove the configuration block.
store.file.dir=file_store/data
store.file.maxBranchSessionSize=16384
store.file.maxGlobalSessionSize=512
store.file.fileWriteBufferCacheSize=16384
store.file.flushDiskMode=async
store.file.sessionReloadReadSize=100
#These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block.
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/yd_oa_db?serverTimeZone=GMT%2B8&useUnicode=true&rewriteBatchedStatements=true
store.db.user=root
store.db.password=root
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.distributedLockTable=distributed_lock
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
#These configurations are required if the `store mode` is `redis`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `redis`, you can remove the configuration block.
store.redis.mode=single
store.redis.single.host=127.0.0.1
store.redis.single.port=6379
store.redis.sentinel.masterName=
store.redis.sentinel.sentinelHosts=
store.redis.sentinel.sentinelPassword=
store.redis.maxConn=10
store.redis.minConn=1
store.redis.maxTotal=100
store.redis.database=0
store.redis.password=
store.redis.queryLimit=100
#Transaction rule configuration, only for the server
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackFailedUnlockEnable=false
server.distributedLockExpireTime=10000
server.xaerNotaRetryTimeout=60000
server.session.branchAsyncQueueSize=5000
server.session.enableBranchAsyncRemove=false
server.enableParallelRequestHandle=false
#Metrics configuration, only for the server
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898
2. springCloud核心架构搭建
如果使用maven引入包后,写代码依然无法找到包,或者莫名其妙报错的,可以先指向Lifecycle中的clean,然后执行install
还不行就点一下刷新Maven依赖按钮
2.1 根目录pom文件
1. 新建一个空项目,新建src文件夹,然后创建pom.xml文件
2. 根目录的pom主要是引入全局依赖的版本控制,根目录也是我们的父工程,而我们的父工程也需要有一个父工程,就是spring-boot-starter-parent。子模块引入jar包时,无需手动指定版本,根目录pom统一控制
3. 同时我们要将通用的jar包控制起来,每个子模块若有差异化,就不配置在父工程(请以给出代码为主,图片仅供参考,日后如果修改,不会改图片,只会改给出的代码)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 指定父工程为spring-boot-starter-parent -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
<relativePath/>
</parent>
<!-- 我们自己的父工程groupID -->
<groupId>com.yd_oa_java_cloud.cloud</groupId>
<!-- 指定自己名字,我们的的坐标就是父工程groupId加上自己的artifactId ,当前跟目录的父工程就是spring-boot-starter-parent-->
<artifactId>yd_oa_java_cloud</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<!--父工程的子模块-->
<modules>
</modules>
<!--统一管理jar包版本-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<skipTests>true</skipTests>
<springboot.version>2.7.18</springboot.version>
<spring-cloud.version>2021.0.6</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>
<spring-openfeign.version>2.2.2.RELEASE</spring-openfeign.version>
<spring-cloud-gateway.version>3.1.9</spring-cloud-gateway.version>
<mybatis.version>1.3.2</mybatis.version>
<logback.version>1.2.10</logback.version>
<mysql.version>8.0.23</mysql.version>
<aspectjweaver.version>1.9.3</aspectjweaver.version>
<fastjson.version>1.2.83</fastjson.version>
<commons.lang3.version>3.4</commons.lang3.version>
<commons.csv.version>1.2</commons.csv.version>
<commons.codec.version>1.9</commons.codec.version>
<commons.io.version>2.5</commons.io.version>
<feign-okhttp.version>10.2.0</feign-okhttp.version>
<okhttp3.version>4.12.0</okhttp3.version>
<lombok.version>1.18.22</lombok.version>
<captcha.verion>1.6.2</captcha.verion>
<es.version>3.3.2</es.version>
</properties>
<!--锁定jar包版本-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot.version}</version>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringCloud Alibaba 微服务 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>${spring-openfeign.version}</version>
</dependency>
<!--网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>${spring-cloud-gateway.version}</version>
</dependency>
<!--seata-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>2021.0.5.0</version>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</exclusion>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.7.18</version>
</dependency>
<!--springboot 集成seata-->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- 数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- 日志版本 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<!--切面-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectjweaver.version}</version>
</dependency>
<!--okhttp-->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp3.version}</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!--apache common-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>${commons.csv.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang3.version}</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>${commons.codec.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.io.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>${es.version}</version>
</dependency>
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>${captcha.verion}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2.2 base模块
base模块和common都是公用的,但是为了避免包的冲突,所以搞两个。base是最基础的包,是给网关gateway使用的,而gateway和web包是冲突的。而common是给业务子模块使用的,它可以引入base,然后额外引入web包,给业务模块使用。
1. 建立base子模块,并建立pom.xml文件
2. 建立src\main\java文件夹,将java标识为source文件夹
3. 新建在main文件夹下,java文件夹同级,建立resources文件夹,标识为Resources Root
4. 编写pom.xml文件,然后将模块加到父模块中
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 父模块坐标 -->
<parent>
<groupId>com.yd_oa_java_cloud.cloud</groupId>
<artifactId>yd_oa_java_cloud</artifactId>
<version>1.0</version>
</parent>
<!-- 自己的坐标-->
<groupId>com.yd_oa_java_cloud.cloud</groupId>
<artifactId>yd_oa_java_base</artifactId>
<version>1.0</version>
<!-- 打包方式为jar-->
<packaging>jar</packaging>
<!-- 配置-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<skipTests>true</skipTests>
</properties>
<!-- jar包-->
<dependencies>
<!-- 日志版本 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--apache common-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
2.3 common模块
base模块只有最基础的包,而common要考虑的就很多了
1. 构建common模块,与base同理创建基本文件夹后,建立pom.xml
2. 编写pom.xml,注意common要引入base模块,最后将模块加入父模块中
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 父模块坐标 -->
<parent>
<groupId>com.yd_oa_java_cloud.cloud</groupId>
<artifactId>yd_oa_java_cloud</artifactId>
<version>1.0</version>
</parent>
<!-- 自己的坐标-->
<groupId>com.yd_oa_java_cloud.cloud</groupId>
<artifactId>yd_oa_java_common</artifactId>
<version>1.0</version>
<!-- 打包方式为jar-->
<packaging>jar</packaging>
<!-- 配置-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<skipTests>true</skipTests>
</properties>
<!-- jar包-->
<dependencies>
<!-- 引入我们的base模块-->
<dependency>
<groupId>com.yd_oa_java_cloud.cloud</groupId>
<artifactId>yd_oa_java_base</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--nacos的配置管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--负载均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- 数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--切面-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<!--okhttp-->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp-sse</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
</dependency>
</dependencies>
</project>
2.4 getway网关
1. 步骤一样,不多赘述,getway网关引入base模块
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.yd_oa_java_cloud.cloud</groupId>
<artifactId>yd_oa_java_cloud</artifactId>
<version>1.0</version>
</parent>
<artifactId>yd_oa_java_gateway</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<!-- <properties>-->
<!-- <maven.compiler.source>21</maven.compiler.source>-->
<!-- <maven.compiler.target>21</maven.compiler.target>-->
<!-- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>-->
<!-- </properties>-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<skipTests>true</skipTests>
</properties>
<dependencies>
<!-- 引入我们的base模块-->
<dependency>
<groupId>com.yd_oa_java_cloud.cloud</groupId>
<artifactId>yd_oa_java_base</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--nacos的配置管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!--负载均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies>
<!-- 最终打包部署时使用 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.6.RELEASE</version>
<configuration>
<mainClass>com.yd_oa_java_cloud.gateway.YdOaCloudGatewayRunApplication</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.5 security权限管理
这个属于普通web服务,也就是一个普通的springboot项目。但是它的权限管理又是几乎所有模块都需要用的,我们直接将其写为单独的微服务,通过一致性处理,解决分布式问题
它只需要引入common模块即可,其余依赖可以在实际写程序时进行引入,不要忘了在父模块中加载这个新伙伴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.yd_oa_java_cloud.cloud</groupId>
<artifactId>yd_oa_java_cloud</artifactId>
<version>1.0</version>
</parent>
<artifactId>yd_oa_java_security</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<!-- <properties>-->
<!-- <maven.compiler.source>21</maven.compiler.source>-->
<!-- <maven.compiler.target>21</maven.compiler.target>-->
<!-- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>-->
<!-- </properties>-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<skipTests>true</skipTests>
</properties>
<dependencies>
<!-- 引入common模块-->
<dependency>
<groupId>com.yd_oa_java_cloud.cloud</groupId>
<artifactId>yd_oa_java_common</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<!-- 打包的时候用-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.6.RELEASE</version>
<configuration>
<mainClass>com.yd_oa_java_cloud.security.YdOaCloudSecurityRunApplication</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
3. 工具类
1. base模块中,专门处理JSON数据的工具类
package com.yd_oa_java_cloud.base.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
/**
* 处理json的工具类
*/
public class JsonUtils {
private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class);
//对象转json
public static String convertObjToJson(Object obj){
return JSON.toJSONString(obj);
}
//json转对象
public static <T> T convertJsonToObj(String json,Class<T> classz){return JSONObject.parseObject(json,classz);}
//json转对象列表
public static <T> List<T> convertJsonArrayToList(String json, Class<T> classz){return JSONArray.parseArray(json,classz);}
}
2. base模块中,建立响应VO(响应值对象ValueObject),封装响应的状态码等信息
根据不同用户习惯,提供两种,一个是ResponseVO,完全通过get和set自定义响应。还有一个是Result类,提供封装好的响应,例如Result.ok(),但是这个类依赖于下面介绍的枚举类,代码放在和枚举类一起
package com.yd_oa_java_cloud.base.entity.vo;
/**
* ResonseValueObject
* RESTful API中,使用VO来封装响应数据是一种常见的做法。响应VO用于封装API接口的返回结果,通常包含状态码、提示信息及数据部分,这样前端可以清晰地获取每次请求的结
* @param <T>
*/
public class ResponseVO<T> {
private String status;//响应状态
private Integer code; //响应码
private String info; //响应信息
private T data; //响应数据
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
3. base模块中,建立响应枚举类,封装响应码和信息
基于枚举类封装的Result
package com.yd_oa_java_cloud.base.entity.enums;
/**
* 响应code,msg枚举类
*/
public enum ResponseCodeEnum {
CODE_20000(20000,"请求成功!"),
CODE_20001(20001,"请求失败!"),
CODE_404(404,"请求地址不存在!"),
CODE_600(600,"请求参数错误!"),
CODE_601(601,"信息已存在!"),
CODE_500(500,"服务器响应出错,请联系管理员!"),
CODE_503(503,"应用服务错误,请联系管理员!"),//具体微服务错误
CODE_50014(50014,"Token过期,请重新登录!"),
CODE_50008(50008,"非法令牌Token!"),
CODE_50012(50012,"其他客户端已登录!"),
CODE_901(901,"未登录或登录超时,请重新登录!"),
;
private Integer code;
private String msg;
ResponseCodeEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
package com.yd_oa_java_cloud.base.entity.vo;
import com.yd_oa_java_cloud.base.entity.enums.ResponseCodeEnum;
import java.io.Serializable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
public class YdOaResult extends LinkedHashMap<String,Object> implements Serializable {
private Integer code;//状态码
private String msg;//返回信息
public YdOaResult(){
}
public YdOaResult(int code, String msg, Object data) {
this.setCode(code);
this.setMsg(msg);
this.setData(data);
}
public Integer getCode() {
return (Integer)this.get("code");
}
public String getMsg() {
return (String)this.get("msg");
}
public Object getData() {
return this.get("data");
}
public YdOaResult setCode(int code) {
this.put("code", code);
return this;
}
public YdOaResult setMsg(String msg) {
this.put("msg", msg);
return this;
}
public YdOaResult setData(Object data) {
this.put("data", data);
return this;
}
public YdOaResult set(String key, Object data) {
this.put(key, data);
return this;
}
public YdOaResult removeDefaultFields() {
this.remove("code");
this.remove("msg");
this.remove("data");
return this;
}
public YdOaResult removeNonDefaultFields() {
Iterator var1 = this.keySet().iterator();
while(var1.hasNext()) {
String key = (String)var1.next();
if (!"code".equals(key) && !"msg".equals(key) && !"data".equals(key)) {
this.remove(key);
}
}
return this;
}
public static YdOaResult ok() {
ResponseCodeEnum code20000 = ResponseCodeEnum.CODE_20000;
return new YdOaResult(code20000.getCode(), code20000.getMsg(), (Object)null);
}
public static YdOaResult ok(String msg) {
ResponseCodeEnum code20000 = ResponseCodeEnum.CODE_20000;
return new YdOaResult(code20000.getCode(), msg, (Object)null);
}
public static YdOaResult code(int code) {
return new YdOaResult(code, (String)null, (Object)null);
}
public static YdOaResult data(Object data) {
ResponseCodeEnum code20000 = ResponseCodeEnum.CODE_20000;
return new YdOaResult(code20000.getCode(),code20000.getMsg(), data);
}
public static YdOaResult error() {
ResponseCodeEnum code20001 = ResponseCodeEnum.CODE_20001;
return new YdOaResult(code20001.getCode(), code20001.getMsg(), (Object)null);
}
public static YdOaResult error(String msg) {
ResponseCodeEnum code20001 = ResponseCodeEnum.CODE_20001;
return new YdOaResult(code20001.getCode(), msg, (Object)null);
}
public static YdOaResult get(int code, String msg, Object data) {
return new YdOaResult(code, msg, data);
}
public static YdOaResult empty() {
return new YdOaResult();
}
public String toString() {
return "{\"code\": " + this.getCode() + ", \"msg\": " + this.transValue(this.getMsg()) + ", \"data\": " + this.transValue(this.getData()) + "}";
}
private String transValue(Object value) {
if (value == null) {
return null;
} else {
return value instanceof String ? "\"" + value + "\"" : String.valueOf(value);
}
}
}
4. base模块构建自定义异常类,封装自定义异常
package com.yd_oa_java_cloud.base.exception;
import com.yd_oa_java_cloud.base.entity.enums.ResponseCodeEnum;
/**
* 自定义异常
*/
public class BusinessException extends RuntimeException{
private ResponseCodeEnum codeEnum;//引入响应信息枚举
private Integer code;//自定义异常响应码
private String message; //自定义异常响应信息
//构造方法
public BusinessException(String message,Throwable e){
super(message,e);//调用父类构造方法,将异常信息传入
this.message = message;
}
public BusinessException(String message){
super(message);
this.message = message;
}
public BusinessException(Throwable e) {super(e);}
public BusinessException(ResponseCodeEnum codeEnum){
super(codeEnum.getMsg());
this.codeEnum=codeEnum;
this.code = codeEnum.getCode();
this.message = codeEnum.getMsg();
}
public BusinessException(Integer code, String message){
super(message);
this.code = code;
this.message = message;
}
public ResponseCodeEnum getCodeEnum() {return codeEnum;}
public Integer getCode() {return code;}
@Override
public String getMessage() {
return message;
}
/**
* 重新fillInStackTrace 业务异常不需要堆栈信息,提高效率
*/
@Override
public Throwable fillInStackTrace() {
return this;
}
}
3. gateway网关
由于篇幅原因,将其放在:https://blog.csdn.net/grd_java/article/details/145000544 |
---|
4. mybatis-plus,代码生成器
按需加载,可以使用mybatis自己写全流程,这一步是可选项
由于篇幅原因,将其放在:https://blog.csdn.net/grd_java/article/details/145061518 |
---|
5. Sa-Token权限管理模块rbac
本来想使用spring security的,但是考虑到实际工作中,大家都在用国产的Sa-Token框架实现相关功能,所以采用此框架实现权限认证
这个框架真的很好用呀,spring security玩了这么久,现在有了Sa-Token以后,除了高安全性需求场景基本用不上spring security了,文档还难读,Sa-Token再发展两年,真的可以把spring security关小黑屋了
由于篇幅原因,将其放在:https://blog.csdn.net/grd_java/article/details/145013189 |
---|