iailab-cloud/iailab-gateway/pom.xml
@@ -20,12 +20,6 @@ </properties> <dependencies> <!-- Spring Cloud 基础 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency> <!-- 业务组件 --> <dependency> <groupId>com.iailab</groupId> iailab-cloud/iailab-gateway/src/main/resources/application.yaml
@@ -1,6 +1,17 @@ spring: application: name: gateway-server profiles: active: local main: allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。 config: import: - optional:classpath:application-${spring.profiles.active}.yaml # 加载【本地】配置 - optional:nacos:${spring.application.name}-${spring.profiles.active}.yaml # 加载【Nacos】的配置 cloud: # Spring Cloud Gateway 配置项,对应 GatewayProperties 类 @@ -74,8 +85,29 @@ uri: grayLb://iailab-monitor predicates: - Path=/iailab-monitor/** ## data-server 服务 - id: data-admin-api # 路由的编号 uri: grayLb://data-server predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组 - Path=/admin-api/data/** filters: - RewritePath=/admin-api/data/v3/api-docs, /v3/api-docs ## model-server 服务 - id: model-admin-api # 路由的编号 uri: grayLb://model-server predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组 - Path=/admin-api/model/** filters: - RewritePath=/admin-api/model/v3/api-docs, /v3/api-docs x-forwarded: prefix-enabled: false # 避免 Swagger 重复带上额外的 /admin-api/system 前缀 prefix-enabled: true # 避免 Swagger 重复带上额外的 /admin-api/system 前缀 server: port: 48080 logging: file: name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 knife4j: # 聚合 Swagger 文档,参考 https://doc.xiaominfo.com/docs/action/springcloud-gateway 文档 @@ -91,6 +123,12 @@ - name: bpm-server service-name: bpm-server url: /admin-api/bpm/v3/api-docs - name: data-server service-name: data-server url: /admin-api/data/v3/api-docs - name: model-server service-name: model-server url: /admin-api/model/v3/api-docs --- #################### 平台相关配置 #################### iailab: iailab-cloud/iailab-monitor/pom.xml
@@ -63,10 +63,21 @@ </dependencies> <build> <!-- 设置构建的 jar 包名 --> <finalName>${project.artifactId}</finalName> <plugins> <!-- 打包 --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring.boot.version}</version> <!-- 如果 spring.boot.version 版本修改,则这里也要跟着修改 --> <executions> <execution> <goals> <goal>repackage</goal> <!-- 将引入的 jar 打入其中 --> </goals> </execution> </executions> </plugin> </plugins> </build> iailab-cloud/iailab-nacos/Dockerfile
@@ -1,17 +1,9 @@ #FROM findepi/graalvm:java17-native FROM openjdk:17.0.2-oraclelinux8 MAINTAINER Lion Li RUN mkdir -p /ruoyi/nacos WORKDIR /ruoyi/nacos FROM eclipse-temurin:8-jre RUN mkdir -p /sda2/iailab/iailab-platform/nacos WORKDIR /sda2/iailab/iailab-platform/nacos EXPOSE 8848 ENV TZ=Asia/Shanghai LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS="-Xms512m -Xmx1024m" ## 将后端项目的 Jar 文件,复制到镜像中 COPY ./iailab-nacos.jar nacos-server.jar ADD ./target/ruoyi-nacos.jar ./app.jar ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom ${JAVA_OPTS} -jar app.jar CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar iailab-nacos.jar iailab-cloud/iailab-nacos/src/main/resources/application.yaml
对比新文件 @@ -0,0 +1,82 @@ db: num: 1 url: '0': jdbc:mysql://172.16.8.100:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true password: '0': 123456 user: '0': root management: endpoints: web: exposure: include: '*' metrics: export: elastic: enabled: false influx: enabled: false nacos: config: push: maxRetryTime: 50 core: auth: caching: enabled: true enable: userAgentAuthWhite: false enabled: true plugin: nacos: token: cache: enable: false expire: seconds: 18000 secret: key: SecretKey012345678901234567890123456789012345678901234567890123456789 server: identity: key: serverIdentity value: security system: type: nacos istio: mcp: server: enabled: false naming: empty-service: auto-clean: true clean: initial-delay-ms: 50000 period-time-ms: 30000 plugin: datasource: log: enabled: true security: ignore: urls: /,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/** server: error: include-message: ALWAYS port: 8848 servlet: contextPath: /nacos spring: application: name: iailab-nacos boot: admin: client: instance: service-host-type: IP password: 123456 url: http://127.0.0.1:9100 username: iailab sql: init: platform: mysql iailab-cloud/iailab-xxl-job/pom.xml
@@ -50,11 +50,6 @@ </licenses> <dependencies> <!-- Spring Cloud 基础 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency> <!-- starter-web:spring-webmvc + autoconfigure + logback + yaml + tomcat --> <dependency> <groupId>org.springframework.boot</groupId> @@ -125,57 +120,79 @@ </dependencies> <build> <finalName>${project.artifactId}</finalName> <plugins> <!-- Source --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>${maven-source-plugin.version}</version> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <executions> <execution> <phase>package</phase> <goals> <goal>jar-no-fork</goal> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <!-- Javadoc --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> <version>${maven-javadoc-plugin.version}</version> <executions> <execution> <phase>package</phase> <goals> <goal>jar</goal> </goals> <configuration> <doclint>none</doclint> </configuration> </execution> </executions> </plugin> <!-- GPG --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-gpg-plugin</artifactId> <version>${maven-gpg-plugin.version}</version> <configuration> <useAgent>false</useAgent> <!-- 作用:项目打成jar的同时将本地jar包也引入进去 --> <includeSystemScope>true</includeSystemScope> </configuration> <!-- <executions>--> <!-- <execution>--> <!-- <phase>verify</phase>--> <!-- <goals>--> <!-- <goal>sign</goal>--> <!-- </goals>--> <!-- </execution>--> <!-- </executions>--> </plugin> </plugins> </build> <!-- <build>--> <!-- <plugins>--> <!-- <!– Source –>--> <!-- <plugin>--> <!-- <groupId>org.apache.maven.plugins</groupId>--> <!-- <artifactId>maven-source-plugin</artifactId>--> <!-- <version>${maven-source-plugin.version}</version>--> <!-- <executions>--> <!-- <execution>--> <!-- <phase>package</phase>--> <!-- <goals>--> <!-- <goal>jar-no-fork</goal>--> <!-- </goals>--> <!-- </execution>--> <!-- </executions>--> <!-- </plugin>--> <!-- <!– Javadoc –>--> <!-- <plugin>--> <!-- <groupId>org.apache.maven.plugins</groupId>--> <!-- <artifactId>maven-javadoc-plugin</artifactId>--> <!-- <version>${maven-javadoc-plugin.version}</version>--> <!-- <executions>--> <!-- <execution>--> <!-- <phase>package</phase>--> <!-- <goals>--> <!-- <goal>jar</goal>--> <!-- </goals>--> <!-- <configuration>--> <!-- <doclint>none</doclint>--> <!-- </configuration>--> <!-- </execution>--> <!-- </executions>--> <!-- </plugin>--> <!-- <!– GPG –>--> <!-- <plugin>--> <!-- <groupId>org.apache.maven.plugins</groupId>--> <!-- <artifactId>maven-gpg-plugin</artifactId>--> <!-- <version>${maven-gpg-plugin.version}</version>--> <!-- <configuration>--> <!-- <useAgent>false</useAgent>--> <!-- </configuration>--> <!--<!– <executions>–>--> <!--<!– <execution>–>--> <!--<!– <phase>verify</phase>–>--> <!--<!– <goals>–>--> <!--<!– <goal>sign</goal>–>--> <!--<!– </goals>–>--> <!--<!– </execution>–>--> <!--<!– </executions>–>--> <!-- </plugin>--> <!-- </plugins>--> <!-- </build>--> </project> iailab-cloud/iailab-xxl-job/src/main/java/com/xxl/job/admin/XxlJobAdminApplication.java
@@ -2,11 +2,13 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; /** * @author xuxueli 2018-10-28 00:38:13 */ @SpringBootApplication @EnableDiscoveryClient public class XxlJobAdminApplication { public static void main(String[] args) { iailab-cloud/iailab-xxl-job/src/main/resources/application.yaml
@@ -1,4 +1,26 @@ server: port: 9090 servlet: context-path: /xxl-job-admin logging: file: name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 spring: application: name: xxl-job-server profiles: # 环境配置 # active: @profiles.active@ active: local # Spring Boot Admin 配置项 boot: admin: # Spring Boot Admin Client 客户端的相关配置 client: instance: service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME] mvc: servlet: load-on-startup: 0 @@ -14,7 +36,7 @@ number_format: 0. new_builtin_class_resolver: safer datasource: url: jdbc:mysql://127.0.0.1:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai url: jdbc:mysql://172.16.8.100:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver @@ -60,6 +82,11 @@ # 服务端点检查 management: server: base-path: /actuator health: mail: enabled: false trace: http: enabled: true iailab-cloud/iailab-xxl-job/src/main/resources/logback.xml
@@ -2,7 +2,7 @@ <configuration debug="false" scan="true" scanPeriod="1 seconds"> <contextName>logback</contextName> <property name="log.path" value="/data/applogs/xxl-job/xxl-job-admin.log"/> <property name="log.path" value="/sda2/data/applogs/xxl-job/xxl-job-admin.log"/> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/config/IailabDataPermissionAutoConfiguration.java
@@ -1,7 +1,8 @@ package com.iailab.framework.datapermission.config; import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor; import com.iailab.framework.datapermission.core.aop.DataPermissionAnnotationAdvisor; import com.iailab.framework.datapermission.core.db.DataPermissionDatabaseInterceptor; import com.iailab.framework.datapermission.core.db.DataPermissionRuleHandler; import com.iailab.framework.datapermission.core.rule.DataPermissionRule; import com.iailab.framework.datapermission.core.rule.DataPermissionRuleFactory; import com.iailab.framework.datapermission.core.rule.DataPermissionRuleFactoryImpl; @@ -26,16 +27,18 @@ } @Bean public DataPermissionDatabaseInterceptor dataPermissionDatabaseInterceptor(MybatisPlusInterceptor interceptor, DataPermissionRuleFactory ruleFactory) { // 创建 DataPermissionDatabaseInterceptor 拦截器 DataPermissionDatabaseInterceptor inner = new DataPermissionDatabaseInterceptor(ruleFactory); public DataPermissionRuleHandler dataPermissionRuleHandler(MybatisPlusInterceptor interceptor, DataPermissionRuleFactory ruleFactory) { // 创建 DataPermissionInterceptor 拦截器 DataPermissionRuleHandler handler = new DataPermissionRuleHandler(ruleFactory); DataPermissionInterceptor inner = new DataPermissionInterceptor(handler); // 添加到 interceptor 中 // 需要加在首个,主要是为了在分页插件前面。这个是 MyBatis Plus 的规定 MyBatisUtils.addInterceptor(interceptor, inner, 0); return inner; return handler; } @Bean public DataPermissionAnnotationAdvisor dataPermissionAnnotationAdvisor() { return new DataPermissionAnnotationAdvisor(); iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java
@@ -156,6 +156,7 @@ } // 拼接条件 return new InExpression(MyBatisUtils.buildColumn(tableName, tableAlias, columnName), // new Parenthesis(new ExpressionList<>(CollectionUtils.convertList(deptIds, LongValue::new)))); new ExpressionList(CollectionUtils.convertList(deptIds, LongValue::new))); } iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/config/MyBatisConfiguration.java
@@ -1,72 +1,84 @@ package com.iailab.framework.mybatis.config; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.iailab.framework.mybatis.core.handler.MybatisHandler; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.type.JdbcType; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; /** * @author houzhongjian * @Title: MyBatisConfiguration * @ProjectName design-parent * @Description: 解决独立启动某个服务时报错问题 No typehandler found for property sqlSessionTemplate * @date 2024/7/2 16:35 */ @Configuration public class MyBatisConfiguration { // 配置mapper的扫描,找到所有的mapper.xml映射文件 @Value("${iailab.info.base-package}") private String mapperLocations; // @Bean(name = "dataSource") // @ConfigurationProperties(prefix = "spring.datasource.test1") //package com.iailab.framework.mybatis.config; // //import com.alibaba.fastjson.JSONArray; //import com.alibaba.fastjson.JSONObject; //import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; //import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; //import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; //import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; //import com.iailab.framework.mybatis.core.handler.MybatisHandler; //import com.iailab.framework.mybatis.interceptor.DataFilterInterceptor; //import org.apache.ibatis.session.SqlSessionFactory; //import org.apache.ibatis.type.JdbcType; //import org.mybatis.spring.SqlSessionFactoryBean; //import org.mybatis.spring.SqlSessionTemplate; //import org.springframework.beans.factory.annotation.Value; //import org.springframework.boot.jdbc.DataSourceBuilder; //import org.springframework.context.annotation.Bean; //import org.springframework.context.annotation.Configuration; //import org.springframework.context.annotation.Primary; //import org.springframework.core.io.support.PathMatchingResourcePatternResolver; //import org.springframework.jdbc.datasource.DataSourceTransactionManager; // // ///** // * @author houzhongjian // * @Title: MyBatisConfiguration // * @ProjectName design-parent // * @Description: 解决独立启动某个服务时报错问题 No typehandler found for property sqlSessionTemplate // * @date 2024/7/2 16:35 // */ //@Configuration //public class MyBatisConfiguration { // // // 配置mapper的扫描,找到所有的mapper.xml映射文件 //// @Value("${iailab.info.base-package}") // @Value("${mybatis-plus.mapper-locations}") // private String mapperLocations; // // @Bean // @Primary // public DataSource dataSource() { // return DataSourceBuilder.create().build(); // public SqlSessionFactory sqlSessionFactory() throws Exception { // SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); // sqlSessionFactoryBean.setDataSource(DataSourceBuilder.create().build()); // sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations)); // sqlSessionFactoryBean.setConfiguration(buildConfiguration()); // return sqlSessionFactoryBean.getObject(); // } @Bean @Primary public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(DataSourceBuilder.create().build()); sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations)); sqlSessionFactoryBean.setConfiguration(buildConfiguration()); return sqlSessionFactoryBean.getObject(); } @Bean @Primary public SqlSessionTemplate sqlSessionTemplate() throws Exception { return new SqlSessionTemplate(sqlSessionFactory()); } @Bean @Primary public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(DataSourceBuilder.create().build()); } private org.apache.ibatis.session.Configuration buildConfiguration() { org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); configuration.getTypeHandlerRegistry().register(JSONObject.class, JdbcType.VARCHAR, MybatisHandler.class); configuration.getTypeHandlerRegistry().register(JSONArray.class, JdbcType.VARCHAR, MybatisHandler.class); return configuration; } } // // @Bean // @Primary // public SqlSessionTemplate sqlSessionTemplate() throws Exception { // return new SqlSessionTemplate(sqlSessionFactory()); // } // // @Bean // @Primary // public DataSourceTransactionManager transactionManager() { // return new DataSourceTransactionManager(DataSourceBuilder.create().build()); // } // // private org.apache.ibatis.session.Configuration buildConfiguration() { // org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); // configuration.getTypeHandlerRegistry().register(JSONObject.class, JdbcType.VARCHAR, MybatisHandler.class); // configuration.getTypeHandlerRegistry().register(JSONArray.class, JdbcType.VARCHAR, MybatisHandler.class); // return configuration; // } // // @Bean // public MybatisPlusInterceptor mybatisPlusInterceptor() { // MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); // // 数据权限 // mybatisPlusInterceptor.addInnerInterceptor(new DataFilterInterceptor()); // // 分页插件 // mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // // 乐观锁 // mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // // 防止全表更新与删除 // mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); // // return mybatisPlusInterceptor; // } // // //} iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/mapper/BaseMapperX.java
@@ -185,7 +185,7 @@ return Db.updateBatchById(entities, size); } default Boolean insertOrUpdate(T entity) { default boolean insertOrUpdate(T entity) { return Db.saveOrUpdate(entity); } iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/JsonLongSetTypeHandler.java
@@ -1,31 +1,31 @@ package com.iailab.framework.mybatis.core.type; import com.iailab.framework.common.util.json.JsonUtils; import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler; import com.fasterxml.jackson.core.type.TypeReference; import java.util.Set; /** * 参考 {@link com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler} 实现 * 在我们将字符串反序列化为 Set 并且泛型为 Long 时,如果每个元素的数值太小,会被处理成 Integer 类型,导致可能存在隐性的 BUG。 * * 例如说哦,SysUserDO 的 postIds 属性 * * @author iailab */ public class JsonLongSetTypeHandler extends AbstractJsonTypeHandler<Object> { private static final TypeReference<Set<Long>> TYPE_REFERENCE = new TypeReference<Set<Long>>(){}; @Override protected Object parse(String json) { return JsonUtils.parseObject(json, TYPE_REFERENCE); } @Override protected String toJson(Object obj) { return JsonUtils.toJsonString(obj); } } //package com.iailab.framework.mybatis.core.type; // //import com.iailab.framework.common.util.json.JsonUtils; //import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler; //import com.fasterxml.jackson.core.type.TypeReference; // //import java.util.Set; // ///** // * 参考 {@link com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler} 实现 // * 在我们将字符串反序列化为 Set 并且泛型为 Long 时,如果每个元素的数值太小,会被处理成 Integer 类型,导致可能存在隐性的 BUG。 // * // * 例如说哦,SysUserDO 的 postIds 属性 // * // * @author iailab // */ //public class JsonLongSetTypeHandler extends AbstractJsonTypeHandler<Object> { // // private static final TypeReference<Set<Long>> TYPE_REFERENCE = new TypeReference<Set<Long>>(){}; // // @Override // protected Object parse(String json) { // return JsonUtils.parseObject(json, TYPE_REFERENCE); // } // // @Override // protected String toJson(Object obj) { // return JsonUtils.toJsonString(obj); // } // //} iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/util/JdbcUtils.java
@@ -1,14 +1,19 @@ package com.iailab.framework.mybatis.core.util; import com.baomidou.dynamic.datasource.DynamicRoutingDataSource; import com.baomidou.mybatisplus.annotation.DbType; import com.iailab.framework.common.util.spring.SpringUtils; import com.iailab.framework.mybatis.core.enums.DbTypeEnum; import javax.sql.DataSource; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; /** * JDBC 工具类 * * @author iailab * @author 芋道源码 */ public class JdbcUtils { @@ -35,8 +40,22 @@ * @return DB 类型 */ public static DbType getDbType(String url) { String name = com.alibaba.druid.util.JdbcUtils.getDbType(url, null); return DbType.getDbType(name); return com.baomidou.mybatisplus.extension.toolkit.JdbcUtils.getDbType(url); } /** * 通过当前数据库连接获得对应的 DB 类型 * * @return DB 类型 */ public static DbType getDbType() { DynamicRoutingDataSource dynamicRoutingDataSource = SpringUtils.getBean(DynamicRoutingDataSource.class); DataSource dataSource = dynamicRoutingDataSource.determineDataSource(); try (Connection conn = dataSource.getConnection()) { return DbTypeEnum.find(conn.getMetaData().getDatabaseProductName()); } catch (SQLException e) { throw new IllegalArgumentException(e.getMessage()); } } } iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/util/MyBatisUtils.java
@@ -1,13 +1,16 @@ package com.iailab.framework.mybatis.core.util; import cn.hutool.core.collection.CollectionUtil; import com.iailab.framework.common.pojo.PageParam; import com.iailab.framework.common.pojo.SortingField; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.iailab.framework.common.pojo.PageParam; import com.iailab.framework.common.pojo.SortingField; import com.iailab.framework.mybatis.core.enums.DbTypeEnum; import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; @@ -56,7 +59,7 @@ /** * 获得 Table 对应的表名 * * <p> * 兼容 MySQL 转义表名 `t_xxx` * * @param table 表 @@ -85,4 +88,19 @@ return new Column(tableName + StringPool.DOT + column); } /** * 跨数据库的 find_in_set 实现 * * @param column 字段名称 * @param value 查询值(不带单引号) * @return sql */ public static String findInSet(String column, Object value) { // 这里不用SqlConstants.DB_TYPE,因为它是使用 primary 数据源的 url 推断出来的类型 DbType dbType = JdbcUtils.getDbType(); return DbTypeEnum.getFindInSetTemplate(dbType) .replace("#{column}", column) .replace("#{value}", StrUtil.toString(value)); } } iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/IailabSecurityAutoConfiguration.java
@@ -1,5 +1,6 @@ package com.iailab.framework.security.config; import cn.hutool.extra.spring.SpringUtil; import com.iailab.framework.security.core.aop.PreAuthenticatedAspect; import com.iailab.framework.security.core.context.TransmittableThreadLocalSecurityContextHolderStrategy; import com.iailab.framework.security.core.filter.TokenAuthenticationFilter; @@ -10,6 +11,7 @@ import com.iailab.framework.web.core.handler.GlobalExceptionHandler; import com.iailab.module.system.api.oauth2.OAuth2TokenApi; import com.iailab.module.system.api.permission.PermissionApi; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.MethodInvokingFactoryBean; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigureOrder; @@ -80,11 +82,23 @@ @Bean public TokenAuthenticationFilter authenticationTokenFilter(GlobalExceptionHandler globalExceptionHandler, OAuth2TokenApi oauth2TokenApi) { try { OAuth2TokenApi oAuth2TokenApi = SpringUtil.getBean("aAuth2TokenApiImpl", OAuth2TokenApi.class); if (oAuth2TokenApi != null) { oauth2TokenApi = oAuth2TokenApi; } } catch (Exception ignored) {} return new TokenAuthenticationFilter(securityProperties, globalExceptionHandler, oauth2TokenApi); } @Bean("ss") // 使用 Spring Security 的缩写,方便使用 public SecurityFrameworkService securityFrameworkService(PermissionApi permissionApi) { try { PermissionApi permissionApiImpl = SpringUtil.getBean("permissionApiImpl", PermissionApi.class); if (permissionApiImpl != null) { permissionApi = permissionApiImpl; } } catch (Exception ignored) {} return new SecurityFrameworkServiceImpl(permissionApi); } iailab-framework/iailab-common/pom.xml
@@ -129,6 +129,11 @@ </dependency> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>transmittable-thread-local</artifactId> </dependency> iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/date/DateUtils.java
@@ -1,10 +1,15 @@ package com.iailab.framework.common.util.date; import cn.hutool.core.date.LocalDateTimeUtil; import org.joda.time.DateTime; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.*; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; /** * 时间工具类 @@ -26,6 +31,44 @@ public static final String FORMAT_YEAR_MONTH_DAY = "yyyy-MM-dd"; public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss"; /** * 日期格式化 日期格式为:yyyy-MM-dd * @param date 日期 * @return 返回yyyy-MM-dd格式日期 */ public static String format(Date date) { return format(date, FORMAT_YEAR_MONTH_DAY); } /** * 日期格式化 日期格式为:yyyy-MM-dd * @param date 日期 * @param pattern 格式,如:DateUtils.DATE_TIME_PATTERN * @return 返回yyyy-MM-dd格式日期 */ public static String format(Date date, String pattern) { if(date != null){ SimpleDateFormat df = new SimpleDateFormat(pattern); return df.format(date); } return null; } /** * 日期解析 * @param date 日期 * @param pattern 格式,如:DateUtils.DATE_TIME_PATTERN * @return 返回Date */ public static Date parse(String date, String pattern) { try { return new SimpleDateFormat(pattern).parse(date); } catch (ParseException e) { e.printStackTrace(); } return null; } /** * 将 LocalDateTime 转换成 Date @@ -146,4 +189,99 @@ return LocalDateTimeUtil.isSameDay(date, LocalDateTime.now().minusDays(1)); } public static List<String> getTimeScale(Date startDate, Date endDate, int seconds) { List<String> days = new ArrayList<String>(); Calendar calendar = Calendar.getInstance(); calendar.setTime(startDate); while (calendar.getTime().compareTo(endDate) <= 0) { days.add(DateUtils.format(calendar.getTime(), FORMAT_YEAR_MONTH_DAY)); calendar.add(Calendar.SECOND, seconds); } return days; } /** * 对日期的【秒】进行加/减 * * @param date 日期 * @param seconds 秒数,负数为减 * @return 加/减几秒后的日期 */ public static Date addDateSeconds(Date date, int seconds) { DateTime dateTime = new DateTime(date); return dateTime.plusSeconds(seconds).toDate(); } /** * 对日期的【分钟】进行加/减 * * @param date 日期 * @param minutes 分钟数,负数为减 * @return 加/减几分钟后的日期 */ public static Date addDateMinutes(Date date, int minutes) { DateTime dateTime = new DateTime(date); return dateTime.plusMinutes(minutes).toDate(); } /** * 对日期的【小时】进行加/减 * * @param date 日期 * @param hours 小时数,负数为减 * @return 加/减几小时后的日期 */ public static Date addDateHours(Date date, int hours) { DateTime dateTime = new DateTime(date); return dateTime.plusHours(hours).toDate(); } /** * 对日期的【天】进行加/减 * * @param date 日期 * @param days 天数,负数为减 * @return 加/减几天后的日期 */ public static Date addDateDays(Date date, int days) { DateTime dateTime = new DateTime(date); return dateTime.plusDays(days).toDate(); } /** * 对日期的【周】进行加/减 * * @param date 日期 * @param weeks 周数,负数为减 * @return 加/减几周后的日期 */ public static Date addDateWeeks(Date date, int weeks) { DateTime dateTime = new DateTime(date); return dateTime.plusWeeks(weeks).toDate(); } /** * 对日期的【月】进行加/减 * * @param date 日期 * @param months 月数,负数为减 * @return 加/减几月后的日期 */ public static Date addDateMonths(Date date, int months) { DateTime dateTime = new DateTime(date); return dateTime.plusMonths(months).toDate(); } /** * 对日期的【年】进行加/减 * * @param date 日期 * @param years 年数,负数为减 * @return 加/减几年后的日期 */ public static Date addDateYears(Date date, int years) { DateTime dateTime = new DateTime(date); return dateTime.plusYears(years).toDate(); } } iailab-module-data/iailab-module-data-api/pom.xml
对比新文件 @@ -0,0 +1,48 @@ <?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.iailab</groupId> <artifactId>iailab-module-data</artifactId> <version>${revision}</version> </parent> <version>${revision}</version> <artifactId>iailab-module-data-api</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>com.iailab</groupId> <artifactId>iailab-common</artifactId> </dependency> <!-- Web 相关 --> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> </dependency> <!-- 参数校验 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> <optional>true</optional> </dependency> <!-- RPC 远程调用相关 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <optional>true</optional> </dependency> </dependencies> </project> iailab-module-data/iailab-module-data-biz/pom.xml
对比新文件 @@ -0,0 +1,188 @@ <?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.iailab</groupId> <artifactId>iailab-module-data</artifactId> <version>${revision}</version> </parent> <artifactId>iailab-module-data-biz</artifactId> <name>${project.artifactId}</name> <packaging>jar</packaging> <dependencies> <dependency> <groupId>com.iailab</groupId> <artifactId>iailab-common-env</artifactId> </dependency> <!-- 消息队列相关 --> <dependency> <groupId>com.iailab</groupId> <artifactId>iailab-common-mq</artifactId> </dependency> <dependency> <groupId>com.iailab</groupId> <artifactId>iailab-common-mybatis</artifactId> </dependency> <dependency> <groupId>com.iailab</groupId> <artifactId>iailab-common-redis</artifactId> </dependency> <dependency> <groupId>com.iailab</groupId> <artifactId>iailab-common-excel</artifactId> </dependency> <dependency> <groupId>com.iailab</groupId> <artifactId>iailab-common-security</artifactId> </dependency> <!-- RPC 远程调用相关 --> <dependency> <groupId>com.iailab</groupId> <artifactId>iailab-common-rpc</artifactId> </dependency> <!-- 监控相关 --> <dependency> <groupId>com.iailab</groupId> <artifactId>iailab-common-monitor</artifactId> </dependency> <!-- Job 定时任务相关 --> <dependency> <groupId>com.iailab</groupId> <artifactId>iailab-common-job</artifactId> </dependency> <dependency> <groupId>com.iailab</groupId> <artifactId>iailab-common-biz-data-permission</artifactId> </dependency> <dependency> <groupId>com.iailab</groupId> <artifactId>iailab-module-data-api</artifactId> <version>${revision}</version> </dependency> <dependency> <groupId>com.iailab</groupId> <artifactId>iailab-module-model-api</artifactId> <version>${revision}</version> </dependency> <dependency> <groupId>com.iailab</groupId> <artifactId>iailab-module-infra-api</artifactId> <version>${revision}</version> </dependency> <dependency> <groupId>com.iailab</groupId> <artifactId>iailab-module-system-api</artifactId> <version>${revision}</version> </dependency> <!-- nacos 客户端 --> <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.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version> </dependency> <!-- <dependency>--> <!-- <groupId>cn.afterturn</groupId>--> <!-- <artifactId>easypoi-base</artifactId>--> <!-- <version>${easypoi.version}</version>--> <!-- </dependency>--> <!-- <dependency>--> <!-- <groupId>cn.afterturn</groupId>--> <!-- <artifactId>easypoi-web</artifactId>--> <!-- <version>${easypoi.version}</version>--> <!-- </dependency>--> <!-- <dependency>--> <!-- <groupId>cn.afterturn</groupId>--> <!-- <artifactId>easypoi-annotation</artifactId>--> <!-- <version>${easypoi.version}</version>--> <!-- </dependency>--> <!-- 引用POI --> <!-- <dependency>--> <!-- <groupId>org.apache.poi</groupId>--> <!-- <artifactId>poi</artifactId>--> <!-- <version>4.1.1</version>--> <!-- </dependency>--> <!-- <dependency>--> <!-- <groupId>org.jetbrains</groupId>--> <!-- <artifactId>annotations</artifactId>--> <!-- <version>17.0.0</version>--> <!-- <scope>compile</scope>--> <!-- </dependency>--> <!-- ModBus TCP --> <dependency> <groupId>com.infiniteautomation</groupId> <artifactId>modbus4j</artifactId> <version>3.0.4</version> </dependency> <!-- OPC UA --> <dependency> <groupId>org.eclipse.milo</groupId> <artifactId>sdk-client</artifactId> <version>0.6.9</version> </dependency> <dependency> <groupId>org.eclipse.milo</groupId> <artifactId>sdk-server</artifactId> <version>0.6.9</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>31.0.1-jre</version> </dependency> <!-- influxdb --> <dependency> <groupId>com.influxdb</groupId> <artifactId>influxdb-client-java</artifactId> <version>6.8.0</version> </dependency> <!-- <!– websocket –>--> <!-- <dependency>--> <!-- <groupId>org.springframework.boot</groupId>--> <!-- <artifactId>spring-boot-starter-websocket</artifactId>--> <!-- </dependency>--> </dependencies> <build> <!-- 设置构建的 jar 包名 --> <finalName>${project.artifactId}</finalName> <plugins> <!-- 打包 --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring.boot.version}</version> <executions> <execution> <goals> <goal>repackage</goal> <!-- 将引入的 jar 打入其中 --> </goals> </execution> </executions> </plugin> </plugins> </build> </project> iailab-module-data/pom.xml
对比新文件 @@ -0,0 +1,25 @@ <?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.iailab</groupId> <artifactId>iailab-platform</artifactId> <version>${revision}</version> </parent> <artifactId>iailab-module-data</artifactId> <packaging>pom</packaging> <modules> <module>iailab-module-data-biz</module> <module>iailab-module-data-api</module> </modules> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> </project> iailab-module-infra/iailab-module-infra-biz/pom.xml
@@ -19,12 +19,6 @@ </description> <dependencies> <!-- Spring Cloud 基础 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency> <!-- 依赖服务 --> <dependency> <groupId>com.iailab</groupId> iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/dal/dataobject/file/FileConfigDO.java
@@ -17,6 +17,8 @@ import com.fasterxml.jackson.core.type.TypeReference; import lombok.*; import java.lang.reflect.Field; /** * 文件配置表 * @@ -65,8 +67,16 @@ public static class FileClientConfigTypeHandler extends AbstractJsonTypeHandler<Object> { public FileClientConfigTypeHandler(Class<?> type) { super(type); } public FileClientConfigTypeHandler(Class<?> type, Field field) { super(type, field); } @Override protected Object parse(String json) { public Object parse(String json) { FileClientConfig config = JsonUtils.parseObjectQuietly(json, new TypeReference<FileClientConfig>() {}); if (config != null) { return config; @@ -92,7 +102,7 @@ } @Override protected String toJson(Object obj) { public String toJson(Object obj) { return JsonUtils.toJsonString(obj); } iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/framework/security/config/SecurityConfiguration.java
@@ -24,8 +24,10 @@ @Override public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) { // Swagger 接口文档 registry.antMatchers("/v3/api-docs/**").permitAll() // 元数据 .antMatchers("/swagger-ui.html").permitAll(); // Swagger UI registry.antMatchers("/v3/api-docs/**").permitAll() .antMatchers("/webjars/**").permitAll() .antMatchers("/swagger-ui").permitAll() .antMatchers("/swagger-ui/**").permitAll(); // Spring Boot Actuator 的安全配置 registry.antMatchers("/actuator").anonymous() .antMatchers("/actuator/**").anonymous(); iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/service/config/ConfigService.java
@@ -60,4 +60,12 @@ */ PageResult<ConfigDO> getConfigPage(@Valid ConfigPageReqVO reqVO); /** * 根据参数编码,获取参数的value值 * * @param configCode 参数编码 */ String getValue(String configCode); } iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/service/config/ConfigServiceImpl.java
@@ -9,10 +9,15 @@ import com.iailab.module.infra.enums.config.ConfigTypeEnum; import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.iailab.module.infra.enums.ErrorCodeConstants.*; @@ -27,6 +32,9 @@ @Resource private ConfigMapper configMapper; @Resource private StringRedisTemplate stringRedisTemplate; @Override public Long createConfig(ConfigSaveReqVO createReqVO) { @@ -106,4 +114,15 @@ } } @Override public String getValue(String configCode) { String paramValue = stringRedisTemplate.opsForValue().get(configCode); if(paramValue == null){ ConfigDO configDO = configMapper.selectByKey(configCode); paramValue = configDO.getValue(); stringRedisTemplate.opsForValue().set(configCode, paramValue); } return paramValue; } } iailab-module-infra/iailab-module-infra-biz/src/main/resources/application-local.yaml
对比新文件 @@ -0,0 +1,164 @@ --- #################### 注册中心 + 配置中心相关配置 #################### spring: cloud: nacos: server-addr: @nacos.server@ # Nacos 服务器地址 username: @nacos.username@ password: @nacos.password@ discovery: # 【配置中心】配置项 namespace: @nacos.namespace@ # 命名空间。这里使用 dev 开发环境 group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP metadata: version: @nacos.metadata.version@ # 服务实例的版本号,可用于灰度发布 config: # 【注册中心】配置项 namespace: @nacos.namespace@ # 命名空间。这里使用 dev 开发环境 group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP --- #################### 数据库相关配置 #################### spring: # 数据源配置项 autoconfigure: exclude: - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 - de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置 - de.codecentric.boot.admin.server.cloud.config.AdminServerDiscoveryAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置 - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置 - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置 datasource: druid: # Druid 【监控】相关的全局配置 web-stat-filter: enabled: true stat-view-servlet: enabled: true allow: # 设置白名单,不填则允许所有访问 url-pattern: /druid/* login-username: # 控制台管理用户名和密码 login-password: filter: stat: enabled: true log-slow-sql: true # 慢 SQL 记录 slow-sql-millis: 100 merge-sql: true wall: config: multi-statement-allow: true dynamic: # 多数据源配置 druid: # Druid 【连接池】相关的全局配置 initial-size: 1 # 初始连接数 min-idle: 1 # 最小连接池数量 max-active: 20 # 最大连接池数量 max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 test-while-idle: true test-on-borrow: false test-on-return: false primary: master datasource: master: url: jdbc:mysql://127.0.0.1:3306/iailab-platform?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 # url: jdbc:mysql://127.0.0.1:3306/iailab-platform?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai # MySQL Connector/J 5.X 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例 # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro # SQLServer 连接的示例 # url: jdbc:dm://10.211.55.4:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 username: root password: 123456 # username: sa # SQL Server 连接的示例 # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W # SQL Server 连接的示例 # username: SYSDBA # DM 连接的示例 # password: SYSDBA # DM 连接的示例 slave: # 模拟从库,可根据自己需要修改 lazy: true # 开启懒加载,保证启动速度 url: jdbc:mysql://127.0.0.1:3306/iailab-platform?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true username: root password: 123456 # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 redis: host: 127.0.0.1 # 地址 port: 6379 # 端口 database: 0 # 数据库索引 password: 123456 # 密码,建议生产环境开启 --- #################### MQ 消息队列相关配置 #################### # rocketmq 配置项,对应 RocketMQProperties 配置类 rocketmq: name-server: 127.0.0.1:9876 # RocketMQ Namesrv spring: # RabbitMQ 配置项,对应 RabbitProperties 配置类 rabbitmq: host: 127.0.0.1 # RabbitMQ 服务的地址 port: 5672 # RabbitMQ 服务的端口 username: guest # RabbitMQ 服务的账号 password: guest # RabbitMQ 服务的密码 # Kafka 配置项,对应 KafkaProperties 配置类 kafka: bootstrap-servers: 127.0.0.1:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔 --- #################### 定时任务相关配置 #################### xxl: job: enabled: false # 是否开启调度中心,默认为 true 开启 admin: addresses: http://127.0.0.1:9090/xxl-job-admin # 调度中心部署跟地址 --- #################### 服务保障相关配置 #################### # Lock4j 配置项 lock4j: acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒 expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒 --- #################### 监控相关配置 #################### # Actuator 监控端点的配置项 management: endpoints: web: base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator exposure: include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 # Spring Boot Admin 配置项 spring: boot: admin: # Spring Boot Admin Client 客户端的相关配置 client: instance: service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME] # Spring Boot Admin Server 服务端的相关配置 context-path: /admin # 配置 Spring # 日志文件配置 logging: level: # 配置自己写的 MyBatis Mapper 打印日志 com.iailab.module.infra.dal.mysql: debug com.iailab.module.infra.dal.mysql.logger.ApiErrorLogMapper: INFO # 配置 ApiErrorLogMapper 的日志级别为 info,避免和 GlobalExceptionHandler 重复打印 com.iailab.module.infra.dal.mysql.file.FileConfigMapper: INFO # 配置 FileConfigMapper 的日志级别为 info --- #################### 平台相关配置 #################### # 平台配置项,设置当前项目所有自定义的配置 iailab: env: # 多环境的配置项 tag: ${HOSTNAME} security: mock-enable: true xss: enable: false exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 access-log: # 访问日志的配置项 enable: false demo: false # 关闭演示模式 iailab-module-infra/iailab-module-infra-biz/src/main/resources/application.yaml
@@ -1,7 +1,18 @@ spring: application: name: infra-server profiles: active: local main: allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。 allow-bean-definition-overriding: true # 允许 Bean 覆盖,例如说 Feign 等会存在重复定义的服务 config: import: - optional:classpath:application-${spring.profiles.active}.yaml # 加载【本地】配置 - optional:nacos:${spring.application.name}-${spring.profiles.active}.yaml # 加载【Nacos】的配置 # Servlet 配置 servlet: @@ -26,6 +37,13 @@ type: REDIS redis: time-to-live: 1h # 设置过期时间为 1 小时 server: port: 48082 logging: file: name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 --- #################### 接口文档配置 #################### @@ -73,7 +91,6 @@ # VO 转换(数据翻译)相关 easy-trans: is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 is-enable-cloud: false # 禁用 TransType.RPC 微服务模式 --- #################### RPC 远程调用相关配置 #################### iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/mcs/entity/StModelResultEntity.java
对比新文件 @@ -0,0 +1,42 @@ package com.iailab.module.mcs.entity; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.util.Date; /** * 模型返回信息表 * * @author lirm ${email} * @since 1.0.0 2023-06-21 */ @Data @TableName("t_st_model_result") public class StModelResultEntity { /** * id */ private String id; /** * 模型ID */ private String modelId; /** * 行号 */ private Integer lineIndex; /** * 输出key */ private String resultKey; /** * 输出值 */ private String resultValue; /** * 输出时间 */ private Date resultTime; } iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/permission/RoleApi.java
@@ -1,17 +1,20 @@ package com.iailab.module.system.api.permission; import com.iailab.framework.common.pojo.CommonResult; import com.iailab.module.system.api.permission.dto.RoleDTO; import com.iailab.module.system.enums.ApiConstants; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import java.util.Collection; @FeignClient(name = ApiConstants.NAME) // TODO iailab:fallbackFactory = @FeignClient(name = ApiConstants.NAME) @Tag(name = "RPC 服务 - 角色") public interface RoleApi { @@ -22,4 +25,11 @@ @Parameter(name = "ids", description = "角色编号数组", example = "1,2", required = true) CommonResult<Boolean> validRoleList(@RequestParam("ids") Collection<Long> ids); @Operation(summary = "Feign接口-保存或者修改角色") @PostMapping("/api/feign/roles/save") void saveRoleInfo(@RequestBody RoleDTO roleDTO); @Operation(summary = "Feign接口-根据角色名称查询角色") @GetMapping("/api/feign/roles/getRoleByName") RoleDTO getRoleByName(@RequestParam("name") String name); } iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/user/AdminUserApi.java
@@ -11,6 +11,8 @@ import io.swagger.v3.oas.annotations.Operation; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import java.util.*; @@ -86,4 +88,8 @@ return getUser(Convert.toLong(id)).getCheckedData(); } @Operation(summary = "Feign接口-保存或者修改用户") @PostMapping("/api/feign/users/saveOrUpdate") void saveOrUpdateUserInfo(@RequestBody AdminUserRespDTO userRespDTO); } iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/user/dto/AdminUserRespDTO.java
@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.util.List; import java.util.Set; @Schema(description = "RPC 服务 - Admin 用户 Response DTO") @@ -12,6 +13,9 @@ @Schema(description = "用户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long id; @Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "admin") private String username; @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王") private String nickname; @@ -28,4 +32,7 @@ @Schema(description = "手机号码", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300") private String mobile; @Schema(description = "角色ID列表") private Set<Long> roleIdList; } iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/enums/oauth2/OAuth2GrantTypeEnum.java
@@ -22,7 +22,7 @@ private final String grantType; public static OAuth2GrantTypeEnum getByGranType(String grantType) { public static OAuth2GrantTypeEnum getByGrantType(String grantType) { return ArrayUtil.firstMatch(o -> o.getGrantType().equals(grantType), values()); } iailab-module-system/iailab-module-system-biz/pom.xml
@@ -19,10 +19,10 @@ <dependencies> <!-- Spring Cloud 基础 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency> <!-- <dependency>--> <!-- <groupId>org.springframework.cloud</groupId>--> <!-- <artifactId>spring-cloud-starter-bootstrap</artifactId>--> <!-- </dependency>--> <dependency> <groupId>com.iailab</groupId> iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/api/permission/RoleApiImpl.java
@@ -1,6 +1,9 @@ package com.iailab.module.system.api.permission; import com.iailab.framework.common.pojo.CommonResult; import com.iailab.framework.common.util.object.ConvertUtils; import com.iailab.module.system.api.permission.dto.RoleDTO; import com.iailab.module.system.dal.dataobject.permission.RoleDO; import com.iailab.module.system.service.permission.RoleService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RestController; @@ -22,4 +25,17 @@ roleService.validateRoleList(ids); return success(true); } @Override public void saveRoleInfo(RoleDTO roleDTO) { RoleDO entity = ConvertUtils.sourceToTarget(roleDTO, RoleDO.class); if (roleService.getRoleByName(entity.getName()) == null) { roleService.insert(entity); } } @Override public RoleDTO getRoleByName(String name) { return ConvertUtils.sourceToTarget(roleService.getRoleByName(name),RoleDTO.class); } } iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/api/user/AdminUserApiImpl.java
@@ -4,10 +4,13 @@ import cn.hutool.core.util.ObjUtil; import com.iailab.framework.common.pojo.CommonResult; import com.iailab.framework.common.util.object.BeanUtils; import com.iailab.framework.common.util.object.ConvertUtils; import com.iailab.module.system.api.user.dto.AdminUserRespDTO; import com.iailab.module.system.controller.admin.user.vo.user.UserSaveReqVO; import com.iailab.module.system.dal.dataobject.dept.DeptDO; import com.iailab.module.system.dal.dataobject.user.AdminUserDO; import com.iailab.module.system.service.dept.DeptService; import com.iailab.module.system.service.permission.PermissionService; import com.iailab.module.system.service.user.AdminUserService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RestController; @@ -27,6 +30,8 @@ private AdminUserService userService; @Resource private DeptService deptService; @Resource private PermissionService permissionService; @Override public CommonResult<AdminUserRespDTO> getUser(Long id) { @@ -86,4 +91,18 @@ return success(true); } @Override public void saveOrUpdateUserInfo(AdminUserRespDTO userRespDTO) { AdminUserDO entity = ConvertUtils.sourceToTarget(userRespDTO, AdminUserDO.class); AdminUserDO dto = userService.getUserByUsername(entity.getUsername()); UserSaveReqVO bean = BeanUtils.toBean(dto, UserSaveReqVO.class); if (dto != null) { bean.setId(dto.getId()); userService.updateUser(bean); } else { userService.createUser(bean); } permissionService.assignUserRole(entity.getId(), userRespDTO.getRoleIdList()); } } iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/auth/AuthController.java
@@ -39,6 +39,7 @@ import static com.iailab.framework.common.util.collection.CollectionUtils.convertSet; import static com.iailab.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "管理后台 - 认证") @RestController @RequestMapping("/system/auth") @@ -109,7 +110,7 @@ // 1.3 获得菜单列表 Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId)); List<MenuDO> menuList = menuService.getMenuList(menuIds); menuList.removeIf(menu -> !CommonStatusEnum.ENABLE.getStatus().equals(menu.getStatus())); // 移除禁用的菜单 menuList = menuService.filterDisableMenus(menuList); // 2. 拼接结果返回 return success(AuthConvert.INSTANCE.convert(user, roles, menuList)); iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/oauth2/OAuth2OpenController.java
@@ -105,7 +105,7 @@ @RequestParam(value = "refresh_token", required = false) String refreshToken) { // 刷新模式 List<String> scopes = OAuth2Utils.buildScopes(scope); // 1.1 校验授权类型 OAuth2GrantTypeEnum grantTypeEnum = OAuth2GrantTypeEnum.getByGranType(grantType); OAuth2GrantTypeEnum grantTypeEnum = OAuth2GrantTypeEnum.getByGrantType(grantType); if (grantTypeEnum == null) { throw exception0(BAD_REQUEST.getCode(), StrUtil.format("未知授权类型({})", grantType)); } iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/permission/RoleDO.java
@@ -1,7 +1,7 @@ package com.iailab.module.system.dal.dataobject.permission; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import com.iailab.framework.common.enums.CommonStatusEnum; import com.iailab.framework.mybatis.core.type.JsonLongSetTypeHandler; import com.iailab.module.system.enums.permission.DataScopeEnum; import com.iailab.framework.tenant.core.db.TenantBaseDO; import com.iailab.module.system.enums.permission.RoleTypeEnum; @@ -72,7 +72,7 @@ * * 适用于 {@link #dataScope} 的值为 {@link DataScopeEnum#DEPT_CUSTOM} 时 */ @TableField(typeHandler = JsonLongSetTypeHandler.class) @TableField(typeHandler = JacksonTypeHandler.class) private Set<Long> dataScopeDeptIds; } iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/tenant/TenantPackageDO.java
@@ -1,8 +1,8 @@ package com.iailab.module.system.dal.dataobject.tenant; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import com.iailab.framework.common.enums.CommonStatusEnum; import com.iailab.framework.mybatis.core.dataobject.BaseDO; import com.iailab.framework.mybatis.core.type.JsonLongSetTypeHandler; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; @@ -46,7 +46,7 @@ /** * 关联的菜单编号 */ @TableField(typeHandler = JsonLongSetTypeHandler.class) @TableField(typeHandler = JacksonTypeHandler.class) private Set<Long> menuIds; } iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/user/AdminUserDO.java
@@ -1,7 +1,7 @@ package com.iailab.module.system.dal.dataobject.user; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import com.iailab.framework.common.enums.CommonStatusEnum; import com.iailab.framework.mybatis.core.type.JsonLongSetTypeHandler; import com.iailab.framework.tenant.core.db.TenantBaseDO; import com.iailab.module.system.enums.common.SexEnum; import com.baomidou.mybatisplus.annotation.KeySequence; @@ -58,7 +58,7 @@ /** * 岗位编号数组 */ @TableField(typeHandler = JsonLongSetTypeHandler.class) @TableField(typeHandler = JacksonTypeHandler.class) private Set<Long> postIds; /** * 用户邮箱 iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/permission/MenuService.java
@@ -1,5 +1,6 @@ package com.iailab.module.system.service.permission; import com.iailab.module.system.controller.admin.permission.vo.menu.MenuListReqVO; import com.iailab.module.system.controller.admin.permission.vo.menu.MenuSaveVO; import com.iailab.module.system.dal.dataobject.permission.MenuDO; @@ -10,7 +11,7 @@ /** * 菜单 Service 接口 * * @author iailab * @author 芋道源码 */ public interface MenuService { @@ -53,6 +54,14 @@ List<MenuDO> getMenuListByTenant(MenuListReqVO reqVO); /** * 过滤掉关闭的菜单及其子菜单 * * @param list 菜单列表 * @return 过滤后的菜单列表 */ List<MenuDO> filterDisableMenus(List<MenuDO> list); /** * 筛选菜单列表 * * @param reqVO 筛选条件请求 VO iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/permission/MenuServiceImpl.java
@@ -1,6 +1,10 @@ package com.iailab.module.system.service.permission; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; import com.iailab.framework.common.enums.CommonStatusEnum; import com.iailab.framework.common.util.object.BeanUtils; import com.iailab.module.system.controller.admin.permission.vo.menu.MenuListReqVO; import com.iailab.module.system.controller.admin.permission.vo.menu.MenuSaveVO; @@ -9,8 +13,6 @@ import com.iailab.module.system.dal.redis.RedisKeyConstants; import com.iailab.module.system.enums.permission.MenuTypeEnum; import com.iailab.module.system.service.tenant.TenantService; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; @@ -19,18 +21,19 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.Collection; import java.util.List; import java.util.*; import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.iailab.framework.common.util.collection.CollectionUtils.convertList; import static com.iailab.framework.common.util.collection.CollectionUtils.convertMap; import static com.iailab.module.system.dal.dataobject.permission.MenuDO.ID_ROOT; import static com.iailab.module.system.enums.ErrorCodeConstants.*; /** * 菜单 Service 实现 * * @author iailab * @author 芋道源码 */ @Service @Slf4j @@ -106,6 +109,7 @@ @Override public List<MenuDO> getMenuListByTenant(MenuListReqVO reqVO) { // 查询所有菜单,并过滤掉关闭的节点 List<MenuDO> menus = getMenuList(reqVO); // 开启多租户的情况下,需要过滤掉未开通的菜单 tenantService.handleTenantMenu(menuIds -> menus.removeIf(menu -> !CollUtil.contains(menuIds, menu.getId()))); @@ -113,6 +117,50 @@ } @Override public List<MenuDO> filterDisableMenus(List<MenuDO> menuList) { if (CollUtil.isEmpty(menuList)){ return Collections.emptyList(); } Map<Long, MenuDO> menuMap = convertMap(menuList, MenuDO::getId); // 遍历 menu 菜单,查找不是禁用的菜单,添加到 enabledMenus 结果 List<MenuDO> enabledMenus = new ArrayList<>(); Set<Long> disabledMenuCache = new HashSet<>(); // 存下递归搜索过被禁用的菜单,防止重复的搜索 for (MenuDO menu : menuList) { if (isMenuDisabled(menu, menuMap, disabledMenuCache)) { continue; } enabledMenus.add(menu); } return enabledMenus; } private boolean isMenuDisabled(MenuDO node, Map<Long, MenuDO> menuMap, Set<Long> disabledMenuCache) { // 如果已经判定是禁用的节点,直接结束 if (disabledMenuCache.contains(node.getId())) { return true; } // 1. 遍历到 parentId 为根节点,则无需判断 Long parentId = node.getParentId(); if (ObjUtil.equal(parentId, ID_ROOT)) { if (CommonStatusEnum.isDisable(node.getStatus())) { disabledMenuCache.add(node.getId()); return true; } return false; } // 2. 继续遍历 parent 节点 MenuDO parent = menuMap.get(parentId); if (parent == null || isMenuDisabled(parent, menuMap, disabledMenuCache)) { disabledMenuCache.add(node.getId()); return true; } return false; } @Override public List<MenuDO> getMenuList(MenuListReqVO reqVO) { return menuMapper.selectList(reqVO); } iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/permission/RoleService.java
@@ -121,4 +121,13 @@ */ void validateRoleList(Collection<Long> ids); /** * 根据角色名获得角色 * * @param name 角色编号 * @return 角色 */ RoleDO getRoleByName(String name); void insert(RoleDO role); } iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/permission/RoleServiceImpl.java
@@ -8,6 +8,7 @@ import com.iailab.framework.common.pojo.PageResult; import com.iailab.framework.common.util.collection.CollectionUtils; import com.iailab.framework.common.util.object.BeanUtils; import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX; import com.iailab.module.system.controller.admin.permission.vo.role.RolePageReqVO; import com.iailab.module.system.controller.admin.permission.vo.role.RoleSaveReqVO; import com.iailab.module.system.dal.dataobject.permission.RoleDO; @@ -249,6 +250,16 @@ }); } @Override public RoleDO getRoleByName(String name) { return roleMapper.selectOne(new LambdaQueryWrapperX<RoleDO>().eq(RoleDO::getName, name)); } @Override public void insert(RoleDO role) { roleMapper.insert(role); } /** * 获得自身的代理对象,解决 AOP 生效问题 * iailab-module-system/iailab-module-system-biz/src/main/resources/application-local.yaml
对比新文件 @@ -0,0 +1,210 @@ --- #################### 注册中心 + 配置中心相关配置 #################### spring: cloud: nacos: server-addr: 127.0.0.1:8848 # Nacos 服务器地址 username: nacos password: nacos discovery: # 【配置中心】配置项 namespace: a7112341-c9e2-4177-bc5b-0d2e8cf0b3bb group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP metadata: version: 1.0.0 # 服务实例的版本号,可用于灰度发布 config: # 【注册中心】配置项 namespace: a7112341-c9e2-4177-bc5b-0d2e8cf0b3bb group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP --- #################### 数据库相关配置 #################### spring: # 数据源配置项 autoconfigure: exclude: - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置 datasource: druid: # Druid 【监控】相关的全局配置 web-stat-filter: enabled: true stat-view-servlet: enabled: true allow: # 设置白名单,不填则允许所有访问 url-pattern: /druid/* login-username: # 控制台管理用户名和密码 login-password: filter: stat: enabled: true log-slow-sql: true # 慢 SQL 记录 slow-sql-millis: 100 merge-sql: true wall: config: multi-statement-allow: true dynamic: # 多数据源配置 druid: # Druid 【连接池】相关的全局配置 initial-size: 1 # 初始连接数 min-idle: 1 # 最小连接池数量 max-active: 20 # 最大连接池数量 max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 test-while-idle: true test-on-borrow: false test-on-return: false primary: master datasource: master: url: jdbc:mysql://127.0.0.1:3306/iailab-platform?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 # url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai # MySQL Connector/J 5.X 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例 # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro # SQLServer 连接的示例 # url: jdbc:dm://10.211.55.4:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 username: root password: 123456 # username: sa # SQL Server 连接的示例 # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W # SQL Server 连接的示例 # username: SYSDBA # DM 连接的示例 # password: SYSDBA # DM 连接的示例 slave: # 模拟从库,可根据自己需要修改 lazy: true # 开启懒加载,保证启动速度 url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true username: root password: 123456 # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 redis: host: 172.16.8.100 # 地址 port: 6379 # 端口 database: 0 # 数据库索引 password: 123456 # 密码,建议生产环境开启 --- #################### MQ 消息队列相关配置 #################### # rocketmq 配置项,对应 RocketMQProperties 配置类 rocketmq: name-server: 127.0.0.1:9876 # RocketMQ Namesrv spring: # RabbitMQ 配置项,对应 RabbitProperties 配置类 rabbitmq: host: 127.0.0.1 # RabbitMQ 服务的地址 port: 5672 # RabbitMQ 服务的端口 username: guest # RabbitMQ 服务的账号 password: guest # RabbitMQ 服务的密码 # Kafka 配置项,对应 KafkaProperties 配置类 kafka: bootstrap-servers: 127.0.0.1:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔 --- #################### 定时任务相关配置 #################### xxl: job: enabled: true # 是否开启调度中心,默认为 true 开启 admin: addresses: http://127.0.0.1:9090/xxl-job-admin # 调度中心部署跟地址 --- #################### 服务保障相关配置 #################### # Lock4j 配置项 lock4j: acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒 expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒 --- #################### 监控相关配置 #################### # Actuator 监控端点的配置项 management: endpoints: web: base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator exposure: include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 # Spring Boot Admin 配置项 spring: boot: admin: # Spring Boot Admin Client 客户端的相关配置 client: instance: service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME] # 日志文件配置 logging: level: # 配置自己写的 MyBatis Mapper 打印日志 com.iailab.module.system.dal.mysql: debug com.iailab.module.system.dal.mysql.sensitiveword.SensitiveWordMapper: INFO # 配置 SensitiveWordMapper 的日志级别为 info com.iailab.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info #org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示 --- #################### 微信公众号、小程序相关配置 #################### wx: mp: # 公众号配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档 # app-id: wx041349c6f39b268b # secret: 5abee519483bc9f8cb37ce280e814bd0 app-id: wx5b23ba7a5589ecbb # 测试号 secret: 2a7b3b20c537e52e74afd395eb85f61f # 存储配置,解决 AccessToken 的跨节点的共享 config-storage: type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 key-prefix: wx # Redis Key 的前缀 http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 miniapp: # 小程序配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md 文档 # appid: wx62056c0d5e8db250 # secret: 333ae72f41552af1e998fe1f54e1584a appid: wx63c280fe3248a3e7 # wenhualian的接口测试号 secret: 6f270509224a7ae1296bbf1c8cb97aed config-storage: type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 key-prefix: wa # Redis Key 的前缀 http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 --- #################### 平台相关配置 #################### # 平台配置项,设置当前项目所有自定义的配置 iailab: env: # 多环境的配置项 tag: ${HOSTNAME} captcha: enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试 security: mock-enable: true xss: enable: false exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 access-log: # 访问日志的配置项 enable: false demo: false # 关闭演示模式 justauth: enabled: true type: DINGTALK: # 钉钉 client-id: dingvrnreaje3yqvzhxg client-secret: i8E6iZyDvZj51JIb0tYsYfVQYOks9Cq1lgryEjFRqC79P3iJcrxEwT6Qk2QvLrLI ignore-check-redirect-uri: true WECHAT_ENTERPRISE: # 企业微信 client-id: wwd411c69a39ad2e54 client-secret: 1wTb7hYxnpT2TUbIeHGXGo7T0odav1ic10mLdyyATOw agent-id: 1000004 ignore-check-redirect-uri: true # noinspection SpringBootApplicationYaml WECHAT_MINI_APP: # 微信小程序 client-id: ${wx.miniapp.appid} client-secret: ${wx.miniapp.secret} ignore-check-redirect-uri: true ignore-check-state: true # 微信小程序,不会使用到 state,所以不进行校验 WECHAT_MP: # 微信公众号 client-id: ${wx.mp.app-id} client-secret: ${wx.mp.secret} ignore-check-redirect-uri: true cache: type: REDIS prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE:: timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟 iailab-module-system/iailab-module-system-biz/src/main/resources/application.yaml
@@ -1,7 +1,18 @@ spring: application: name: system-server profiles: active: local main: allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。 allow-bean-definition-overriding: true # 允许 Bean 覆盖,例如说 Feign 等会存在重复定义的服务 config: import: - optional:classpath:application-${spring.profiles.active}.yaml # 加载【本地】配置 - optional:nacos:${spring.application.name}-${spring.profiles.active}.yaml # 加载【Nacos】的配置 # Servlet 配置 servlet: @@ -26,6 +37,13 @@ type: REDIS redis: time-to-live: 1h # 设置过期时间为 1 小时 server: port: 48081 logging: file: name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 --- #################### 接口文档配置 #################### @@ -146,7 +164,7 @@ version: ${iailab.info.version} base-package: ${iailab.info.base-package} captcha: enable: true # 验证码的开关,默认为 true; enable: false # 验证码的开关,默认为 true; tenant: # 多租户相关配置项 enable: true ignore-urls: pom.xml
@@ -8,15 +8,15 @@ <version>${revision}</version> <packaging>pom</packaging> <modules> <!-- <module>iailab-server</module>--> <!-- <module>iailab-dependencies</module>--> <module>iailab-framework</module> <module>iailab-cloud</module> <!-- 各种 module 拓展 --> <module>iailab-module-system</module> <module>iailab-module-infra</module> <module>iailab-module-bpm</module> <module>iailab-module-report</module> <module>iailab-cloud</module> <module>iailab-module-data</module> <module>iailab-module-model</module> </modules> <name>${project.artifactId}</name> @@ -34,28 +34,29 @@ <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version> <!-- 统一依赖管理 --> <spring.boot.version>2.7.18</spring.boot.version> <spring.cloud.version>2021.0.5</spring.cloud.version> <spring.cloud.alibaba.version>2021.0.5.0</spring.cloud.alibaba.version> <spring.cloud.version>2021.0.9</spring.cloud.version> <spring.cloud.alibaba.version>2021.0.6.1</spring.cloud.alibaba.version> <!-- Web 相关 --> <servlet.versoin>2.5</servlet.versoin> <springdoc.version>1.6.15</springdoc.version> <knife4j.version>4.3.0</knife4j.version> <springdoc.version>1.7.0</springdoc.version> <knife4j.version>4.5.0</knife4j.version> <!-- DB 相关 --> <druid.version>1.2.21</druid.version> <mybatis-plus.version>3.5.5</mybatis-plus.version> <mybatis-plus-generator.version>3.5.5</mybatis-plus-generator.version> <dynamic-datasource.version>4.3.0</dynamic-datasource.version> <mybatis-plus-join.version>1.4.10</mybatis-plus-join.version> <easy-trans.version>2.2.11</easy-trans.version> <redisson.version>3.18.0</redisson.version> <!-- Spring Boot 2.X 最多使用 3.18.0 版本,否则会报 Tuple NoClassDefFoundError --> <druid.version>1.2.23</druid.version> <mybatis.version>3.5.16</mybatis.version> <mybatis-plus.version>3.5.7</mybatis-plus.version> <mybatis-plus-generator.version>3.5.7</mybatis-plus-generator.version> <dynamic-datasource.version>4.3.1</dynamic-datasource.version> <mybatis-plus-join.version>1.4.13</mybatis-plus-join.version> <easy-trans.version>3.0.5</easy-trans.version> <redisson.version>3.32.0</redisson.version> <!-- Spring Boot 2.X 最多使用 3.18.0 版本,否则会报 Tuple NoClassDefFoundError --> <dm8.jdbc.version>8.1.3.62</dm8.jdbc.version> <!-- 消息队列 --> <rocketmq-spring.version>2.2.3</rocketmq-spring.version> <rocketmq-spring.version>2.3.0</rocketmq-spring.version> <!-- RPC 相关 --> <!-- Config 配置中心相关 --> <apollo.version>1.9.2</apollo.version> <!-- Job 定时任务相关 --> <xxl-job.version>2.3.1</xxl-job.version> <xxl-job.version>2.4.0</xxl-job.version> <!-- 服务保障相关 --> <lock4j.version>2.2.7</lock4j.version> <!-- 监控相关 --> @@ -70,20 +71,21 @@ <flowable.version>6.8.0</flowable.version> <!-- 工具类相关 --> <captcha-plus.version>1.0.8</captcha-plus.version> <jsoup.version>1.17.2</jsoup.version> <lombok.version>1.18.30</lombok.version> <jsoup.version>1.18.1</jsoup.version> <lombok.version>1.18.34</lombok.version> <mapstruct.version>1.5.5.Final</mapstruct.version> <hutool.version>5.8.25</hutool.version> <easyexcel.verion>3.3.3</easyexcel.verion> <hutool.version>5.8.29</hutool.version> <joda.time.version>2.10.14</joda.time.version> <easyexcel.verion>3.3.4</easyexcel.verion> <velocity.version>2.3</velocity.version> <screw.version>1.0.5</screw.version> <!-- <screw.version>1.0.5</screw.version>--> <fastjson.version>1.2.83</fastjson.version> <guava.version>33.0.0-jre</guava.version> <guice.version>5.1.0</guice.version> <guava.version>33.2.1-jre</guava.version> <!-- <guice.version>5.1.0</guice.version>--> <transmittable-thread-local.version>2.14.5</transmittable-thread-local.version> <commons-net.version>3.10.0</commons-net.version> <commons-net.version>3.11.1</commons-net.version> <jsch.version>0.1.55</jsch.version> <tika-core.version>2.9.1</tika-core.version> <tika-core.version>2.9.2</tika-core.version> <ip2region.version>2.7.0</ip2region.version> <bizlog-sdk.version>3.0.6</bizlog-sdk.version> <reflections.version>0.10.2</reflections.version> @@ -121,6 +123,21 @@ <!-- 默认环境 --> <activeByDefault>true</activeByDefault> </activation> </profile> <profile> <id>test</id> <properties> <!-- 环境标识,需要与配置文件的名称相对应 --> <profiles.active>test</profiles.active> <nacos.server>172.16.8.100:8848</nacos.server> <nacos.discovery.group>DEFAULT_GROUP</nacos.discovery.group> <nacos.config.group>DEFAULT_GROUP</nacos.config.group> <nacos.username>nacos</nacos.username> <nacos.password>nacos</nacos.password> <nacos.namespace>a7112341-c9e2-4177-bc5b-0d2e8cf0b3bb</nacos.namespace> <nacos.metadata.version>1.0.0</nacos.metadata.version> <logstash.address>127.0.0.1:4560</logstash.address> </properties> </profile> <profile> <id>prod</id> @@ -532,6 +549,12 @@ </dependency> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>${joda.time.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>${easyexcel.verion}</version>